Compare commits
164 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78402f6546 | ||
|
|
a1b5fbb1fe | ||
|
|
b71f633fac | ||
|
|
dbb674aa8e | ||
|
|
018daf7f09 | ||
|
|
a07a84a8b1 | ||
|
|
0f36f34a4f | ||
|
|
cf2cebd0fc | ||
|
|
90dd59abe6 | ||
|
|
5332ed6bef | ||
|
|
d45d4ded99 | ||
|
|
25b5590d2c | ||
|
|
d2b2ced5bf | ||
|
|
c551953283 | ||
|
|
5ae1f38ea8 | ||
|
|
372f12de95 | ||
|
|
9cfa88dd8c | ||
|
|
7b355ebc49 | ||
|
|
43a56c8ec8 | ||
|
|
3da90bfa97 | ||
|
|
dd572a7456 | ||
|
|
8cd818b80e | ||
|
|
530bbc07c5 | ||
|
|
a992f7a0e8 | ||
|
|
ca3718594d | ||
|
|
17a66853d5 | ||
|
|
8c317c1396 | ||
|
|
20f888b991 | ||
|
|
cd0d3862c7 | ||
|
|
443ffb7906 | ||
|
|
5967c83b03 | ||
|
|
66498a03ce | ||
|
|
9ec772f723 | ||
|
|
20eb56db2d | ||
|
|
e4d064aaa3 | ||
|
|
5602dfa09a | ||
|
|
0138b412b4 | ||
|
|
20a934c9ab | ||
|
|
09d2b397dc | ||
|
|
482a99cf15 | ||
|
|
81ac45a1d4 | ||
|
|
0b8078f3bf | ||
|
|
8b6ace902c | ||
|
|
1dead9fca5 | ||
|
|
524c4b71d7 | ||
|
|
e51318768d | ||
|
|
c821bb20d0 | ||
|
|
c6b693b4ac | ||
|
|
2c5caabab0 | ||
|
|
b7479e8342 | ||
|
|
ffca124762 | ||
|
|
9bedbf6fb8 | ||
|
|
853150e458 | ||
|
|
1ddd48e008 | ||
|
|
17d24d642e | ||
|
|
87a46684cd | ||
|
|
e4c5193945 | ||
|
|
2e969bf6dd | ||
|
|
6db26d9f7b | ||
|
|
4f02c9ec36 | ||
|
|
2fdd39fba5 | ||
|
|
fe1ddc3a94 | ||
|
|
cff2d805db | ||
|
|
34425d3e47 | ||
|
|
4ac4f00620 | ||
|
|
e30a4623c5 | ||
|
|
e2f4dcaaee | ||
|
|
ebbf64ddae | ||
|
|
8b105ad22b | ||
|
|
f3416c5b1d | ||
|
|
e194fc5ee4 | ||
|
|
e465c81bf1 | ||
|
|
9dce6a99fd | ||
|
|
6f2c53d14e | ||
|
|
9044ae4ade | ||
|
|
0a422174bc | ||
|
|
c2020fe77c | ||
|
|
8beca6fcc7 | ||
|
|
18769df2ca | ||
|
|
2806fd6cdb | ||
|
|
b607940c8c | ||
|
|
dff599df4c | ||
|
|
b3cd38e019 | ||
|
|
61975e1992 | ||
|
|
1a8ad69f23 | ||
|
|
f21e40151b | ||
|
|
4e58769648 | ||
|
|
f9d6001025 | ||
|
|
ae5f5f90ff | ||
|
|
89db21d734 | ||
|
|
0e4b072650 | ||
|
|
13b0e00b27 | ||
|
|
bf5d8ca19e | ||
|
|
4a3339c09c | ||
|
|
b28c2b28b2 | ||
|
|
fcb3e648d2 | ||
|
|
5d6f08e38f | ||
|
|
b932af1c97 | ||
|
|
8874eb2b1c | ||
|
|
dcf9816a72 | ||
|
|
c8722c9f62 | ||
|
|
a82a2ccffe | ||
|
|
0bf70e443e | ||
|
|
3d6d690583 | ||
|
|
783f76d55d | ||
|
|
1dd46fb777 | ||
|
|
22bbd3a4ca | ||
|
|
3cd4b2251f | ||
|
|
9e4b003608 | ||
|
|
e66d0bc6b8 | ||
|
|
9a4abd78ed | ||
|
|
826bee8b1e | ||
|
|
143020dc27 | ||
|
|
be23065988 | ||
|
|
2cb62eae96 | ||
|
|
76c411d1e2 | ||
|
|
16fa91c2a1 | ||
|
|
b77f8717fe | ||
|
|
59ecf43c5f | ||
|
|
1fd8546354 | ||
|
|
7cb95cb3f6 | ||
|
|
160d19d6c1 | ||
|
|
a0550ca141 | ||
|
|
ac68fc016d | ||
|
|
5170307f72 | ||
|
|
3af0e51bd2 | ||
|
|
f34d1fe081 | ||
|
|
83c72ebba5 | ||
|
|
6ca8e6b3ea | ||
|
|
ba24fc2fab | ||
|
|
7f28b22599 | ||
|
|
4345db0d2e | ||
|
|
eddc10c3e2 | ||
|
|
46eaada0c4 | ||
|
|
f8b2dea270 | ||
|
|
90ebf0e0f8 | ||
|
|
1a819c807e | ||
|
|
3220809c04 | ||
|
|
72d5255c9e | ||
|
|
5995563a80 | ||
|
|
347743d93a | ||
|
|
3c067ce723 | ||
|
|
8dd2170dfa | ||
|
|
5f3a3dd5cf | ||
|
|
8ad3563963 | ||
|
|
492128ef86 | ||
|
|
b4936274f2 | ||
|
|
64ccd5ba53 | ||
|
|
7ae88f7560 | ||
|
|
ae70af26d1 | ||
|
|
483bdc237c | ||
|
|
2c564b47f4 | ||
|
|
fc80d0b5f3 | ||
|
|
d094c189d3 | ||
|
|
40d8819e77 | ||
|
|
4a3d019f06 | ||
|
|
5366a4a6ed | ||
|
|
e8230d8e5b | ||
|
|
ebdbb9011f | ||
|
|
e43793354e | ||
|
|
438c54599e | ||
|
|
da42183177 | ||
|
|
295fa3f122 | ||
|
|
cb87f1cc36 |
37
.github/actions/run-tests/action.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
name: 'Package plugin'
|
||||||
|
description: 'Packages the plugin for specified architecture and build config.'
|
||||||
|
inputs:
|
||||||
|
target:
|
||||||
|
description: 'Build target'
|
||||||
|
required: true
|
||||||
|
workingDirectory:
|
||||||
|
description: 'Working directory'
|
||||||
|
required: false
|
||||||
|
default: ${{ github.workspace }}
|
||||||
|
runs:
|
||||||
|
using: 'composite'
|
||||||
|
steps:
|
||||||
|
- name: Run macOS tests
|
||||||
|
if: ${{ runner.os == 'macOS' }}
|
||||||
|
shell: zsh {0}
|
||||||
|
run: |
|
||||||
|
if [[ '${{ inputs.target }}' != 'x86_64' ]]; then
|
||||||
|
echo tests skipped!
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
${{ inputs.workingDirectory }}/build_x86_64/tests/advanced-scene-switcher-tests
|
||||||
|
|
||||||
|
- name: Run Linux packaging
|
||||||
|
if: ${{ runner.os == 'Linux' }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if [[ '${{ inputs.target }}' != 'x86_64' ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
${{ inputs.workingDirectory }}/build_x86_64/tests/advanced-scene-switcher-tests
|
||||||
|
|
||||||
|
- name: Run Windows packaging
|
||||||
|
if: ${{ runner.os == 'Windows' }}
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
${{ inputs.workingDirectory }}/build_x64/tests/RelWithDebInfo/advanced-scene-switcher-tests.exe
|
||||||
87
.github/scripts/.build.zsh
vendored
@@ -170,26 +170,38 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
|
|
||||||
local product_name
|
local product_name
|
||||||
local product_version
|
local product_version
|
||||||
|
local git_tag="$(git describe --tags)"
|
||||||
|
|
||||||
read -r product_name product_version <<< \
|
read -r product_name product_version <<< \
|
||||||
"$(jq -r '. | {name, version} | join(" ")' ${buildspec_file})"
|
"$(jq -r '. | {name, version} | join(" ")' ${buildspec_file})"
|
||||||
|
|
||||||
local opencv_dir="${project_root}/deps/opencv"
|
if [[ "${git_tag}" =~ '^([0-9]+\.){0,2}(\*|[0-9]+)$' ]] {
|
||||||
local opencv_build_dir="${opencv_dir}/build_${target##*-}"
|
log_info "Using git tag as version identifier '${git_tag}'"
|
||||||
|
product_version="${git_tag}"
|
||||||
|
} else {
|
||||||
|
log_info "Using buildspec.json version identifier '${product_version}'"
|
||||||
|
}
|
||||||
|
|
||||||
case ${host_os} {
|
case ${host_os} {
|
||||||
macos)
|
macos)
|
||||||
sed -i '' \
|
sed -i '' \
|
||||||
"s/project(\(.*\) VERSION \(.*\))/project(${product_name} VERSION ${product_version})/" \
|
"s/project(\(.*\) VERSION \(.*\))/project(${product_name} VERSION ${product_version})/" \
|
||||||
"${project_root}/CMakeLists.txt"
|
"${project_root}/CMakeLists.txt"
|
||||||
|
|
||||||
# Note: IPP must be set to OFF to avoid build failures on ARM architectures
|
local opencv_dir="${project_root}/deps/opencv"
|
||||||
|
local opencv_build_dir="${opencv_dir}/build_${target##*-}"
|
||||||
|
|
||||||
local -a opencv_cmake_args=(
|
local -a opencv_cmake_args=(
|
||||||
-DCMAKE_BUILD_TYPE=Release
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
-DBUILD_LIST=core,imgproc,objdetect
|
-DBUILD_LIST=core,imgproc,objdetect
|
||||||
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
|
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
|
||||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
||||||
-DWITH_IPP=OFF
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if [ "${target}" != "macos-x86_64" ]; then
|
||||||
|
opencv_cmake_args+=(-DWITH_IPP=OFF)
|
||||||
|
fi
|
||||||
|
|
||||||
pushd ${opencv_dir}
|
pushd ${opencv_dir}
|
||||||
log_info "Configure OpenCV ..."
|
log_info "Configure OpenCV ..."
|
||||||
cmake -S . -B ${opencv_build_dir} -G ${generator} ${opencv_cmake_args}
|
cmake -S . -B ${opencv_build_dir} -G ${generator} ${opencv_cmake_args}
|
||||||
@@ -198,9 +210,73 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
cmake --build ${opencv_build_dir} --config Release
|
cmake --build ${opencv_build_dir} --config Release
|
||||||
|
|
||||||
log_info "Installing OpenCV..."
|
log_info "Installing OpenCV..."
|
||||||
cmake --install ${opencv_build_dir} --config Release --prefix ${opencv_build_dir}
|
cmake --install ${opencv_build_dir} --config Release || true
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
local leptonica_dir="${project_root}/deps/leptonica"
|
||||||
|
local leptonica_build_dir="${leptonica_dir}/build_${target##*-}"
|
||||||
|
|
||||||
|
local -a leptonica_cmake_args=(
|
||||||
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
|
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
|
||||||
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
||||||
|
-DSW_BUILD=OFF
|
||||||
|
-DOPENJPEG_SUPPORT=OFF
|
||||||
|
-DLIBWEBP_SUPPORT=OFF
|
||||||
|
-DCMAKE_DISABLE_FIND_PACKAGE_GIF=TRUE
|
||||||
|
-DCMAKE_DISABLE_FIND_PACKAGE_JPEG=TRUE
|
||||||
|
-DCMAKE_DISABLE_FIND_PACKAGE_TIFF=TRUE
|
||||||
|
-DCMAKE_DISABLE_FIND_PACKAGE_PNG=TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
pushd ${leptonica_dir}
|
||||||
|
log_info "Configure Leptonica ..."
|
||||||
|
cmake -S . -B ${leptonica_build_dir} -G ${generator} ${leptonica_cmake_args}
|
||||||
|
|
||||||
|
log_info "Building Leptonica ..."
|
||||||
|
cmake --build ${leptonica_build_dir} --config Release
|
||||||
|
|
||||||
|
log_info "Installing Leptonica..."
|
||||||
|
# Workaround for "unknown file attribute: H" errors when running install
|
||||||
|
cmake --install ${leptonica_build_dir} --config Release || :
|
||||||
|
popd
|
||||||
|
|
||||||
|
local tesseract_dir="${project_root}/deps/tesseract"
|
||||||
|
local tesseract_build_dir="${tesseract_dir}/build_${target##*-}"
|
||||||
|
|
||||||
|
local -a tesseract_cmake_args=(
|
||||||
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
|
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
|
||||||
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
||||||
|
-DSW_BUILD=OFF
|
||||||
|
-DBUILD_TRAINING_TOOLS=OFF
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ "${target}" != "macos-x86_64" ]; then
|
||||||
|
tesseract_cmake_args+=(
|
||||||
|
-DCMAKE_SYSTEM_PROCESSOR=aarch64
|
||||||
|
-DHAVE_AVX=FALSE
|
||||||
|
-DHAVE_AVX2=FALSE
|
||||||
|
-DHAVE_AVX512F=FALSE
|
||||||
|
-DHAVE_FMA=FALSE
|
||||||
|
-DHAVE_SSE4_1=FALSE
|
||||||
|
-DHAVE_NEON=TRUE
|
||||||
|
)
|
||||||
|
sed -i'.original' 's/HAVE_NEON FALSE/HAVE_NEON TRUE/g' "${tesseract_dir}/CMakeLists.txt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
pushd ${tesseract_dir}
|
||||||
|
log_info "Configure Tesseract ..."
|
||||||
|
cmake -S . -B ${tesseract_build_dir} -G ${generator} ${tesseract_cmake_args}
|
||||||
|
|
||||||
|
log_info "Building Tesseract ..."
|
||||||
|
#cmake --build ${tesseract_build_dir} --config Release --target libtesseract
|
||||||
|
cmake --build ${tesseract_build_dir} --config Release
|
||||||
|
|
||||||
|
log_info "Installing Tesseract..."
|
||||||
|
#cmake --install ${tesseract_build_dir} --config Release --component libtesseract
|
||||||
|
cmake --install ${tesseract_build_dir} --config Release
|
||||||
|
popd
|
||||||
;;
|
;;
|
||||||
linux)
|
linux)
|
||||||
sed -i'' \
|
sed -i'' \
|
||||||
@@ -242,7 +318,6 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
||||||
-DOBS_CODESIGN_LINKER=ON
|
-DOBS_CODESIGN_LINKER=ON
|
||||||
-DOBS_BUNDLE_CODESIGN_IDENTITY="${CODESIGN_IDENT:--}"
|
-DOBS_BUNDLE_CODESIGN_IDENTITY="${CODESIGN_IDENT:--}"
|
||||||
-DOpenCV_DIR="${opencv_build_dir}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
;;
|
;;
|
||||||
|
|||||||
9
.github/scripts/.package.zsh
vendored
@@ -128,9 +128,18 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
|
|
||||||
local product_name
|
local product_name
|
||||||
local product_version
|
local product_version
|
||||||
|
local git_tag="$(git describe --tags)"
|
||||||
|
|
||||||
read -r product_name product_version <<< \
|
read -r product_name product_version <<< \
|
||||||
"$(jq -r '. | {name, version} | join(" ")' ${project_root}/buildspec.json)"
|
"$(jq -r '. | {name, version} | join(" ")' ${project_root}/buildspec.json)"
|
||||||
|
|
||||||
|
if [[ "${git_tag}" =~ '^([0-9]+\.){0,2}(\*|[0-9]+)$' ]] {
|
||||||
|
log_info "Using git tag as version identifier '${git_tag}'"
|
||||||
|
product_version="${git_tag}"
|
||||||
|
} else {
|
||||||
|
log_info "Using buildspec.json version identifier '${product_version}'"
|
||||||
|
}
|
||||||
|
|
||||||
if [[ ${host_os} == 'macos' ]] {
|
if [[ ${host_os} == 'macos' ]] {
|
||||||
autoload -Uz check_packages read_codesign read_codesign_installer read_codesign_pass
|
autoload -Uz check_packages read_codesign read_codesign_installer read_codesign_pass
|
||||||
|
|
||||||
|
|||||||
101
.github/scripts/Build-Windows.ps1
vendored
@@ -37,7 +37,7 @@ function Build {
|
|||||||
|
|
||||||
$UtilityFunctions = Get-ChildItem -Path $PSScriptRoot/utils.pwsh/*.ps1 -Recurse
|
$UtilityFunctions = Get-ChildItem -Path $PSScriptRoot/utils.pwsh/*.ps1 -Recurse
|
||||||
|
|
||||||
foreach($Utility in $UtilityFunctions) {
|
foreach ($Utility in $UtilityFunctions) {
|
||||||
Write-Debug "Loading $($Utility.FullName)"
|
Write-Debug "Loading $($Utility.FullName)"
|
||||||
. $Utility.FullName
|
. $Utility.FullName
|
||||||
}
|
}
|
||||||
@@ -57,18 +57,22 @@ function Build {
|
|||||||
$CmakeGenerator = $script:VisualStudioVersion
|
$CmakeGenerator = $script:VisualStudioVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$DepsPath = "plugin-deps-${script:DepsVersion}-qt${script:QtVersion}-${script:Target}"
|
||||||
|
$DepInstallPath = "$(Resolve-Path -Path ${ProjectRoot}/../obs-build-dependencies/${DepsPath})"
|
||||||
|
|
||||||
|
$OpenCVPath = "${ProjectRoot}/deps/opencv"
|
||||||
|
$OpenCVBuildPath = "${OpenCVPath}/build"
|
||||||
|
|
||||||
Push-Location -Stack BuildOpenCVTemp
|
Push-Location -Stack BuildOpenCVTemp
|
||||||
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
|
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
|
||||||
Ensure-Location $ProjectRoot
|
Ensure-Location $ProjectRoot
|
||||||
|
|
||||||
$OpenCVPath = "${ProjectRoot}/deps/opencv"
|
|
||||||
$OpenCVBuildPath = "${OpenCVPath}/build"
|
|
||||||
$OpenCVCmakeArgs = @(
|
$OpenCVCmakeArgs = @(
|
||||||
'-G', $CmakeGenerator
|
'-G', $CmakeGenerator
|
||||||
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
||||||
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
||||||
"-DCMAKE_BUILD_TYPE=Release"
|
"-DCMAKE_BUILD_TYPE=Release"
|
||||||
"-DCMAKE_PREFIX_PATH:PATH=$(Resolve-Path -Path ${ProjectRoot}/../obs-build-dependencies/${DepsPath})"
|
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
|
||||||
"-DBUILD_LIST=core,imgproc,objdetect"
|
"-DBUILD_LIST=core,imgproc,objdetect"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -80,18 +84,92 @@ function Build {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if ( $VerbosePreference -eq 'Continue' ) {
|
if ( $VerbosePreference -eq 'Continue' ) {
|
||||||
$OpenCVCmakeArgs+=('--verbose')
|
$OpenCVCmakeArgs += ('--verbose')
|
||||||
}
|
}
|
||||||
|
|
||||||
Log-Information "Building OpenCV..."
|
Log-Information "Building OpenCV..."
|
||||||
Invoke-External cmake --build "${OpenCVBuildPath}" @OpenCVCmakeArgs
|
Invoke-External cmake --build "${OpenCVBuildPath}" @OpenCVCmakeArgs
|
||||||
}
|
}
|
||||||
Log-Information "Install OpenCV}..."
|
Log-Information "Install OpenCV}..."
|
||||||
Invoke-External cmake --install "${OpenCVBuildPath}" --prefix "${OpenCVBuildPath}" @OpenCVCmakeArgs
|
Invoke-External cmake --install "${OpenCVBuildPath}" --prefix "${DepInstallPath}" @OpenCVCmakeArgs
|
||||||
|
|
||||||
|
$LeptonicaPath = "${ProjectRoot}/deps/leptonica"
|
||||||
|
$LeptonicaBuildPath = "${LeptonicaPath}/build"
|
||||||
|
|
||||||
|
Push-Location -Stack BuildLeptonicaTemp
|
||||||
|
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
|
||||||
|
Ensure-Location $ProjectRoot
|
||||||
|
|
||||||
|
$LeptonicaCmakeArgs = @(
|
||||||
|
'-G', $CmakeGenerator
|
||||||
|
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
||||||
|
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
||||||
|
"-DCMAKE_BUILD_TYPE=Release"
|
||||||
|
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
|
||||||
|
"-DCMAKE_INSTALL_PREFIX:PATH=${DepInstallPath}"
|
||||||
|
"-DSW_BUILD=OFF"
|
||||||
|
"-DLIBWEBP_SUPPORT=OFF"
|
||||||
|
)
|
||||||
|
|
||||||
|
Log-Information "Configuring leptonica..."
|
||||||
|
Invoke-External cmake -S ${LeptonicaPath} -B ${LeptonicaBuildPath} @LeptonicaCmakeArgs
|
||||||
|
|
||||||
|
$LeptonicaCmakeArgs = @(
|
||||||
|
'--config', "Release"
|
||||||
|
)
|
||||||
|
|
||||||
|
if ( $VerbosePreference -eq 'Continue' ) {
|
||||||
|
$LeptonicaCmakeArgs += ('--verbose')
|
||||||
|
}
|
||||||
|
|
||||||
|
Log-Information "Building leptonica..."
|
||||||
|
Invoke-External cmake --build "${LeptonicaBuildPath}" @LeptonicaCmakeArgs
|
||||||
|
}
|
||||||
|
Log-Information "Install leptonica..."
|
||||||
|
Invoke-External cmake --install "${LeptonicaBuildPath}" --prefix "${DepInstallPath}" @LeptonicaCmakeArgs
|
||||||
|
|
||||||
|
Push-Location -Stack BuildTesseractTemp
|
||||||
|
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
|
||||||
|
Ensure-Location $ProjectRoot
|
||||||
|
|
||||||
|
$TesseractPath = "${ProjectRoot}/deps/tesseract"
|
||||||
|
$TesseractBuildPath = "${TesseractPath}/build"
|
||||||
|
|
||||||
|
# Explicitly disable PkgConfig and tiff as it will lead build errors
|
||||||
|
$TesseractCmakeArgs = @(
|
||||||
|
'-G', $CmakeGenerator
|
||||||
|
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
||||||
|
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
||||||
|
"-DCMAKE_BUILD_TYPE=Release"
|
||||||
|
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
|
||||||
|
"-DCMAKE_INSTALL_PREFIX:PATH=${DepInstallPath}"
|
||||||
|
"-DSW_BUILD=OFF"
|
||||||
|
"-DDISABLE_CURL=ON"
|
||||||
|
"-DBUILD_TRAINING_TOOLS=OFF"
|
||||||
|
"-DCMAKE_DISABLE_FIND_PACKAGE_TIFF=TRUE"
|
||||||
|
"-DCMAKE_DISABLE_FIND_PACKAGE_PkgConfig=TRUE"
|
||||||
|
)
|
||||||
|
|
||||||
|
Log-Information "Configuring tesseract..."
|
||||||
|
Invoke-External cmake -S ${TesseractPath} -B ${TesseractBuildPath} @TesseractCmakeArgs
|
||||||
|
|
||||||
|
$TesseractCmakeArgs = @(
|
||||||
|
'--config', "Release"
|
||||||
|
)
|
||||||
|
|
||||||
|
if ( $VerbosePreference -eq 'Continue' ) {
|
||||||
|
$TesseractCmakeArgs += ('--verbose')
|
||||||
|
}
|
||||||
|
|
||||||
|
Log-Information "Building tesseract..."
|
||||||
|
Invoke-External cmake --build "${TesseractBuildPath}" @TesseractCmakeArgs
|
||||||
|
}
|
||||||
|
Log-Information "Install tesseract..."
|
||||||
|
Invoke-External cmake --install "${TesseractBuildPath}" --prefix "${DepInstallPath}" @TesseractCmakeArgs
|
||||||
|
|
||||||
(Get-Content -Path ${ProjectRoot}/CMakeLists.txt -Raw) `
|
(Get-Content -Path ${ProjectRoot}/CMakeLists.txt -Raw) `
|
||||||
-replace "project\((.*) VERSION (.*)\)", "project(${ProductName} VERSION ${ProductVersion})" `
|
-replace "project\((.*) VERSION (.*)\)", "project(${ProductName} VERSION ${ProductVersion})" `
|
||||||
| Out-File -Path ${ProjectRoot}/CMakeLists.txt
|
| Out-File -Path ${ProjectRoot}/CMakeLists.txt
|
||||||
|
|
||||||
Setup-Obs
|
Setup-Obs
|
||||||
|
|
||||||
@@ -99,18 +177,13 @@ function Build {
|
|||||||
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
|
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
|
||||||
Ensure-Location $ProjectRoot
|
Ensure-Location $ProjectRoot
|
||||||
|
|
||||||
$OpenCVPath = "${ProjectRoot}/deps/opencv"
|
|
||||||
$OpenCVBuildPath = "${OpenCVPath}/build"
|
|
||||||
|
|
||||||
$DepsPath = "plugin-deps-${script:DepsVersion}-qt${script:QtVersion}-${script:Target}"
|
|
||||||
$CmakeArgs = @(
|
$CmakeArgs = @(
|
||||||
'-G', $CmakeGenerator
|
'-G', $CmakeGenerator
|
||||||
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
||||||
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
||||||
"-DCMAKE_BUILD_TYPE=${Configuration}"
|
"-DCMAKE_BUILD_TYPE=${Configuration}"
|
||||||
"-DCMAKE_PREFIX_PATH:PATH=$(Resolve-Path -Path "${ProjectRoot}/../obs-build-dependencies/${DepsPath}")"
|
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
|
||||||
"-DQT_VERSION=${script:QtVersion}"
|
"-DQT_VERSION=${script:QtVersion}"
|
||||||
"-DOpenCV_DIR=${OpenCVBuildPath}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Log-Debug "Attempting to configure OBS with CMake arguments: $($CmakeArgs | Out-String)"
|
Log-Debug "Attempting to configure OBS with CMake arguments: $($CmakeArgs | Out-String)"
|
||||||
@@ -122,7 +195,7 @@ function Build {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if ( $VerbosePreference -eq 'Continue' ) {
|
if ( $VerbosePreference -eq 'Continue' ) {
|
||||||
$CmakeArgs+=('--verbose')
|
$CmakeArgs += ('--verbose')
|
||||||
}
|
}
|
||||||
|
|
||||||
Log-Information "Building ${ProductName}..."
|
Log-Information "Building ${ProductName}..."
|
||||||
|
|||||||
1
.github/scripts/utils.zsh/setup_linux
vendored
@@ -38,6 +38,7 @@ if (( ! (${skips[(Ie)all]} + ${skips[(Ie)deps]}) )) {
|
|||||||
libxtst-dev \
|
libxtst-dev \
|
||||||
libxss-dev \
|
libxss-dev \
|
||||||
libopencv-dev \
|
libopencv-dev \
|
||||||
|
libtesseract-dev \
|
||||||
libprocps-dev
|
libprocps-dev
|
||||||
|
|
||||||
local -a _qt_packages=()
|
local -a _qt_packages=()
|
||||||
|
|||||||
45
.github/workflows/main.yml
vendored
@@ -113,7 +113,11 @@ jobs:
|
|||||||
id: ccache-cache
|
id: ccache-cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ${{ github.workspace }}/.ccache
|
path: |
|
||||||
|
${{ github.workspace }}/.ccache
|
||||||
|
${{ github.workspace }}/plugin/deps/opencv/build_*
|
||||||
|
${{ github.workspace }}/plugin/deps/leptonica/build_*
|
||||||
|
${{ github.workspace }}/plugin/deps/tesseract/build*
|
||||||
key: macos-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
|
key: macos-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
macos-${{ matrix.arch }}-ccache-plugin-
|
macos-${{ matrix.arch }}-ccache-plugin-
|
||||||
@@ -151,6 +155,12 @@ jobs:
|
|||||||
codesign: 'true'
|
codesign: 'true'
|
||||||
codesignIdent: ${{ env.CODESIGN_IDENT }}
|
codesignIdent: ${{ env.CODESIGN_IDENT }}
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
uses: ./plugin/.github/actions/run-tests
|
||||||
|
with:
|
||||||
|
workingDirectory: ${{ github.workspace }}/plugin
|
||||||
|
target: ${{ matrix.arch }}
|
||||||
|
|
||||||
- name: Package Plugin
|
- name: Package Plugin
|
||||||
uses: ./plugin/.github/actions/package-plugin
|
uses: ./plugin/.github/actions/package-plugin
|
||||||
with:
|
with:
|
||||||
@@ -221,7 +231,8 @@ jobs:
|
|||||||
id: ccache-cache
|
id: ccache-cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ${{ github.workspace }}/.ccache
|
path: |
|
||||||
|
${{ github.workspace }}/.ccache
|
||||||
key: linux-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
|
key: linux-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
linux-${{ matrix.arch }}-ccache-plugin-
|
linux-${{ matrix.arch }}-ccache-plugin-
|
||||||
@@ -245,6 +256,12 @@ jobs:
|
|||||||
config: RelWithDebInfo
|
config: RelWithDebInfo
|
||||||
portable: ${{ matrix.portable }}
|
portable: ${{ matrix.portable }}
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
uses: ./plugin/.github/actions/run-tests
|
||||||
|
with:
|
||||||
|
workingDirectory: ${{ github.workspace }}/plugin
|
||||||
|
target: ${{ matrix.arch }}
|
||||||
|
|
||||||
- name: Package Plugin
|
- name: Package Plugin
|
||||||
uses: ./plugin/.github/actions/package-plugin
|
uses: ./plugin/.github/actions/package-plugin
|
||||||
with:
|
with:
|
||||||
@@ -301,9 +318,24 @@ jobs:
|
|||||||
id: setup
|
id: setup
|
||||||
run: |
|
run: |
|
||||||
## SETUP ENVIRONMENT SCRIPT
|
## SETUP ENVIRONMENT SCRIPT
|
||||||
|
$CcacheDate = (Get-Date -Format "yyyy-M-d")
|
||||||
|
"ccacheDate=${CcacheDate}" >> $env:GITHUB_OUTPUT
|
||||||
$CommitHash = (git rev-parse HEAD)[0..8] -join ''
|
$CommitHash = (git rev-parse HEAD)[0..8] -join ''
|
||||||
"commitHash=${CommitHash}" >> $env:GITHUB_OUTPUT
|
"commitHash=${CommitHash}" >> $env:GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Restore Compilation Cache
|
||||||
|
id: ccache-cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}/.ccache
|
||||||
|
${{ github.workspace }}/plugin/deps/opencv/build_*
|
||||||
|
${{ github.workspace }}/plugin/deps/leptonica/build_*
|
||||||
|
${{ github.workspace }}/plugin/deps/tesseract/build*
|
||||||
|
key: windows-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
|
||||||
|
restore-keys: |
|
||||||
|
windows-${{ matrix.arch }}-ccache-plugin-
|
||||||
|
|
||||||
- name: Check for GitHub Labels
|
- name: Check for GitHub Labels
|
||||||
id: seekingTesters
|
id: seekingTesters
|
||||||
working-directory: ${{ github.workspace }}/plugin
|
working-directory: ${{ github.workspace }}/plugin
|
||||||
@@ -333,6 +365,12 @@ jobs:
|
|||||||
config: RelWithDebInfo
|
config: RelWithDebInfo
|
||||||
visualStudio: 'Visual Studio 17 2022'
|
visualStudio: 'Visual Studio 17 2022'
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
uses: ./plugin/.github/actions/run-tests
|
||||||
|
with:
|
||||||
|
workingDirectory: ${{ github.workspace }}/plugin
|
||||||
|
target: ${{ matrix.arch }}
|
||||||
|
|
||||||
- name: Package Plugin
|
- name: Package Plugin
|
||||||
uses: ./plugin/.github/actions/package-plugin
|
uses: ./plugin/.github/actions/package-plugin
|
||||||
with:
|
with:
|
||||||
@@ -387,10 +425,11 @@ jobs:
|
|||||||
for file in ${{ github.workspace }}/**/@(*.pkg|*.exe|*.deb|*.zip); do
|
for file in ${{ github.workspace }}/**/@(*.pkg|*.exe|*.deb|*.zip); do
|
||||||
echo " ${file##*/}: $(sha256sum "${file}" | cut -d " " -f 1)" >> ${{ github.workspace }}/CHECKSUMS.txt
|
echo " ${file##*/}: $(sha256sum "${file}" | cut -d " " -f 1)" >> ${{ github.workspace }}/CHECKSUMS.txt
|
||||||
done
|
done
|
||||||
|
cat ${{ github.workspace }}/CHECKSUMS.txt
|
||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
id: create_release
|
id: create_release
|
||||||
uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
|
|||||||
9
.gitmodules
vendored
@@ -10,3 +10,12 @@
|
|||||||
[submodule "deps/openvr"]
|
[submodule "deps/openvr"]
|
||||||
path = deps/openvr
|
path = deps/openvr
|
||||||
url = https://github.com/ValveSoftware/openvr.git
|
url = https://github.com/ValveSoftware/openvr.git
|
||||||
|
[submodule "deps/leptonica"]
|
||||||
|
path = deps/leptonica
|
||||||
|
url = https://github.com/DanBloomberg/leptonica.git
|
||||||
|
[submodule "deps/tesseract"]
|
||||||
|
path = deps/tesseract
|
||||||
|
url = https://github.com/tesseract-ocr/tesseract.git
|
||||||
|
[submodule "deps/libremidi"]
|
||||||
|
path = deps/libremidi
|
||||||
|
url = https://github.com/jcelerier/libremidi.git
|
||||||
|
|||||||
@@ -42,21 +42,20 @@ target_sources(
|
|||||||
src/general.cpp
|
src/general.cpp
|
||||||
src/hotkey.cpp
|
src/hotkey.cpp
|
||||||
src/hotkey.hpp
|
src/hotkey.hpp
|
||||||
src/hotkey.hpp
|
|
||||||
src/platform-funcs.hpp
|
src/platform-funcs.hpp
|
||||||
src/scene-group.cpp
|
|
||||||
src/scene-group.hpp
|
|
||||||
src/status-control.cpp
|
src/status-control.cpp
|
||||||
src/status-control.hpp
|
src/status-control.hpp
|
||||||
src/switcher-data-structs.cpp
|
src/switcher-data.cpp
|
||||||
src/switcher-data-structs.hpp
|
src/switcher-data.hpp
|
||||||
src/version.cpp
|
src/version.cpp
|
||||||
src/version.h)
|
src/version.h)
|
||||||
|
|
||||||
# Legacy function sources
|
# Legacy function sources
|
||||||
target_sources(
|
target_sources(
|
||||||
${LIB_NAME}
|
${LIB_NAME}
|
||||||
PRIVATE src/legacy/scene-trigger.cpp
|
PRIVATE src/legacy/scene-group.cpp
|
||||||
|
src/legacy/scene-group.hpp
|
||||||
|
src/legacy/scene-trigger.cpp
|
||||||
src/legacy/scene-trigger.hpp
|
src/legacy/scene-trigger.hpp
|
||||||
src/legacy/switch-audio.cpp
|
src/legacy/switch-audio.cpp
|
||||||
src/legacy/switch-audio.hpp
|
src/legacy/switch-audio.hpp
|
||||||
@@ -74,7 +73,6 @@ target_sources(
|
|||||||
src/legacy/switch-network.hpp
|
src/legacy/switch-network.hpp
|
||||||
src/legacy/switch-pause.cpp
|
src/legacy/switch-pause.cpp
|
||||||
src/legacy/switch-pause.hpp
|
src/legacy/switch-pause.hpp
|
||||||
src/legacy/switch-priority.cpp
|
|
||||||
src/legacy/switch-random.cpp
|
src/legacy/switch-random.cpp
|
||||||
src/legacy/switch-random.hpp
|
src/legacy/switch-random.hpp
|
||||||
src/legacy/switch-screen-region.cpp
|
src/legacy/switch-screen-region.cpp
|
||||||
@@ -109,10 +107,14 @@ target_sources(
|
|||||||
src/macro-core/macro-action-macro.hpp
|
src/macro-core/macro-action-macro.hpp
|
||||||
src/macro-core/macro-action-media.cpp
|
src/macro-core/macro-action-media.cpp
|
||||||
src/macro-core/macro-action-media.hpp
|
src/macro-core/macro-action-media.hpp
|
||||||
|
src/macro-core/macro-action-osc.cpp
|
||||||
|
src/macro-core/macro-action-osc.hpp
|
||||||
src/macro-core/macro-action-plugin-state.cpp
|
src/macro-core/macro-action-plugin-state.cpp
|
||||||
src/macro-core/macro-action-plugin-state.hpp
|
src/macro-core/macro-action-plugin-state.hpp
|
||||||
src/macro-core/macro-action-profile.cpp
|
src/macro-core/macro-action-profile.cpp
|
||||||
src/macro-core/macro-action-profile.hpp
|
src/macro-core/macro-action-profile.hpp
|
||||||
|
src/macro-core/macro-action-projector.cpp
|
||||||
|
src/macro-core/macro-action-projector.hpp
|
||||||
src/macro-core/macro-action-random.cpp
|
src/macro-core/macro-action-random.cpp
|
||||||
src/macro-core/macro-action-random.hpp
|
src/macro-core/macro-action-random.hpp
|
||||||
src/macro-core/macro-action-recording.cpp
|
src/macro-core/macro-action-recording.cpp
|
||||||
@@ -163,6 +165,8 @@ target_sources(
|
|||||||
src/macro-core/macro-condition-cursor.hpp
|
src/macro-core/macro-condition-cursor.hpp
|
||||||
src/macro-core/macro-condition-date.cpp
|
src/macro-core/macro-condition-date.cpp
|
||||||
src/macro-core/macro-condition-date.hpp
|
src/macro-core/macro-condition-date.hpp
|
||||||
|
src/macro-core/macro-condition-display.cpp
|
||||||
|
src/macro-core/macro-condition-display.hpp
|
||||||
src/macro-core/macro-condition-edit.cpp
|
src/macro-core/macro-condition-edit.cpp
|
||||||
src/macro-core/macro-condition-edit.hpp
|
src/macro-core/macro-condition-edit.hpp
|
||||||
src/macro-core/macro-condition-file.cpp
|
src/macro-core/macro-condition-file.cpp
|
||||||
@@ -189,6 +193,8 @@ target_sources(
|
|||||||
src/macro-core/macro-condition-recording.hpp
|
src/macro-core/macro-condition-recording.hpp
|
||||||
src/macro-core/macro-condition-replay-buffer.cpp
|
src/macro-core/macro-condition-replay-buffer.cpp
|
||||||
src/macro-core/macro-condition-replay-buffer.hpp
|
src/macro-core/macro-condition-replay-buffer.hpp
|
||||||
|
src/macro-core/macro-condition-run.cpp
|
||||||
|
src/macro-core/macro-condition-run.hpp
|
||||||
src/macro-core/macro-condition-scene-order.cpp
|
src/macro-core/macro-condition-scene-order.cpp
|
||||||
src/macro-core/macro-condition-scene-order.hpp
|
src/macro-core/macro-condition-scene-order.hpp
|
||||||
src/macro-core/macro-condition-scene-transform.cpp
|
src/macro-core/macro-condition-scene-transform.cpp
|
||||||
@@ -217,6 +223,8 @@ target_sources(
|
|||||||
src/macro-core/macro-condition-window.hpp
|
src/macro-core/macro-condition-window.hpp
|
||||||
src/macro-core/macro-condition.cpp
|
src/macro-core/macro-condition.cpp
|
||||||
src/macro-core/macro-condition.hpp
|
src/macro-core/macro-condition.hpp
|
||||||
|
src/macro-core/macro-dock.cpp
|
||||||
|
src/macro-core/macro-dock.hpp
|
||||||
src/macro-core/macro-properties.cpp
|
src/macro-core/macro-properties.cpp
|
||||||
src/macro-core/macro-properties.hpp
|
src/macro-core/macro-properties.hpp
|
||||||
src/macro-core/macro-ref.cpp
|
src/macro-core/macro-ref.cpp
|
||||||
@@ -244,12 +252,28 @@ target_sources(
|
|||||||
src/utils/duration-control.hpp
|
src/utils/duration-control.hpp
|
||||||
src/utils/item-selection-helpers.cpp
|
src/utils/item-selection-helpers.cpp
|
||||||
src/utils/item-selection-helpers.hpp
|
src/utils/item-selection-helpers.hpp
|
||||||
|
src/utils/log-helper.hpp
|
||||||
src/utils/file-selection.cpp
|
src/utils/file-selection.cpp
|
||||||
src/utils/file-selection.hpp
|
src/utils/file-selection.hpp
|
||||||
|
src/utils/filter-selection.cpp
|
||||||
|
src/utils/filter-selection.hpp
|
||||||
src/utils/macro-list.cpp
|
src/utils/macro-list.cpp
|
||||||
src/utils/macro-list.hpp
|
src/utils/macro-list.hpp
|
||||||
|
src/utils/math-helpers.cpp
|
||||||
|
src/utils/math-helpers.hpp
|
||||||
|
src/utils/mouse-wheel-guard.cpp
|
||||||
|
src/utils/mouse-wheel-guard.hpp
|
||||||
src/utils/name-dialog.cpp
|
src/utils/name-dialog.cpp
|
||||||
src/utils/name-dialog.hpp
|
src/utils/name-dialog.hpp
|
||||||
|
src/utils/obs-dock.hpp
|
||||||
|
src/utils/obs-module-helper.cpp
|
||||||
|
src/utils/obs-module-helper.hpp
|
||||||
|
src/utils/osc-helpers.cpp
|
||||||
|
src/utils/osc-helpers.hpp
|
||||||
|
src/utils/priority-helper.cpp
|
||||||
|
src/utils/priority-helper.hpp
|
||||||
|
src/utils/process-config.cpp
|
||||||
|
src/utils/process-config.hpp
|
||||||
src/utils/regex-config.cpp
|
src/utils/regex-config.cpp
|
||||||
src/utils/regex-config.hpp
|
src/utils/regex-config.hpp
|
||||||
src/utils/resizing-text-edit.cpp
|
src/utils/resizing-text-edit.cpp
|
||||||
@@ -258,6 +282,8 @@ target_sources(
|
|||||||
src/utils/scene-item-selection.hpp
|
src/utils/scene-item-selection.hpp
|
||||||
src/utils/scene-selection.cpp
|
src/utils/scene-selection.cpp
|
||||||
src/utils/scene-selection.hpp
|
src/utils/scene-selection.hpp
|
||||||
|
src/utils/scene-switch-helpers.cpp
|
||||||
|
src/utils/scene-switch-helpers.hpp
|
||||||
src/utils/screenshot-helper.cpp
|
src/utils/screenshot-helper.cpp
|
||||||
src/utils/screenshot-helper.hpp
|
src/utils/screenshot-helper.hpp
|
||||||
src/utils/section.cpp
|
src/utils/section.cpp
|
||||||
@@ -266,12 +292,26 @@ target_sources(
|
|||||||
src/utils/slider-spinbox.hpp
|
src/utils/slider-spinbox.hpp
|
||||||
src/utils/source-selection.cpp
|
src/utils/source-selection.cpp
|
||||||
src/utils/source-selection.hpp
|
src/utils/source-selection.hpp
|
||||||
|
src/utils/string-list.cpp
|
||||||
|
src/utils/string-list.hpp
|
||||||
|
src/utils/striped-frame.cpp
|
||||||
|
src/utils/striped-frame.hpp
|
||||||
|
src/utils/sync-helper.cpp
|
||||||
|
src/utils/sync-helper.hpp
|
||||||
src/utils/transition-selection.cpp
|
src/utils/transition-selection.cpp
|
||||||
src/utils/transition-selection.hpp
|
src/utils/transition-selection.hpp
|
||||||
src/utils/utility.cpp
|
src/utils/utility.cpp
|
||||||
src/utils/utility.hpp
|
src/utils/utility.hpp
|
||||||
src/utils/variable.cpp
|
src/utils/variable.cpp
|
||||||
src/utils/variable.hpp
|
src/utils/variable.hpp
|
||||||
|
src/utils/variable-line-edit.cpp
|
||||||
|
src/utils/variable-line-edit.hpp
|
||||||
|
src/utils/variable-number.tpp
|
||||||
|
src/utils/variable-number.hpp
|
||||||
|
src/utils/variable-spinbox.cpp
|
||||||
|
src/utils/variable-spinbox.hpp
|
||||||
|
src/utils/variable-string.cpp
|
||||||
|
src/utils/variable-string.hpp
|
||||||
src/utils/variable-text-edit.cpp
|
src/utils/variable-text-edit.cpp
|
||||||
src/utils/variable-text-edit.hpp
|
src/utils/variable-text-edit.hpp
|
||||||
src/utils/volume-control.cpp
|
src/utils/volume-control.cpp
|
||||||
@@ -318,7 +358,8 @@ target_include_directories(
|
|||||||
${LIB_NAME}
|
${LIB_NAME}
|
||||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
|
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/websocketpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/deps/websocketpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/obs-websocket/lib")
|
"${CMAKE_CURRENT_SOURCE_DIR}/deps/obs-websocket/lib"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/deps/exprtk")
|
||||||
|
|
||||||
# --- End of section ---
|
# --- End of section ---
|
||||||
|
|
||||||
@@ -329,7 +370,8 @@ if(OS_WINDOWS)
|
|||||||
|
|
||||||
target_compile_definitions(${LIB_NAME} PRIVATE UNICODE _UNICODE)
|
target_compile_definitions(${LIB_NAME} PRIVATE UNICODE _UNICODE)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
target_compile_options(${LIB_NAME} PUBLIC /MP /d2FH4- /wd4267 /wd4267)
|
target_compile_options(${LIB_NAME} PUBLIC /MP /d2FH4- /wd4267 /wd4267
|
||||||
|
/bigobj)
|
||||||
endif()
|
endif()
|
||||||
target_sources(${LIB_NAME} PRIVATE src/win/advanced-scene-switcher-win.cpp)
|
target_sources(${LIB_NAME} PRIVATE src/win/advanced-scene-switcher-win.cpp)
|
||||||
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
||||||
@@ -446,3 +488,4 @@ endif()
|
|||||||
# --- End of section ---
|
# --- End of section ---
|
||||||
|
|
||||||
add_subdirectory(src/macro-external)
|
add_subdirectory(src/macro-external)
|
||||||
|
add_subdirectory(tests)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ DirExistsWarning=no
|
|||||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
Source: "..\release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
Source: "..\release\*"; Excludes: "*.zip"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
Source: "..\LICENSE"; Flags: dontcopy
|
Source: "..\LICENSE"; Flags: dontcopy
|
||||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Nach Ausführen von Aktion
|
|||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="In diesem Zeitraum werden potentielle erfüllte Bedingungen ignoriert!"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="In diesem Zeitraum werden potentielle erfüllte Bedingungen ignoriert!"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Ausführliches Logging"
|
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Ausführliches Logging"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Fensterposition und -größe speichern"
|
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Fensterposition und -größe speichern"
|
||||||
|
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Benachrichtigungen im System-Tray anzeigen"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Deaktiviere UI Tipps"
|
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Deaktiviere UI Tipps"
|
||||||
|
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="Tabs verstecken, die in Makros repräsentiert sind"
|
||||||
|
AdvSceneSwitcher.generalTab.matchBehavior="Verhalten anpassen"
|
||||||
AdvSceneSwitcher.generalTab.priority="Priorität"
|
AdvSceneSwitcher.generalTab.priority="Priorität"
|
||||||
AdvSceneSwitcher.generalTab.priority.description="Szenenwechselmethoden sortiert nach Priorität"
|
AdvSceneSwitcher.generalTab.priority.description="Szenenwechselmethoden sortiert nach Priorität"
|
||||||
AdvSceneSwitcher.generalTab.priority.threadPriority="Benutze Thread Priorität"
|
AdvSceneSwitcher.generalTab.priority.threadPriority="Benutze Thread Priorität"
|
||||||
@@ -51,11 +54,541 @@ AdvSceneSwitcher.generalTab.priority.media="Medien"
|
|||||||
AdvSceneSwitcher.generalTab.priority.time="Zeit"
|
AdvSceneSwitcher.generalTab.priority.time="Zeit"
|
||||||
AdvSceneSwitcher.generalTab.priority.audio="Audio"
|
AdvSceneSwitcher.generalTab.priority.audio="Audio"
|
||||||
AdvSceneSwitcher.generalTab.priority.video="Video"
|
AdvSceneSwitcher.generalTab.priority.video="Video"
|
||||||
|
AdvSceneSwitcher.generalTab.priority.macro="Makro"
|
||||||
|
AdvSceneSwitcher.generalTab.transition="Übergänge"
|
||||||
AdvSceneSwitcher.generalTab.setTransitionBy="Beim Ändern des Szenenübergangs:"
|
AdvSceneSwitcher.generalTab.setTransitionBy="Beim Ändern des Szenenübergangs:"
|
||||||
AdvSceneSwitcher.generalTab.transitionOverride="Verwende Übergangsüberschreibungen"
|
AdvSceneSwitcher.generalTab.transitionOverride="Verwende Übergangsüberschreibungen"
|
||||||
AdvSceneSwitcher.generalTab.adjustActiveTransitionType="Wechsle den aktiven Szenenübergangtyp"
|
AdvSceneSwitcher.generalTab.adjustActiveTransitionType="Wechsle den aktiven Szenenübergangtyp"
|
||||||
AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="Mindestens eine Option muss aktiv sein:\n\n - Verwende Übergangsüberschreibungen\n\n - Wechsle den aktiven Szenenübergangtyp"
|
AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="Mindestens eine Option muss aktiv sein:\n\n - Verwende Übergangsüberschreibungen\n\n - Wechsle den aktiven Szenenübergangtyp"
|
||||||
|
|
||||||
|
; Macro Tab
|
||||||
|
AdvSceneSwitcher.macroTab.title="Makro"
|
||||||
|
AdvSceneSwitcher.macroTab.macros="Makros"
|
||||||
|
AdvSceneSwitcher.macroTab.priorityWarning="Hinweis: Es wird empfohlen, Makros als Funktion mit höchster Priorität zu konfigurieren.\nDiese Einstellung kann im Allgemein-Tab geändert werden."
|
||||||
|
AdvSceneSwitcher.macroTab.help="Mit Makros können eine Reihe von Aktionen in Abhängigkeit von mehreren Bedingungen ausgeführt werden.\n\nKlicke auf das hervorgehobene Plus-Symbol, um ein neues Makro hinzuzufügen."
|
||||||
|
AdvSceneSwitcher.macroTab.editConditionHelp="In diesem Abschnitt können Bedingungen für die Makros definiert werden.\n\nWähle auf der linken Seite ein vorhandenes Makro aus oder füge ein neues hinzu.\nKlicke dann auf die Plus-Schaltfläche unten, um eine neue Bedingung hinzuzufügen."
|
||||||
|
AdvSceneSwitcher.macroTab.editActionHelp="In diesem Abschnitt können Aktionen für die Makros definiert werden.\n\nWähle auf der linken Seite ein vorhandenes Makro aus oder füge ein neues hinzu.\nKlicke dann auf die Plus-Schaltfläche unten, um eine neue Aktion hinzuzufügen."
|
||||||
|
AdvSceneSwitcher.macroTab.edit="Makro bearbeiten"
|
||||||
|
AdvSceneSwitcher.macroTab.edit.logic="Logik-Typ:"
|
||||||
|
AdvSceneSwitcher.macroTab.edit.condition="Bedingungs-Typ:"
|
||||||
|
AdvSceneSwitcher.macroTab.edit.action="Aktions-Typ:"
|
||||||
|
AdvSceneSwitcher.macroTab.add="Neues Makro hinzufügen"
|
||||||
|
AdvSceneSwitcher.macroTab.name="Name:"
|
||||||
|
AdvSceneSwitcher.macroTab.run="Makro ausführen"
|
||||||
|
AdvSceneSwitcher.macroTab.runFail="Ausführen von \"%1\" fehlgeschlagen!\nEntweder ist eine der Aktionen fehlgeschlagen oder das Makro wird bereits ausgeführt."
|
||||||
|
AdvSceneSwitcher.macroTab.runInParallel="Parallel zu anderen Makros ausführen"
|
||||||
|
AdvSceneSwitcher.macroTab.onChange="Nur bei Änderung ausführen"
|
||||||
|
AdvSceneSwitcher.macroTab.defaultname="Makro %1"
|
||||||
|
AdvSceneSwitcher.macroTab.defaultGroupName="Gruppe %1"
|
||||||
|
AdvSceneSwitcher.macroTab.exists="Makro-Name existiert bereits"
|
||||||
|
AdvSceneSwitcher.macroTab.groupDeleteConfirm="Sicher, dass \"%1\" und alle zugehörigen Elemente gelöscht werden?"
|
||||||
|
AdvSceneSwitcher.macroTab.copy="Kopie des aktuellen Makros erstellen"
|
||||||
|
AdvSceneSwitcher.macroTab.group="Ausgewählte Elemente gruppieren"
|
||||||
|
AdvSceneSwitcher.macroTab.ungroup="Gruppierung ausgewählter Gruppen aufheben"
|
||||||
|
AdvSceneSwitcher.macroTab.expandAll="Alle erweitern"
|
||||||
|
AdvSceneSwitcher.macroTab.collapseAll="Alle einklappen"
|
||||||
|
AdvSceneSwitcher.macroTab.maximize="Maximieren"
|
||||||
|
AdvSceneSwitcher.macroTab.minimize="Minimieren"
|
||||||
|
AdvSceneSwitcher.macroTab.highlightSettings="Visuelle Einstellungen"
|
||||||
|
AdvSceneSwitcher.macroTab.hotkeySettings="Hotkey-Einstellungen"
|
||||||
|
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Kürzlich ausgeführte Makros hervorheben"
|
||||||
|
AdvSceneSwitcher.macroTab.highlightTrueConditions="Bedingungen des aktuell ausgewählten Makros hervorheben, die kürzlich als wahr bewertet wurden"
|
||||||
|
AdvSceneSwitcher.macroTab.highlightPerformedActions="Zuletzt ausgeführte Aktionen des aktuell ausgewählten Makros hervorheben"
|
||||||
|
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Hotkeys zur Steuerung des Pausen-Status neuer Makros registrieren"
|
||||||
|
AdvSceneSwitcher.macroTab.currentDisableHotkeys="Hotkeys zur Steuerung des Pausen-Status ausgewählter Makros registrieren"
|
||||||
|
|
||||||
|
; Macro List
|
||||||
|
AdvSceneSwitcher.macroList.deleted="gelöscht"
|
||||||
|
AdvSceneSwitcher.macroList.duplicate="\"%1\" ist bereits ausgewählt!"
|
||||||
|
|
||||||
|
; Macro Logic
|
||||||
|
AdvSceneSwitcher.logic.none="Eintrag ignorieren"
|
||||||
|
AdvSceneSwitcher.logic.and="Und"
|
||||||
|
AdvSceneSwitcher.logic.or="Oder"
|
||||||
|
AdvSceneSwitcher.logic.andNot="Und nicht"
|
||||||
|
AdvSceneSwitcher.logic.orNot="Oder nicht"
|
||||||
|
AdvSceneSwitcher.logic.rootNone="Wenn"
|
||||||
|
AdvSceneSwitcher.logic.not="Wenn nicht"
|
||||||
|
|
||||||
|
; Macro Conditions
|
||||||
|
AdvSceneSwitcher.condition.audio="Audio"
|
||||||
|
AdvSceneSwitcher.condition.audio.state.below="unter"
|
||||||
|
AdvSceneSwitcher.condition.audio.state.exact="genau"
|
||||||
|
AdvSceneSwitcher.condition.audio.state.above="über"
|
||||||
|
AdvSceneSwitcher.condition.audio.state.mute="stummgeschaltet"
|
||||||
|
AdvSceneSwitcher.condition.audio.state.unmute="nicht stummgeschaltet"
|
||||||
|
AdvSceneSwitcher.condition.audio.type.output="Ausgabe-Lautstärke"
|
||||||
|
AdvSceneSwitcher.condition.audio.type.volume="Konfigurierter Lautstärkepegel"
|
||||||
|
AdvSceneSwitcher.condition.audio.type.syncOffset="Sync-Offset"
|
||||||
|
AdvSceneSwitcher.condition.audio.type.monitor="Audio-Monitoring"
|
||||||
|
AdvSceneSwitcher.condition.audio.type.balance="Audio-Balance"
|
||||||
|
AdvSceneSwitcher.condition.audio.entry="{{checkType}} von {{audioSources}} ist {{condition}}{{volume}}{{syncOffset}}{{monitorTypes}}"
|
||||||
|
AdvSceneSwitcher.condition.cursor="Cursor"
|
||||||
|
AdvSceneSwitcher.condition.cursor.type.region="ist in der Region"
|
||||||
|
AdvSceneSwitcher.condition.cursor.type.moving="bewegt sich"
|
||||||
|
AdvSceneSwitcher.condition.cursor.type.click="geklickt"
|
||||||
|
AdvSceneSwitcher.condition.cursor.button.left="Linke Maustaste"
|
||||||
|
AdvSceneSwitcher.condition.cursor.button.middle="Mittlere Maustaste"
|
||||||
|
AdvSceneSwitcher.condition.cursor.button.right="Rechte Maustaste"
|
||||||
|
AdvSceneSwitcher.condition.cursor.showFrame="Rahmen anzeigen"
|
||||||
|
AdvSceneSwitcher.condition.cursor.hideFrame="Rahmen ausblenden"
|
||||||
|
AdvSceneSwitcher.condition.cursor.entry.line1="Cursor {{conditions}}{{buttons}}{{minX}}{{minY}}{{maxX}}{{maxY}}{{toggleFrameButton}}"
|
||||||
|
AdvSceneSwitcher.condition.cursor.entry.line2="Cursor ist aktuell bei {{xPos}} x {{yPos}}"
|
||||||
|
AdvSceneSwitcher.condition.scene="Szene"
|
||||||
|
AdvSceneSwitcher.condition.scene.type.current="Aktuelle Szene ist"
|
||||||
|
AdvSceneSwitcher.condition.scene.type.previous="Vorherige Szene ist"
|
||||||
|
AdvSceneSwitcher.condition.scene.type.changed="Szene geändert"
|
||||||
|
AdvSceneSwitcher.condition.scene.type.notChanged="Szene hat sich nicht verändert"
|
||||||
|
AdvSceneSwitcher.condition.scene.type.currentPattern="Aktuelle Szene entspricht"
|
||||||
|
AdvSceneSwitcher.condition.scene.type.previousPattern="Vorherige Szene entspricht"
|
||||||
|
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Während des Übergangs die Ziel-Szene überprüfen"
|
||||||
|
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Während des Übergangs die Quell-Szene überprüfen"
|
||||||
|
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
||||||
|
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
||||||
|
AdvSceneSwitcher.condition.window="Fenster"
|
||||||
|
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} existiert und ..."
|
||||||
|
AdvSceneSwitcher.condition.window.entry.line2="... ist {{fullscreen}} Vollbild {{maximized}} Maximiert {{focused}} Fokusiert {{windowFocusChanged}} Vordergrundfenster geändert"
|
||||||
|
AdvSceneSwitcher.condition.window.entry.line3="Aktuelles Vordergrundfenster: {{focusWindow}}"
|
||||||
|
AdvSceneSwitcher.condition.file="Datei"
|
||||||
|
AdvSceneSwitcher.condition.file.type.match="entspricht"
|
||||||
|
AdvSceneSwitcher.condition.file.type.contentChange="Inhalt geändert"
|
||||||
|
AdvSceneSwitcher.condition.file.type.dateChange="Änderungsdatum geändert"
|
||||||
|
AdvSceneSwitcher.condition.file.remote="Entfernte Datei"
|
||||||
|
AdvSceneSwitcher.condition.file.local="Lokale Datei"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||||
|
AdvSceneSwitcher.condition.media="Medien"
|
||||||
|
AdvSceneSwitcher.condition.media.source="Quelle"
|
||||||
|
AdvSceneSwitcher.condition.media.anyOnScene="Beliebige Medienquelle in"
|
||||||
|
AdvSceneSwitcher.condition.media.allOnScene="Alle Medienquellen in"
|
||||||
|
AdvSceneSwitcher.condition.media.matchOnChange="Nur bei Änderung übereinstimmen (Hinweis: Diese Option wird in einer zukünftigen Version entfernt werden - bitte stattdessen Dauer-Modifikatoren verwenden)"
|
||||||
|
AdvSceneSwitcher.condition.media.inconsistencyInfo="Leider verhalten sich nicht alle Medien-Quell-Typen gleich (z.B. Medien-Quelle vs. VLC-Video-Quelle \"Gestoppt\"-Status).\nBitte experimentieren, was in eurem Setup funktioniert!"
|
||||||
|
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}Status ist{{states}}und{{timeRestrictions}}{{time}}"
|
||||||
|
AdvSceneSwitcher.condition.video="Video"
|
||||||
|
AdvSceneSwitcher.condition.video.condition.match="entspricht genau"
|
||||||
|
AdvSceneSwitcher.condition.video.condition.differ="stimmt nicht überein"
|
||||||
|
AdvSceneSwitcher.condition.video.condition.hasChanged="hat sich geändert"
|
||||||
|
AdvSceneSwitcher.condition.video.condition.hasNotChanged="hat sich nicht verändert"
|
||||||
|
AdvSceneSwitcher.condition.video.condition.noImage="hat keine Ausgabe"
|
||||||
|
AdvSceneSwitcher.condition.video.condition.pattern="entspricht dem Muster"
|
||||||
|
AdvSceneSwitcher.condition.video.condition.object="enthält Objekt"
|
||||||
|
AdvSceneSwitcher.condition.video.condition.brightness="Helligkeit"
|
||||||
|
AdvSceneSwitcher.condition.video.askFileAction="Vorhandene Datei verwenden oder einen Screenshot der aktuell ausgewählten Quelle erstellen?"
|
||||||
|
AdvSceneSwitcher.condition.video.askFileAction.file="Vorhandene Datei verwenden"
|
||||||
|
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Screenshot erstellen"
|
||||||
|
AdvSceneSwitcher.condition.video.reduceLatency="Reduzierung der Abgleichslatenz"
|
||||||
|
AdvSceneSwitcher.condition.video.reduceLatency.tooltip="Durch die Aktivierung wird die Abgleichslatenz verringert, aber die Bedingungsprüfungen aller Makros werden insgesamt langsamer."
|
||||||
|
AdvSceneSwitcher.condition.video.usePatternForChangedCheck="Musterabgleich verwenden"
|
||||||
|
AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip="So kann gesteuert werden, wie stark sich das Bild ändern muss, damit die Bedingung erfüllt ist."
|
||||||
|
AdvSceneSwitcher.condition.video.patternThreshold="Schwellenwert: "
|
||||||
|
AdvSceneSwitcher.condition.video.patternThresholdDescription="Ein höherer Schwellenwert bedeutet, dass das Muster stärker an die Videoquelle angepasst werden muss."
|
||||||
|
AdvSceneSwitcher.condition.video.patternThresholdUseAlphaAsMask="Alphakanal als Maske für Muster verwenden."
|
||||||
|
AdvSceneSwitcher.condition.video.brightnessThreshold="Durchschnittliche Helligkeit liegt über:"
|
||||||
|
AdvSceneSwitcher.condition.video.brightnessThresholdDescription="Ein hoher Wert steht für ein helles Bild, ein niedriger Wert für ein dunkles Bild."
|
||||||
|
AdvSceneSwitcher.condition.video.currentBrightness="Aktuelle durchschnittliche Helligkeit: %1"
|
||||||
|
AdvSceneSwitcher.condition.video.objectScaleThreshold="Skalierungsfaktor: "
|
||||||
|
AdvSceneSwitcher.condition.video.objectScaleThresholdDescription="Ein niedrigerer Skalierungsfaktor führt zu mehr Übereinstimmungen, aber zu einer höheren CPU-Belastung."
|
||||||
|
AdvSceneSwitcher.condition.video.minNeighborDescription="Ein höherer Wert für die Mindestanzahl von Nachbarn führt zu weniger, aber qualitativ besseren Übereinstimmungen."
|
||||||
|
AdvSceneSwitcher.condition.video.showMatch="Treffer anzeigen"
|
||||||
|
AdvSceneSwitcher.condition.video.showMatch.loading="Treffer werden gesucht"
|
||||||
|
AdvSceneSwitcher.condition.video.screenshotFail="Screenshot der Quelle konnte nicht erstellt werden!"
|
||||||
|
AdvSceneSwitcher.condition.video.screenshotEmpty="Screenshot ist leer - Ist die Quelle sichtbar?"
|
||||||
|
AdvSceneSwitcher.condition.video.patternMatchFail="Das Muster wurde nicht gefunden!"
|
||||||
|
AdvSceneSwitcher.condition.video.patternMatchSuccess="Das Muster ist rot hervorgehoben."
|
||||||
|
AdvSceneSwitcher.condition.video.objectMatchFail="Objekt wurde nicht gefunden!"
|
||||||
|
AdvSceneSwitcher.condition.video.objectMatchSuccess="Objekt ist rot hervorgehoben."
|
||||||
|
AdvSceneSwitcher.condition.video.modelLoadFail="Modelldaten konnten nicht geladen werden!"
|
||||||
|
AdvSceneSwitcher.condition.video.type.main="OBS's Haupt-Ausgabe"
|
||||||
|
AdvSceneSwitcher.condition.video.type.source="Quelle"
|
||||||
|
AdvSceneSwitcher.condition.video.type.scene="Szene"
|
||||||
|
AdvSceneSwitcher.condition.video.entry="{{videoInputTypes}}{{sources}}{{scenes}}{{condition}}{{imagePath}}"
|
||||||
|
AdvSceneSwitcher.condition.video.entry.modelPath="Modelldaten (Haar-Kaskaden-Klassifikator): {{modelDataPath}}"
|
||||||
|
AdvSceneSwitcher.condition.video.entry.minNeighbor="Minimale Anzahl von Nachbarn: {{minNeighbors}}"
|
||||||
|
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}Reduzieren Sie die CPU-Belastung, indem Sie die Prüfung nur alle {{throttleCount}} Millisekunden"
|
||||||
|
AdvSceneSwitcher.condition.video.entry.checkAreaEnable="Kontrolle nur im Bereich durchführen"
|
||||||
|
AdvSceneSwitcher.condition.video.entry.checkArea="{{checkAreaEnable}}{{checkArea}}{{selectArea}}"
|
||||||
|
AdvSceneSwitcher.condition.video.minSize="Minimale Größe:"
|
||||||
|
AdvSceneSwitcher.condition.video.maxSize="Maximale Größe:"
|
||||||
|
AdvSceneSwitcher.condition.video.selectArea="Bereich auswählen"
|
||||||
|
AdvSceneSwitcher.condition.video.selectArea.status="Nur der markierte Bereich wird überprüft"
|
||||||
|
AdvSceneSwitcher.condition.video.width="Breite"
|
||||||
|
AdvSceneSwitcher.condition.video.height="Höhe"
|
||||||
|
AdvSceneSwitcher.condition.stream="Stream"
|
||||||
|
AdvSceneSwitcher.condition.stream.state.start="Stream läuft"
|
||||||
|
AdvSceneSwitcher.condition.stream.state.stop="Stream gestoppt"
|
||||||
|
AdvSceneSwitcher.condition.stream.state.starting="Stream wird gestartet"
|
||||||
|
AdvSceneSwitcher.condition.stream.state.stopping="Stream wird gestoppt"
|
||||||
|
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
|
||||||
|
AdvSceneSwitcher.condition.record="Aufnahme"
|
||||||
|
AdvSceneSwitcher.condition.record.state.start="Aufnahme läuft"
|
||||||
|
AdvSceneSwitcher.condition.record.state.pause="Aufnahme pausiert"
|
||||||
|
AdvSceneSwitcher.condition.record.state.stop="Aufnahme gestoppt"
|
||||||
|
AdvSceneSwitcher.condition.record.entry="{{recordState}}"
|
||||||
|
AdvSceneSwitcher.condition.process="Prozess"
|
||||||
|
AdvSceneSwitcher.condition.process.entry="{{processes}} läuft {{focused}} und ist fokusiert"
|
||||||
|
AdvSceneSwitcher.condition.process.entry.focus="Aktueller Vordergrundprozess: {{focusProcess}}"
|
||||||
|
AdvSceneSwitcher.condition.idle="Leerlauf"
|
||||||
|
AdvSceneSwitcher.condition.idle.entry="Keine Tastatur- oder Mauseingaben für {{duration}}"
|
||||||
|
AdvSceneSwitcher.condition.pluginState="Plugin-Status"
|
||||||
|
AdvSceneSwitcher.condition.pluginState.state.start="Plugin gestartet"
|
||||||
|
AdvSceneSwitcher.condition.pluginState.state.restart="Plugin neu gestartet"
|
||||||
|
AdvSceneSwitcher.condition.pluginState.state.running="Plugin läuft"
|
||||||
|
AdvSceneSwitcher.condition.pluginState.state.shutdown="OBS wird runtergefahren"
|
||||||
|
AdvSceneSwitcher.condition.pluginState.state.sceneCollection="Szenensammlung geladen"
|
||||||
|
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Szene durch vorheriges Makro geändert"
|
||||||
|
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
|
||||||
|
AdvSceneSwitcher.condition.timer="Timer"
|
||||||
|
AdvSceneSwitcher.condition.timer.type.fixed="Fixe"
|
||||||
|
AdvSceneSwitcher.condition.timer.type.random="Zufällige"
|
||||||
|
AdvSceneSwitcher.condition.timer.pause="Pausieren"
|
||||||
|
AdvSceneSwitcher.condition.timer.continue="Fortfahren"
|
||||||
|
AdvSceneSwitcher.condition.timer.entry.line1.fixed="{{type}} Dauer von {{duration}} ist abgelaufen"
|
||||||
|
AdvSceneSwitcher.condition.timer.entry.line1.random="{{type}} Dauer von {{duration}} bis {{duration2}} ist abgelaufen"
|
||||||
|
AdvSceneSwitcher.condition.timer.entry.line2="Restliche Zeit: {{remaining}} Sekunden"
|
||||||
|
AdvSceneSwitcher.condition.timer.entry.line3="{{pauseContinue}} {{reset}} {{saveRemaining}} Verbleibende Zeit speichern {{autoReset}} Automatisches Zurücksetzen des Timers nach Erreichen der Dauer"
|
||||||
|
AdvSceneSwitcher.condition.timer.reset="Zurücksetzen"
|
||||||
|
AdvSceneSwitcher.condition.macro="Makro"
|
||||||
|
AdvSceneSwitcher.condition.macro.type.count="Zähler"
|
||||||
|
AdvSceneSwitcher.condition.macro.type.state="Zustand"
|
||||||
|
AdvSceneSwitcher.condition.macro.type.multiState="Mehrere Zustände"
|
||||||
|
AdvSceneSwitcher.condition.macro.type.selection="Bedingungs-Typ: {{types}}"
|
||||||
|
AdvSceneSwitcher.condition.macro.count.type.below="Weniger als"
|
||||||
|
AdvSceneSwitcher.condition.macro.count.type.above="Mehr als"
|
||||||
|
AdvSceneSwitcher.condition.macro.count.type.equal="Exakt"
|
||||||
|
AdvSceneSwitcher.condition.macro.state.type.below="Weniger als"
|
||||||
|
AdvSceneSwitcher.condition.macro.state.type.above="Mehr als"
|
||||||
|
AdvSceneSwitcher.condition.macro.state.type.equal="Exakt"
|
||||||
|
AdvSceneSwitcher.condition.macro.count.reset="Zurücksetzen"
|
||||||
|
AdvSceneSwitcher.condition.macro.pausedWarning="Ausgewähltes Makro ist derzeit pausiert!"
|
||||||
|
AdvSceneSwitcher.condition.macro.state.entry="Bedingungen für {{macros}} sind wahr"
|
||||||
|
AdvSceneSwitcher.condition.macro.multistate.entry="Bedingungen für {{multiStateConditions}}{{multiStateCount}} der folgenden Makros wahr sind:"
|
||||||
|
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} wurde ausgeführt {{conditions}} {{count}} Mal"
|
||||||
|
AdvSceneSwitcher.condition.macro.count.entry.line2="Aktuelle Anzahl: {{currentCount}} {{resetCount}}"
|
||||||
|
AdvSceneSwitcher.condition.source="Quelle"
|
||||||
|
AdvSceneSwitcher.condition.source.type.active="Ist aktiv"
|
||||||
|
AdvSceneSwitcher.condition.source.type.showing="Wird angezeigt"
|
||||||
|
AdvSceneSwitcher.condition.source.type.settings="Einstellungen stimmen überein"
|
||||||
|
AdvSceneSwitcher.condition.source.getSettings="Aktuelle Einstellungen abfragen"
|
||||||
|
AdvSceneSwitcher.condition.source.entry.line1="{{sources}} {{conditions}}"
|
||||||
|
AdvSceneSwitcher.condition.source.entry.line2="{{settings}}"
|
||||||
|
AdvSceneSwitcher.condition.source.entry.line3="{{regex}} {{getSettings}}"
|
||||||
|
AdvSceneSwitcher.condition.virtualCamera="Virtuelle Kamera"
|
||||||
|
AdvSceneSwitcher.condition.virtualCamera.state.start="Virtuelle Kamera gestartet"
|
||||||
|
AdvSceneSwitcher.condition.virtualCamera.state.stop="Virtuelle Kamera gestoppt"
|
||||||
|
AdvSceneSwitcher.condition.virtualCamera.entry="{{states}}"
|
||||||
|
AdvSceneSwitcher.condition.filter="Filter"
|
||||||
|
AdvSceneSwitcher.condition.filter.type.active="Ist aktiviert"
|
||||||
|
AdvSceneSwitcher.condition.filter.type.showing="Ist deaktiviert"
|
||||||
|
AdvSceneSwitcher.condition.filter.type.settings="Einstellungen passen"
|
||||||
|
AdvSceneSwitcher.condition.filter.getSettings="Aktuelle Einstellungen abrufen"
|
||||||
|
AdvSceneSwitcher.condition.filter.entry.line1="Auf {{sources}} {{filters}} {{conditions}}"
|
||||||
|
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
||||||
|
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
|
||||||
|
AdvSceneSwitcher.condition.sceneOrder="Reihenfolge der Szenenelemente"
|
||||||
|
AdvSceneSwitcher.condition.sceneOrder.type.above="Ist über"
|
||||||
|
AdvSceneSwitcher.condition.sceneOrder.type.below="Ist unter"
|
||||||
|
AdvSceneSwitcher.condition.sceneOrder.type.position="Ist in Position"
|
||||||
|
AdvSceneSwitcher.condition.sceneOrder.positionInfo="Der Positionswert beginnt ganz unten bei 0 und erhöht sich für jedes Szenenelement, auch in Szenengruppen, um eins"
|
||||||
|
AdvSceneSwitcher.condition.sceneOrder.entry="Auf{{scenes}}{{sources}}{{conditions}}{{sources2}}{{position}}"
|
||||||
|
AdvSceneSwitcher.condition.hotkey="Hotkey"
|
||||||
|
AdvSceneSwitcher.condition.hotkey.name="Makro-Trigger-Hotkey"
|
||||||
|
AdvSceneSwitcher.condition.hotkey.tip="Hinweis: Die Tastenkombinationen für diesen Hotkey können in den OBS-Einstellungen konfiguriert werden"
|
||||||
|
AdvSceneSwitcher.condition.hotkey.entry.line1="Hotkey ist gedrückt"
|
||||||
|
AdvSceneSwitcher.condition.hotkey.entry.line2="Name: {{name}}"
|
||||||
|
AdvSceneSwitcher.condition.replay="Replay Buffer"
|
||||||
|
AdvSceneSwitcher.condition.replay.state.stopped="Replay Buffer gestoppt"
|
||||||
|
AdvSceneSwitcher.condition.replay.state.started="Replay Buffer gestartet"
|
||||||
|
AdvSceneSwitcher.condition.replay.state.saved="Replay Buffer gespeichert"
|
||||||
|
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
||||||
|
AdvSceneSwitcher.condition.date="Datum"
|
||||||
|
AdvSceneSwitcher.condition.date.anyDay="Beliebiger Tag"
|
||||||
|
AdvSceneSwitcher.condition.date.monday="Montag"
|
||||||
|
AdvSceneSwitcher.condition.date.tuesday="Dienstag"
|
||||||
|
AdvSceneSwitcher.condition.date.wednesday="Mittwoch"
|
||||||
|
AdvSceneSwitcher.condition.date.thursday="Donnerstag"
|
||||||
|
AdvSceneSwitcher.condition.date.friday="Freitag"
|
||||||
|
AdvSceneSwitcher.condition.date.saturday="Samstag"
|
||||||
|
AdvSceneSwitcher.condition.date.sunday="Sonntag"
|
||||||
|
AdvSceneSwitcher.condition.date.state.at="Am"
|
||||||
|
AdvSceneSwitcher.condition.date.state.after="Nach"
|
||||||
|
AdvSceneSwitcher.condition.date.state.before="Vor"
|
||||||
|
AdvSceneSwitcher.condition.date.state.between="Zwischen"
|
||||||
|
AdvSceneSwitcher.condition.date.state.pattern="Muster"
|
||||||
|
AdvSceneSwitcher.condition.date.separator="und"
|
||||||
|
AdvSceneSwitcher.condition.date.ignoreDate="Wenn diese Option nicht aktiviert ist, wird die Datumskomponente ignoriert"
|
||||||
|
AdvSceneSwitcher.condition.date.ignoreTime="Wenn diese Option nicht aktiviert ist, wird die Zeitkomponente ignoriert"
|
||||||
|
AdvSceneSwitcher.condition.date.showAdvancedSettings="Erweiterte Einstellungen anzeigen"
|
||||||
|
AdvSceneSwitcher.condition.date.showSimpleSettings="Einfache Einstellungen anzeigen"
|
||||||
|
AdvSceneSwitcher.condition.date.entry.simple="Am {{dayOfWeek}} {{weekCondition}} {{ignoreWeekTime}}{{weekTime}}"
|
||||||
|
AdvSceneSwitcher.condition.date.entry.advanced="{{condition}} {{ignoreDate}}{{date}} {{ignoreTime}}{{time}} {{separator}} {{date2}} {{time2}}"
|
||||||
|
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}} Wiederholen alle {{duration}} bei Datumsübereinstimmung"
|
||||||
|
AdvSceneSwitcher.condition.date.entry.pattern="Aktuelles Datum \"{{currentDate}}\" entspricht dem Muster {{pattern}}"
|
||||||
|
AdvSceneSwitcher.condition.date.entry.nextMatchDate="Nächster Treffer bei: %1"
|
||||||
|
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} Bei Wiederholung ausgewähltes Datum auf Wiederholungsdatum aktualisieren"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform="Szenenelement transformieren"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.getTransform="Transformation erhalten"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.entry.line1="Auf{{scenes}}{{sources}}passt zur Transformation"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
|
||||||
|
AdvSceneSwitcher.condition.transition="Übergang"
|
||||||
|
AdvSceneSwitcher.condition.transition.type.current="Aktueller Übergangstyp ist"
|
||||||
|
AdvSceneSwitcher.condition.transition.type.duration="Aktuelle Übergangsdauer beträgt"
|
||||||
|
AdvSceneSwitcher.condition.transition.type.started="Übergang gestartet"
|
||||||
|
AdvSceneSwitcher.condition.transition.type.ended="Übergang beendet"
|
||||||
|
AdvSceneSwitcher.condition.transition.type.transitionSource="Übergang von"
|
||||||
|
AdvSceneSwitcher.condition.transition.type.transitionTarget="Übergang zu"
|
||||||
|
AdvSceneSwitcher.condition.transition.durationSuffix="Sekunden"
|
||||||
|
AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{scenes}}{{duration}}{{durationSuffix}}"
|
||||||
|
AdvSceneSwitcher.condition.sceneVisibility="Sichtbarkeit von Szenenelementen"
|
||||||
|
AdvSceneSwitcher.condition.sceneVisibility.type.shown="ist sichtbar"
|
||||||
|
AdvSceneSwitcher.condition.sceneVisibility.type.hidden="ist versteckt"
|
||||||
|
AdvSceneSwitcher.condition.sceneVisibility.type.changed="Sichtbarkeit verändert"
|
||||||
|
AdvSceneSwitcher.condition.sceneVisibility.entry="Auf{{scenes}}{{sources}}{{conditions}}"
|
||||||
|
AdvSceneSwitcher.condition.studioMode="Studio-Modus"
|
||||||
|
AdvSceneSwitcher.condition.studioMode.state.active="Studio-Modus ist aktiviert"
|
||||||
|
AdvSceneSwitcher.condition.studioMode.state.notActive="Studio-Modus ist nicht aktiviert"
|
||||||
|
AdvSceneSwitcher.condition.studioMode.state.previewScene="Vorschau-Szene ist"
|
||||||
|
AdvSceneSwitcher.condition.studioMode.entry="{{conditions}}{{scenes}}"
|
||||||
|
AdvSceneSwitcher.condition.openvr="OpenVR"
|
||||||
|
AdvSceneSwitcher.condition.openvr.errorStatus="OpenVR Fehler: "
|
||||||
|
AdvSceneSwitcher.condition.openvr.entry.line1="HMD ist in ..."
|
||||||
|
AdvSceneSwitcher.condition.openvr.entry.line2="{{controls}}"
|
||||||
|
AdvSceneSwitcher.condition.openvr.entry.line3="HMD ist derzeit bei {{xPos}} x {{yPos}} x {{zPos}}"
|
||||||
|
AdvSceneSwitcher.condition.stats="OBS-Statistiken"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.fps="FPS"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.CPUUsage="CPU-Auslastung"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.HDDSpaceAvailable="Verfügbarer Speicherplatz"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.memoryUsage="Speicherverbrauch"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.averageTimeToRender="Durchschnittliche Zeit zum Rendern eines Frames"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.skippedFrames="Übersprungene Frames aufgrund der Kodierungsverzögerung"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.missedFrames="Verpasste Frames durch Rendering-Verzögerung"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.droppedFrames.stream="Verlorene Frames im Stream"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.megabytesSent.stream="Gesamtdatenmenge des Streams"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.bitrate.stream="Stream-Bitrate"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.droppedFrames.recording="Verlorene Frames bei der Aufnahme"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.megabytesSent.recording="Gesamtdatenmenge der Aufnahme"
|
||||||
|
AdvSceneSwitcher.condition.stats.type.bitrate.recording="Aufnahme-Bitrate"
|
||||||
|
AdvSceneSwitcher.condition.stats.condition.above="über"
|
||||||
|
AdvSceneSwitcher.condition.stats.condition.equals="gleich"
|
||||||
|
AdvSceneSwitcher.condition.stats.condition.below="unter"
|
||||||
|
AdvSceneSwitcher.condition.stats.dockHint="Das Dock \"Stats\" öffnen, um den aktuellen Status anzuzeigen"
|
||||||
|
AdvSceneSwitcher.condition.stats.entry="{{stats}} ist {{condition}} {{value}}"
|
||||||
|
AdvSceneSwitcher.condition.profile="Profil"
|
||||||
|
AdvSceneSwitcher.condition.profile.entry="Derzeit aktives Profil ist {{profiles}}"
|
||||||
|
AdvSceneSwitcher.condition.websocket="Websocket"
|
||||||
|
AdvSceneSwitcher.condition.websocket.type.request="Anfrage"
|
||||||
|
AdvSceneSwitcher.condition.websocket.type.event="Ereignis"
|
||||||
|
AdvSceneSwitcher.condition.websocket.useRegex="Reguläre Ausdrücke verwenden"
|
||||||
|
AdvSceneSwitcher.condition.websocket.entry.request="{{type}} wurde empfangen:"
|
||||||
|
AdvSceneSwitcher.condition.websocket.entry.event="{{type}} wurde empfangen von {{connection}}:"
|
||||||
|
AdvSceneSwitcher.condition.variable="Variabel"
|
||||||
|
AdvSceneSwitcher.condition.variable.type.compare="entspricht"
|
||||||
|
AdvSceneSwitcher.condition.variable.type.empty="ist leer"
|
||||||
|
AdvSceneSwitcher.condition.variable.type.number="ist eine Zahl"
|
||||||
|
AdvSceneSwitcher.condition.variable.type.lessThan="ist kleiner als"
|
||||||
|
AdvSceneSwitcher.condition.variable.type.greaterThan="ist größer als"
|
||||||
|
AdvSceneSwitcher.condition.variable.type.valueChanged="Wert verändert"
|
||||||
|
AdvSceneSwitcher.condition.variable.type.equalsVariable="entspricht Variable"
|
||||||
|
AdvSceneSwitcher.condition.variable.type.lessThanVariable="ist kleiner als die Variable"
|
||||||
|
AdvSceneSwitcher.condition.variable.type.greaterThanVariable="ist größer als die Variable"
|
||||||
|
AdvSceneSwitcher.condition.variable.entry="{{variables}}{{conditions}}{{strValue}}{{numValue}}{{variables2}}"
|
||||||
|
|
||||||
|
; Macro Actions
|
||||||
|
AdvSceneSwitcher.action.switchScene="Szene wechseln"
|
||||||
|
AdvSceneSwitcher.action.scene.entry="Wechsle zu Szene{{scenes}}mittels{{transitions}}mit einer Dauer von{{duration}}Sekunden"
|
||||||
|
AdvSceneSwitcher.action.scene.entry.noDuration="Wechsle zu Szene{{scenes}}mittels{{transitions}}"
|
||||||
|
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Warten, bis der Übergang zur Zielszene abgeschlossen ist"
|
||||||
|
AdvSceneSwitcher.action.wait="Warten"
|
||||||
|
AdvSceneSwitcher.action.wait.type.fixed="fixe"
|
||||||
|
AdvSceneSwitcher.action.wait.type.random="zufällig"
|
||||||
|
AdvSceneSwitcher.action.wait.entry.fixed="Warte für {{waitType}} Dauer von {{duration}}"
|
||||||
|
AdvSceneSwitcher.action.wait.entry.random="Warte für {{waitType}} Dauer von {{duration}} bis {{duration2}}"
|
||||||
|
AdvSceneSwitcher.action.audio="Audio"
|
||||||
|
AdvSceneSwitcher.action.audio.type.mute="Stummgeschaltet"
|
||||||
|
AdvSceneSwitcher.action.audio.type.unmute="Nicht stummgeschaltet"
|
||||||
|
AdvSceneSwitcher.action.audio.type.sourceVolume="Quell-Lautstärke einstellen"
|
||||||
|
AdvSceneSwitcher.action.audio.type.masterVolume="Master-Lautstärke einstellen"
|
||||||
|
AdvSceneSwitcher.action.audio.type.syncOffset="Sync-Offset einstellen"
|
||||||
|
AdvSceneSwitcher.action.audio.type.monitor="Audio-Monitoring einstellen"
|
||||||
|
AdvSceneSwitcher.action.audio.type.balance="Audio-Balance einstellen"
|
||||||
|
AdvSceneSwitcher.action.audio.balance.description="Den Schieberegler in die Richtung des Audiokanals drehen, auf den fokussiert werden soll."
|
||||||
|
AdvSceneSwitcher.action.audio.fade.type.duration="über eine Dauer von"
|
||||||
|
AdvSceneSwitcher.action.audio.fade.type.rate="mit einer Rate von"
|
||||||
|
AdvSceneSwitcher.action.audio.fade.duration="{{fade}}Blende {{fadeTypes}} {{duration}} Sekunden."
|
||||||
|
AdvSceneSwitcher.action.audio.fade.rate="{{fade}}Blende {{fadeTypes}} {{rate}}pro Sekunde."
|
||||||
|
AdvSceneSwitcher.action.audio.fade.wait="Warten, bis die Blende abgeschlossen ist."
|
||||||
|
AdvSceneSwitcher.action.audio.fade.abort="Abbruch einer bereits aktiven Blende."
|
||||||
|
AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}"
|
||||||
|
AdvSceneSwitcher.action.recording="Aufnahme"
|
||||||
|
AdvSceneSwitcher.action.recording.type.stop="Aufnahme stoppen"
|
||||||
|
AdvSceneSwitcher.action.recording.type.start="Aufnahme starten"
|
||||||
|
AdvSceneSwitcher.action.recording.type.pause="Aufnahme pausieren"
|
||||||
|
AdvSceneSwitcher.action.recording.type.unpause="Aufnahme nicht mehr pausieren"
|
||||||
|
AdvSceneSwitcher.action.recording.type.split="Aufnahme-Datei teilen"
|
||||||
|
AdvSceneSwitcher.action.recording.pause.hint="Bitte beachten, dass je nach Aufnahmeeinstellung die Aufnahme möglicherweise nicht unterbrochen werden kann"
|
||||||
|
AdvSceneSwitcher.action.recording.split.hint="Vergewissern, dass die automatische Dateiaufteilung in den OBS-Einstellungen aktiviert ist!"
|
||||||
|
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
|
AdvSceneSwitcher.action.replay="Replay Buffer"
|
||||||
|
AdvSceneSwitcher.action.replay.saveWarn="Warnung: Ein zu häufiges Speichern kann dazu führen, dass der Replay Buffer nicht gespeichert wird!"
|
||||||
|
AdvSceneSwitcher.action.replay.type.stop="Replay Buffer stoppen"
|
||||||
|
AdvSceneSwitcher.action.replay.type.start="Replay Buffer starten"
|
||||||
|
AdvSceneSwitcher.action.replay.type.save="Replay Buffer speichern"
|
||||||
|
AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||||
|
AdvSceneSwitcher.action.streaming="Stream"
|
||||||
|
AdvSceneSwitcher.action.streaming.type.stop="Stream stoppen"
|
||||||
|
AdvSceneSwitcher.action.streaming.type.start="Stream starten"
|
||||||
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||||
|
AdvSceneSwitcher.action.run="Ausführen"
|
||||||
|
AdvSceneSwitcher.action.run.arguments="Argumente:"
|
||||||
|
AdvSceneSwitcher.action.run.addArgument="Argument hinzufügen"
|
||||||
|
AdvSceneSwitcher.action.run.addArgumentDescription="Neues Argument hinzufügen:"
|
||||||
|
AdvSceneSwitcher.action.run.entry="Ausführen {{filePath}}"
|
||||||
|
AdvSceneSwitcher.action.run.entry.workingDirectory="Arbeitsverzeichnis:{{workingDirectory}}"
|
||||||
|
AdvSceneSwitcher.action.sceneVisibility="Sichtbarkeit von Szenenelementen"
|
||||||
|
AdvSceneSwitcher.action.sceneVisibility.type.show="Anzeigen"
|
||||||
|
AdvSceneSwitcher.action.sceneVisibility.type.hide="Verstecken"
|
||||||
|
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Umschalten"
|
||||||
|
AdvSceneSwitcher.action.sceneVisibility.type.source="Quelle"
|
||||||
|
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Beliebig"
|
||||||
|
AdvSceneSwitcher.action.sceneVisibility.entry="Auf{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
|
||||||
|
AdvSceneSwitcher.action.filter="Filter"
|
||||||
|
AdvSceneSwitcher.action.filter.type.enable="Aktivieren"
|
||||||
|
AdvSceneSwitcher.action.filter.type.disable="Deaktivieren"
|
||||||
|
AdvSceneSwitcher.action.filter.type.settings="Einstellungen festlegen"
|
||||||
|
AdvSceneSwitcher.action.filter.entry="Auf {{sources}} {{actions}} {{filters}}"
|
||||||
|
AdvSceneSwitcher.action.filter.getSettings="Aktuelle Einstellungen abfragen"
|
||||||
|
AdvSceneSwitcher.action.source="Quelle"
|
||||||
|
AdvSceneSwitcher.action.source.type.enable="Aktivieren"
|
||||||
|
AdvSceneSwitcher.action.source.type.disable="Deaktivieren"
|
||||||
|
AdvSceneSwitcher.action.source.type.settings="Einstellungen festlegen"
|
||||||
|
AdvSceneSwitcher.action.source.type.refreshSettings="Aktualisieren der Quelleneinstellungen"
|
||||||
|
AdvSceneSwitcher.action.source.type.pressSettingsButton="Drücken der Einstellungstaste"
|
||||||
|
AdvSceneSwitcher.action.source.type.refreshSettings.tooltip="Kann verwendet werden, um Browser-, Medien- usw. Quellen zu aktualisieren"
|
||||||
|
AdvSceneSwitcher.action.source.noSettingsButtons="Keine Buttons gefunden!"
|
||||||
|
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
|
||||||
|
AdvSceneSwitcher.action.source.warning="Warnung: Das globale Aktivieren und Deaktivieren von Quellen kann nicht über die OBS-Benutzeroberfläche gesteuert werden"
|
||||||
|
AdvSceneSwitcher.action.source.getSettings="Aktuelle Einstellungen abfragen"
|
||||||
|
AdvSceneSwitcher.action.media="Medien"
|
||||||
|
AdvSceneSwitcher.action.media.type.play="Abspielen"
|
||||||
|
AdvSceneSwitcher.action.media.type.pause="Pausieren"
|
||||||
|
AdvSceneSwitcher.action.media.type.stop="Stoppen"
|
||||||
|
AdvSceneSwitcher.action.media.type.restart="Neu starten"
|
||||||
|
AdvSceneSwitcher.action.media.type.next="Nächste"
|
||||||
|
AdvSceneSwitcher.action.media.type.previous="Vorherige"
|
||||||
|
AdvSceneSwitcher.action.media.type.seek="Suche nach"
|
||||||
|
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
|
||||||
|
AdvSceneSwitcher.action.macro="Makro"
|
||||||
|
AdvSceneSwitcher.action.macro.type.pause="Pausieren"
|
||||||
|
AdvSceneSwitcher.action.macro.type.unpause="Nicht mehr pausieren"
|
||||||
|
AdvSceneSwitcher.action.macro.type.resetCounter="Zähler zurücksetzen"
|
||||||
|
AdvSceneSwitcher.action.macro.type.run="Aktionen ausführen"
|
||||||
|
AdvSceneSwitcher.action.macro.type.stop="Aktionen stoppen"
|
||||||
|
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
|
||||||
|
AdvSceneSwitcher.action.pluginState="Plugin-Status"
|
||||||
|
AdvSceneSwitcher.action.pluginState.type.stop="Erweiterten Automatischen Szenenwechsler stoppen"
|
||||||
|
AdvSceneSwitcher.action.pluginState.type.noMatch="Ändern des Nichtübereinstimmungsverhaltens:"
|
||||||
|
AdvSceneSwitcher.action.pluginState.type.import="Einstellungen importieren aus"
|
||||||
|
AdvSceneSwitcher.action.pluginState.importWarning="Hinweis: Die Aktion wird ignoriert, solange das Einstellungsfenster geöffnet ist."
|
||||||
|
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
|
||||||
|
AdvSceneSwitcher.action.virtualCamera="Virtuelle Kamera"
|
||||||
|
AdvSceneSwitcher.action.virtualCamera.type.stop="Virtuelle Kamera stoppen"
|
||||||
|
AdvSceneSwitcher.action.virtualCamera.type.start="Virtuelle Kamera starten"
|
||||||
|
AdvSceneSwitcher.action.virtualCamera.entry="{{actions}}"
|
||||||
|
AdvSceneSwitcher.action.hotkey="Hotkey"
|
||||||
|
AdvSceneSwitcher.action.hotkey.leftShift="Linke Umschalttaste"
|
||||||
|
AdvSceneSwitcher.action.hotkey.rightShift="Rechte Umschalttaste"
|
||||||
|
AdvSceneSwitcher.action.hotkey.leftCtrl="Linke Strg-Taste"
|
||||||
|
AdvSceneSwitcher.action.hotkey.rightCtrl="Rechte Strg-Taste"
|
||||||
|
AdvSceneSwitcher.action.hotkey.leftAlt="Linke Alt-Taste"
|
||||||
|
AdvSceneSwitcher.action.hotkey.rightAlt="Rechte Alt-Taste"
|
||||||
|
AdvSceneSwitcher.action.hotkey.leftMeta="Linke Meta-Taste"
|
||||||
|
AdvSceneSwitcher.action.hotkey.rightMeta="Rechte Meta-Taste"
|
||||||
|
AdvSceneSwitcher.action.hotkey.onlyOBS="Tastendruck nur an OBS senden"
|
||||||
|
AdvSceneSwitcher.action.hotkey.disabled="Globale Tastendrücke können nicht simuliert werden - die Funktionalität beschränkt sich auf das Senden von Tastendrücken an OBS!"
|
||||||
|
AdvSceneSwitcher.action.hotkey.entry="Drücke {{keys}} für {{duration}}"
|
||||||
|
AdvSceneSwitcher.action.sceneOrder="Reihenfolge der Szenenelemente"
|
||||||
|
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Nach oben verschieben"
|
||||||
|
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Nach unten verschieben"
|
||||||
|
AdvSceneSwitcher.action.sceneOrder.type.moveTop="An erste Stelle verschieben"
|
||||||
|
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="An letzte Stelle verschieben"
|
||||||
|
AdvSceneSwitcher.action.sceneOrder.type.movePosition="An Position verschieben"
|
||||||
|
AdvSceneSwitcher.action.sceneOrder.entry="Auf{{scenes}}{{actions}}{{sources}}{{position}}"
|
||||||
|
AdvSceneSwitcher.action.sceneTransform="Szenenelement transformieren"
|
||||||
|
AdvSceneSwitcher.action.sceneTransform.getTransform="Transformation erhalten"
|
||||||
|
AdvSceneSwitcher.action.sceneTransform.entry="Auf{{scenes}}transformieren{{sources}}"
|
||||||
|
AdvSceneSwitcher.action.file="Datei"
|
||||||
|
AdvSceneSwitcher.action.file.type.write="Schreiben"
|
||||||
|
AdvSceneSwitcher.action.file.type.append="Anhängen"
|
||||||
|
AdvSceneSwitcher.action.file.entry="{{actions}} in {{filePath}}:"
|
||||||
|
AdvSceneSwitcher.action.studioMode="Studio-Modus"
|
||||||
|
AdvSceneSwitcher.action.studioMode.type.swap="Vorschau- und Programm-Szene tauschen"
|
||||||
|
AdvSceneSwitcher.action.studioMode.type.setScene="Vorschau-Szene einstellen auf"
|
||||||
|
AdvSceneSwitcher.action.studioMode.type.enable="Studio-Modus aktivieren"
|
||||||
|
AdvSceneSwitcher.action.studioMode.type.disable="Studio-Modus deaktivieren"
|
||||||
|
AdvSceneSwitcher.action.studioMode.entry="{{actions}}{{scenes}}"
|
||||||
|
AdvSceneSwitcher.action.transition="Übergang"
|
||||||
|
AdvSceneSwitcher.action.transition.type.scene="Szenenübergang"
|
||||||
|
AdvSceneSwitcher.action.transition.type.sceneOverride="Szenenübergang überschreiben"
|
||||||
|
AdvSceneSwitcher.action.transition.type.sourceShow="Übergang der Quelle anzeigen"
|
||||||
|
AdvSceneSwitcher.action.transition.type.sourceHide="Übergang der Quelle verstecken"
|
||||||
|
AdvSceneSwitcher.action.transition.entry.line1="Anpassen {{type}}{{scenes}}{{sources}}"
|
||||||
|
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}Übergangstyp festlegen auf {{transitions}}"
|
||||||
|
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}Übergangsdauer festlegen auf {{duration}}Sekunden"
|
||||||
|
AdvSceneSwitcher.action.timer="Timer"
|
||||||
|
AdvSceneSwitcher.action.timer.type.pause="Pausieren"
|
||||||
|
AdvSceneSwitcher.action.timer.type.continue="Fortsetzen"
|
||||||
|
AdvSceneSwitcher.action.timer.type.reset="Zurücksetzen"
|
||||||
|
AdvSceneSwitcher.action.timer.type.setTimeRemaining="Verbleibende Zeit einstellen der"
|
||||||
|
AdvSceneSwitcher.action.timer.entry="{{timerAction}} Timer von {{macros}} {{duration}}"
|
||||||
|
AdvSceneSwitcher.action.random="Zufall"
|
||||||
|
AdvSceneSwitcher.action.random.allowRepeat="Aufeinanderfolgende Ausführung desselben Makros zulassen"
|
||||||
|
AdvSceneSwitcher.action.random.entry="Zufällige Ausführung eines der folgenden Makros (pausierte Makros werden ignoriert)"
|
||||||
|
AdvSceneSwitcher.action.systray="Benachrichtigung im System-Tray"
|
||||||
|
AdvSceneSwitcher.action.screenshot="Screenshot"
|
||||||
|
AdvSceneSwitcher.action.screenshot.save.default="Standard"
|
||||||
|
AdvSceneSwitcher.action.screenshot.save.custom="Benutzerdefiniert"
|
||||||
|
AdvSceneSwitcher.action.screenshot.type.source="Quelle"
|
||||||
|
AdvSceneSwitcher.action.screenshot.type.scene="Szene"
|
||||||
|
AdvSceneSwitcher.action.screenshot.mainOutput="OBS's Haupt-Ausgabe"
|
||||||
|
AdvSceneSwitcher.action.screenshot.blackscreenNote="Quellen oder Szenen, die nicht immer gerendert werden, können dazu führen, dass einige Teile der Screenshots leer bleiben."
|
||||||
|
AdvSceneSwitcher.action.screenshot.entry="Screenshot{{targetType}}{{sources}}{{scenes}}und speichere in{{saveType}}Pfad"
|
||||||
|
AdvSceneSwitcher.action.profile="Profil"
|
||||||
|
AdvSceneSwitcher.action.profile.entry="Aktives Profil umschalten auf {{profiles}}"
|
||||||
|
AdvSceneSwitcher.action.sceneCollection="Szenensammlung"
|
||||||
|
AdvSceneSwitcher.action.sceneCollection.entry="Aktive Szenensammlung umschalten auf {{sceneCollections}}"
|
||||||
|
AdvSceneSwitcher.action.sceneCollection.warning="Hinweis: Alle danach folgenden Aktionen werden nicht ausgeführt, da durch die Änderung der Szenensammlung auch die Einstellungen des Szenenwechslers neu geladen werden.\nDie Szenensammlungsaktion wird ignoriert, solange das Einstellungsfenster geöffnet ist."
|
||||||
|
AdvSceneSwitcher.action.sequence="Sequenz"
|
||||||
|
AdvSceneSwitcher.action.sequence.entry="Jedes Mal, wenn diese Aktion ausgeführt wird, wird das nächste Makro in der Liste ausgeführt (pausierte Makros werden ignoriert)"
|
||||||
|
AdvSceneSwitcher.action.sequence.status="Zuletzt ausgeführtes Makro: %1 - Nächstes auszuführendes Makro: %2"
|
||||||
|
AdvSceneSwitcher.action.sequence.status.none="keines"
|
||||||
|
AdvSceneSwitcher.action.sequence.restart="Neustart am Anfang, wenn das Ende der Liste erreicht ist"
|
||||||
|
AdvSceneSwitcher.action.sequence.continueFrom="Weiter mit ausgewähltem Element"
|
||||||
|
AdvSceneSwitcher.action.websocket="Websocket"
|
||||||
|
AdvSceneSwitcher.action.websocket.type.request="Anfrage"
|
||||||
|
AdvSceneSwitcher.action.websocket.type.event="Ereignis"
|
||||||
|
AdvSceneSwitcher.action.websocket.entry.request="Szenenwechsler {{type}} via {{connection}} senden"
|
||||||
|
AdvSceneSwitcher.action.websocket.entry.event="Szenenwechsler {{type}} an verbundene Clients senden"
|
||||||
|
AdvSceneSwitcher.action.http="HTTP"
|
||||||
|
AdvSceneSwitcher.action.http.type.get="GET"
|
||||||
|
AdvSceneSwitcher.action.http.type.post="POST"
|
||||||
|
AdvSceneSwitcher.action.http.entry.line1="Sende {{method}} an {{url}}"
|
||||||
|
AdvSceneSwitcher.action.http.entry.line2="Timeout: {{timeout}} Sekunden"
|
||||||
|
AdvSceneSwitcher.action.variable="Variabel"
|
||||||
|
AdvSceneSwitcher.action.variable.type.set="Auf festen Wert einstellen"
|
||||||
|
AdvSceneSwitcher.action.variable.type.append="Anhängen"
|
||||||
|
AdvSceneSwitcher.action.variable.type.appendVar="Variable anhängen"
|
||||||
|
AdvSceneSwitcher.action.variable.type.increment="Erhöhen"
|
||||||
|
AdvSceneSwitcher.action.variable.type.decrement="Verringern"
|
||||||
|
AdvSceneSwitcher.action.variable.type.setActionValue="Auf Aktionswert setzen"
|
||||||
|
AdvSceneSwitcher.action.variable.type.setConditionValue="Auf Bedingungswert setzen"
|
||||||
|
AdvSceneSwitcher.action.variable.invalidSelection="Ungültige Auswahl!"
|
||||||
|
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Aktionen wird nicht unterstützt!"
|
||||||
|
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Bedingungen wird nicht unterstützt!"
|
||||||
|
AdvSceneSwitcher.action.variable.currentSegmentValue="Aktueller Wert:"
|
||||||
|
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}"
|
||||||
|
|
||||||
|
|
||||||
; Transition Tab
|
; Transition Tab
|
||||||
AdvSceneSwitcher.transitionTab.title="Szenenübergänge"
|
AdvSceneSwitcher.transitionTab.title="Szenenübergänge"
|
||||||
AdvSceneSwitcher.transitionTab.transitionForAToB="Szenenübergänge für automatisierte Szenenwechsel von Szene A zu Szene B"
|
AdvSceneSwitcher.transitionTab.transitionForAToB="Szenenübergänge für automatisierte Szenenwechsel von Szene A zu Szene B"
|
||||||
@@ -117,6 +650,7 @@ AdvSceneSwitcher.mediaTab.states.Paused="Pausiert"
|
|||||||
AdvSceneSwitcher.mediaTab.states.stopped="Gestoppt"
|
AdvSceneSwitcher.mediaTab.states.stopped="Gestoppt"
|
||||||
AdvSceneSwitcher.mediaTab.states.ended="Beendet"
|
AdvSceneSwitcher.mediaTab.states.ended="Beendet"
|
||||||
AdvSceneSwitcher.mediaTab.states.error="Fehler"
|
AdvSceneSwitcher.mediaTab.states.error="Fehler"
|
||||||
|
AdvSceneSwitcher.mediaTab.states.playlistEnd="Ended(Playlist)"
|
||||||
AdvSceneSwitcher.mediaTab.states.any="Beliebig"
|
AdvSceneSwitcher.mediaTab.states.any="Beliebig"
|
||||||
AdvSceneSwitcher.mediaTab.timeRestriction.none="Keine Auswahl"
|
AdvSceneSwitcher.mediaTab.timeRestriction.none="Keine Auswahl"
|
||||||
AdvSceneSwitcher.mediaTab.timeRestriction.shorter="Dauer kürzer"
|
AdvSceneSwitcher.mediaTab.timeRestriction.shorter="Dauer kürzer"
|
||||||
@@ -190,10 +724,10 @@ AdvSceneSwitcher.sceneSequenceTab.loadFail="Laden der Einstellungen ist fehlgesc
|
|||||||
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="Laden der Einstellungen war erfolgreich!"
|
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="Laden der Einstellungen war erfolgreich!"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.fileType="Text Dateien (*.txt)"
|
AdvSceneSwitcher.sceneSequenceTab.fileType="Text Dateien (*.txt)"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.interruptible="kann unterbrochen werden"
|
AdvSceneSwitcher.sceneSequenceTab.interruptible="kann unterbrochen werden"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Andere Szenenwechselmethoden können diese Sequenz unterbrechen"
|
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Andere Szenenwechselmethoden können diese Sequenz unterbrechen"
|
||||||
|
AdvSceneSwitcher.sceneSequenceTab.entry="Wenn {{startScenes}} aktiv ist wechsle zu {{scenes}} nach {{delay}} mit {{transitions}} {{interruptible}}"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.extendEdit="Szenenfolge erweitern"
|
AdvSceneSwitcher.sceneSequenceTab.extendEdit="Szenenfolge erweitern"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.extendEntry="Nach {{delay}} wechsle zu {{scenes}} mit {{transitions}}"
|
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."
|
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
|
; Audio Tab
|
||||||
@@ -221,6 +755,7 @@ AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Dieser Tab ermöglicht es
|
|||||||
|
|
||||||
; Network Tab
|
; Network Tab
|
||||||
AdvSceneSwitcher.networkTab.title="Netzwerk"
|
AdvSceneSwitcher.networkTab.title="Netzwerk"
|
||||||
|
AdvSceneSwitcher.networkTab.description="Über diesen Tab kann die aktive Szene einer anderen OBS-Instanz ferngesteuert werden.\nBitte beachten, dass die Szenennamen auf allen OBS-Instanzen exakt übereinstimmen müssen."
|
||||||
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.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.server="Server starten (Sendet Szenenwechselnachrichten zu allen verbundenen Clients)"
|
AdvSceneSwitcher.networkTab.server="Server starten (Sendet Szenenwechselnachrichten zu allen verbundenen Clients)"
|
||||||
AdvSceneSwitcher.networkTab.server.port="Port"
|
AdvSceneSwitcher.networkTab.server.port="Port"
|
||||||
@@ -287,35 +822,111 @@ AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="Virtuelle
|
|||||||
AdvSceneSwitcher.sceneTriggerTab.entry="Wenn {{scenes}} {{triggers}} {{actions}} {{audioSources}} nach {{duration}} "
|
AdvSceneSwitcher.sceneTriggerTab.entry="Wenn {{scenes}} {{triggers}} {{actions}} {{audioSources}} nach {{duration}} "
|
||||||
AdvSceneSwitcher.sceneTriggerTab.help="Dieser Tab ermöglicht es automatisiert Handlungen, wie etwa das Stoppen von einer Aufnahme oder des Streamens, bei einem Szenenwechsel auszuführen."
|
AdvSceneSwitcher.sceneTriggerTab.help="Dieser Tab ermöglicht es automatisiert Handlungen, wie etwa das Stoppen von einer Aufnahme oder des Streamens, bei einem Szenenwechsel auszuführen."
|
||||||
|
|
||||||
|
|
||||||
; Hotkey
|
; Hotkey
|
||||||
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Starte den Erweiteren Szenenwechsler"
|
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Starte den Erweiterten Szenenwechsler"
|
||||||
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Stoppe den Erweiteren Szenenwechsler"
|
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Stoppe den Erweiterten Szenenwechsler"
|
||||||
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="Starte/Stoppe den Erweiteren Szenenwechsler"
|
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="Starte/Stoppe den Erweiterten Szenenwechsler"
|
||||||
|
AdvSceneSwitcher.hotkey.macro.pause="Pausiere Makro %1"
|
||||||
|
AdvSceneSwitcher.hotkey.macro.unpause="Makro %1 nicht mehr pausieren"
|
||||||
|
AdvSceneSwitcher.hotkey.macro.togglePause="Pause von Makro %1 togglen"
|
||||||
|
AdvSceneSwitcher.hotkey.upMacroSegmentHotkey="Makro-Segmentauswahl nach oben verschieben"
|
||||||
|
AdvSceneSwitcher.hotkey.downMacroSegmentHotkey="Makro-Segmentauswahl nach unten verschieben"
|
||||||
|
AdvSceneSwitcher.hotkey.removeMacroSegmentHotkey="Ausgewähltes Makro-Segment entfernen"
|
||||||
|
|
||||||
AdvSceneSwitcher.askBackup="Neue Version des Erweiterten Automatischen Szenenwechslers wurde erkannt.\nSoll ein Backup der alten Einstellungen angelegt werden?"
|
AdvSceneSwitcher.askBackup="Neue Version des Erweiterten Automatischen Szenenwechslers wurde erkannt.\nSoll ein Backup der alten Einstellungen angelegt werden?"
|
||||||
|
AdvSceneSwitcher.askForMacro="Makro auswählen {{macroSelection}}"
|
||||||
|
|
||||||
AdvSceneSwitcher.close="Schließen"
|
AdvSceneSwitcher.close="Schließen"
|
||||||
AdvSceneSwitcher.browse="Öffnen"
|
AdvSceneSwitcher.browse="Öffnen"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.item.select="--Element auswählen--"
|
||||||
|
AdvSceneSwitcher.item.add="Neues Element hinzufügen"
|
||||||
|
AdvSceneSwitcher.item.rename="Umbenennen"
|
||||||
|
AdvSceneSwitcher.item.remove="Entfernen"
|
||||||
|
AdvSceneSwitcher.item.properties="Einstellungen"
|
||||||
|
AdvSceneSwitcher.item.newName="Neuer Name:"
|
||||||
|
AdvSceneSwitcher.item.emptyName="Leerer Name nicht zulässig!"
|
||||||
|
AdvSceneSwitcher.item.nameNotAvailable="Name nicht verfügbar!"
|
||||||
|
AdvSceneSwitcher.item.nameReserved="Name reserviert!"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.variable.select="--Variable auswählen--"
|
||||||
|
AdvSceneSwitcher.variable.add="Neue Variable hinzufügen"
|
||||||
|
AdvSceneSwitcher.variable.name="Name:"
|
||||||
|
AdvSceneSwitcher.variable.value="Aktueller Wert:"
|
||||||
|
AdvSceneSwitcher.variable.save="Verhalten speichern / laden"
|
||||||
|
AdvSceneSwitcher.variable.save.dontSave="Variablenwert nicht speichern"
|
||||||
|
AdvSceneSwitcher.variable.save.save="Variablenwert speichern"
|
||||||
|
AdvSceneSwitcher.variable.save.default="Auf Wert setzen"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.connection.select="--Verbindung auswählen--"
|
||||||
|
AdvSceneSwitcher.connection.add="Neue Verbindung hinzufügen"
|
||||||
|
AdvSceneSwitcher.connection.name="Name:"
|
||||||
|
AdvSceneSwitcher.connection.address="Adresse:"
|
||||||
|
AdvSceneSwitcher.connection.port="Port:"
|
||||||
|
AdvSceneSwitcher.connection.password="Passwort:"
|
||||||
|
AdvSceneSwitcher.connection.reconnect="Automatisch neu verbinden:"
|
||||||
|
AdvSceneSwitcher.connection.reconnectDelay="Automatisch neu verbinden nach:"
|
||||||
|
AdvSceneSwitcher.connection.connectOnStart="Beim Start verbinden:"
|
||||||
|
AdvSceneSwitcher.connection.test="Verbindung testen"
|
||||||
|
AdvSceneSwitcher.connection.status.disconnected="Verbindung getrennt"
|
||||||
|
AdvSceneSwitcher.connection.status.connecting="Verbindung wird aufgebaut"
|
||||||
|
AdvSceneSwitcher.connection.status.connected="Verbunden, aber nicht authentifiziert"
|
||||||
|
AdvSceneSwitcher.connection.status.authenticated="Verbunden und authentifiziert"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.regex.enable="Reguläre Ausdrücke aktivieren"
|
||||||
|
AdvSceneSwitcher.regex.partialMatch="Teilweise Übereinstimmung zulassen"
|
||||||
|
AdvSceneSwitcher.regex.caseInsensitive="Groß- und Kleinschreibung wird nicht berücksichtigt"
|
||||||
|
AdvSceneSwitcher.regex.dotMatchNewline=". erkennt Zeilenumbrüche"
|
||||||
|
AdvSceneSwitcher.regex.multiLine="^ und $ erkennen Start/Ende einer Zeile"
|
||||||
|
AdvSceneSwitcher.regex.extendedPattern="Qt's ExtendedPatternSyntax aktivieren"
|
||||||
|
|
||||||
AdvSceneSwitcher.selectScene="--Szene auswählen--"
|
AdvSceneSwitcher.selectScene="--Szene auswählen--"
|
||||||
AdvSceneSwitcher.selectPreviousScene="Vorhergehende Szene"
|
AdvSceneSwitcher.selectPreviousScene="Vorherige Szene"
|
||||||
AdvSceneSwitcher.currentTransition="Aktueller Szenenübergang"
|
AdvSceneSwitcher.selectCurrentScene="Aktuelle Szene"
|
||||||
AdvSceneSwitcher.selectTransition="--Szenenübergang auswählen--"
|
AdvSceneSwitcher.selectPreviewScene="Vorschau-Szene"
|
||||||
|
AdvSceneSwitcher.selectAnyScene="Beliebige Szene"
|
||||||
|
AdvSceneSwitcher.currentTransition="Aktueller Übergang"
|
||||||
|
AdvSceneSwitcher.anyTransition="Beliebiger Übergang"
|
||||||
|
AdvSceneSwitcher.selectTransition="--Übergang auswählen--"
|
||||||
AdvSceneSwitcher.selectWindow="--Fenster auswählen--"
|
AdvSceneSwitcher.selectWindow="--Fenster auswählen--"
|
||||||
AdvSceneSwitcher.selectAudioSource="--Audio Quelle auswählen--"
|
AdvSceneSwitcher.selectSource="--Quelle auswählen--"
|
||||||
AdvSceneSwitcher.selectVideoSource="--Video Quelle auswählen--"
|
AdvSceneSwitcher.selectAudioSource="--Audio-Quelle auswählen--"
|
||||||
AdvSceneSwitcher.selectMediaSource="--Medien Quelle auswählen--"
|
AdvSceneSwitcher.selectVideoSource="--Video-Quelle auswählen--"
|
||||||
|
AdvSceneSwitcher.OBSVideoOutput="OBS's Haupt-Ausgabe"
|
||||||
|
AdvSceneSwitcher.selectMediaSource="--Medien-Quelle auswählen--"
|
||||||
AdvSceneSwitcher.selectProcess="--Prozess auswählen--"
|
AdvSceneSwitcher.selectProcess="--Prozess auswählen--"
|
||||||
|
AdvSceneSwitcher.selectFilter="--Filter auswählen--"
|
||||||
|
AdvSceneSwitcher.selectMacro="--Makro auswählen--"
|
||||||
|
AdvSceneSwitcher.selectItem="--Element auswählen--"
|
||||||
|
AdvSceneSwitcher.selectProfile="--Profil auswählen--"
|
||||||
|
AdvSceneSwitcher.selectSceneCollection="--Szenensammlung auswählen--"
|
||||||
AdvSceneSwitcher.enterPath="--Pfad eingeben--"
|
AdvSceneSwitcher.enterPath="--Pfad eingeben--"
|
||||||
AdvSceneSwitcher.enterText="--Text eingeben--"
|
AdvSceneSwitcher.enterText="--Text eingeben--"
|
||||||
AdvSceneSwitcher.invaildEntriesWillNotBeSaved="Ungültige Einträge werden nicht gespeichert"
|
AdvSceneSwitcher.enterURL="--URL eingebenL--"
|
||||||
AdvSceneSwitcher.selectWindowTip="Benutze \"OBS\" um das OBS-Studio Fenster auszuwählen\nBenutze\"Task Switching\"um die ALT + TAB Tastenkombination auszuwählen"
|
AdvSceneSwitcher.invaildEntriesWillNotBeSaved="ungültige Einträge werden nicht gespeichert"
|
||||||
|
AdvSceneSwitcher.selectWindowTip="Verwende \"OBS\", um das OBS-Fenster zu definieren.\n Verwende \"Task Switching\", um ALT + TAB festzulegen."
|
||||||
|
AdvSceneSwitcher.sceneItemSelection.all="Alle"
|
||||||
|
AdvSceneSwitcher.sceneItemSelection.any="Beliebige"
|
||||||
|
|
||||||
AdvSceneSwitcher.status.active="Aktiv"
|
AdvSceneSwitcher.status.active="Aktiv"
|
||||||
AdvSceneSwitcher.status.inactive="Inaktiv"
|
AdvSceneSwitcher.status.inactive="Inaktiv"
|
||||||
|
AdvSceneSwitcher.running="Plugin läuft"
|
||||||
|
AdvSceneSwitcher.stopped="Plugin gestoppt"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Dies scheint das erste Mal zu sein, dass der Erweiterte Szenenwechsler gestartet wurde.<br>Bitte schaue ins <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> für eine Liste von Anleitungen und Beispielen.<br>Nicht zögern und Fragen im <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">Thread</span></a> des Plugins im OBS-Forum stellen!!</p></body></html>"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.deprecatedTabWarning="Die Entwicklung für dieses Tab wurde gestoppt!\nBitte stattdessen zur Verwendung des Makros-Tab übergehen.\nDieser Hinweis kann im Allgemein-Tab deaktiviert werden."
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="Millisekunden"
|
AdvSceneSwitcher.unit.milliseconds="Millisekunden"
|
||||||
AdvSceneSwitcher.unit.secends="Sekunden"
|
AdvSceneSwitcher.unit.secends="Sekunden"
|
||||||
AdvSceneSwitcher.unit.minutes="Minuten"
|
AdvSceneSwitcher.unit.minutes="Minuten"
|
||||||
AdvSceneSwitcher.unit.hours="Stunden"
|
AdvSceneSwitcher.unit.hours="Stunden"
|
||||||
|
AdvSceneSwitcher.duration.condition.none="Kein Dauer-Modifikator"
|
||||||
|
AdvSceneSwitcher.duration.condition.more="Mindestens für"
|
||||||
|
AdvSceneSwitcher.duration.condition.equal="Für genau"
|
||||||
|
AdvSceneSwitcher.duration.condition.less="Höchstens für"
|
||||||
|
AdvSceneSwitcher.duration.condition.within="In den letzten"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.audio.monitor.none="Monitoring aus"
|
||||||
|
AdvSceneSwitcher.audio.monitor.monitorOnly="Nur Monitoring (Ausgabe stummschalten)"
|
||||||
|
AdvSceneSwitcher.audio.monitor.both="Monitoring und Ausgabe"
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ AdvSceneSwitcher.generalTab.status.autoStart.never="Never"
|
|||||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="Recording"
|
AdvSceneSwitcher.generalTab.status.autoStart.recording="Recording"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Streaming"
|
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Streaming"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Recording or Streaming"
|
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Recording or Streaming"
|
||||||
AdvSceneSwitcher.generalTab.status.checkInterval="Check switch conditions every"
|
AdvSceneSwitcher.generalTab.status.checkInterval="Check conditions every"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior="General behavior"
|
AdvSceneSwitcher.generalTab.generalBehavior="General behavior"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="If no actions are performed for"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="If no actions are performed for"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Will only ever be as accurate as the configured check interval."
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Will only ever be as accurate as the configured check interval."
|
||||||
@@ -30,6 +30,8 @@ AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Enable verbose loggi
|
|||||||
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Save window position and size"
|
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Save window position and size"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Show system tray notifications"
|
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Show system tray notifications"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Disable UI hints"
|
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Disable UI hints"
|
||||||
|
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailure="Display warning if plugins cannot be loaded"
|
||||||
|
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage="<html><body>Loading of the following plugin libraries was unsuccessful, which could result in some Advanced Scene Switcher functions not being available:%1Check the OBS logs for details.<br>This message can be disabled on the General tab.</body></html>"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="Hide tabs which can be represented via macros"
|
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="Hide tabs which can be represented via macros"
|
||||||
AdvSceneSwitcher.generalTab.matchBehavior="Match behavior"
|
AdvSceneSwitcher.generalTab.matchBehavior="Match behavior"
|
||||||
AdvSceneSwitcher.generalTab.priority="Priority"
|
AdvSceneSwitcher.generalTab.priority="Priority"
|
||||||
@@ -82,20 +84,36 @@ AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
|||||||
AdvSceneSwitcher.macroTab.defaultGroupName="Group %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="Group %1"
|
||||||
AdvSceneSwitcher.macroTab.exists="Macro name exists already"
|
AdvSceneSwitcher.macroTab.exists="Macro name exists already"
|
||||||
AdvSceneSwitcher.macroTab.groupDeleteConfirm="Are you sure you want to delete \"%1\" and all its elements?"
|
AdvSceneSwitcher.macroTab.groupDeleteConfirm="Are you sure you want to delete \"%1\" and all its elements?"
|
||||||
AdvSceneSwitcher.macroTab.copy="Create copy of current macro"
|
AdvSceneSwitcher.macroTab.deleteMultipleMacrosConfirmation="Are you sure you want to delete %1 macros?"
|
||||||
AdvSceneSwitcher.macroTab.group="Group selected items"
|
AdvSceneSwitcher.macroTab.deleteSingleMacroConfirmation="Are you sure you want to delete \"%1\"?"
|
||||||
AdvSceneSwitcher.macroTab.ungroup="Ungroup selected groups"
|
AdvSceneSwitcher.macroTab.contextMenuAdd="Add"
|
||||||
|
AdvSceneSwitcher.macroTab.copy="Duplicate Macro"
|
||||||
|
AdvSceneSwitcher.macroTab.group="Group Selected Macros"
|
||||||
|
AdvSceneSwitcher.macroTab.ungroup="Ungroup Selected Groups"
|
||||||
|
AdvSceneSwitcher.macroTab.rename="Rename"
|
||||||
|
AdvSceneSwitcher.macroTab.remove="Remove"
|
||||||
AdvSceneSwitcher.macroTab.expandAll="Expand all"
|
AdvSceneSwitcher.macroTab.expandAll="Expand all"
|
||||||
AdvSceneSwitcher.macroTab.collapseAll="Collapse all"
|
AdvSceneSwitcher.macroTab.collapseAll="Collapse all"
|
||||||
AdvSceneSwitcher.macroTab.maximize="Maximize"
|
AdvSceneSwitcher.macroTab.maximize="Maximize"
|
||||||
AdvSceneSwitcher.macroTab.minimize="Minimize"
|
AdvSceneSwitcher.macroTab.minimize="Minimize"
|
||||||
AdvSceneSwitcher.macroTab.highlightSettings="Visual settings"
|
AdvSceneSwitcher.macroTab.highlightSettings="Visual settings"
|
||||||
AdvSceneSwitcher.macroTab.hotkeySettings="Hotkey settings"
|
AdvSceneSwitcher.macroTab.hotkeySettings="Hotkey settings"
|
||||||
|
AdvSceneSwitcher.macroTab.dockSettings="Dock settings"
|
||||||
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Highlight recently executed macros"
|
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Highlight recently executed macros"
|
||||||
AdvSceneSwitcher.macroTab.highlightTrueConditions="Highlight conditions of currently selected macro that evaluated to true recently"
|
AdvSceneSwitcher.macroTab.highlightTrueConditions="Highlight conditions of currently selected macro that evaluated to true recently"
|
||||||
AdvSceneSwitcher.macroTab.highlightPerformedActions="Highlight recently performed actions of currently selected macro"
|
AdvSceneSwitcher.macroTab.highlightPerformedActions="Highlight recently performed actions of currently selected macro"
|
||||||
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Register hotkeys to control the pause state of new macros"
|
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Register hotkeys to control the pause state of new macros"
|
||||||
AdvSceneSwitcher.macroTab.currentDisableHotkeys="Register hotkeys to control the pause state of selected macro"
|
AdvSceneSwitcher.macroTab.currentDisableHotkeys="Register hotkeys to control the pause state of selected macro"
|
||||||
|
AdvSceneSwitcher.macroTab.currentRegisterDock="Register dock widget to control the pause state of selected macro or run it manually"
|
||||||
|
AdvSceneSwitcher.macroTab.currentDockAddRunButton="Add button to run the macro"
|
||||||
|
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="Add button to pause or unpause the macro"
|
||||||
|
AdvSceneSwitcher.macroTab.currentDockButtonText.run="Run button text:"
|
||||||
|
AdvSceneSwitcher.macroTab.currentDockButtonText.pause="Pause button text:"
|
||||||
|
AdvSceneSwitcher.macroTab.currentDockButtonText.unpause="Unpause button text:"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.macroDock.pause="Pause"
|
||||||
|
AdvSceneSwitcher.macroDock.unpause="Unpause"
|
||||||
|
AdvSceneSwitcher.macroDock.run="Run"
|
||||||
|
|
||||||
; Macro List
|
; Macro List
|
||||||
AdvSceneSwitcher.macroList.deleted="deleted"
|
AdvSceneSwitcher.macroList.deleted="deleted"
|
||||||
@@ -146,9 +164,14 @@ AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="During transi
|
|||||||
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
||||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
||||||
AdvSceneSwitcher.condition.window="Window"
|
AdvSceneSwitcher.condition.window="Window"
|
||||||
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} exist and ..."
|
AdvSceneSwitcher.condition.window.entry.window="{{checkTitle}}Window title matches{{windowRegex}}{{windows}}"
|
||||||
AdvSceneSwitcher.condition.window.entry.line2="... is {{fullscreen}} fullscreen {{maximized}} maximized {{focused}} focused {{windowFocusChanged}} foreground window changed"
|
AdvSceneSwitcher.condition.window.entry.fullscreen="{{fullscreen}}Window is fullscreen"
|
||||||
AdvSceneSwitcher.condition.window.entry.line3="Current foreground window: {{focusWindow}}"
|
AdvSceneSwitcher.condition.window.entry.maximized="{{maximized}}Window is maximized"
|
||||||
|
AdvSceneSwitcher.condition.window.entry.focused="{{focused}}Window is focused"
|
||||||
|
AdvSceneSwitcher.condition.window.entry.focusedChange="{{windowFocusChanged}}Focus window changed"
|
||||||
|
AdvSceneSwitcher.condition.window.entry.text="{{checkText}}Window contains text{{textRegex}}{{windowText}}"
|
||||||
|
AdvSceneSwitcher.condition.window.entry.text.note="This option might not work on every text being displayed in a window.\nIf that is the case, you can consider using the Video conditions OCR check instead."
|
||||||
|
AdvSceneSwitcher.condition.window.entry.currentFocus="Current focus window:{{focusWindow}}"
|
||||||
AdvSceneSwitcher.condition.file="File"
|
AdvSceneSwitcher.condition.file="File"
|
||||||
AdvSceneSwitcher.condition.file.type.match="matches"
|
AdvSceneSwitcher.condition.file.type.match="matches"
|
||||||
AdvSceneSwitcher.condition.file.type.contentChange="content changed"
|
AdvSceneSwitcher.condition.file.type.contentChange="content changed"
|
||||||
@@ -174,6 +197,7 @@ AdvSceneSwitcher.condition.video.condition.noImage="has no output"
|
|||||||
AdvSceneSwitcher.condition.video.condition.pattern="matches pattern"
|
AdvSceneSwitcher.condition.video.condition.pattern="matches pattern"
|
||||||
AdvSceneSwitcher.condition.video.condition.object="contains object"
|
AdvSceneSwitcher.condition.video.condition.object="contains object"
|
||||||
AdvSceneSwitcher.condition.video.condition.brightness="brightness"
|
AdvSceneSwitcher.condition.video.condition.brightness="brightness"
|
||||||
|
AdvSceneSwitcher.condition.video.condition.ocr="contains text"
|
||||||
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="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.file="Use existing file"
|
||||||
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Create screenshot"
|
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Create screenshot"
|
||||||
@@ -184,6 +208,11 @@ AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip="This will al
|
|||||||
AdvSceneSwitcher.condition.video.patternThreshold="Threshold: "
|
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.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.patternThresholdUseAlphaAsMask="Use alpha channel as mask for pattern."
|
||||||
|
AdvSceneSwitcher.condition.video.patternMatchMode="Use pattern matching mode {{patternMatchingModes}}"
|
||||||
|
AdvSceneSwitcher.condition.video.patternMatchMode.crossCorrelation="Cross correlation"
|
||||||
|
AdvSceneSwitcher.condition.video.patternMatchMode.correlationCoefficient="Correlation coefficient"
|
||||||
|
AdvSceneSwitcher.condition.video.patternMatchMode.squaredDifference="Squared difference"
|
||||||
|
AdvSceneSwitcher.condition.video.patternMatchMode.tip="The best method to use depends on the specific problem and the characteristics of the images involved.\nIn practice, it's often necessary to experiment with different methods and parameters to find the best match for a particular use case."
|
||||||
AdvSceneSwitcher.condition.video.brightnessThreshold="Average brightness is above:"
|
AdvSceneSwitcher.condition.video.brightnessThreshold="Average brightness is above:"
|
||||||
AdvSceneSwitcher.condition.video.brightnessThresholdDescription="A high value is indicating a bright image and a low one a darker one."
|
AdvSceneSwitcher.condition.video.brightnessThresholdDescription="A high value is indicating a bright image and a low one a darker one."
|
||||||
AdvSceneSwitcher.condition.video.currentBrightness="Current average brightness: %1"
|
AdvSceneSwitcher.condition.video.currentBrightness="Current average brightness: %1"
|
||||||
@@ -198,7 +227,18 @@ AdvSceneSwitcher.condition.video.patternMatchFail="Pattern was not found!"
|
|||||||
AdvSceneSwitcher.condition.video.patternMatchSuccess="Pattern is highlighted in red"
|
AdvSceneSwitcher.condition.video.patternMatchSuccess="Pattern is highlighted in red"
|
||||||
AdvSceneSwitcher.condition.video.objectMatchFail="Object was not found!"
|
AdvSceneSwitcher.condition.video.objectMatchFail="Object was not found!"
|
||||||
AdvSceneSwitcher.condition.video.objectMatchSuccess="Object is highlighted in red"
|
AdvSceneSwitcher.condition.video.objectMatchSuccess="Object is highlighted in red"
|
||||||
|
AdvSceneSwitcher.condition.video.ocrMatchSuccess="Detected text:\n\n%1"
|
||||||
AdvSceneSwitcher.condition.video.modelLoadFail="Model data could not be loaded!"
|
AdvSceneSwitcher.condition.video.modelLoadFail="Model data could not be loaded!"
|
||||||
|
AdvSceneSwitcher.condition.video.selectColor="Select Color"
|
||||||
|
AdvSceneSwitcher.condition.video.ocrMode.singleColumn="Single column of text of variable sizes"
|
||||||
|
AdvSceneSwitcher.condition.video.ocrMode.singleBlockVertText="Single uniform block of vertically aligned text"
|
||||||
|
AdvSceneSwitcher.condition.video.ocrMode.singleBlock="Single uniform block of text"
|
||||||
|
AdvSceneSwitcher.condition.video.ocrMode.singleLine="Single text line"
|
||||||
|
AdvSceneSwitcher.condition.video.ocrMode.singleWord="Single word"
|
||||||
|
AdvSceneSwitcher.condition.video.ocrMode.circleWord="Single word in a circle"
|
||||||
|
AdvSceneSwitcher.condition.video.ocrMode.singleChar="Single character"
|
||||||
|
AdvSceneSwitcher.condition.video.ocrMode.sparseText="Find text in no particular order"
|
||||||
|
AdvSceneSwitcher.condition.video.ocrMode.sparseTextOSD="Find text in no particular order (OSD)"
|
||||||
AdvSceneSwitcher.condition.video.type.main="OBS's main output"
|
AdvSceneSwitcher.condition.video.type.main="OBS's main output"
|
||||||
AdvSceneSwitcher.condition.video.type.source="Source"
|
AdvSceneSwitcher.condition.video.type.source="Source"
|
||||||
AdvSceneSwitcher.condition.video.type.scene="Scene"
|
AdvSceneSwitcher.condition.video.type.scene="Scene"
|
||||||
@@ -208,6 +248,8 @@ AdvSceneSwitcher.condition.video.entry.minNeighbor="Minimum neighbors: {{minNeig
|
|||||||
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}Reduce CPU load by performing check only every {{throttleCount}} milliseconds"
|
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}Reduce CPU load by performing check only every {{throttleCount}} milliseconds"
|
||||||
AdvSceneSwitcher.condition.video.entry.checkAreaEnable="Perform check only in area"
|
AdvSceneSwitcher.condition.video.entry.checkAreaEnable="Perform check only in area"
|
||||||
AdvSceneSwitcher.condition.video.entry.checkArea="{{checkAreaEnable}}{{checkArea}}{{selectArea}}"
|
AdvSceneSwitcher.condition.video.entry.checkArea="{{checkAreaEnable}}{{checkArea}}{{selectArea}}"
|
||||||
|
AdvSceneSwitcher.condition.video.entry.orcColorPick="Check for text color:{{textColor}}{{selectColor}}"
|
||||||
|
AdvSceneSwitcher.condition.video.entry.orcTextType="Check for text type:{{textType}}"
|
||||||
AdvSceneSwitcher.condition.video.minSize="Minimum size:"
|
AdvSceneSwitcher.condition.video.minSize="Minimum size:"
|
||||||
AdvSceneSwitcher.condition.video.maxSize="Maximum size:"
|
AdvSceneSwitcher.condition.video.maxSize="Maximum size:"
|
||||||
AdvSceneSwitcher.condition.video.selectArea="Select area"
|
AdvSceneSwitcher.condition.video.selectArea="Select area"
|
||||||
@@ -219,7 +261,8 @@ AdvSceneSwitcher.condition.stream.state.start="Stream running"
|
|||||||
AdvSceneSwitcher.condition.stream.state.stop="Stream stopped"
|
AdvSceneSwitcher.condition.stream.state.stop="Stream stopped"
|
||||||
AdvSceneSwitcher.condition.stream.state.starting="Stream starting"
|
AdvSceneSwitcher.condition.stream.state.starting="Stream starting"
|
||||||
AdvSceneSwitcher.condition.stream.state.stopping="Stream stopping"
|
AdvSceneSwitcher.condition.stream.state.stopping="Stream stopping"
|
||||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
|
AdvSceneSwitcher.condition.stream.state.keyFrameInterval="Keyframe interval equals"
|
||||||
|
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
|
||||||
AdvSceneSwitcher.condition.record="Recording"
|
AdvSceneSwitcher.condition.record="Recording"
|
||||||
AdvSceneSwitcher.condition.record.state.start="Recording running"
|
AdvSceneSwitcher.condition.record.state.start="Recording running"
|
||||||
AdvSceneSwitcher.condition.record.state.pause="Recording paused"
|
AdvSceneSwitcher.condition.record.state.pause="Recording paused"
|
||||||
@@ -284,7 +327,7 @@ AdvSceneSwitcher.condition.filter.type.settings="Settings match"
|
|||||||
AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
|
AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
|
||||||
AdvSceneSwitcher.condition.filter.entry.line1="On {{sources}} {{filters}} {{conditions}}"
|
AdvSceneSwitcher.condition.filter.entry.line1="On {{sources}} {{filters}} {{conditions}}"
|
||||||
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
||||||
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
|
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}}{{getSettings}}"
|
||||||
AdvSceneSwitcher.condition.sceneOrder="Scene item order"
|
AdvSceneSwitcher.condition.sceneOrder="Scene item order"
|
||||||
AdvSceneSwitcher.condition.sceneOrder.type.above="Is above"
|
AdvSceneSwitcher.condition.sceneOrder.type.above="Is above"
|
||||||
AdvSceneSwitcher.condition.sceneOrder.type.below="Is below"
|
AdvSceneSwitcher.condition.sceneOrder.type.below="Is below"
|
||||||
@@ -393,6 +436,16 @@ AdvSceneSwitcher.condition.variable.type.equalsVariable="equals variable"
|
|||||||
AdvSceneSwitcher.condition.variable.type.lessThanVariable="is less than variable"
|
AdvSceneSwitcher.condition.variable.type.lessThanVariable="is less than variable"
|
||||||
AdvSceneSwitcher.condition.variable.type.greaterThanVariable="is greater than variable"
|
AdvSceneSwitcher.condition.variable.type.greaterThanVariable="is greater than variable"
|
||||||
AdvSceneSwitcher.condition.variable.entry="{{variables}}{{conditions}}{{strValue}}{{numValue}}{{variables2}}"
|
AdvSceneSwitcher.condition.variable.entry="{{variables}}{{conditions}}{{strValue}}{{numValue}}{{variables2}}"
|
||||||
|
AdvSceneSwitcher.condition.run="Run"
|
||||||
|
AdvSceneSwitcher.condition.run.entry="Process exits before timeout of{{timeout}} seconds"
|
||||||
|
AdvSceneSwitcher.condition.run.entry.exit="{{checkExitCode}}Check for exit code{{exitCode}}"
|
||||||
|
AdvSceneSwitcher.condition.midi="MIDI"
|
||||||
|
AdvSceneSwitcher.condition.midi.entry="Mesasge was received from {{device}} which matches:"
|
||||||
|
AdvSceneSwitcher.condition.midi.entry.listen="Set MIDI message selection to messages incoming on selected device: {{listenButton}}"
|
||||||
|
AdvSceneSwitcher.condition.display="Display"
|
||||||
|
AdvSceneSwitcher.condition.display.type.displayName="Name of connected displays matches"
|
||||||
|
AdvSceneSwitcher.condition.display.type.displayCount="Number of connected displays is"
|
||||||
|
AdvSceneSwitcher.condition.display.entry="{{conditions}}{{displays}}{{regex}}{{displayCount}}"
|
||||||
|
|
||||||
; Macro Actions
|
; Macro Actions
|
||||||
AdvSceneSwitcher.action.switchScene="Switch scene"
|
AdvSceneSwitcher.action.switchScene="Switch scene"
|
||||||
@@ -426,9 +479,11 @@ AdvSceneSwitcher.action.recording.type.start="Start recording"
|
|||||||
AdvSceneSwitcher.action.recording.type.pause="Pause recording"
|
AdvSceneSwitcher.action.recording.type.pause="Pause recording"
|
||||||
AdvSceneSwitcher.action.recording.type.unpause="Unpause recording"
|
AdvSceneSwitcher.action.recording.type.unpause="Unpause recording"
|
||||||
AdvSceneSwitcher.action.recording.type.split="Split recording file"
|
AdvSceneSwitcher.action.recording.type.split="Split recording file"
|
||||||
|
AdvSceneSwitcher.action.recording.type.changeOutputFolder="Change output folder"
|
||||||
|
AdvSceneSwitcher.action.recording.type.changeOutputFileFormat="Change filename formatting"
|
||||||
AdvSceneSwitcher.action.recording.pause.hint="Note that depending on your recording settings you might not be able to pause recording"
|
AdvSceneSwitcher.action.recording.pause.hint="Note that depending on your recording settings you might not be able to pause recording"
|
||||||
AdvSceneSwitcher.action.recording.split.hint="Make sure to enable automatic file splitting in the OBS settings first!"
|
AdvSceneSwitcher.action.recording.split.hint="Make sure to enable automatic file splitting in the OBS settings first!"
|
||||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
|
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
AdvSceneSwitcher.action.replay="Replay buffer"
|
AdvSceneSwitcher.action.replay="Replay buffer"
|
||||||
AdvSceneSwitcher.action.replay.saveWarn="Warning: Saving too frequently might result in the replay buffer not actually being saved!"
|
AdvSceneSwitcher.action.replay.saveWarn="Warning: Saving too frequently might result in the replay buffer not actually being saved!"
|
||||||
AdvSceneSwitcher.action.replay.type.stop="Stop replay buffer"
|
AdvSceneSwitcher.action.replay.type.stop="Stop replay buffer"
|
||||||
@@ -438,13 +493,9 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
|||||||
AdvSceneSwitcher.action.streaming="Streaming"
|
AdvSceneSwitcher.action.streaming="Streaming"
|
||||||
AdvSceneSwitcher.action.streaming.type.stop="Stop streaming"
|
AdvSceneSwitcher.action.streaming.type.stop="Stop streaming"
|
||||||
AdvSceneSwitcher.action.streaming.type.start="Start streaming"
|
AdvSceneSwitcher.action.streaming.type.start="Start streaming"
|
||||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
AdvSceneSwitcher.action.streaming.type.keyFrameInterval="Set keyframe interval"
|
||||||
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||||
AdvSceneSwitcher.action.run="Run"
|
AdvSceneSwitcher.action.run="Run"
|
||||||
AdvSceneSwitcher.action.run.arguments="Arguments:"
|
|
||||||
AdvSceneSwitcher.action.run.addArgument="Add argument"
|
|
||||||
AdvSceneSwitcher.action.run.addArgumentDescription="Add new argument:"
|
|
||||||
AdvSceneSwitcher.action.run.entry="Run {{filePath}}"
|
|
||||||
AdvSceneSwitcher.action.run.entry.workingDirectory="Working directory:{{workingDirectory}}"
|
|
||||||
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
|
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
|
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
|
AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
|
||||||
@@ -490,6 +541,8 @@ AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher
|
|||||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:"
|
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:"
|
||||||
AdvSceneSwitcher.action.pluginState.type.import="Import settings from"
|
AdvSceneSwitcher.action.pluginState.type.import="Import settings from"
|
||||||
AdvSceneSwitcher.action.pluginState.importWarning="Note: Action will be ignored while settings window is opened."
|
AdvSceneSwitcher.action.pluginState.importWarning="Note: Action will be ignored while settings window is opened."
|
||||||
|
AdvSceneSwitcher.action.pluginState.type.terminate="Shut down OBS"
|
||||||
|
AdvSceneSwitcher.action.pluginState.terminateConfirm="OBS will be shut down automatically in 10 seconds!\nDo you want to continue shutting down OBS?"
|
||||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
|
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
|
||||||
AdvSceneSwitcher.action.virtualCamera="Virtual camera"
|
AdvSceneSwitcher.action.virtualCamera="Virtual camera"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.stop="Stop virtual camera"
|
AdvSceneSwitcher.action.virtualCamera.type.stop="Stop virtual camera"
|
||||||
@@ -506,7 +559,7 @@ AdvSceneSwitcher.action.hotkey.leftMeta="Left Meta"
|
|||||||
AdvSceneSwitcher.action.hotkey.rightMeta="Right Meta"
|
AdvSceneSwitcher.action.hotkey.rightMeta="Right Meta"
|
||||||
AdvSceneSwitcher.action.hotkey.onlyOBS="Send keypress only to OBS"
|
AdvSceneSwitcher.action.hotkey.onlyOBS="Send keypress only to OBS"
|
||||||
AdvSceneSwitcher.action.hotkey.disabled="Cannot simulate global key presses - functionality limited to sending key press to OBS!"
|
AdvSceneSwitcher.action.hotkey.disabled="Cannot simulate global key presses - functionality limited to sending key press to OBS!"
|
||||||
AdvSceneSwitcher.action.hotkey.entry="Press {{keys}} for {{duration}} milliseconds"
|
AdvSceneSwitcher.action.hotkey.entry="Press {{keys}} for {{duration}}"
|
||||||
AdvSceneSwitcher.action.sceneOrder="Scene item order"
|
AdvSceneSwitcher.action.sceneOrder="Scene item order"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Move up"
|
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Move up"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Move down"
|
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Move down"
|
||||||
@@ -545,7 +598,10 @@ AdvSceneSwitcher.action.random="Random"
|
|||||||
AdvSceneSwitcher.action.random.allowRepeat="Allow consecutive execution of the same macro"
|
AdvSceneSwitcher.action.random.allowRepeat="Allow consecutive execution of the same macro"
|
||||||
AdvSceneSwitcher.action.random.entry="Randomly run any of the following macros (paused macros are ignored)"
|
AdvSceneSwitcher.action.random.entry="Randomly run any of the following macros (paused macros are ignored)"
|
||||||
AdvSceneSwitcher.action.systray="System tray notification"
|
AdvSceneSwitcher.action.systray="System tray notification"
|
||||||
AdvSceneSwitcher.action.systray.entry="Show notification: {{message}}"
|
AdvSceneSwitcher.action.systray.title="Title:"
|
||||||
|
AdvSceneSwitcher.action.systray.message="Message:"
|
||||||
|
AdvSceneSwitcher.action.systray.icon="Icon:"
|
||||||
|
AdvSceneSwitcher.action.systray.iconHint="Leave blank to use the default icon"
|
||||||
AdvSceneSwitcher.action.screenshot="Screenshot"
|
AdvSceneSwitcher.action.screenshot="Screenshot"
|
||||||
AdvSceneSwitcher.action.screenshot.save.default="Default"
|
AdvSceneSwitcher.action.screenshot.save.default="Default"
|
||||||
AdvSceneSwitcher.action.screenshot.save.custom="Custom"
|
AdvSceneSwitcher.action.screenshot.save.custom="Custom"
|
||||||
@@ -571,6 +627,9 @@ AdvSceneSwitcher.action.websocket.type.event="Event"
|
|||||||
AdvSceneSwitcher.action.websocket.entry.request="Send scene switcher {{type}} via {{connection}}"
|
AdvSceneSwitcher.action.websocket.entry.request="Send scene switcher {{type}} via {{connection}}"
|
||||||
AdvSceneSwitcher.action.websocket.entry.event="Send scene switcher {{type}} to connected clients"
|
AdvSceneSwitcher.action.websocket.entry.event="Send scene switcher {{type}} to connected clients"
|
||||||
AdvSceneSwitcher.action.http="Http"
|
AdvSceneSwitcher.action.http="Http"
|
||||||
|
AdvSceneSwitcher.action.http.setHeaders="Set headers"
|
||||||
|
AdvSceneSwitcher.action.http.headers="Headers:"
|
||||||
|
AdvSceneSwitcher.action.http.addHeader="Add header"
|
||||||
AdvSceneSwitcher.action.http.type.get="GET"
|
AdvSceneSwitcher.action.http.type.get="GET"
|
||||||
AdvSceneSwitcher.action.http.type.post="POST"
|
AdvSceneSwitcher.action.http.type.post="POST"
|
||||||
AdvSceneSwitcher.action.http.entry.line1="Send {{method}} to {{url}}"
|
AdvSceneSwitcher.action.http.entry.line1="Send {{method}} to {{url}}"
|
||||||
@@ -583,12 +642,38 @@ AdvSceneSwitcher.action.variable.type.increment="Increment"
|
|||||||
AdvSceneSwitcher.action.variable.type.decrement="Decrement"
|
AdvSceneSwitcher.action.variable.type.decrement="Decrement"
|
||||||
AdvSceneSwitcher.action.variable.type.setActionValue="Set to action value"
|
AdvSceneSwitcher.action.variable.type.setActionValue="Set to action value"
|
||||||
AdvSceneSwitcher.action.variable.type.setConditionValue="Set to condition value"
|
AdvSceneSwitcher.action.variable.type.setConditionValue="Set to condition value"
|
||||||
|
AdvSceneSwitcher.action.variable.type.roundToInt="Round to nearest integer"
|
||||||
|
AdvSceneSwitcher.action.variable.type.subString="Set to substring of current value"
|
||||||
|
AdvSceneSwitcher.action.variable.type.findAndReplace="Find and replace in current value"
|
||||||
|
AdvSceneSwitcher.action.variable.type.mathExpression="Mathematical expression"
|
||||||
|
AdvSceneSwitcher.action.variable.mathExpression.example="( 1 + 2 * 3 ) / 4"
|
||||||
|
AdvSceneSwitcher.action.variable.findAndReplace.find="Text to find"
|
||||||
|
AdvSceneSwitcher.action.variable.findAndReplace.replace="Text to replace with"
|
||||||
|
AdvSceneSwitcher.action.variable.subString.begin="Beginning"
|
||||||
|
AdvSceneSwitcher.action.variable.subString.all="All"
|
||||||
AdvSceneSwitcher.action.variable.invalidSelection="Invalid selection!"
|
AdvSceneSwitcher.action.variable.invalidSelection="Invalid selection!"
|
||||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Getting variable values from %1 actions is not supported!"
|
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Getting variable values from %1 actions is not supported!"
|
||||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Getting variable values from %1 conditions is not supported!"
|
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Getting variable values from %1 conditions is not supported!"
|
||||||
AdvSceneSwitcher.action.variable.currentSegmentValue="Current value:"
|
AdvSceneSwitcher.action.variable.currentSegmentValue="Current value:"
|
||||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}"
|
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}"
|
||||||
|
AdvSceneSwitcher.action.variable.entry.substringIndex="Substring start:{{subStringStart}} Substring size:{{subStringSize}}"
|
||||||
|
AdvSceneSwitcher.action.variable.entry.substringRegex="Assign value of{{regexMatchIdx}}match using regular expression:"
|
||||||
|
AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{replaceStr}}"
|
||||||
|
AdvSceneSwitcher.action.projector="Projector"
|
||||||
|
AdvSceneSwitcher.action.projector.type.source="Source"
|
||||||
|
AdvSceneSwitcher.action.projector.type.scene="Scene"
|
||||||
|
AdvSceneSwitcher.action.projector.type.preview="Preview"
|
||||||
|
AdvSceneSwitcher.action.projector.type.program="Program"
|
||||||
|
AdvSceneSwitcher.action.projector.type.multiview="Multiview"
|
||||||
|
AdvSceneSwitcher.action.projector.display="Display"
|
||||||
|
AdvSceneSwitcher.action.projector.windowed="Windowed"
|
||||||
|
AdvSceneSwitcher.action.projector.fullscreen="Fullscreen"
|
||||||
|
AdvSceneSwitcher.action.projector.entry="Open{{windowTypes}}projector of{{types}}{{scenes}}{{sources}}"
|
||||||
|
AdvSceneSwitcher.action.projector.entry.monitor="on{{monitors}}"
|
||||||
|
AdvSceneSwitcher.action.midi="MIDI"
|
||||||
|
AdvSceneSwitcher.action.midi.entry="Send message to {{device}}:"
|
||||||
|
AdvSceneSwitcher.action.midi.entry.listen="Set MIDI message selection to messages incoming on {{listenDevices}}: {{listenButton}}"
|
||||||
|
AdvSceneSwitcher.action.osc="Open Sound Control"
|
||||||
|
|
||||||
; Transition Tab
|
; Transition Tab
|
||||||
AdvSceneSwitcher.transitionTab.title="Transition"
|
AdvSceneSwitcher.transitionTab.title="Transition"
|
||||||
@@ -868,6 +953,7 @@ AdvSceneSwitcher.connection.password="Password:"
|
|||||||
AdvSceneSwitcher.connection.reconnect="Reconnect automatically:"
|
AdvSceneSwitcher.connection.reconnect="Reconnect automatically:"
|
||||||
AdvSceneSwitcher.connection.reconnectDelay="Automatically reconnect after:"
|
AdvSceneSwitcher.connection.reconnectDelay="Automatically reconnect after:"
|
||||||
AdvSceneSwitcher.connection.connectOnStart="Connect on startup:"
|
AdvSceneSwitcher.connection.connectOnStart="Connect on startup:"
|
||||||
|
AdvSceneSwitcher.connection.useOBSWebsocketProtocol="<html><head/><body><p>Use the obs-websocket <a href=\"https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md\"><span style=\" text-decoration: underline; color:#268bd2;\">protocol</span></a></p></body></html>"
|
||||||
AdvSceneSwitcher.connection.test="Test connection"
|
AdvSceneSwitcher.connection.test="Test connection"
|
||||||
AdvSceneSwitcher.connection.status.disconnected="Disconnected"
|
AdvSceneSwitcher.connection.status.disconnected="Disconnected"
|
||||||
AdvSceneSwitcher.connection.status.connecting="Connecting"
|
AdvSceneSwitcher.connection.status.connecting="Connecting"
|
||||||
@@ -881,6 +967,68 @@ AdvSceneSwitcher.regex.dotMatchNewline=". matches newlines"
|
|||||||
AdvSceneSwitcher.regex.multiLine="^ and $ match start/end of line"
|
AdvSceneSwitcher.regex.multiLine="^ and $ match start/end of line"
|
||||||
AdvSceneSwitcher.regex.extendedPattern="Enable Qt's ExtendedPatternSyntax"
|
AdvSceneSwitcher.regex.extendedPattern="Enable Qt's ExtendedPatternSyntax"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.process.showAdvanced="Show advanced settings"
|
||||||
|
AdvSceneSwitcher.process.arguments="Arguments:"
|
||||||
|
AdvSceneSwitcher.process.addArgument="Add argument"
|
||||||
|
AdvSceneSwitcher.process.addArgumentDescription="Add new argument:"
|
||||||
|
AdvSceneSwitcher.process.entry="Run{{filePath}}{{advancedSettings}}"
|
||||||
|
AdvSceneSwitcher.process.entry.workingDirectory="Working directory:{{workingDirectory}}"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.math.expressionFail="Failed evaluate expression"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.midi.deviceNamePattern="[Port #%1] %2"
|
||||||
|
AdvSceneSwitcher.midi.message.type="Type:"
|
||||||
|
AdvSceneSwitcher.midi.message.type.optional="Any"
|
||||||
|
AdvSceneSwitcher.midi.message.type.invalid="Invalid"
|
||||||
|
AdvSceneSwitcher.midi.message.type.noteOff="Note Off"
|
||||||
|
AdvSceneSwitcher.midi.message.type.noteOn="Note On"
|
||||||
|
AdvSceneSwitcher.midi.message.type.polyphonicPressure="Polyphonic Pressure"
|
||||||
|
AdvSceneSwitcher.midi.message.type.controlChange="Control Change"
|
||||||
|
AdvSceneSwitcher.midi.message.type.programChange="Program Change"
|
||||||
|
AdvSceneSwitcher.midi.message.type.channelAftertouch="Channel Aftertouch"
|
||||||
|
AdvSceneSwitcher.midi.message.type.pitchBend="Pitch Bend"
|
||||||
|
AdvSceneSwitcher.midi.message.type.systemExclusive="System Exclusive"
|
||||||
|
AdvSceneSwitcher.midi.message.type.timeCode="Time Code"
|
||||||
|
AdvSceneSwitcher.midi.message.type.songPositionPointer="Song Position Pointer"
|
||||||
|
AdvSceneSwitcher.midi.message.type.songSelect="Song Select"
|
||||||
|
AdvSceneSwitcher.midi.message.type.reserved1="Reserved (1)"
|
||||||
|
AdvSceneSwitcher.midi.message.type.reserved2="Reserved (2)"
|
||||||
|
AdvSceneSwitcher.midi.message.type.tuneRequest="Tune Request"
|
||||||
|
AdvSceneSwitcher.midi.message.type.endOfSystemExclusive="End of System Exclusive"
|
||||||
|
AdvSceneSwitcher.midi.message.type.timeClock="Time Clock"
|
||||||
|
AdvSceneSwitcher.midi.message.type.reserved3="Reserved (3)"
|
||||||
|
AdvSceneSwitcher.midi.message.type.startFile="Start File"
|
||||||
|
AdvSceneSwitcher.midi.message.type.continueFile="Continue File"
|
||||||
|
AdvSceneSwitcher.midi.message.type.stopFile="Stop File"
|
||||||
|
AdvSceneSwitcher.midi.message.type.reserved4="Reserved (4)"
|
||||||
|
AdvSceneSwitcher.midi.message.type.activeSensing="Active Sensing"
|
||||||
|
AdvSceneSwitcher.midi.message.type.systemReset="System Reset"
|
||||||
|
AdvSceneSwitcher.midi.message.type.unknown="Unknown"
|
||||||
|
AdvSceneSwitcher.midi.message.channel="Channel:"
|
||||||
|
AdvSceneSwitcher.midi.message.note="Note / Value(1):"
|
||||||
|
AdvSceneSwitcher.midi.message.value="Value(2):"
|
||||||
|
AdvSceneSwitcher.midi.message.placeholder="Any"
|
||||||
|
AdvSceneSwitcher.midi.resetDevices="Reconnect all MIDI devices"
|
||||||
|
AdvSceneSwitcher.midi.startListen="Start listening"
|
||||||
|
AdvSceneSwitcher.midi.stopListen="Stop listening"
|
||||||
|
AdvSceneSwitcher.midi.startListenFail="Device is busy!\nSomething else is already listening!"
|
||||||
|
AdvSceneSwitcher.midi.deviceOpenFail="Failed to initialize MIDI device!"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.osc.network="Network"
|
||||||
|
AdvSceneSwitcher.osc.network.protocol="Protocol:"
|
||||||
|
AdvSceneSwitcher.osc.network.address="Address:"
|
||||||
|
AdvSceneSwitcher.osc.network.port="Port:"
|
||||||
|
AdvSceneSwitcher.osc.message="Message"
|
||||||
|
AdvSceneSwitcher.osc.message.type.none="None"
|
||||||
|
AdvSceneSwitcher.osc.message.type.float="Float"
|
||||||
|
AdvSceneSwitcher.osc.message.type.int="Integer"
|
||||||
|
AdvSceneSwitcher.osc.message.type.string="String"
|
||||||
|
AdvSceneSwitcher.osc.message.type.binaryBlob="Binary blob"
|
||||||
|
AdvSceneSwitcher.osc.message.type.true="True"
|
||||||
|
AdvSceneSwitcher.osc.message.type.false="False"
|
||||||
|
AdvSceneSwitcher.osc.message.type.infinity="Infinitum"
|
||||||
|
AdvSceneSwitcher.osc.message.type.null="Nil"
|
||||||
|
|
||||||
AdvSceneSwitcher.selectScene="--select scene--"
|
AdvSceneSwitcher.selectScene="--select scene--"
|
||||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ AdvSceneSwitcher.condition.stream.state.start="Transmisión en ejecución"
|
|||||||
AdvSceneSwitcher.condition.stream.state.stop="Transmisión detenida"
|
AdvSceneSwitcher.condition.stream.state.stop="Transmisión detenida"
|
||||||
AdvSceneSwitcher.condition.stream.state.starting="Inicio de transmisión"
|
AdvSceneSwitcher.condition.stream.state.starting="Inicio de transmisión"
|
||||||
AdvSceneSwitcher.condition.stream.state.stopping="Detener transmisión"
|
AdvSceneSwitcher.condition.stream.state.stopping="Detener transmisión"
|
||||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
|
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
|
||||||
AdvSceneSwitcher.condition.record="Grabación"
|
AdvSceneSwitcher.condition.record="Grabación"
|
||||||
AdvSceneSwitcher.condition.record.state.start="Grabación en ejecución"
|
AdvSceneSwitcher.condition.record.state.start="Grabación en ejecución"
|
||||||
AdvSceneSwitcher.condition.record.state.pause="Grabación en pausa"
|
AdvSceneSwitcher.condition.record.state.pause="Grabación en pausa"
|
||||||
@@ -350,7 +350,7 @@ AdvSceneSwitcher.action.recording.type.start="Iniciar grabación"
|
|||||||
AdvSceneSwitcher.action.recording.type.pause="Pausar grabación"
|
AdvSceneSwitcher.action.recording.type.pause="Pausar grabación"
|
||||||
AdvSceneSwitcher.action.recording.type.unpause="Reanudar grabación"
|
AdvSceneSwitcher.action.recording.type.unpause="Reanudar grabación"
|
||||||
AdvSceneSwitcher.action.recording.pause.hint="Tenga en cuenta que, dependiendo de la configuración de grabación, es posible que no pueda pausar la grabación"
|
AdvSceneSwitcher.action.recording.pause.hint="Tenga en cuenta que, dependiendo de la configuración de grabación, es posible que no pueda pausar la grabación"
|
||||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
|
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
AdvSceneSwitcher.action.replay="Búfer de reproducción"
|
AdvSceneSwitcher.action.replay="Búfer de reproducción"
|
||||||
AdvSceneSwitcher.action.replay.saveWarn="Advertencia: ¡Guardar con demasiada frecuencia puede hacer que el búfer de reproducción no se guarde realmente!"
|
AdvSceneSwitcher.action.replay.saveWarn="Advertencia: ¡Guardar con demasiada frecuencia puede hacer que el búfer de reproducción no se guarde realmente!"
|
||||||
AdvSceneSwitcher.action.replay.type.stop="Detener el búfer de reproducción"
|
AdvSceneSwitcher.action.replay.type.stop="Detener el búfer de reproducción"
|
||||||
@@ -360,7 +360,7 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
|||||||
AdvSceneSwitcher.action.streaming="Transmisión"
|
AdvSceneSwitcher.action.streaming="Transmisión"
|
||||||
AdvSceneSwitcher.action.streaming.type.stop="Detener transmisión"
|
AdvSceneSwitcher.action.streaming.type.stop="Detener transmisión"
|
||||||
AdvSceneSwitcher.action.streaming.type.start="Iniciar transmisión"
|
AdvSceneSwitcher.action.streaming.type.start="Iniciar transmisión"
|
||||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||||
AdvSceneSwitcher.action.run="Ejecutar"
|
AdvSceneSwitcher.action.run="Ejecutar"
|
||||||
AdvSceneSwitcher.action.run.arguments="Argumentos:"
|
AdvSceneSwitcher.action.run.arguments="Argumentos:"
|
||||||
AdvSceneSwitcher.action.run.addArgument="Agregar argumento"
|
AdvSceneSwitcher.action.run.addArgument="Agregar argumento"
|
||||||
@@ -422,7 +422,7 @@ AdvSceneSwitcher.action.hotkey.leftMeta="Meta izquierda"
|
|||||||
AdvSceneSwitcher.action.hotkey.rightMeta="Meta derecho"
|
AdvSceneSwitcher.action.hotkey.rightMeta="Meta derecho"
|
||||||
AdvSceneSwitcher.action.hotkey.onlyOBS="Enviar pulsación de tecla solo a OBS"
|
AdvSceneSwitcher.action.hotkey.onlyOBS="Enviar pulsación de tecla solo a OBS"
|
||||||
AdvSceneSwitcher.action.hotkey.disabled="No se puede simular la pulsación de teclas: ¡funcionalidad desactivada!"
|
AdvSceneSwitcher.action.hotkey.disabled="No se puede simular la pulsación de teclas: ¡funcionalidad desactivada!"
|
||||||
AdvSceneSwitcher.action.hotkey.entry="Presione {{keys}} durante {{duration}} milisegundos"
|
AdvSceneSwitcher.action.hotkey.entry="Presione {{keys}} durante {{duration}}"
|
||||||
AdvSceneSwitcher.action.sceneOrder="Orden de elementos de escena"
|
AdvSceneSwitcher.action.sceneOrder="Orden de elementos de escena"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Mover hacia arriba"
|
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Mover hacia arriba"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Mover hacia abajo"
|
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Mover hacia abajo"
|
||||||
@@ -460,7 +460,6 @@ AdvSceneSwitcher.action.timer.entry="{{timerAction}} temporizadores en {{macros}
|
|||||||
AdvSceneSwitcher.action.random="Aleatorio"
|
AdvSceneSwitcher.action.random="Aleatorio"
|
||||||
AdvSceneSwitcher.action.random.entry="Ejecute aleatoriamente cualquiera de las siguientes macros (las macros en pausa se ignoran)"
|
AdvSceneSwitcher.action.random.entry="Ejecute aleatoriamente cualquiera de las siguientes macros (las macros en pausa se ignoran)"
|
||||||
AdvSceneSwitcher.action.systray="Notificación de la bandeja del sistema"
|
AdvSceneSwitcher.action.systray="Notificación de la bandeja del sistema"
|
||||||
AdvSceneSwitcher.action.systray.entry="Mostrar notificación: {{message}}"
|
|
||||||
AdvSceneSwitcher.action.screenshot="Captura de pantalla"
|
AdvSceneSwitcher.action.screenshot="Captura de pantalla"
|
||||||
AdvSceneSwitcher.action.screenshot.mainOutput="Salida principal de OBS"
|
AdvSceneSwitcher.action.screenshot.mainOutput="Salida principal de OBS"
|
||||||
AdvSceneSwitcher.action.profile="Perfil"
|
AdvSceneSwitcher.action.profile="Perfil"
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ AdvSceneSwitcher.action.recording.type.start="Начать запись"
|
|||||||
AdvSceneSwitcher.action.recording.type.pause="Пауза записи"
|
AdvSceneSwitcher.action.recording.type.pause="Пауза записи"
|
||||||
AdvSceneSwitcher.action.recording.type.unpause="Снять запись с паузы"
|
AdvSceneSwitcher.action.recording.type.unpause="Снять запись с паузы"
|
||||||
AdvSceneSwitcher.action.recording.pause.hint="Обратите внимание, что в зависимости от настроек записи вы можете не иметь возможности приостановить запись"
|
AdvSceneSwitcher.action.recording.pause.hint="Обратите внимание, что в зависимости от настроек записи вы можете не иметь возможности приостановить запись"
|
||||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
|
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
AdvSceneSwitcher.action.replay="Буфер воспроизведения"
|
AdvSceneSwitcher.action.replay="Буфер воспроизведения"
|
||||||
AdvSceneSwitcher.action.replay.type.stop="Остановить буфер воспроизведения"
|
AdvSceneSwitcher.action.replay.type.stop="Остановить буфер воспроизведения"
|
||||||
AdvSceneSwitcher.action.replay.type.start="Начать воспроизведение буфера"
|
AdvSceneSwitcher.action.replay.type.start="Начать воспроизведение буфера"
|
||||||
@@ -144,7 +144,7 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
|||||||
AdvSceneSwitcher.action.streaming="Потоковое вещание"
|
AdvSceneSwitcher.action.streaming="Потоковое вещание"
|
||||||
AdvSceneSwitcher.action.streaming.type.stop="Остановить потоковое вещание"
|
AdvSceneSwitcher.action.streaming.type.stop="Остановить потоковое вещание"
|
||||||
AdvSceneSwitcher.action.streaming.type.start="Начать потоковое вещание"
|
AdvSceneSwitcher.action.streaming.type.start="Начать потоковое вещание"
|
||||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||||
AdvSceneSwitcher.action.run="Запустить"
|
AdvSceneSwitcher.action.run="Запустить"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ AdvSceneSwitcher.condition.stream.state.start="Yayın çalışıyor"
|
|||||||
AdvSceneSwitcher.condition.stream.state.stop="Yayın durdu"
|
AdvSceneSwitcher.condition.stream.state.stop="Yayın durdu"
|
||||||
AdvSceneSwitcher.condition.stream.state.starting="Yayın başlıyor"
|
AdvSceneSwitcher.condition.stream.state.starting="Yayın başlıyor"
|
||||||
AdvSceneSwitcher.condition.stream.state.stopping="Yayın duruyor"
|
AdvSceneSwitcher.condition.stream.state.stopping="Yayın duruyor"
|
||||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
|
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
|
||||||
AdvSceneSwitcher.condition.record="Kayıt"
|
AdvSceneSwitcher.condition.record="Kayıt"
|
||||||
AdvSceneSwitcher.condition.record.state.start="Kayıt Çalışıyor"
|
AdvSceneSwitcher.condition.record.state.start="Kayıt Çalışıyor"
|
||||||
AdvSceneSwitcher.condition.record.state.pause="Kayıt durakladı"
|
AdvSceneSwitcher.condition.record.state.pause="Kayıt durakladı"
|
||||||
@@ -281,7 +281,7 @@ AdvSceneSwitcher.action.recording.type.start="Kayıt Başlat"
|
|||||||
AdvSceneSwitcher.action.recording.type.pause="Kayıt Duraklat"
|
AdvSceneSwitcher.action.recording.type.pause="Kayıt Duraklat"
|
||||||
AdvSceneSwitcher.action.recording.type.unpause="Kayıt Duraklatma"
|
AdvSceneSwitcher.action.recording.type.unpause="Kayıt Duraklatma"
|
||||||
AdvSceneSwitcher.action.recording.pause.hint="Kayıt ayarlarınıza bağlı olarak kaydı duraklatamayabileceğinizi unutmayın."
|
AdvSceneSwitcher.action.recording.pause.hint="Kayıt ayarlarınıza bağlı olarak kaydı duraklatamayabileceğinizi unutmayın."
|
||||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
|
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
AdvSceneSwitcher.action.replay="Tekrar arabelleği"
|
AdvSceneSwitcher.action.replay="Tekrar arabelleği"
|
||||||
AdvSceneSwitcher.action.replay.type.stop="Tekrar arabelleğini durdur"
|
AdvSceneSwitcher.action.replay.type.stop="Tekrar arabelleğini durdur"
|
||||||
AdvSceneSwitcher.action.replay.type.start="Tekrar arabelleğini başlat"
|
AdvSceneSwitcher.action.replay.type.start="Tekrar arabelleğini başlat"
|
||||||
@@ -290,7 +290,7 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
|||||||
AdvSceneSwitcher.action.streaming="Yayın"
|
AdvSceneSwitcher.action.streaming="Yayın"
|
||||||
AdvSceneSwitcher.action.streaming.type.stop="Yayın durdur"
|
AdvSceneSwitcher.action.streaming.type.stop="Yayın durdur"
|
||||||
AdvSceneSwitcher.action.streaming.type.start="Yayın başlat"
|
AdvSceneSwitcher.action.streaming.type.start="Yayın başlat"
|
||||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||||
AdvSceneSwitcher.action.run="Çalıştır"
|
AdvSceneSwitcher.action.run="Çalıştır"
|
||||||
AdvSceneSwitcher.action.run.arguments="Argümanlar:"
|
AdvSceneSwitcher.action.run.arguments="Argümanlar:"
|
||||||
AdvSceneSwitcher.action.run.addArgument="Argüman ekle"
|
AdvSceneSwitcher.action.run.addArgument="Argüman ekle"
|
||||||
@@ -350,7 +350,7 @@ AdvSceneSwitcher.action.hotkey.leftMeta="Sol Meta"
|
|||||||
AdvSceneSwitcher.action.hotkey.rightMeta="Sağ Meta"
|
AdvSceneSwitcher.action.hotkey.rightMeta="Sağ Meta"
|
||||||
AdvSceneSwitcher.action.hotkey.onlyOBS="Tuşa basımı yalnızca OBS'ye gönder"
|
AdvSceneSwitcher.action.hotkey.onlyOBS="Tuşa basımı yalnızca OBS'ye gönder"
|
||||||
AdvSceneSwitcher.action.hotkey.disabled="Tuşa basma simülasyonu yapılamıyor - işlevsellik devre dışı!"
|
AdvSceneSwitcher.action.hotkey.disabled="Tuşa basma simülasyonu yapılamıyor - işlevsellik devre dışı!"
|
||||||
AdvSceneSwitcher.action.hotkey.entry="Bas {{keys}} uygun {{duration}} millisaniye"
|
AdvSceneSwitcher.action.hotkey.entry="Bas {{keys}} uygun {{duration}}"
|
||||||
AdvSceneSwitcher.action.sceneOrder="Sahne öğesi sırası"
|
AdvSceneSwitcher.action.sceneOrder="Sahne öğesi sırası"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Yukarı taşı"
|
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Yukarı taşı"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Aşağı indir"
|
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Aşağı indir"
|
||||||
@@ -377,7 +377,6 @@ AdvSceneSwitcher.action.timer.entry="{{timerAction}} zamanlayıcılar açık {{m
|
|||||||
AdvSceneSwitcher.action.random="Rastgele"
|
AdvSceneSwitcher.action.random="Rastgele"
|
||||||
AdvSceneSwitcher.action.random.entry="Aşağıdaki makrolardan herhangi birini rastgele çalıştırın (duraklatılmış makrolar yoksayılır)"
|
AdvSceneSwitcher.action.random.entry="Aşağıdaki makrolardan herhangi birini rastgele çalıştırın (duraklatılmış makrolar yoksayılır)"
|
||||||
AdvSceneSwitcher.action.systray="Sistem tepsisi bildirimi"
|
AdvSceneSwitcher.action.systray="Sistem tepsisi bildirimi"
|
||||||
AdvSceneSwitcher.action.systray.entry="Bildirimleri göster: {{message}}"
|
|
||||||
AdvSceneSwitcher.action.screenshot="Ekran görüntüsü"
|
AdvSceneSwitcher.action.screenshot="Ekran görüntüsü"
|
||||||
AdvSceneSwitcher.action.screenshot.mainOutput="OBS'nin ana çıkışı"
|
AdvSceneSwitcher.action.screenshot.mainOutput="OBS'nin ana çıkışı"
|
||||||
AdvSceneSwitcher.action.profile="Profil"
|
AdvSceneSwitcher.action.profile="Profil"
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ AdvSceneSwitcher.condition.stream.state.start="推流启动"
|
|||||||
AdvSceneSwitcher.condition.stream.state.stop="推流停止"
|
AdvSceneSwitcher.condition.stream.state.stop="推流停止"
|
||||||
AdvSceneSwitcher.condition.stream.state.starting="推流启动中"
|
AdvSceneSwitcher.condition.stream.state.starting="推流启动中"
|
||||||
AdvSceneSwitcher.condition.stream.state.stopping="推流停止中"
|
AdvSceneSwitcher.condition.stream.state.stopping="推流停止中"
|
||||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
|
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
|
||||||
AdvSceneSwitcher.condition.record="录制"
|
AdvSceneSwitcher.condition.record="录制"
|
||||||
AdvSceneSwitcher.condition.record.state.start="录制运行中"
|
AdvSceneSwitcher.condition.record.state.start="录制运行中"
|
||||||
AdvSceneSwitcher.condition.record.state.pause="录制暂停"
|
AdvSceneSwitcher.condition.record.state.pause="录制暂停"
|
||||||
@@ -393,7 +393,7 @@ AdvSceneSwitcher.action.recording.type.unpause="取消录制暂停"
|
|||||||
AdvSceneSwitcher.action.recording.type.split="分割录制文件"
|
AdvSceneSwitcher.action.recording.type.split="分割录制文件"
|
||||||
AdvSceneSwitcher.action.recording.pause.hint="请注意,根据您的录制设置,您可能无法暂停录制"
|
AdvSceneSwitcher.action.recording.pause.hint="请注意,根据您的录制设置,您可能无法暂停录制"
|
||||||
AdvSceneSwitcher.action.recording.split.hint="确保先在OBS设置中启用自动分割文件!"
|
AdvSceneSwitcher.action.recording.split.hint="确保先在OBS设置中启用自动分割文件!"
|
||||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
|
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
AdvSceneSwitcher.action.replay="回放缓冲区"
|
AdvSceneSwitcher.action.replay="回放缓冲区"
|
||||||
AdvSceneSwitcher.action.replay.saveWarn="警告:保存过于频繁可能会导致重播缓冲区实际上未保存!"
|
AdvSceneSwitcher.action.replay.saveWarn="警告:保存过于频繁可能会导致重播缓冲区实际上未保存!"
|
||||||
AdvSceneSwitcher.action.replay.type.stop="停止回放缓冲区"
|
AdvSceneSwitcher.action.replay.type.stop="停止回放缓冲区"
|
||||||
@@ -403,7 +403,7 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
|||||||
AdvSceneSwitcher.action.streaming="推流"
|
AdvSceneSwitcher.action.streaming="推流"
|
||||||
AdvSceneSwitcher.action.streaming.type.stop="停止推流"
|
AdvSceneSwitcher.action.streaming.type.stop="停止推流"
|
||||||
AdvSceneSwitcher.action.streaming.type.start="开始推流"
|
AdvSceneSwitcher.action.streaming.type.start="开始推流"
|
||||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||||
AdvSceneSwitcher.action.run="运行"
|
AdvSceneSwitcher.action.run="运行"
|
||||||
AdvSceneSwitcher.action.run.arguments="参数:"
|
AdvSceneSwitcher.action.run.arguments="参数:"
|
||||||
AdvSceneSwitcher.action.run.addArgument="添加参数"
|
AdvSceneSwitcher.action.run.addArgument="添加参数"
|
||||||
@@ -467,7 +467,7 @@ AdvSceneSwitcher.action.hotkey.leftMeta="左 Meta"
|
|||||||
AdvSceneSwitcher.action.hotkey.rightMeta="右 Meta"
|
AdvSceneSwitcher.action.hotkey.rightMeta="右 Meta"
|
||||||
AdvSceneSwitcher.action.hotkey.onlyOBS="仅向OBS发送按键"
|
AdvSceneSwitcher.action.hotkey.onlyOBS="仅向OBS发送按键"
|
||||||
AdvSceneSwitcher.action.hotkey.disabled="无法模拟按键-功能已禁用!"
|
AdvSceneSwitcher.action.hotkey.disabled="无法模拟按键-功能已禁用!"
|
||||||
AdvSceneSwitcher.action.hotkey.entry="按下 {{keys}} for {{duration}} 毫秒"
|
AdvSceneSwitcher.action.hotkey.entry="按下 {{keys}} for {{duration}}"
|
||||||
AdvSceneSwitcher.action.sceneOrder="场景项目顺序"
|
AdvSceneSwitcher.action.sceneOrder="场景项目顺序"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="上移"
|
AdvSceneSwitcher.action.sceneOrder.type.moveUp="上移"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="下移"
|
AdvSceneSwitcher.action.sceneOrder.type.moveDown="下移"
|
||||||
@@ -505,7 +505,6 @@ AdvSceneSwitcher.action.timer.entry="{{timerAction}} 定时在 {{macros}} {{dura
|
|||||||
AdvSceneSwitcher.action.random="随机"
|
AdvSceneSwitcher.action.random="随机"
|
||||||
AdvSceneSwitcher.action.random.entry="随机运行以下任何宏(忽略暂停的宏)"
|
AdvSceneSwitcher.action.random.entry="随机运行以下任何宏(忽略暂停的宏)"
|
||||||
AdvSceneSwitcher.action.systray="系统托盘通知"
|
AdvSceneSwitcher.action.systray="系统托盘通知"
|
||||||
AdvSceneSwitcher.action.systray.entry="显示通知: {{message}}"
|
|
||||||
AdvSceneSwitcher.action.screenshot="截图"
|
AdvSceneSwitcher.action.screenshot="截图"
|
||||||
AdvSceneSwitcher.action.screenshot.save.default="默认"
|
AdvSceneSwitcher.action.screenshot.save.default="默认"
|
||||||
AdvSceneSwitcher.action.screenshot.save.custom="其他"
|
AdvSceneSwitcher.action.screenshot.save.custom="其他"
|
||||||
@@ -541,7 +540,7 @@ AdvSceneSwitcher.action.variable.type.append="追加"
|
|||||||
AdvSceneSwitcher.action.variable.type.appendVar="追加变量"
|
AdvSceneSwitcher.action.variable.type.appendVar="追加变量"
|
||||||
AdvSceneSwitcher.action.variable.type.increment="增加"
|
AdvSceneSwitcher.action.variable.type.increment="增加"
|
||||||
AdvSceneSwitcher.action.variable.type.decrement="减少"
|
AdvSceneSwitcher.action.variable.type.decrement="减少"
|
||||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}"
|
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}"
|
||||||
|
|
||||||
|
|
||||||
; Transition Tab
|
; Transition Tab
|
||||||
|
|||||||
4
data/res/images/DarkAdvanced.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m 13.855469 0 l -1.539063 1.4375 c -0.453125 0.421875 -0.53125 1.148438 -0.269531 1.707031 l -5.886719 5.996094 c -0.011718 0 -0.019531 0 -0.03125 0 c -0.257812 -0.128906 -0.550781 -0.183594 -0.839844 -0.148437 c -0.328124 0.046874 -0.632812 0.199218 -0.867187 0.441406 l -3.945313 3.996094 c -0.3906245 0.375 -0.5468745 0.933593 -0.4062495 1.457031 c 0.1406255 0.523437 0.5546875 0.929687 1.0820315 1.058593 c 0.527344 0.132813 1.082031 -0.03125 1.453125 -0.425781 l 3.945312 -3.996093 c 0.472657 -0.453126 0.59375 -1.15625 0.296875 -1.738282 l 5.890625 -5.964844 c 0.558594 0.25 1.273438 0.148438 1.707031 -0.289062 l 1.414063 -1.5625 z m -10.308594 0.0898438 c -0.398437 0 -0.785156 0.0937502 -1.140625 0.2187502 l 1.882812 1.878906 c 0.390626 0.382812 0.390626 1 0 1.386719 l -0.710937 0.707031 c -0.386719 0.386719 -1 0.386719 -1.390625 0 l -1.882812 -1.878906 c -0.125 0.355468 -0.2187505 0.742187 -0.2187505 1.140625 c 0 1.90625 1.5507815 3.453125 3.4609375 3.453125 c 0.402344 0 0.789063 -0.09375 1.144531 -0.21875 l 1.175782 1.171875 h 0.058593 l 2.070313 -2.0625 l -1.203125 -1.203125 c 0.125 -0.359375 0.214843 -0.742188 0.214843 -1.140625 c 0 -1.90625 -1.546874 -3.4531252 -3.460937 -3.4531252 z m 6.550781 7.8906252 l -2.070312 2.066406 c 0.011718 0.027344 0.023437 0.058594 0.03125 0.089844 l 1.144531 1.140625 c -0.125 0.355468 -0.21875 0.742187 -0.21875 1.140625 c 0 1.902343 1.550781 3.449219 3.460937 3.449219 c 0.433594 0 0.855469 -0.101563 1.238282 -0.246094 l -2.007813 -2 c -0.386719 -0.386719 -0.386719 -1.035156 0 -1.417969 l 0.679688 -0.679687 c 0.195312 -0.191407 0.457031 -0.308594 0.710937 -0.308594 s 0.515625 0.117187 0.710938 0.308594 l 1.945312 1.941406 c 0.105469 -0.328125 0.183594 -0.683594 0.183594 -1.046875 c 0 -1.90625 -1.546875 -3.453125 -3.460938 -3.453125 c -0.398437 0 -0.785156 0.09375 -1.140624 0.21875 z m 0 0" fill="#fefefe"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
7
data/res/images/DarkGroup.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g fill="#fefefe">
|
||||||
|
<path d="m 3 1 c -1.644531 0 -3 1.355469 -3 3 v 8 c 0 1.644531 1.355469 3 3 3 h 8.882812 c 0.832032 0 1.578126 -0.402344 2.054688 -0.9375 c 0.472656 -0.53125 0.738281 -1.167969 0.910156 -1.800781 l 0.972656 -2.609375 c 0.390626 -1.449219 -0.09375 -2.652344 -0.820312 -3.167969 c -0.484375 -0.34375 -0.714844 -0.292969 -1 -0.324219 v -1.160156 c 0 -0.855469 -0.558594 -1.589844 -1.09375 -1.828125 c -0.53125 -0.238281 -1.011719 -0.167969 -1.011719 -0.167969 l 0.105469 -0.003906 h -3.585938 l -1.707031 -1.707031 c -0.1875 -0.1875 -0.441406 -0.292969 -0.707031 -0.292969 z m 0 2 h 2.585938 l 1.707031 1.707031 c 0.1875 0.1875 0.441406 0.292969 0.707031 0.292969 h 4 c 0.035156 0 0.070312 -0.003906 0.105469 -0.007812 c 0 0 0.019531 0.019531 -0.011719 0.003906 c -0.035156 -0.011719 -0.09375 -0.25 -0.09375 0.003906 v 2 c 0 0.550781 0.449219 1 1 1 c 1 0 1.046875 0.703125 0.886719 1.128906 l -0.972657 2.609375 c -0.117187 0.4375 -0.296874 0.800781 -0.472656 0.996094 c -0.175781 0.199219 -0.285156 0.265625 -0.558594 0.265625 h -8.882812 c -0.570312 0 -1 -0.429688 -1 -1 v -8 c 0 -0.570312 0.46875 -0.792969 1 -1 z m 0 0"/>
|
||||||
|
<path d="m 7 6 l 0.042969 0.003906 c -0.914063 -0.042968 -1.75 0.390625 -2.195313 0.96875 c -0.710937 1.222656 -1.15625 2.277344 -1.800781 3.71875 c -0.171875 0.523438 0.117187 1.089844 0.640625 1.261719 c 0.527344 0.171875 1.09375 -0.117187 1.261719 -0.640625 c 0.488281 -1.011719 0.921875 -1.816406 1.339843 -2.808594 c 0.210938 -0.503906 0.703126 -0.492187 0.898438 -0.503906 h 5.8125 c 0.550781 0 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m 0 0"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
24
data/res/images/DarkNote.svg
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<svg width="640" height="640" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" version="1.1">
|
||||||
|
<defs>
|
||||||
|
<path d="m599.62,325.49c0,151.77 -123.21,274.98 -274.98,274.98c-151.76,0 -274.97,-123.21 -274.97,-274.98c0,-151.76 123.21,-274.97 274.97,-274.97c151.77,0 274.98,123.21 274.98,274.97z" id="c3Wyq0kfYS"/>
|
||||||
|
<mask height="689.95" id="maskanTyyngos" maskUnits="userSpaceOnUse" width="689.95" x="-20.33" y="-19.48">
|
||||||
|
<rect fill="white" height="689.95" id="svg_1" width="689.95" x="-20.33" y="-19.48"/>
|
||||||
|
<use fill="black" id="svg_2" xlink:href="#c3Wyq0kfYS"/>
|
||||||
|
</mask>
|
||||||
|
<path d="m334.97,96.07c4.54,0 8.23,3.68 8.23,8.23c0,46.94 0,179.54 0,226.48c0,4.54 -3.69,8.22 -8.23,8.22c-5.77,0 -14.88,0 -20.66,0c-4.54,0 -8.22,-3.68 -8.22,-8.22c0,-46.94 0,-179.54 0,-226.48c0,-4.55 3.68,-8.23 8.22,-8.23c5.78,0 14.89,0 20.66,0z" id="fxMeu932c"/>
|
||||||
|
<path d="m471.96,338.21c0.01,3.1 -2.5,5.62 -5.59,5.63c-32.02,0.09 -122.45,0.37 -154.46,0.47c-3.1,0.01 -5.61,-2.49 -5.62,-5.59c-0.02,-6.3 -0.06,-19.59 -0.08,-25.89c-0.01,-3.1 2.49,-5.62 5.59,-5.63c32.01,-0.09 122.44,-0.37 154.45,-0.47c3.1,-0.01 5.62,2.5 5.63,5.59c0.02,6.3 0.06,19.59 0.08,25.89z" id="h65nGmP2BL"/>
|
||||||
|
</defs>
|
||||||
|
<g class="layer">
|
||||||
|
<title>Layer 1</title>
|
||||||
|
<path fill="none" fill-opacity="null" id="svg_11" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02"/>
|
||||||
|
<ellipse cx="103.84" cy="562.04" fill="#fefefe" id="svg_3" rx="80" ry="45" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-18.699, 103.843, 562.038)"/>
|
||||||
|
<ellipse cx="506" cy="554" fill="#fefefe" id="svg_4" rx="77" ry="45" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-18.699, 506, 554)"/>
|
||||||
|
<rect fill="#fefefe" height="359" id="svg_7" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" stroke-width="0" width="58" x="122" y="185"/>
|
||||||
|
<rect fill="#fefefe" height="453" id="svg_8" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="58" x="522" y="84.5"/>
|
||||||
|
<rect fill="#fefefe" height="37" id="svg_9" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-14.1985, 351.556, 146.245)" width="463.07" x="120.02" y="127.74"/>
|
||||||
|
<rect fill="none" fill-opacity="null" height="0" id="svg_10" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="0" x="538.25" y="107.12"/>
|
||||||
|
<path d="m537.42,112.06l0,-67.88l17.58,67.88z" fill="#fefefe" id="svg_16" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-90, 546.203, 78.1248)"/>
|
||||||
|
<rect fill="#fefefe" height="0" id="svg_18" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="0" x="82.12" y="287.56"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.1 KiB |
10
data/res/images/DarkRegex.svg
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" version="1.1">
|
||||||
|
<!-- Created with SVG-edit - https://github.com/SVG-Edit/svgedit-->
|
||||||
|
|
||||||
|
<g class="layer">
|
||||||
|
<title>Layer 1</title>
|
||||||
|
<text fill="#fefefe" font-family="Serif" font-size="24" id="svg_1" stroke="#fefefe" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" text-anchor="middle" transform="matrix(1.0974, 0, 0, 1.0974, -4.98544, 4.97639)" x="14" xml:space="preserve" y="13">*</text>
|
||||||
|
<rect fill="#fefefe" height="3.3" id="svg_2" stroke="#fefefe" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="matrix(1, 0, 0, 1, 0, 0)" width="5" x="1" y="12"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 815 B |
@@ -1,3 +1,2 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?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="#fefefe" stroke-width="70" stroke-opacity="1"></use></g></g><g><use xlink:href="#fxMeu932c" opacity="1" fill="#fefefe" fill-opacity="1"></use></g><g><use xlink:href="#h65nGmP2BL" opacity="1" fill="#fefefe" fill-opacity="1"></use></g></g></g></svg>
|
||||||
<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>
|
|
||||||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
4
data/res/images/LightAdvanced.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m 13.855469 0 l -1.539063 1.4375 c -0.453125 0.421875 -0.53125 1.148438 -0.269531 1.707031 l -5.886719 5.996094 c -0.011718 0 -0.019531 0 -0.03125 0 c -0.257812 -0.128906 -0.550781 -0.183594 -0.839844 -0.148437 c -0.328124 0.046874 -0.632812 0.199218 -0.867187 0.441406 l -3.945313 3.996094 c -0.3906245 0.375 -0.5468745 0.933593 -0.4062495 1.457031 c 0.1406255 0.523437 0.5546875 0.929687 1.0820315 1.058593 c 0.527344 0.132813 1.082031 -0.03125 1.453125 -0.425781 l 3.945312 -3.996093 c 0.472657 -0.453126 0.59375 -1.15625 0.296875 -1.738282 l 5.890625 -5.964844 c 0.558594 0.25 1.273438 0.148438 1.707031 -0.289062 l 1.414063 -1.5625 z m -10.308594 0.0898438 c -0.398437 0 -0.785156 0.0937502 -1.140625 0.2187502 l 1.882812 1.878906 c 0.390626 0.382812 0.390626 1 0 1.386719 l -0.710937 0.707031 c -0.386719 0.386719 -1 0.386719 -1.390625 0 l -1.882812 -1.878906 c -0.125 0.355468 -0.2187505 0.742187 -0.2187505 1.140625 c 0 1.90625 1.5507815 3.453125 3.4609375 3.453125 c 0.402344 0 0.789063 -0.09375 1.144531 -0.21875 l 1.175782 1.171875 h 0.058593 l 2.070313 -2.0625 l -1.203125 -1.203125 c 0.125 -0.359375 0.214843 -0.742188 0.214843 -1.140625 c 0 -1.90625 -1.546874 -3.4531252 -3.460937 -3.4531252 z m 6.550781 7.8906252 l -2.070312 2.066406 c 0.011718 0.027344 0.023437 0.058594 0.03125 0.089844 l 1.144531 1.140625 c -0.125 0.355468 -0.21875 0.742187 -0.21875 1.140625 c 0 1.902343 1.550781 3.449219 3.460937 3.449219 c 0.433594 0 0.855469 -0.101563 1.238282 -0.246094 l -2.007813 -2 c -0.386719 -0.386719 -0.386719 -1.035156 0 -1.417969 l 0.679688 -0.679687 c 0.195312 -0.191407 0.457031 -0.308594 0.710937 -0.308594 s 0.515625 0.117187 0.710938 0.308594 l 1.945312 1.941406 c 0.105469 -0.328125 0.183594 -0.683594 0.183594 -1.046875 c 0 -1.90625 -1.546875 -3.453125 -3.460938 -3.453125 c -0.398437 0 -0.785156 0.09375 -1.140624 0.21875 z m 0 0" fill="#202020"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
7
data/res/images/LightGroup.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g fill="#202020">
|
||||||
|
<path d="m 3 1 c -1.644531 0 -3 1.355469 -3 3 v 8 c 0 1.644531 1.355469 3 3 3 h 8.882812 c 0.832032 0 1.578126 -0.402344 2.054688 -0.9375 c 0.472656 -0.53125 0.738281 -1.167969 0.910156 -1.800781 l 0.972656 -2.609375 c 0.390626 -1.449219 -0.09375 -2.652344 -0.820312 -3.167969 c -0.484375 -0.34375 -0.714844 -0.292969 -1 -0.324219 v -1.160156 c 0 -0.855469 -0.558594 -1.589844 -1.09375 -1.828125 c -0.53125 -0.238281 -1.011719 -0.167969 -1.011719 -0.167969 l 0.105469 -0.003906 h -3.585938 l -1.707031 -1.707031 c -0.1875 -0.1875 -0.441406 -0.292969 -0.707031 -0.292969 z m 0 2 h 2.585938 l 1.707031 1.707031 c 0.1875 0.1875 0.441406 0.292969 0.707031 0.292969 h 4 c 0.035156 0 0.070312 -0.003906 0.105469 -0.007812 c 0 0 0.019531 0.019531 -0.011719 0.003906 c -0.035156 -0.011719 -0.09375 -0.25 -0.09375 0.003906 v 2 c 0 0.550781 0.449219 1 1 1 c 1 0 1.046875 0.703125 0.886719 1.128906 l -0.972657 2.609375 c -0.117187 0.4375 -0.296874 0.800781 -0.472656 0.996094 c -0.175781 0.199219 -0.285156 0.265625 -0.558594 0.265625 h -8.882812 c -0.570312 0 -1 -0.429688 -1 -1 v -8 c 0 -0.570312 0.46875 -0.792969 1 -1 z m 0 0"/>
|
||||||
|
<path d="m 7 6 l 0.042969 0.003906 c -0.914063 -0.042968 -1.75 0.390625 -2.195313 0.96875 c -0.710937 1.222656 -1.15625 2.277344 -1.800781 3.71875 c -0.171875 0.523438 0.117187 1.089844 0.640625 1.261719 c 0.527344 0.171875 1.09375 -0.117187 1.261719 -0.640625 c 0.488281 -1.011719 0.921875 -1.816406 1.339843 -2.808594 c 0.210938 -0.503906 0.703126 -0.492187 0.898438 -0.503906 h 5.8125 c 0.550781 0 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m 0 0"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
24
data/res/images/LightNote.svg
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<svg width="640" height="640" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" version="1.1">
|
||||||
|
<defs>
|
||||||
|
<path d="m599.62,325.49c0,151.77 -123.21,274.98 -274.98,274.98c-151.76,0 -274.97,-123.21 -274.97,-274.98c0,-151.76 123.21,-274.97 274.97,-274.97c151.77,0 274.98,123.21 274.98,274.97z" id="c3Wyq0kfYS"/>
|
||||||
|
<mask height="689.95" id="maskanTyyngos" maskUnits="userSpaceOnUse" width="689.95" x="-20.33" y="-19.48">
|
||||||
|
<rect fill="white" height="689.95" id="svg_1" width="689.95" x="-20.33" y="-19.48"/>
|
||||||
|
<use fill="black" id="svg_2" xlink:href="#c3Wyq0kfYS"/>
|
||||||
|
</mask>
|
||||||
|
<path d="m334.97,96.07c4.54,0 8.23,3.68 8.23,8.23c0,46.94 0,179.54 0,226.48c0,4.54 -3.69,8.22 -8.23,8.22c-5.77,0 -14.88,0 -20.66,0c-4.54,0 -8.22,-3.68 -8.22,-8.22c0,-46.94 0,-179.54 0,-226.48c0,-4.55 3.68,-8.23 8.22,-8.23c5.78,0 14.89,0 20.66,0z" id="fxMeu932c"/>
|
||||||
|
<path d="m471.96,338.21c0.01,3.1 -2.5,5.62 -5.59,5.63c-32.02,0.09 -122.45,0.37 -154.46,0.47c-3.1,0.01 -5.61,-2.49 -5.62,-5.59c-0.02,-6.3 -0.06,-19.59 -0.08,-25.89c-0.01,-3.1 2.49,-5.62 5.59,-5.63c32.01,-0.09 122.44,-0.37 154.45,-0.47c3.1,-0.01 5.62,2.5 5.63,5.59c0.02,6.3 0.06,19.59 0.08,25.89z" id="h65nGmP2BL"/>
|
||||||
|
</defs>
|
||||||
|
<g class="layer">
|
||||||
|
<title>Layer 1</title>
|
||||||
|
<path fill="none" fill-opacity="null" id="svg_11" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02"/>
|
||||||
|
<ellipse cx="103.84" cy="562.04" fill="#202020" id="svg_3" rx="80" ry="45" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-18.699, 103.843, 562.038)"/>
|
||||||
|
<ellipse cx="506" cy="554" fill="#202020" id="svg_4" rx="77" ry="45" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-18.699, 506, 554)"/>
|
||||||
|
<rect fill="#202020" height="359" id="svg_7" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" stroke-width="0" width="58" x="122" y="185"/>
|
||||||
|
<rect fill="#202020" height="453" id="svg_8" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="58" x="522" y="84.5"/>
|
||||||
|
<rect fill="#202020" height="37" id="svg_9" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-14.1985, 351.556, 146.245)" width="463.07" x="120.02" y="127.74"/>
|
||||||
|
<rect fill="none" fill-opacity="null" height="0" id="svg_10" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="0" x="538.25" y="107.12"/>
|
||||||
|
<path d="m537.42,112.06l0,-67.88l17.58,67.88z" fill="#202020" id="svg_16" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-90, 546.203, 78.1248)"/>
|
||||||
|
<rect fill="#202020" height="0" id="svg_18" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="0" x="82.12" y="287.56"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.1 KiB |
10
data/res/images/LightRegex.svg
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" version="1.1">
|
||||||
|
<!-- Created with SVG-edit - https://github.com/SVG-Edit/svgedit-->
|
||||||
|
|
||||||
|
<g class="layer">
|
||||||
|
<title>Layer 1</title>
|
||||||
|
<text fill="#202020" font-family="Serif" font-size="24" id="svg_1" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" text-anchor="middle" transform="matrix(1.0974, 0, 0, 1.0974, -4.98544, 4.97639)" x="14" xml:space="preserve" y="13">*</text>
|
||||||
|
<rect fill="#202020" height="3.3" id="svg_2" stroke="#202020" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="matrix(1, 0, 0, 1, 0, 0)" width="5" x="1" y="12"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 815 B |
2
data/res/images/LightTime.svg
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<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="#202020" stroke-width="70" stroke-opacity="1"></use></g></g><g><use xlink:href="#fxMeu932c" opacity="1" fill="#202020" fill-opacity="1"></use></g><g><use xlink:href="#h65nGmP2BL" opacity="1" fill="#202020" fill-opacity="1"></use></g></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
BIN
data/res/ocr/eng.traineddata
Normal file
41032
deps/exprtk/exprtk.hpp
vendored
Normal file
1
deps/leptonica
vendored
Submodule
1
deps/libremidi
vendored
Submodule
1
deps/tesseract
vendored
Submodule
@@ -256,6 +256,30 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_26">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="warnPluginLoadFailure">
|
||||||
|
<property name="text">
|
||||||
|
<string>AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailure</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_19">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_24">
|
<layout class="QHBoxLayout" name="horizontalLayout_24">
|
||||||
<item>
|
<item>
|
||||||
@@ -634,7 +658,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="MacroTree" name="macros">
|
<widget class="advss::MacroTree" name="macros">
|
||||||
<property name="showDropIndicator" stdset="0">
|
<property name="showDropIndicator" stdset="0">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@@ -4539,7 +4563,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>MacroTree</class>
|
<class>advss::MacroTree</class>
|
||||||
<extends>QListView</extends>
|
<extends>QListView</extends>
|
||||||
<header>macro-tree.hpp</header>
|
<header>macro-tree.hpp</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
|||||||
@@ -9,26 +9,15 @@
|
|||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
#include "status-control.hpp"
|
#include "status-control.hpp"
|
||||||
|
#include "scene-switch-helpers.hpp"
|
||||||
#include "curl-helper.hpp"
|
#include "curl-helper.hpp"
|
||||||
|
#include "platform-funcs.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
const char *obs_module_text(const char *text)
|
namespace advss {
|
||||||
{
|
|
||||||
return switcher->translate(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
obs_module_t *obs_current_module()
|
|
||||||
{
|
|
||||||
return switcher->modulePtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
SwitcherData *switcher = nullptr;
|
|
||||||
SwitcherData *GetSwitcher()
|
|
||||||
{
|
|
||||||
return switcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
AdvSceneSwitcher *AdvSceneSwitcher::window = nullptr;
|
AdvSceneSwitcher *AdvSceneSwitcher::window = nullptr;
|
||||||
|
|
||||||
@@ -40,11 +29,9 @@ AdvSceneSwitcher::AdvSceneSwitcher(QWidget *parent)
|
|||||||
{
|
{
|
||||||
switcher->settingsWindowOpened = true;
|
switcher->settingsWindowOpened = true;
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
|
||||||
switcher->Prune();
|
switcher->Prune();
|
||||||
loadUI();
|
LoadUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
AdvSceneSwitcher::~AdvSceneSwitcher()
|
AdvSceneSwitcher::~AdvSceneSwitcher()
|
||||||
@@ -55,51 +42,76 @@ AdvSceneSwitcher::~AdvSceneSwitcher()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool translationAvailable()
|
static bool translationAvailable()
|
||||||
{
|
{
|
||||||
return !!strcmp(obs_module_text("AdvSceneSwitcher.pluginName"),
|
return !!strcmp(obs_module_text("AdvSceneSwitcher.pluginName"),
|
||||||
"AdvSceneSwitcher.pluginName");
|
"AdvSceneSwitcher.pluginName");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::loadUI()
|
static void DisplayMissingDependencyWarning()
|
||||||
{
|
{
|
||||||
if (!translationAvailable()) {
|
if (!switcher->warnPluginLoadFailure ||
|
||||||
QString msg = "Failed to find plug-in's 'data' directory.\n"
|
switcher->loadFailureLibs.isEmpty()) {
|
||||||
"Please check installation instructions!\n\n"
|
return;
|
||||||
"Data most likely expected at:\n\n";
|
|
||||||
#ifdef _WIN32
|
|
||||||
msg += QString::fromStdString(
|
|
||||||
(std::filesystem::current_path().string()));
|
|
||||||
msg += "/";
|
|
||||||
#endif
|
|
||||||
msg += obs_get_module_data_path(obs_current_module());
|
|
||||||
(void)DisplayMessage(msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setupGeneralTab();
|
QString failedLibsString = "<ul>";
|
||||||
setupTitleTab();
|
for (const auto &lib : switcher->loadFailureLibs) {
|
||||||
setupExecutableTab();
|
failedLibsString += "<li>" + lib + "</li>";
|
||||||
setupRegionTab();
|
}
|
||||||
setupPauseTab();
|
failedLibsString += "</ul>";
|
||||||
setupSequenceTab();
|
QString warning(obs_module_text(
|
||||||
setupTransitionsTab();
|
"AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage"));
|
||||||
setupIdleTab();
|
DisplayMessage(warning.arg(failedLibsString));
|
||||||
setupRandomTab();
|
}
|
||||||
setupMediaTab();
|
|
||||||
setupFileTab();
|
|
||||||
setupTimeTab();
|
|
||||||
setupAudioTab();
|
|
||||||
setupVideoTab();
|
|
||||||
setupNetworkTab();
|
|
||||||
setupSceneGroupTab();
|
|
||||||
setupTriggerTab();
|
|
||||||
setupMacroTab();
|
|
||||||
|
|
||||||
setDeprecationWarnings();
|
static void DisplayMissingDataDirWarning()
|
||||||
setTabOrder();
|
{
|
||||||
setCurrentTab();
|
if (translationAvailable()) {
|
||||||
restoreWindowGeo();
|
return;
|
||||||
checkFirstTimeSetup();
|
}
|
||||||
|
|
||||||
|
QString msg = "Failed to find plug-in's 'data' directory.\n"
|
||||||
|
"Please check installation instructions!\n\n"
|
||||||
|
"Data most likely expected at:\n\n";
|
||||||
|
#ifdef _WIN32
|
||||||
|
msg += QString::fromStdString(
|
||||||
|
(std::filesystem::current_path().string()));
|
||||||
|
msg += "/";
|
||||||
|
#endif
|
||||||
|
msg += obs_get_module_data_path(obs_current_module());
|
||||||
|
DisplayMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::LoadUI()
|
||||||
|
{
|
||||||
|
DisplayMissingDataDirWarning();
|
||||||
|
DisplayMissingDependencyWarning();
|
||||||
|
|
||||||
|
SetupGeneralTab();
|
||||||
|
SetupTitleTab();
|
||||||
|
SetupExecutableTab();
|
||||||
|
SetupRegionTab();
|
||||||
|
SetupPauseTab();
|
||||||
|
SetupSequenceTab();
|
||||||
|
SetupTransitionsTab();
|
||||||
|
SetupIdleTab();
|
||||||
|
SetupRandomTab();
|
||||||
|
SetupMediaTab();
|
||||||
|
SetupFileTab();
|
||||||
|
SetupTimeTab();
|
||||||
|
SetupAudioTab();
|
||||||
|
SetupVideoTab();
|
||||||
|
SetupNetworkTab();
|
||||||
|
SetupSceneGroupTab();
|
||||||
|
SetupTriggerTab();
|
||||||
|
SetupMacroTab();
|
||||||
|
|
||||||
|
SetDeprecationWarnings();
|
||||||
|
SetTabOrder();
|
||||||
|
SetCurrentTab();
|
||||||
|
RestoreWindowGeo();
|
||||||
|
CheckFirstTimeSetup();
|
||||||
|
|
||||||
loading = false;
|
loading = false;
|
||||||
}
|
}
|
||||||
@@ -107,13 +119,15 @@ void AdvSceneSwitcher::loadUI()
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Saving and loading
|
* Saving and loading
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
static void AskForBackup(obs_data_t *obj);
|
||||||
|
|
||||||
static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
||||||
{
|
{
|
||||||
if (saving) {
|
if (saving) {
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->Prune();
|
switcher->Prune();
|
||||||
obs_data_t *obj = obs_data_create();
|
obs_data_t *obj = obs_data_create();
|
||||||
switcher->saveSettings(obj);
|
switcher->SaveSettings(obj);
|
||||||
obs_data_set_obj(save_data, "advanced-scene-switcher", obj);
|
obs_data_set_obj(save_data, "advanced-scene-switcher", obj);
|
||||||
obs_data_release(obj);
|
obs_data_release(obj);
|
||||||
} else {
|
} else {
|
||||||
@@ -127,10 +141,10 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||||||
if (!obj) {
|
if (!obj) {
|
||||||
obj = obs_data_create();
|
obj = obs_data_create();
|
||||||
}
|
}
|
||||||
if (switcher->versionChanged(obj, g_GIT_SHA1)) {
|
if (switcher->VersionChanged(obj, g_GIT_SHA1)) {
|
||||||
AskForBackup(obj);
|
AskForBackup(obj);
|
||||||
}
|
}
|
||||||
switcher->loadSettings(obj);
|
switcher->LoadSettings(obj);
|
||||||
obs_data_release(obj);
|
obs_data_release(obj);
|
||||||
switcher->m.unlock();
|
switcher->m.unlock();
|
||||||
|
|
||||||
@@ -140,6 +154,34 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void AskForBackup(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
bool backupSettings = DisplayMessage(
|
||||||
|
obs_module_text("AdvSceneSwitcher.askBackup"), true);
|
||||||
|
|
||||||
|
if (!backupSettings) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString path = QFileDialog::getSaveFileName(
|
||||||
|
nullptr,
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle"),
|
||||||
|
GetDefaultSettingsSaveLocation(),
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType"));
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile file(path);
|
||||||
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_data_save_json(obj, file.fileName().toUtf8().constData());
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Main switcher thread
|
* Main switcher thread
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@@ -155,6 +197,7 @@ void SwitcherData::Thread()
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
std::unique_lock<std::mutex> lock(m);
|
std::unique_lock<std::mutex> lock(m);
|
||||||
|
mainLoopLock = &lock;
|
||||||
|
|
||||||
bool match = false;
|
bool match = false;
|
||||||
OBSWeakSource scene;
|
OBSWeakSource scene;
|
||||||
@@ -182,7 +225,7 @@ void SwitcherData::Thread()
|
|||||||
}
|
}
|
||||||
|
|
||||||
vblog(LOG_INFO, "try to sleep for %ld", duration.count());
|
vblog(LOG_INFO, "try to sleep for %ld", duration.count());
|
||||||
setWaitScene();
|
SetWaitScene();
|
||||||
cv.wait_for(lock, duration);
|
cv.wait_for(lock, duration);
|
||||||
|
|
||||||
startTime = std::chrono::high_resolution_clock::now();
|
startTime = std::chrono::high_resolution_clock::now();
|
||||||
@@ -196,13 +239,13 @@ void SwitcherData::Thread()
|
|||||||
if (checkPause()) {
|
if (checkPause()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
setPreconditions();
|
SetPreconditions();
|
||||||
match = checkForMatch(scene, transition, linger,
|
match = CheckForMatch(scene, transition, linger,
|
||||||
setPrevSceneAfterLinger, macroMatch);
|
setPrevSceneAfterLinger, macroMatch);
|
||||||
if (stop) {
|
if (stop) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
checkNoMatchSwitch(match, scene, transition, sleep);
|
CheckNoMatchSwitch(match, scene, transition, sleep);
|
||||||
checkSwitchCooldown(match);
|
checkSwitchCooldown(match);
|
||||||
|
|
||||||
if (linger) {
|
if (linger) {
|
||||||
@@ -210,14 +253,14 @@ void SwitcherData::Thread()
|
|||||||
vblog(LOG_INFO, "sleep for %ld before switching scene",
|
vblog(LOG_INFO, "sleep for %ld before switching scene",
|
||||||
duration.count());
|
duration.count());
|
||||||
|
|
||||||
setWaitScene();
|
SetWaitScene();
|
||||||
cv.wait_for(lock, duration);
|
cv.wait_for(lock, duration);
|
||||||
|
|
||||||
if (stop) {
|
if (stop) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sceneChangedDuringWait()) {
|
if (SceneChangedDuringWait()) {
|
||||||
vblog(LOG_INFO,
|
vblog(LOG_INFO,
|
||||||
"scene was changed manually - ignoring match");
|
"scene was changed manually - ignoring match");
|
||||||
|
|
||||||
@@ -228,26 +271,13 @@ void SwitcherData::Thread()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearWebsocketMessages();
|
ResetForNextInterval();
|
||||||
|
|
||||||
// After this point we will call frontend functions like
|
|
||||||
// obs_frontend_set_current_scene() and
|
|
||||||
// obs_frontend_set_current_transition()
|
|
||||||
//
|
|
||||||
// During this time SaveSceneSwitcher() could be called
|
|
||||||
// leading to a deadlock with the frontend function being stuck
|
|
||||||
// in QMetaObject::invokeMethod() holding the mutex and
|
|
||||||
// OBS being stuck in SaveSceneSwitcher().
|
|
||||||
//
|
|
||||||
// So we have to unlock() risking race conditions as these are
|
|
||||||
// less frequent than the above described deadlock
|
|
||||||
lock.unlock();
|
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
if (macroMatch) {
|
if (macroMatch) {
|
||||||
runMacros();
|
RunMacros();
|
||||||
} else {
|
} else {
|
||||||
switchScene({scene, transition, 0});
|
SwitchScene({scene, transition, 0});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,10 +286,11 @@ void SwitcherData::Thread()
|
|||||||
switcher->firstIntervalAfterStop = false;
|
switcher->firstIntervalAfterStop = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainLoopLock = nullptr;
|
||||||
blog(LOG_INFO, "stopped");
|
blog(LOG_INFO, "stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::setPreconditions()
|
void SwitcherData::SetPreconditions()
|
||||||
{
|
{
|
||||||
// Window title
|
// Window title
|
||||||
lastTitle = currentTitle;
|
lastTitle = currentTitle;
|
||||||
@@ -287,13 +318,23 @@ void SwitcherData::setPreconditions()
|
|||||||
GetForegroundProcessName(currentForegroundProcess);
|
GetForegroundProcessName(currentForegroundProcess);
|
||||||
|
|
||||||
// Cursor
|
// Cursor
|
||||||
std::pair<int, int> cursorPos = getCursorPos();
|
std::pair<int, int> cursorPos = GetCursorPos();
|
||||||
cursorPosChanged = cursorPos.first != switcher->lastCursorPos.first ||
|
cursorPosChanged = cursorPos.first != switcher->lastCursorPos.first ||
|
||||||
cursorPos.second != switcher->lastCursorPos.second;
|
cursorPos.second != switcher->lastCursorPos.second;
|
||||||
lastCursorPos = getCursorPos();
|
lastCursorPos = GetCursorPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SwitcherData::checkForMatch(OBSWeakSource &scene,
|
void SwitcherData::ResetForNextInterval()
|
||||||
|
{
|
||||||
|
// Core reset functions
|
||||||
|
ClearWebsocketMessages();
|
||||||
|
// Plugin reset functions
|
||||||
|
for (const auto &func : resetForNextIntervalFuncs) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SwitcherData::CheckForMatch(OBSWeakSource &scene,
|
||||||
OBSWeakSource &transition, int &linger,
|
OBSWeakSource &transition, int &linger,
|
||||||
bool &setPrevSceneAfterLinger,
|
bool &setPrevSceneAfterLinger,
|
||||||
bool ¯oMatch)
|
bool ¯oMatch)
|
||||||
@@ -343,7 +384,7 @@ bool SwitcherData::checkForMatch(OBSWeakSource &scene,
|
|||||||
match = checkVideoSwitch(scene, transition);
|
match = checkVideoSwitch(scene, transition);
|
||||||
break;
|
break;
|
||||||
case macro_func:
|
case macro_func:
|
||||||
if (checkMacros()) {
|
if (CheckMacros()) {
|
||||||
match = true;
|
match = true;
|
||||||
macroMatch = true;
|
macroMatch = true;
|
||||||
}
|
}
|
||||||
@@ -360,48 +401,20 @@ bool SwitcherData::checkForMatch(OBSWeakSource &scene,
|
|||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
void switchScene(const sceneSwitchInfo &sceneSwitch, bool force)
|
static void ResetMacros()
|
||||||
{
|
{
|
||||||
if (!sceneSwitch.scene && switcher->verbose) {
|
for (auto &m : switcher->macros) {
|
||||||
blog(LOG_INFO, "nothing to switch to");
|
m->ResetRunCount();
|
||||||
return;
|
m->ResetTimers();
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_source_t *source = obs_weak_source_get_source(sceneSwitch.scene);
|
|
||||||
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
|
||||||
|
|
||||||
if (source && (source != currentSource || force)) {
|
|
||||||
transitionData currentTransitionData;
|
|
||||||
setNextTransition(sceneSwitch, currentSource,
|
|
||||||
currentTransitionData);
|
|
||||||
obs_frontend_set_current_scene(source);
|
|
||||||
if (switcher->transitionOverrideOverride) {
|
|
||||||
restoreTransitionOverride(source,
|
|
||||||
currentTransitionData);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switcher->verbose) {
|
|
||||||
blog(LOG_INFO, "switched scene");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switcher->networkConfig.ShouldSendSceneChange()) {
|
|
||||||
switcher->server.sendMessage(sceneSwitch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
obs_source_release(currentSource);
|
|
||||||
obs_source_release(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
void switchPreviewScene(const OBSWeakSource &ws)
|
|
||||||
{
|
|
||||||
auto source = obs_weak_source_get_source(ws);
|
|
||||||
obs_frontend_set_current_preview_scene(source);
|
|
||||||
obs_source_release(source);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::Start()
|
void SwitcherData::Start()
|
||||||
{
|
{
|
||||||
if (!(th && th->isRunning())) {
|
if (!(th && th->isRunning())) {
|
||||||
|
ResetForNextInterval();
|
||||||
|
ResetMacros();
|
||||||
|
|
||||||
stop = false;
|
stop = false;
|
||||||
th = new SwitcherThread();
|
th = new SwitcherThread();
|
||||||
th->start((QThread::Priority)threadPriority);
|
th->start((QThread::Priority)threadPriority);
|
||||||
@@ -426,14 +439,6 @@ void SwitcherData::Start()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetMacros()
|
|
||||||
{
|
|
||||||
for (auto &m : switcher->macros) {
|
|
||||||
m->ResetRunCount();
|
|
||||||
m->ResetTimers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitcherData::Stop()
|
void SwitcherData::Stop()
|
||||||
{
|
{
|
||||||
if (th && th->isRunning()) {
|
if (th && th->isRunning()) {
|
||||||
@@ -447,7 +452,6 @@ void SwitcherData::Stop()
|
|||||||
th = nullptr;
|
th = nullptr;
|
||||||
|
|
||||||
writeToStatusFile("Advanced Scene Switcher stopped");
|
writeToStatusFile("Advanced Scene Switcher stopped");
|
||||||
ResetMacros();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
server.stop();
|
server.stop();
|
||||||
@@ -460,13 +464,13 @@ void SwitcherData::Stop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::setWaitScene()
|
void SwitcherData::SetWaitScene()
|
||||||
{
|
{
|
||||||
waitScene = obs_frontend_get_current_scene();
|
waitScene = obs_frontend_get_current_scene();
|
||||||
obs_source_release(waitScene);
|
obs_source_release(waitScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SwitcherData::sceneChangedDuringWait()
|
bool SwitcherData::SceneChangedDuringWait()
|
||||||
{
|
{
|
||||||
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
||||||
if (!currentSource) {
|
if (!currentSource) {
|
||||||
@@ -479,7 +483,7 @@ bool SwitcherData::sceneChangedDuringWait()
|
|||||||
// Relies on the fact that switcher->currentScene will only be updated on event
|
// Relies on the fact that switcher->currentScene will only be updated on event
|
||||||
// OBS_FRONTEND_EVENT_SCENE_CHANGED but obs_frontend_get_current_scene() will
|
// OBS_FRONTEND_EVENT_SCENE_CHANGED but obs_frontend_get_current_scene() will
|
||||||
// already return the scene to be transitioned to.
|
// already return the scene to be transitioned to.
|
||||||
bool SwitcherData::anySceneTransitionStarted()
|
bool SwitcherData::AnySceneTransitionStarted()
|
||||||
{
|
{
|
||||||
auto currentSceneSrouce = obs_frontend_get_current_scene();
|
auto currentSceneSrouce = obs_frontend_get_current_scene();
|
||||||
auto currentScene = obs_source_get_weak_source(currentSceneSrouce);
|
auto currentScene = obs_source_get_weak_source(currentSceneSrouce);
|
||||||
@@ -500,13 +504,13 @@ extern "C" void FreeSceneSwitcher()
|
|||||||
switcher = nullptr;
|
switcher = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSceneChange()
|
static void handleSceneChange()
|
||||||
{
|
{
|
||||||
switcher->lastSceneChangeTime =
|
switcher->lastSceneChangeTime =
|
||||||
std::chrono::high_resolution_clock::now();
|
std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
// Stop waiting if scene was changed
|
// Stop waiting if scene was changed
|
||||||
if (switcher->sceneChangedDuringWait()) {
|
if (switcher->SceneChangedDuringWait()) {
|
||||||
switcher->cv.notify_one();
|
switcher->cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,31 +538,33 @@ void handleSceneChange()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLiveTime()
|
static void setLiveTime()
|
||||||
{
|
{
|
||||||
switcher->liveTime = QDateTime::currentDateTime();
|
switcher->liveTime = QDateTime::currentDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetLiveTime()
|
static void resetLiveTime()
|
||||||
{
|
{
|
||||||
switcher->liveTime = QDateTime();
|
switcher->liveTime = QDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkAutoStartRecording()
|
static void checkAutoStartRecording()
|
||||||
{
|
{
|
||||||
if (switcher->autoStartEvent == AutoStartEvent::RECORDING ||
|
if (switcher->autoStartEvent == SwitcherData::AutoStart::RECORDING ||
|
||||||
switcher->autoStartEvent == AutoStartEvent::RECORINDG_OR_STREAMING)
|
switcher->autoStartEvent ==
|
||||||
|
SwitcherData::AutoStart::RECORINDG_OR_STREAMING)
|
||||||
switcher->Start();
|
switcher->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkAutoStartStreaming()
|
static void checkAutoStartStreaming()
|
||||||
{
|
{
|
||||||
if (switcher->autoStartEvent == AutoStartEvent::STREAMING ||
|
if (switcher->autoStartEvent == SwitcherData::AutoStart::STREAMING ||
|
||||||
switcher->autoStartEvent == AutoStartEvent::RECORINDG_OR_STREAMING)
|
switcher->autoStartEvent ==
|
||||||
|
SwitcherData::AutoStart::RECORINDG_OR_STREAMING)
|
||||||
switcher->Start();
|
switcher->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handlePeviewSceneChange()
|
static void handlePeviewSceneChange()
|
||||||
{
|
{
|
||||||
if (switcher->networkConfig.ShouldSendPrviewSceneChange()) {
|
if (switcher->networkConfig.ShouldSendPrviewSceneChange()) {
|
||||||
auto source = obs_frontend_get_current_preview_scene();
|
auto source = obs_frontend_get_current_preview_scene();
|
||||||
@@ -569,43 +575,45 @@ void handlePeviewSceneChange()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setReplayBufferSaved()
|
static void setReplayBufferSaved()
|
||||||
{
|
{
|
||||||
switcher->replayBufferSaved = true;
|
switcher->replayBufferSaved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTranstionEnd()
|
static void setTranstionEnd()
|
||||||
{
|
{
|
||||||
switcher->lastTransitionEndTime =
|
switcher->lastTransitionEndTime =
|
||||||
std::chrono::high_resolution_clock::now();
|
std::chrono::high_resolution_clock::now();
|
||||||
switcher->macroTransitionCv.notify_all();
|
switcher->macroTransitionCv.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStreamStarting()
|
static void setStreamStarting()
|
||||||
{
|
{
|
||||||
switcher->lastStreamStartingTime =
|
switcher->lastStreamStartingTime =
|
||||||
std::chrono::high_resolution_clock::now();
|
std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStreamStopping()
|
static void setStreamStopping()
|
||||||
{
|
{
|
||||||
switcher->lastStreamStoppingTime =
|
switcher->lastStreamStoppingTime =
|
||||||
std::chrono::high_resolution_clock::now();
|
std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleExit()
|
static void handleExit()
|
||||||
{
|
{
|
||||||
|
if (!switcher) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switcher->obsIsShuttingDown = true;
|
switcher->obsIsShuttingDown = true;
|
||||||
if (switcher && switcher->obsIsShuttingDown &&
|
if (switcher->shutdownConditionCount) {
|
||||||
switcher->shutdownConditionCount) {
|
|
||||||
switcher->Stop();
|
switcher->Stop();
|
||||||
switcher->checkMacros();
|
switcher->CheckMacros();
|
||||||
switcher->runMacros();
|
switcher->RunMacros();
|
||||||
}
|
}
|
||||||
FreeSceneSwitcher();
|
FreeSceneSwitcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSceneCollectionChanging()
|
static void handleSceneCollectionChanging()
|
||||||
{
|
{
|
||||||
if (switcher->settingsWindowOpened) {
|
if (switcher->settingsWindowOpened) {
|
||||||
AdvSceneSwitcher::window->close();
|
AdvSceneSwitcher::window->close();
|
||||||
@@ -671,7 +679,7 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadPlugins()
|
static void LoadPlugins()
|
||||||
{
|
{
|
||||||
QFileInfo libPath(
|
QFileInfo libPath(
|
||||||
QString(obs_get_module_binary_path(obs_current_module())));
|
QString(obs_get_module_binary_path(obs_current_module())));
|
||||||
@@ -695,6 +703,7 @@ void LoadPlugins()
|
|||||||
blog(LOG_WARNING, "failed to load \"%s\": %s",
|
blog(LOG_WARNING, "failed to load \"%s\": %s",
|
||||||
file.toStdString().c_str(),
|
file.toStdString().c_str(),
|
||||||
lib->errorString().toStdString().c_str());
|
lib->errorString().toStdString().c_str());
|
||||||
|
switcher->loadFailureLibs << file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -714,14 +723,12 @@ void OpenSettingsWindow()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void InitSceneSwitcher(obs_module_t *m, translateFunc t)
|
extern "C" void InitSceneSwitcher(obs_module_t *module, translateFunc translate)
|
||||||
{
|
{
|
||||||
blog(LOG_INFO, "version: %s", g_GIT_TAG);
|
blog(LOG_INFO, "version: %s", g_GIT_TAG);
|
||||||
blog(LOG_INFO, "version: %s", g_GIT_SHA1);
|
blog(LOG_INFO, "version: %s", g_GIT_SHA1);
|
||||||
|
|
||||||
switcher = new SwitcherData;
|
switcher = new SwitcherData(module, translate);
|
||||||
switcher->modulePtr = m;
|
|
||||||
switcher->translate = t;
|
|
||||||
|
|
||||||
PlatformInit();
|
PlatformInit();
|
||||||
LoadPlugins();
|
LoadPlugins();
|
||||||
@@ -734,3 +741,5 @@ extern "C" void InitSceneSwitcher(obs_module_t *m, translateFunc t)
|
|||||||
obs_module_text("AdvSceneSwitcher.pluginName"));
|
obs_module_text("AdvSceneSwitcher.pluginName"));
|
||||||
action->connect(action, &QAction::triggered, OpenSettingsWindow);
|
action->connect(action, &QAction::triggered, OpenSettingsWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "switcher-data-structs.hpp"
|
#include "macro-segment-list.hpp"
|
||||||
#include "platform-funcs.hpp"
|
#include "log-helper.hpp"
|
||||||
|
|
||||||
#include <macro-segment-list.hpp>
|
|
||||||
#include <ui_advanced-scene-switcher.h>
|
#include <ui_advanced-scene-switcher.h>
|
||||||
|
|
||||||
#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 QCloseEvent;
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
class MacroActionEdit;
|
class MacroActionEdit;
|
||||||
class MacroConditionEdit;
|
class MacroConditionEdit;
|
||||||
|
class Duration;
|
||||||
|
class SequenceWidget;
|
||||||
|
struct SceneGroup;
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Advanced Scene Switcher window
|
* Advanced Scene Switcher window
|
||||||
@@ -33,20 +32,54 @@ public:
|
|||||||
void reject() override;
|
void reject() override;
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
|
|
||||||
void SetShowFrames();
|
void LoadUI();
|
||||||
void SetHideFrames();
|
|
||||||
void clearFrames(QListWidget *list);
|
|
||||||
|
|
||||||
int IgnoreWindowsFindByData(const QString &window);
|
void SetTabOrder();
|
||||||
int IgnoreIdleWindowsFindByData(const QString &window);
|
void SetCurrentTab();
|
||||||
|
void RestoreWindowGeo();
|
||||||
|
void CheckFirstTimeSetup();
|
||||||
|
|
||||||
|
/* --- Begin of general tab section --- */
|
||||||
|
public:
|
||||||
|
void SetupGeneralTab();
|
||||||
void UpdateNonMatchingScene(const QString &name);
|
void UpdateNonMatchingScene(const QString &name);
|
||||||
void OpenSequenceExtendEdit(SequenceWidget *sw);
|
void SetDeprecationWarnings();
|
||||||
void SetEditSceneGroup(SceneGroup &sg);
|
|
||||||
|
|
||||||
bool addNewMacro(std::shared_ptr<Macro> &res, std::string &name,
|
public slots:
|
||||||
|
void on_noMatchDontSwitch_clicked();
|
||||||
|
void on_noMatchSwitch_clicked();
|
||||||
|
void on_noMatchRandomSwitch_clicked();
|
||||||
|
void NoMatchDelayDurationChanged(const Duration &);
|
||||||
|
void CooldownDurationChanged(const Duration &);
|
||||||
|
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_tabMoved(int from, int to);
|
||||||
|
void on_tabWidget_currentChanged(int index);
|
||||||
|
void on_exportSettings_clicked();
|
||||||
|
void on_importSettings_clicked();
|
||||||
|
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_warnPluginLoadFailure_stateChanged(int state);
|
||||||
|
void on_hideLegacyTabs_stateChanged(int state);
|
||||||
|
void on_priorityUp_clicked();
|
||||||
|
void on_priorityDown_clicked();
|
||||||
|
void on_threadPriority_currentTextChanged(const QString &text);
|
||||||
|
|
||||||
|
/* --- End of legacy tab section --- */
|
||||||
|
|
||||||
|
/* --- Begin of macro tab section --- */
|
||||||
|
public:
|
||||||
|
void SetupMacroTab();
|
||||||
|
bool AddNewMacro(std::shared_ptr<Macro> &res, std::string &name,
|
||||||
std::string format = "");
|
std::string format = "");
|
||||||
std::shared_ptr<Macro> getSelectedMacro();
|
void RemoveMacro(std::shared_ptr<Macro> &);
|
||||||
|
void RenameMacro(std::shared_ptr<Macro> &, const QString &name);
|
||||||
|
std::shared_ptr<Macro> GetSelectedMacro();
|
||||||
|
std::vector<std::shared_ptr<Macro>> GetSelectedMacros();
|
||||||
void SetEditMacro(Macro &m);
|
void SetEditMacro(Macro &m);
|
||||||
void SetMacroEditAreaDisabled(bool);
|
void SetMacroEditAreaDisabled(bool);
|
||||||
void HighlightAction(int idx, QColor color = QColor(Qt::green));
|
void HighlightAction(int idx, QColor color = QColor(Qt::green));
|
||||||
@@ -58,68 +91,7 @@ public:
|
|||||||
void SwapActions(Macro *m, int pos1, int pos2);
|
void SwapActions(Macro *m, int pos1, int pos2);
|
||||||
void SwapConditions(Macro *m, int pos1, int pos2);
|
void SwapConditions(Macro *m, int pos1, int pos2);
|
||||||
|
|
||||||
void loadUI();
|
|
||||||
void setupGeneralTab();
|
|
||||||
void setupTitleTab();
|
|
||||||
void setupExecutableTab();
|
|
||||||
void setupRegionTab();
|
|
||||||
void setupPauseTab();
|
|
||||||
void setupSequenceTab();
|
|
||||||
void setupTransitionsTab();
|
|
||||||
void setupIdleTab();
|
|
||||||
void setupRandomTab();
|
|
||||||
void setupMediaTab();
|
|
||||||
void setupFileTab();
|
|
||||||
void setupTimeTab();
|
|
||||||
void setupAudioTab();
|
|
||||||
void setupSceneGroupTab();
|
|
||||||
void setupTriggerTab();
|
|
||||||
void setupVideoTab();
|
|
||||||
void setupNetworkTab();
|
|
||||||
void setupMacroTab();
|
|
||||||
void setDeprecationWarnings();
|
|
||||||
void setTabOrder();
|
|
||||||
void setCurrentTab();
|
|
||||||
void restoreWindowGeo();
|
|
||||||
void checkFirstTimeSetup();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void MacroAdded(const QString &name);
|
|
||||||
void MacroRemoved(const QString &name);
|
|
||||||
void MacroRenamed(const QString &oldName, const QString &newName);
|
|
||||||
void MacroSegmentOrderChanged();
|
|
||||||
void HighlightMacrosChanged(bool value);
|
|
||||||
void HighlightActionsChanged(bool value);
|
|
||||||
void HighlightConditionsChanged(bool value);
|
|
||||||
void SceneGroupAdded(const QString &name);
|
|
||||||
void SceneGroupRemoved(const QString &name);
|
|
||||||
void SceneGroupRenamed(const QString &oldName, const QString newName);
|
|
||||||
void ConnectionAdded(const QString &);
|
|
||||||
void ConnectionRenamed(const QString &oldName, const QString &newName);
|
|
||||||
void ConnectionRemoved(const QString &);
|
|
||||||
void VariableAdded(const QString &);
|
|
||||||
void VariableRenamed(const QString &oldName, const QString &newName);
|
|
||||||
void VariableRemoved(const QString &);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void on_windowUp_clicked();
|
|
||||||
void on_windowDown_clicked();
|
|
||||||
void on_windowAdd_clicked();
|
|
||||||
void on_windowRemove_clicked();
|
|
||||||
void on_noMatchDontSwitch_clicked();
|
|
||||||
void on_noMatchSwitch_clicked();
|
|
||||||
void on_noMatchRandomSwitch_clicked();
|
|
||||||
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_tabMoved(int from, int to);
|
|
||||||
void on_tabWidget_currentChanged(int index);
|
|
||||||
|
|
||||||
void on_macroAdd_clicked();
|
void on_macroAdd_clicked();
|
||||||
void on_macroRemove_clicked();
|
void on_macroRemove_clicked();
|
||||||
void on_macroUp_clicked();
|
void on_macroUp_clicked();
|
||||||
@@ -145,6 +117,7 @@ public slots:
|
|||||||
void ShowMacroActionsContextMenu(const QPoint &);
|
void ShowMacroActionsContextMenu(const QPoint &);
|
||||||
void ShowMacroConditionsContextMenu(const QPoint &);
|
void ShowMacroConditionsContextMenu(const QPoint &);
|
||||||
void CopyMacro();
|
void CopyMacro();
|
||||||
|
void RenameCurrentMacro();
|
||||||
void ExpandAllActions();
|
void ExpandAllActions();
|
||||||
void ExpandAllConditions();
|
void ExpandAllConditions();
|
||||||
void CollapseAllActions();
|
void CollapseAllActions();
|
||||||
@@ -171,135 +144,21 @@ public slots:
|
|||||||
void HighlightOnChange();
|
void HighlightOnChange();
|
||||||
void on_macroProperties_clicked();
|
void on_macroProperties_clicked();
|
||||||
|
|
||||||
void on_screenRegionSwitches_currentRowChanged(int idx);
|
signals:
|
||||||
void on_showFrame_clicked();
|
void MacroAdded(const QString &name);
|
||||||
void on_screenRegionAdd_clicked();
|
void MacroRemoved(const QString &name);
|
||||||
void on_screenRegionRemove_clicked();
|
void MacroRenamed(const QString &oldName, const QString &newName);
|
||||||
void on_screenRegionUp_clicked();
|
void MacroSegmentOrderChanged();
|
||||||
void on_screenRegionDown_clicked();
|
void HighlightMacrosChanged(bool value);
|
||||||
|
void HighlightActionsChanged(bool value);
|
||||||
|
void HighlightConditionsChanged(bool value);
|
||||||
|
|
||||||
void on_pauseUp_clicked();
|
void ConnectionAdded(const QString &);
|
||||||
void on_pauseDown_clicked();
|
void ConnectionRenamed(const QString &oldName, const QString &newName);
|
||||||
void on_pauseAdd_clicked();
|
void ConnectionRemoved(const QString &);
|
||||||
void on_pauseRemove_clicked();
|
void VariableAdded(const QString &);
|
||||||
|
void VariableRenamed(const QString &oldName, const QString &newName);
|
||||||
void on_ignoreWindows_currentRowChanged(int idx);
|
void VariableRemoved(const QString &);
|
||||||
void on_ignoreWindowsAdd_clicked();
|
|
||||||
void on_ignoreWindowsRemove_clicked();
|
|
||||||
|
|
||||||
void on_sceneSequenceAdd_clicked();
|
|
||||||
void on_sceneSequenceRemove_clicked();
|
|
||||||
void on_sceneSequenceUp_clicked();
|
|
||||||
void on_sceneSequenceDown_clicked();
|
|
||||||
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_hideLegacyTabs_stateChanged(int state);
|
|
||||||
|
|
||||||
void on_exportSettings_clicked();
|
|
||||||
void on_importSettings_clicked();
|
|
||||||
|
|
||||||
void on_transitionsAdd_clicked();
|
|
||||||
void on_transitionsRemove_clicked();
|
|
||||||
void on_transitionsUp_clicked();
|
|
||||||
void on_transitionsDown_clicked();
|
|
||||||
void on_defaultTransitionsAdd_clicked();
|
|
||||||
void on_defaultTransitionsRemove_clicked();
|
|
||||||
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);
|
|
||||||
void on_readPathLineEdit_textChanged(const QString &text);
|
|
||||||
void on_writePathLineEdit_textChanged(const QString &text);
|
|
||||||
void on_browseButton_2_clicked();
|
|
||||||
|
|
||||||
void on_executableUp_clicked();
|
|
||||||
void on_executableDown_clicked();
|
|
||||||
void on_executableAdd_clicked();
|
|
||||||
void on_executableRemove_clicked();
|
|
||||||
|
|
||||||
void on_idleCheckBox_stateChanged(int state);
|
|
||||||
void on_ignoreIdleWindows_currentRowChanged(int idx);
|
|
||||||
void on_ignoreIdleAdd_clicked();
|
|
||||||
void on_ignoreIdleRemove_clicked();
|
|
||||||
|
|
||||||
void on_randomAdd_clicked();
|
|
||||||
void on_randomRemove_clicked();
|
|
||||||
|
|
||||||
void on_fileAdd_clicked();
|
|
||||||
void on_fileRemove_clicked();
|
|
||||||
void on_fileSwitches_currentRowChanged(int idx);
|
|
||||||
void on_fileUp_clicked();
|
|
||||||
void on_fileDown_clicked();
|
|
||||||
|
|
||||||
void on_mediaAdd_clicked();
|
|
||||||
void on_mediaRemove_clicked();
|
|
||||||
void on_mediaUp_clicked();
|
|
||||||
void on_mediaDown_clicked();
|
|
||||||
|
|
||||||
void on_timeAdd_clicked();
|
|
||||||
void on_timeRemove_clicked();
|
|
||||||
void on_timeUp_clicked();
|
|
||||||
void on_timeDown_clicked();
|
|
||||||
|
|
||||||
void on_audioAdd_clicked();
|
|
||||||
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();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool MacroTabIsInFocus();
|
bool MacroTabIsInFocus();
|
||||||
@@ -314,29 +173,209 @@ private:
|
|||||||
MacroSection lastInteracted = MacroSection::CONDITIONS;
|
MacroSection lastInteracted = MacroSection::CONDITIONS;
|
||||||
int currentConditionIdx = -1;
|
int currentConditionIdx = -1;
|
||||||
int currentActionIdx = -1;
|
int currentActionIdx = -1;
|
||||||
|
|
||||||
|
/* --- End of macro tab section --- */
|
||||||
|
|
||||||
|
/* --- Begin of legacy tab section --- */
|
||||||
|
public:
|
||||||
|
void ClearFrames(QListWidget *list);
|
||||||
|
int IgnoreWindowsFindByData(const QString &window);
|
||||||
|
int IgnoreIdleWindowsFindByData(const QString &window);
|
||||||
|
void OpenSequenceExtendEdit(SequenceWidget *sw);
|
||||||
|
|
||||||
|
// Window tab
|
||||||
|
public:
|
||||||
|
void SetupTitleTab();
|
||||||
|
public slots:
|
||||||
|
void on_windowUp_clicked();
|
||||||
|
void on_windowDown_clicked();
|
||||||
|
void on_windowAdd_clicked();
|
||||||
|
void on_windowRemove_clicked();
|
||||||
|
void on_ignoreWindows_currentRowChanged(int idx);
|
||||||
|
void on_ignoreWindowsAdd_clicked();
|
||||||
|
void on_ignoreWindowsRemove_clicked();
|
||||||
|
|
||||||
|
// Screen region tab
|
||||||
|
public:
|
||||||
|
void SetupRegionTab();
|
||||||
|
public slots:
|
||||||
|
void SetShowFrames();
|
||||||
|
void SetHideFrames();
|
||||||
|
void on_screenRegionSwitches_currentRowChanged(int idx);
|
||||||
|
void on_showFrame_clicked();
|
||||||
|
void on_screenRegionAdd_clicked();
|
||||||
|
void on_screenRegionRemove_clicked();
|
||||||
|
void on_screenRegionUp_clicked();
|
||||||
|
void on_screenRegionDown_clicked();
|
||||||
|
void updateScreenRegionCursorPos();
|
||||||
|
|
||||||
|
// Pause tab
|
||||||
|
public:
|
||||||
|
void SetupPauseTab();
|
||||||
|
public slots:
|
||||||
|
void on_pauseUp_clicked();
|
||||||
|
void on_pauseDown_clicked();
|
||||||
|
void on_pauseAdd_clicked();
|
||||||
|
void on_pauseRemove_clicked();
|
||||||
|
|
||||||
|
// Sequence tab
|
||||||
|
public:
|
||||||
|
void SetupSequenceTab();
|
||||||
|
public slots:
|
||||||
|
void on_sceneSequenceAdd_clicked();
|
||||||
|
void on_sceneSequenceRemove_clicked();
|
||||||
|
void on_sceneSequenceUp_clicked();
|
||||||
|
void on_sceneSequenceDown_clicked();
|
||||||
|
void on_sceneSequenceSave_clicked();
|
||||||
|
void on_sceneSequenceLoad_clicked();
|
||||||
|
void on_sequenceEdit_clicked();
|
||||||
|
void on_sceneSequenceSwitches_itemDoubleClicked(QListWidgetItem *item);
|
||||||
|
|
||||||
|
// Transition tab
|
||||||
|
public:
|
||||||
|
void SetupTransitionsTab();
|
||||||
|
public slots:
|
||||||
|
void on_transitionsAdd_clicked();
|
||||||
|
void on_transitionsRemove_clicked();
|
||||||
|
void on_transitionsUp_clicked();
|
||||||
|
void on_transitionsDown_clicked();
|
||||||
|
void on_defaultTransitionsAdd_clicked();
|
||||||
|
void on_defaultTransitionsRemove_clicked();
|
||||||
|
void on_defaultTransitionsUp_clicked();
|
||||||
|
void on_defaultTransitionsDown_clicked();
|
||||||
|
void on_transitionOverridecheckBox_stateChanged(int state);
|
||||||
|
void on_adjustActiveTransitionType_stateChanged(int state);
|
||||||
|
void DefTransitionDelayValueChanged(int value);
|
||||||
|
|
||||||
|
// Executable tab
|
||||||
|
public:
|
||||||
|
void SetupExecutableTab();
|
||||||
|
public slots:
|
||||||
|
void on_executableUp_clicked();
|
||||||
|
void on_executableDown_clicked();
|
||||||
|
void on_executableAdd_clicked();
|
||||||
|
void on_executableRemove_clicked();
|
||||||
|
|
||||||
|
// Idle tab
|
||||||
|
public:
|
||||||
|
void SetupIdleTab();
|
||||||
|
public slots:
|
||||||
|
void on_idleCheckBox_stateChanged(int state);
|
||||||
|
void on_ignoreIdleWindows_currentRowChanged(int idx);
|
||||||
|
void on_ignoreIdleAdd_clicked();
|
||||||
|
void on_ignoreIdleRemove_clicked();
|
||||||
|
|
||||||
|
// Random tab
|
||||||
|
public:
|
||||||
|
void SetupRandomTab();
|
||||||
|
public slots:
|
||||||
|
void on_randomAdd_clicked();
|
||||||
|
void on_randomRemove_clicked();
|
||||||
|
|
||||||
|
// File tab
|
||||||
|
public:
|
||||||
|
void SetupFileTab();
|
||||||
|
public slots:
|
||||||
|
void on_fileAdd_clicked();
|
||||||
|
void on_fileRemove_clicked();
|
||||||
|
void on_fileSwitches_currentRowChanged(int idx);
|
||||||
|
void on_fileUp_clicked();
|
||||||
|
void on_fileDown_clicked();
|
||||||
|
void on_browseButton_clicked();
|
||||||
|
void on_readFileCheckBox_stateChanged(int state);
|
||||||
|
void on_readPathLineEdit_textChanged(const QString &text);
|
||||||
|
void on_writePathLineEdit_textChanged(const QString &text);
|
||||||
|
void on_browseButton_2_clicked();
|
||||||
|
|
||||||
|
// Media tab
|
||||||
|
public:
|
||||||
|
void SetupMediaTab();
|
||||||
|
public slots:
|
||||||
|
void on_mediaAdd_clicked();
|
||||||
|
void on_mediaRemove_clicked();
|
||||||
|
void on_mediaUp_clicked();
|
||||||
|
void on_mediaDown_clicked();
|
||||||
|
|
||||||
|
// Time tab
|
||||||
|
public:
|
||||||
|
void SetupTimeTab();
|
||||||
|
public slots:
|
||||||
|
void on_timeAdd_clicked();
|
||||||
|
void on_timeRemove_clicked();
|
||||||
|
void on_timeUp_clicked();
|
||||||
|
void on_timeDown_clicked();
|
||||||
|
|
||||||
|
// Video tab
|
||||||
|
public:
|
||||||
|
void SetupAudioTab();
|
||||||
|
public slots:
|
||||||
|
void on_audioAdd_clicked();
|
||||||
|
void on_audioRemove_clicked();
|
||||||
|
void on_audioUp_clicked();
|
||||||
|
void on_audioDown_clicked();
|
||||||
|
void on_audioFallback_toggled(bool on);
|
||||||
|
|
||||||
|
// Video tab
|
||||||
|
public:
|
||||||
|
void SetupVideoTab();
|
||||||
|
public slots:
|
||||||
|
void on_videoAdd_clicked();
|
||||||
|
void on_videoRemove_clicked();
|
||||||
|
void on_videoUp_clicked();
|
||||||
|
void on_videoDown_clicked();
|
||||||
|
void on_getScreenshot_clicked();
|
||||||
|
|
||||||
|
// Scene group tab
|
||||||
|
public:
|
||||||
|
void SetupNetworkTab();
|
||||||
|
public slots:
|
||||||
|
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();
|
||||||
|
|
||||||
|
// Scene group tab
|
||||||
|
public:
|
||||||
|
void SetupSceneGroupTab();
|
||||||
|
void SetEditSceneGroup(SceneGroup &sg);
|
||||||
|
public slots:
|
||||||
|
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();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void SceneGroupAdded(const QString &name);
|
||||||
|
void SceneGroupRemoved(const QString &name);
|
||||||
|
void SceneGroupRenamed(const QString &oldName, const QString newName);
|
||||||
|
|
||||||
|
// Trigger tab
|
||||||
|
public:
|
||||||
|
void SetupTriggerTab();
|
||||||
|
public slots:
|
||||||
|
void on_triggerAdd_clicked();
|
||||||
|
void on_triggerRemove_clicked();
|
||||||
|
void on_triggerUp_clicked();
|
||||||
|
void on_triggerDown_clicked();
|
||||||
|
|
||||||
|
/* --- End of legacy tab section --- */
|
||||||
};
|
};
|
||||||
|
|
||||||
void OpenSettingsWindow();
|
void OpenSettingsWindow();
|
||||||
|
|
||||||
/******************************************************************************
|
} // namespace advss
|
||||||
* Sceneswitch helper
|
|
||||||
******************************************************************************/
|
|
||||||
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, bool force = false);
|
|
||||||
void switchPreviewScene(const OBSWeakSource &ws);
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Settings helper
|
|
||||||
******************************************************************************/
|
|
||||||
void AskForBackup(obs_data_t *obj);
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Main SwitcherData
|
|
||||||
******************************************************************************/
|
|
||||||
struct SwitcherData;
|
|
||||||
extern SwitcherData *switcher;
|
|
||||||
SwitcherData *GetSwitcher();
|
|
||||||
|
|||||||
412
src/general.cpp
@@ -1,11 +1,13 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
#include "status-control.hpp"
|
#include "status-control.hpp"
|
||||||
#include "file-selection.hpp"
|
#include "file-selection.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QStandardPaths>
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
void AdvSceneSwitcher::reject()
|
void AdvSceneSwitcher::reject()
|
||||||
{
|
{
|
||||||
@@ -30,7 +32,7 @@ void AdvSceneSwitcher::on_noMatchDontSwitch_clicked()
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->switchIfNotMatching = NO_SWITCH;
|
switcher->switchIfNotMatching = SwitcherData::NoMatch::NO_SWITCH;
|
||||||
ui->noMatchSwitchScene->setEnabled(false);
|
ui->noMatchSwitchScene->setEnabled(false);
|
||||||
ui->randomDisabledWarning->setVisible(true);
|
ui->randomDisabledWarning->setVisible(true);
|
||||||
}
|
}
|
||||||
@@ -42,7 +44,7 @@ void AdvSceneSwitcher::on_noMatchSwitch_clicked()
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->switchIfNotMatching = SWITCH;
|
switcher->switchIfNotMatching = SwitcherData::NoMatch::SWITCH;
|
||||||
ui->noMatchSwitchScene->setEnabled(true);
|
ui->noMatchSwitchScene->setEnabled(true);
|
||||||
UpdateNonMatchingScene(ui->noMatchSwitchScene->currentText());
|
UpdateNonMatchingScene(ui->noMatchSwitchScene->currentText());
|
||||||
ui->randomDisabledWarning->setVisible(true);
|
ui->randomDisabledWarning->setVisible(true);
|
||||||
@@ -55,49 +57,29 @@ void AdvSceneSwitcher::on_noMatchRandomSwitch_clicked()
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->switchIfNotMatching = RANDOM_SWITCH;
|
switcher->switchIfNotMatching = SwitcherData::NoMatch::RANDOM_SWITCH;
|
||||||
ui->noMatchSwitchScene->setEnabled(false);
|
ui->noMatchSwitchScene->setEnabled(false);
|
||||||
ui->randomDisabledWarning->setVisible(false);
|
ui->randomDisabledWarning->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::NoMatchDelayDurationChanged(double sec)
|
void AdvSceneSwitcher::NoMatchDelayDurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->noMatchDelay.seconds = sec;
|
switcher->noMatchDelay = dur;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::NoMatchDelayUnitChanged(DurationUnit unit)
|
void AdvSceneSwitcher::CooldownDurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->noMatchDelay.displayUnit = unit;
|
switcher->cooldown = dur;
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::CooldownDurationChanged(double sec)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->cooldown.seconds = sec;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::CooldownUnitChanged(DurationUnit unit)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->cooldown.displayUnit = unit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_startupBehavior_currentIndexChanged(int index)
|
void AdvSceneSwitcher::on_startupBehavior_currentIndexChanged(int index)
|
||||||
@@ -107,7 +89,8 @@ void AdvSceneSwitcher::on_startupBehavior_currentIndexChanged(int index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->startupBehavior = (StartupBehavior)index;
|
switcher->startupBehavior =
|
||||||
|
static_cast<SwitcherData::StartupBehavior>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_autoStartEvent_currentIndexChanged(int index)
|
void AdvSceneSwitcher::on_autoStartEvent_currentIndexChanged(int index)
|
||||||
@@ -117,7 +100,7 @@ void AdvSceneSwitcher::on_autoStartEvent_currentIndexChanged(int index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->autoStartEvent = static_cast<AutoStartEvent>(index);
|
switcher->autoStartEvent = static_cast<SwitcherData::AutoStart>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_noMatchSwitchScene_currentTextChanged(
|
void AdvSceneSwitcher::on_noMatchSwitchScene_currentTextChanged(
|
||||||
@@ -192,7 +175,16 @@ void AdvSceneSwitcher::on_uiHintsDisable_stateChanged(int state)
|
|||||||
switcher->disableHints = state;
|
switcher->disableHints = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isLegacyTab(const QString &name)
|
void AdvSceneSwitcher::on_warnPluginLoadFailure_stateChanged(int state)
|
||||||
|
{
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switcher->warnPluginLoadFailure = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isLegacyTab(const QString &name)
|
||||||
{
|
{
|
||||||
return name == obs_module_text(
|
return name == obs_module_text(
|
||||||
"AdvSceneSwitcher.sceneGroupTab.title") ||
|
"AdvSceneSwitcher.sceneGroupTab.title") ||
|
||||||
@@ -237,7 +229,7 @@ void AdvSceneSwitcher::on_hideLegacyTabs_stateChanged(int state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setDeprecationWarnings()
|
void AdvSceneSwitcher::SetDeprecationWarnings()
|
||||||
{
|
{
|
||||||
QString toolTip =
|
QString toolTip =
|
||||||
switcher->disableHints
|
switcher->disableHints
|
||||||
@@ -251,53 +243,13 @@ void AdvSceneSwitcher::setDeprecationWarnings()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString getDefaultSaveLocation()
|
|
||||||
{
|
|
||||||
QString desktopPath = QStandardPaths::writableLocation(
|
|
||||||
QStandardPaths::DesktopLocation);
|
|
||||||
auto scName = obs_frontend_get_current_scene_collection();
|
|
||||||
QString sceneCollectionName(scName);
|
|
||||||
bfree(scName);
|
|
||||||
auto timestamp = QDateTime::currentDateTime();
|
|
||||||
return desktopPath + "/adv-ss-" + sceneCollectionName + "-" +
|
|
||||||
timestamp.toString("yyyy.MM.dd.hh.mm.ss");
|
|
||||||
}
|
|
||||||
|
|
||||||
void AskForBackup(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
bool backupSettings = DisplayMessage(
|
|
||||||
obs_module_text("AdvSceneSwitcher.askBackup"), true);
|
|
||||||
|
|
||||||
if (!backupSettings) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString path = QFileDialog::getSaveFileName(
|
|
||||||
nullptr,
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle"),
|
|
||||||
getDefaultSaveLocation(),
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType"));
|
|
||||||
if (path.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile file(path);
|
|
||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
obs_data_save_json(obj, file.fileName().toUtf8().constData());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_exportSettings_clicked()
|
void AdvSceneSwitcher::on_exportSettings_clicked()
|
||||||
{
|
{
|
||||||
QString directory = QFileDialog::getSaveFileName(
|
QString directory = QFileDialog::getSaveFileName(
|
||||||
this,
|
this,
|
||||||
tr(obs_module_text(
|
tr(obs_module_text(
|
||||||
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle")),
|
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle")),
|
||||||
getDefaultSaveLocation(),
|
GetDefaultSettingsSaveLocation(),
|
||||||
tr(obs_module_text(
|
tr(obs_module_text(
|
||||||
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType")));
|
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType")));
|
||||||
if (directory.isEmpty()) {
|
if (directory.isEmpty()) {
|
||||||
@@ -310,7 +262,7 @@ void AdvSceneSwitcher::on_exportSettings_clicked()
|
|||||||
}
|
}
|
||||||
|
|
||||||
obs_data_t *obj = obs_data_create();
|
obs_data_t *obj = obs_data_create();
|
||||||
switcher->saveSettings(obj);
|
switcher->SaveSettings(obj);
|
||||||
obs_data_save_json(obj, file.fileName().toUtf8().constData());
|
obs_data_save_json(obj, file.fileName().toUtf8().constData());
|
||||||
obs_data_release(obj);
|
obs_data_release(obj);
|
||||||
}
|
}
|
||||||
@@ -350,7 +302,7 @@ void AdvSceneSwitcher::on_importSettings_clicked()
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->loadSettings(obj);
|
switcher->LoadSettings(obj);
|
||||||
obs_data_release(obj);
|
obs_data_release(obj);
|
||||||
switcher->lastImportPath = path.toStdString();
|
switcher->lastImportPath = path.toStdString();
|
||||||
|
|
||||||
@@ -366,7 +318,7 @@ void AdvSceneSwitcher::on_importSettings_clicked()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int findTabIndex(QTabWidget *tabWidget, int pos)
|
static int findTabIndex(QTabWidget *tabWidget, int pos)
|
||||||
{
|
{
|
||||||
int at = -1;
|
int at = -1;
|
||||||
|
|
||||||
@@ -440,10 +392,10 @@ int findTabIndex(QTabWidget *tabWidget, int pos)
|
|||||||
return at;
|
return at;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setTabOrder()
|
void AdvSceneSwitcher::SetTabOrder()
|
||||||
{
|
{
|
||||||
if (!switcher->tabOrderValid()) {
|
if (!switcher->TabOrderValid()) {
|
||||||
switcher->resetTabOrder();
|
switcher->ResetTabOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
QTabBar *bar = ui->tabWidget->tabBar();
|
QTabBar *bar = ui->tabWidget->tabBar();
|
||||||
@@ -458,22 +410,22 @@ void AdvSceneSwitcher::setTabOrder()
|
|||||||
connect(bar, &QTabBar::tabMoved, this, &AdvSceneSwitcher::on_tabMoved);
|
connect(bar, &QTabBar::tabMoved, this, &AdvSceneSwitcher::on_tabMoved);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setCurrentTab()
|
void AdvSceneSwitcher::SetCurrentTab()
|
||||||
{
|
{
|
||||||
if (switcher->lastOpenedTab >= 0) {
|
if (switcher->lastOpenedTab >= 0) {
|
||||||
ui->tabWidget->setCurrentIndex(switcher->lastOpenedTab);
|
ui->tabWidget->setCurrentIndex(switcher->lastOpenedTab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::restoreWindowGeo()
|
void AdvSceneSwitcher::RestoreWindowGeo()
|
||||||
{
|
{
|
||||||
if (switcher->saveWindowGeo && windowPosValid(switcher->windowPos)) {
|
if (switcher->saveWindowGeo && WindowPosValid(switcher->windowPos)) {
|
||||||
this->resize(switcher->windowSize);
|
this->resize(switcher->windowSize);
|
||||||
this->move(switcher->windowPos);
|
this->move(switcher->windowPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::checkFirstTimeSetup()
|
void AdvSceneSwitcher::CheckFirstTimeSetup()
|
||||||
{
|
{
|
||||||
if (switcher->firstBoot && !switcher->disableHints) {
|
if (switcher->firstBoot && !switcher->disableHints) {
|
||||||
switcher->firstBoot = false;
|
switcher->firstBoot = false;
|
||||||
@@ -494,7 +446,7 @@ void AdvSceneSwitcher::on_tabMoved(int from, int to)
|
|||||||
void AdvSceneSwitcher::on_tabWidget_currentChanged(int)
|
void AdvSceneSwitcher::on_tabWidget_currentChanged(int)
|
||||||
{
|
{
|
||||||
switcher->showFrame = false;
|
switcher->showFrame = false;
|
||||||
clearFrames(ui->screenRegionSwitches);
|
ClearFrames(ui->screenRegionSwitches);
|
||||||
SetShowFrames();
|
SetShowFrames();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,7 +483,7 @@ void AdvSceneSwitcher::on_adjustActiveTransitionType_stateChanged(int state)
|
|||||||
switcher->adjustActiveTransitionType = state;
|
switcher->adjustActiveTransitionType = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::loadSettings(obs_data_t *obj)
|
void SwitcherData::LoadSettings(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
return;
|
return;
|
||||||
@@ -540,9 +492,9 @@ void SwitcherData::loadSettings(obs_data_t *obj)
|
|||||||
// Needs to be loaded before any entries which might rely on scene group
|
// Needs to be loaded before any entries which might rely on scene group
|
||||||
// selections to be available.
|
// selections to be available.
|
||||||
loadSceneGroups(obj);
|
loadSceneGroups(obj);
|
||||||
loadVariables(obj);
|
LoadVariables(obj);
|
||||||
loadMacros(obj);
|
LoadConnections(obj);
|
||||||
loadConnections(obj);
|
LoadMacros(obj);
|
||||||
loadWindowTitleSwitches(obj);
|
loadWindowTitleSwitches(obj);
|
||||||
loadScreenRegionSwitches(obj);
|
loadScreenRegionSwitches(obj);
|
||||||
loadPauseSwitches(obj);
|
loadPauseSwitches(obj);
|
||||||
@@ -558,24 +510,24 @@ void SwitcherData::loadSettings(obs_data_t *obj)
|
|||||||
loadVideoSwitches(obj);
|
loadVideoSwitches(obj);
|
||||||
loadNetworkSettings(obj);
|
loadNetworkSettings(obj);
|
||||||
loadSceneTriggers(obj);
|
loadSceneTriggers(obj);
|
||||||
loadGeneralSettings(obj);
|
LoadGeneralSettings(obj);
|
||||||
loadHotkeys(obj);
|
LoadHotkeys(obj);
|
||||||
loadUISettings(obj);
|
LoadUISettings(obj);
|
||||||
|
|
||||||
// Reset on startup and scene collection change
|
// Reset on startup and scene collection change
|
||||||
switcher->lastOpenedTab = -1;
|
switcher->lastOpenedTab = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::saveSettings(obs_data_t *obj)
|
void SwitcherData::SaveSettings(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
saveSceneGroups(obj);
|
saveSceneGroups(obj);
|
||||||
saveMacros(obj);
|
SaveMacros(obj);
|
||||||
saveConnections(obj);
|
SaveConnections(obj);
|
||||||
saveVariables(obj);
|
SaveVariables(obj);
|
||||||
saveWindowTitleSwitches(obj);
|
saveWindowTitleSwitches(obj);
|
||||||
saveScreenRegionSwitches(obj);
|
saveScreenRegionSwitches(obj);
|
||||||
savePauseSwitches(obj);
|
savePauseSwitches(obj);
|
||||||
@@ -591,27 +543,29 @@ void SwitcherData::saveSettings(obs_data_t *obj)
|
|||||||
saveVideoSwitches(obj);
|
saveVideoSwitches(obj);
|
||||||
saveNetworkSwitches(obj);
|
saveNetworkSwitches(obj);
|
||||||
saveSceneTriggers(obj);
|
saveSceneTriggers(obj);
|
||||||
saveGeneralSettings(obj);
|
SaveGeneralSettings(obj);
|
||||||
saveHotkeys(obj);
|
SaveHotkeys(obj);
|
||||||
saveUISettings(obj);
|
SaveUISettings(obj);
|
||||||
saveVersion(obj, g_GIT_SHA1);
|
SaveVersion(obj, g_GIT_SHA1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
obs_data_set_int(obj, "interval", interval);
|
obs_data_set_int(obj, "interval", interval);
|
||||||
|
|
||||||
std::string nonMatchingSceneName = GetWeakSourceName(nonMatchingScene);
|
std::string nonMatchingSceneName = GetWeakSourceName(nonMatchingScene);
|
||||||
obs_data_set_string(obj, "non_matching_scene",
|
obs_data_set_string(obj, "non_matching_scene",
|
||||||
nonMatchingSceneName.c_str());
|
nonMatchingSceneName.c_str());
|
||||||
obs_data_set_int(obj, "switch_if_not_matching", switchIfNotMatching);
|
obs_data_set_int(obj, "switch_if_not_matching",
|
||||||
noMatchDelay.Save(obj, "noMatchDelay", "noMatchDelayUnit");
|
static_cast<int>(switchIfNotMatching));
|
||||||
|
noMatchDelay.Save(obj, "noMatchDelay");
|
||||||
|
|
||||||
cooldown.Save(obj, "cooldown", "cooldownUnit");
|
cooldown.Save(obj, "cooldown");
|
||||||
|
|
||||||
obs_data_set_bool(obj, "active", sceneColletionStop ? true : !stop);
|
obs_data_set_bool(obj, "active", sceneColletionStop ? true : !stop);
|
||||||
sceneColletionStop = false;
|
sceneColletionStop = false;
|
||||||
obs_data_set_int(obj, "startup_behavior", startupBehavior);
|
obs_data_set_int(obj, "startup_behavior",
|
||||||
|
static_cast<int>(startupBehavior));
|
||||||
|
|
||||||
obs_data_set_int(obj, "autoStartEvent",
|
obs_data_set_int(obj, "autoStartEvent",
|
||||||
static_cast<int>(autoStartEvent));
|
static_cast<int>(autoStartEvent));
|
||||||
@@ -620,6 +574,7 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
|||||||
obs_data_set_bool(obj, "showSystemTrayNotifications",
|
obs_data_set_bool(obj, "showSystemTrayNotifications",
|
||||||
showSystemTrayNotifications);
|
showSystemTrayNotifications);
|
||||||
obs_data_set_bool(obj, "disableHints", disableHints);
|
obs_data_set_bool(obj, "disableHints", disableHints);
|
||||||
|
obs_data_set_bool(obj, "warnPluginLoadFailure", warnPluginLoadFailure);
|
||||||
obs_data_set_bool(obj, "hideLegacyTabs", hideLegacyTabs);
|
obs_data_set_bool(obj, "hideLegacyTabs", hideLegacyTabs);
|
||||||
|
|
||||||
obs_data_set_int(obj, "priority0", functionNamesByPriority[0]);
|
obs_data_set_int(obj, "priority0", functionNamesByPriority[0]);
|
||||||
@@ -636,83 +591,55 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
|||||||
|
|
||||||
obs_data_set_int(obj, "threadPriority", threadPriority);
|
obs_data_set_int(obj, "threadPriority", threadPriority);
|
||||||
|
|
||||||
obs_data_set_bool(obj, "tansitionOverrideOverride",
|
obs_data_set_bool(obj, "transitionOverrideOverride",
|
||||||
transitionOverrideOverride);
|
transitionOverrideOverride);
|
||||||
obs_data_set_default_bool(obj, "adjustActiveTransitionType",
|
|
||||||
adjustActiveTransitionType);
|
|
||||||
obs_data_set_bool(obj, "adjustActiveTransitionType",
|
obs_data_set_bool(obj, "adjustActiveTransitionType",
|
||||||
adjustActiveTransitionType);
|
adjustActiveTransitionType);
|
||||||
|
|
||||||
obs_data_set_string(obj, "lastImportPath", lastImportPath.c_str());
|
obs_data_set_string(obj, "lastImportPath", lastImportPath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
void SwitcherData::LoadGeneralSettings(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
obs_data_set_default_int(obj, "interval", default_interval);
|
obs_data_set_default_int(obj, "interval", default_interval);
|
||||||
interval = obs_data_get_int(obj, "interval");
|
interval = obs_data_get_int(obj, "interval");
|
||||||
|
|
||||||
obs_data_set_default_int(obj, "switch_if_not_matching", NO_SWITCH);
|
obs_data_set_default_int(obj, "switch_if_not_matching",
|
||||||
|
static_cast<int>(NoMatch::NO_SWITCH));
|
||||||
switchIfNotMatching =
|
switchIfNotMatching =
|
||||||
(NoMatch)obs_data_get_int(obj, "switch_if_not_matching");
|
(NoMatch)obs_data_get_int(obj, "switch_if_not_matching");
|
||||||
std::string nonMatchingSceneName =
|
std::string nonMatchingSceneName =
|
||||||
obs_data_get_string(obj, "non_matching_scene");
|
obs_data_get_string(obj, "non_matching_scene");
|
||||||
nonMatchingScene = GetWeakSourceByName(nonMatchingSceneName.c_str());
|
nonMatchingScene = GetWeakSourceByName(nonMatchingSceneName.c_str());
|
||||||
noMatchDelay.Load(obj, "noMatchDelay", "noMatchDelayUnit");
|
noMatchDelay.Load(obj, "noMatchDelay");
|
||||||
|
|
||||||
cooldown.Load(obj, "cooldown", "cooldownUnit");
|
cooldown.Load(obj, "cooldown");
|
||||||
|
|
||||||
stop = !obs_data_get_bool(obj, "active");
|
stop = !obs_data_get_bool(obj, "active");
|
||||||
startupBehavior =
|
startupBehavior =
|
||||||
(StartupBehavior)obs_data_get_int(obj, "startup_behavior");
|
(StartupBehavior)obs_data_get_int(obj, "startup_behavior");
|
||||||
if (startupBehavior == START) {
|
if (startupBehavior == StartupBehavior::START) {
|
||||||
stop = false;
|
stop = false;
|
||||||
}
|
}
|
||||||
if (startupBehavior == STOP) {
|
if (startupBehavior == StartupBehavior::STOP) {
|
||||||
stop = true;
|
stop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
autoStartEvent = static_cast<AutoStartEvent>(
|
autoStartEvent =
|
||||||
obs_data_get_int(obj, "autoStartEvent"));
|
static_cast<AutoStart>(obs_data_get_int(obj, "autoStartEvent"));
|
||||||
|
|
||||||
verbose = obs_data_get_bool(obj, "verbose");
|
verbose = obs_data_get_bool(obj, "verbose");
|
||||||
showSystemTrayNotifications =
|
showSystemTrayNotifications =
|
||||||
obs_data_get_bool(obj, "showSystemTrayNotifications");
|
obs_data_get_bool(obj, "showSystemTrayNotifications");
|
||||||
disableHints = obs_data_get_bool(obj, "disableHints");
|
disableHints = obs_data_get_bool(obj, "disableHints");
|
||||||
|
obs_data_set_default_bool(obj, "warnPluginLoadFailure", true);
|
||||||
|
warnPluginLoadFailure = obs_data_get_bool(obj, "warnPluginLoadFailure");
|
||||||
obs_data_set_default_bool(obj, "hideLegacyTabs", true);
|
obs_data_set_default_bool(obj, "hideLegacyTabs", true);
|
||||||
hideLegacyTabs = obs_data_get_bool(obj, "hideLegacyTabs");
|
hideLegacyTabs = obs_data_get_bool(obj, "hideLegacyTabs");
|
||||||
|
|
||||||
obs_data_set_default_int(obj, "priority0", default_priority_0);
|
SetDefaultFunctionPriorities(obj);
|
||||||
obs_data_set_default_int(obj, "priority1", default_priority_1);
|
if (!PrioFuncsValid()) {
|
||||||
obs_data_set_default_int(obj, "priority2", default_priority_2);
|
functionNamesByPriority = GetDefaultFunctionPriorityList();
|
||||||
obs_data_set_default_int(obj, "priority3", default_priority_3);
|
|
||||||
obs_data_set_default_int(obj, "priority4", default_priority_4);
|
|
||||||
obs_data_set_default_int(obj, "priority5", default_priority_5);
|
|
||||||
obs_data_set_default_int(obj, "priority6", default_priority_6);
|
|
||||||
obs_data_set_default_int(obj, "priority7", default_priority_7);
|
|
||||||
obs_data_set_default_int(obj, "priority8", default_priority_8);
|
|
||||||
|
|
||||||
functionNamesByPriority[0] = (obs_data_get_int(obj, "priority0"));
|
|
||||||
functionNamesByPriority[1] = (obs_data_get_int(obj, "priority1"));
|
|
||||||
functionNamesByPriority[2] = (obs_data_get_int(obj, "priority2"));
|
|
||||||
functionNamesByPriority[3] = (obs_data_get_int(obj, "priority3"));
|
|
||||||
functionNamesByPriority[4] = (obs_data_get_int(obj, "priority4"));
|
|
||||||
functionNamesByPriority[5] = (obs_data_get_int(obj, "priority5"));
|
|
||||||
functionNamesByPriority[6] = (obs_data_get_int(obj, "priority6"));
|
|
||||||
functionNamesByPriority[7] = (obs_data_get_int(obj, "priority7"));
|
|
||||||
functionNamesByPriority[8] = (obs_data_get_int(obj, "priority8"));
|
|
||||||
functionNamesByPriority[9] = (obs_data_get_int(obj, "priority9"));
|
|
||||||
functionNamesByPriority[10] = (obs_data_get_int(obj, "priority10"));
|
|
||||||
if (!prioFuncsValid()) {
|
|
||||||
functionNamesByPriority[0] = (default_priority_0);
|
|
||||||
functionNamesByPriority[1] = (default_priority_1);
|
|
||||||
functionNamesByPriority[2] = (default_priority_2);
|
|
||||||
functionNamesByPriority[3] = (default_priority_3);
|
|
||||||
functionNamesByPriority[4] = (default_priority_4);
|
|
||||||
functionNamesByPriority[5] = (default_priority_5);
|
|
||||||
functionNamesByPriority[6] = (default_priority_6);
|
|
||||||
functionNamesByPriority[7] = (default_priority_7);
|
|
||||||
functionNamesByPriority[8] = (default_priority_8);
|
|
||||||
functionNamesByPriority[9] = (default_priority_9);
|
|
||||||
functionNamesByPriority[10] = (default_priority_10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_data_set_default_int(obj, "threadPriority",
|
obs_data_set_default_int(obj, "threadPriority",
|
||||||
@@ -720,14 +647,21 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
|||||||
threadPriority = obs_data_get_int(obj, "threadPriority");
|
threadPriority = obs_data_get_int(obj, "threadPriority");
|
||||||
|
|
||||||
transitionOverrideOverride =
|
transitionOverrideOverride =
|
||||||
obs_data_get_bool(obj, "tansitionOverrideOverride");
|
obs_data_get_bool(obj, "transitionOverrideOverride");
|
||||||
adjustActiveTransitionType =
|
adjustActiveTransitionType =
|
||||||
obs_data_get_bool(obj, "adjustActiveTransitionType");
|
obs_data_get_bool(obj, "adjustActiveTransitionType");
|
||||||
|
|
||||||
|
if (!transitionOverrideOverride && !adjustActiveTransitionType) {
|
||||||
|
blog(LOG_INFO,
|
||||||
|
"reset transition behaviour to adjust active transition type");
|
||||||
|
adjustActiveTransitionType = true;
|
||||||
|
}
|
||||||
|
|
||||||
lastImportPath = obs_data_get_string(obj, "lastImportPath");
|
lastImportPath = obs_data_get_string(obj, "lastImportPath");
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveSplitterPos(QList<int> &sizes, obs_data_t *obj, const std::string name)
|
static void saveSplitterPos(QList<int> &sizes, obs_data_t *obj,
|
||||||
|
const std::string name)
|
||||||
{
|
{
|
||||||
auto array = obs_data_array_create();
|
auto array = obs_data_array_create();
|
||||||
for (int i = 0; i < sizes.count(); ++i) {
|
for (int i = 0; i < sizes.count(); ++i) {
|
||||||
@@ -740,7 +674,8 @@ void saveSplitterPos(QList<int> &sizes, obs_data_t *obj, const std::string name)
|
|||||||
obs_data_array_release(array);
|
obs_data_array_release(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadSplitterPos(QList<int> &sizes, obs_data_t *obj, const std::string name)
|
static void loadSplitterPos(QList<int> &sizes, obs_data_t *obj,
|
||||||
|
const std::string name)
|
||||||
{
|
{
|
||||||
sizes.clear();
|
sizes.clear();
|
||||||
obs_data_array_t *array = obs_data_get_array(obj, name.c_str());
|
obs_data_array_t *array = obs_data_get_array(obj, name.c_str());
|
||||||
@@ -753,7 +688,7 @@ void loadSplitterPos(QList<int> &sizes, obs_data_t *obj, const std::string name)
|
|||||||
obs_data_array_release(array);
|
obs_data_array_release(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::saveUISettings(obs_data_t *obj)
|
void SwitcherData::SaveUISettings(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
obs_data_set_int(obj, "generalTabPos", tabOrder[0]);
|
obs_data_set_int(obj, "generalTabPos", tabOrder[0]);
|
||||||
obs_data_set_int(obj, "macroTabPos", tabOrder[1]);
|
obs_data_set_int(obj, "macroTabPos", tabOrder[1]);
|
||||||
@@ -786,7 +721,7 @@ void SwitcherData::saveUISettings(obs_data_t *obj)
|
|||||||
"macroListMacroEditSplitterPosition");
|
"macroListMacroEditSplitterPosition");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::loadUISettings(obs_data_t *obj)
|
void SwitcherData::LoadUISettings(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
obs_data_set_default_int(obj, "generalTabPos", 0);
|
obs_data_set_default_int(obj, "generalTabPos", 0);
|
||||||
obs_data_set_default_int(obj, "macroTabPos", 1);
|
obs_data_set_default_int(obj, "macroTabPos", 1);
|
||||||
@@ -827,8 +762,8 @@ void SwitcherData::loadUISettings(obs_data_t *obj)
|
|||||||
tabOrder.emplace_back((int)(obs_data_get_int(obj, "sceneGroupTabPos")));
|
tabOrder.emplace_back((int)(obs_data_get_int(obj, "sceneGroupTabPos")));
|
||||||
tabOrder.emplace_back((int)(obs_data_get_int(obj, "triggerTabPos")));
|
tabOrder.emplace_back((int)(obs_data_get_int(obj, "triggerTabPos")));
|
||||||
|
|
||||||
if (!tabOrderValid()) {
|
if (!TabOrderValid()) {
|
||||||
resetTabOrder();
|
ResetTabOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
saveWindowGeo = obs_data_get_bool(obj, "saveWindowGeo");
|
saveWindowGeo = obs_data_get_bool(obj, "saveWindowGeo");
|
||||||
@@ -842,7 +777,7 @@ void SwitcherData::loadUISettings(obs_data_t *obj)
|
|||||||
"macroListMacroEditSplitterPosition");
|
"macroListMacroEditSplitterPosition");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SwitcherData::tabOrderValid()
|
bool SwitcherData::TabOrderValid()
|
||||||
{
|
{
|
||||||
auto tmp = std::vector<int>(tab_count);
|
auto tmp = std::vector<int>(tab_count);
|
||||||
std::iota(tmp.begin(), tmp.end(), 0);
|
std::iota(tmp.begin(), tmp.end(), 0);
|
||||||
@@ -856,13 +791,13 @@ bool SwitcherData::tabOrderValid()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::resetTabOrder()
|
void SwitcherData::ResetTabOrder()
|
||||||
{
|
{
|
||||||
tabOrder = std::vector<int>(tab_count);
|
tabOrder = std::vector<int>(tab_count);
|
||||||
std::iota(tabOrder.begin(), tabOrder.end(), 0);
|
std::iota(tabOrder.begin(), tabOrder.end(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::checkNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
void SwitcherData::CheckNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
||||||
OBSWeakSource &transition, int &sleep)
|
OBSWeakSource &transition, int &sleep)
|
||||||
{
|
{
|
||||||
if (match) {
|
if (match) {
|
||||||
@@ -874,12 +809,12 @@ void SwitcherData::checkNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switchIfNotMatching == SWITCH && nonMatchingScene) {
|
if (switchIfNotMatching == NoMatch::SWITCH && nonMatchingScene) {
|
||||||
match = true;
|
match = true;
|
||||||
scene = nonMatchingScene;
|
scene = nonMatchingScene;
|
||||||
transition = nullptr;
|
transition = nullptr;
|
||||||
}
|
}
|
||||||
if (switchIfNotMatching == RANDOM_SWITCH) {
|
if (switchIfNotMatching == NoMatch::RANDOM_SWITCH) {
|
||||||
match = checkRandom(scene, transition, sleep);
|
match = checkRandom(scene, transition, sleep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -898,7 +833,7 @@ void SwitcherData::checkSwitchCooldown(bool &match)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void populateStartupBehavior(QComboBox *cb)
|
static void populateStartupBehavior(QComboBox *cb)
|
||||||
{
|
{
|
||||||
cb->addItem(obs_module_text(
|
cb->addItem(obs_module_text(
|
||||||
"AdvSceneSwitcher.generalTab.status.onStartup.asLastRun"));
|
"AdvSceneSwitcher.generalTab.status.onStartup.asLastRun"));
|
||||||
@@ -908,7 +843,7 @@ void populateStartupBehavior(QComboBox *cb)
|
|||||||
"AdvSceneSwitcher.generalTab.status.onStartup.doNotStart"));
|
"AdvSceneSwitcher.generalTab.status.onStartup.doNotStart"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void populateAutoStartEventSelection(QComboBox *cb)
|
static void populateAutoStartEventSelection(QComboBox *cb)
|
||||||
{
|
{
|
||||||
cb->addItem(obs_module_text(
|
cb->addItem(obs_module_text(
|
||||||
"AdvSceneSwitcher.generalTab.status.autoStart.never"));
|
"AdvSceneSwitcher.generalTab.status.autoStart.never"));
|
||||||
@@ -920,53 +855,8 @@ void populateAutoStartEventSelection(QComboBox *cb)
|
|||||||
"AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming"));
|
"AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupGeneralTab()
|
static void populatePriorityFunctionList(QListWidget *list)
|
||||||
{
|
{
|
||||||
populateSceneSelection(ui->noMatchSwitchScene, false);
|
|
||||||
|
|
||||||
if (switcher->switchIfNotMatching == SWITCH) {
|
|
||||||
ui->noMatchSwitch->setChecked(true);
|
|
||||||
ui->noMatchSwitchScene->setEnabled(true);
|
|
||||||
} else if (switcher->switchIfNotMatching == NO_SWITCH) {
|
|
||||||
ui->noMatchDontSwitch->setChecked(true);
|
|
||||||
ui->noMatchSwitchScene->setEnabled(false);
|
|
||||||
} else {
|
|
||||||
ui->noMatchRandomSwitch->setChecked(true);
|
|
||||||
ui->noMatchSwitchScene->setEnabled(false);
|
|
||||||
}
|
|
||||||
ui->noMatchSwitchScene->setCurrentText(
|
|
||||||
GetWeakSourceName(switcher->nonMatchingScene).c_str());
|
|
||||||
|
|
||||||
DurationSelection *noMatchDelay = new DurationSelection();
|
|
||||||
noMatchDelay->SetDuration(switcher->noMatchDelay);
|
|
||||||
noMatchDelay->setToolTip(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip"));
|
|
||||||
ui->noMatchLayout->addWidget(noMatchDelay);
|
|
||||||
QWidget::connect(noMatchDelay, SIGNAL(DurationChanged(double)), this,
|
|
||||||
SLOT(NoMatchDelayDurationChanged(double)));
|
|
||||||
QWidget::connect(noMatchDelay, SIGNAL(UnitChanged(DurationUnit)), this,
|
|
||||||
SLOT(NoMatchDelayUnitChanged(DurationUnit)));
|
|
||||||
|
|
||||||
ui->checkInterval->setValue(switcher->interval);
|
|
||||||
|
|
||||||
DurationSelection *cooldownTime = new DurationSelection();
|
|
||||||
cooldownTime->SetDuration(switcher->cooldown);
|
|
||||||
cooldownTime->setToolTip(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint"));
|
|
||||||
ui->cooldownLayout->addWidget(cooldownTime);
|
|
||||||
ui->cooldownLayout->addStretch();
|
|
||||||
QWidget::connect(cooldownTime, SIGNAL(DurationChanged(double)), this,
|
|
||||||
SLOT(CooldownDurationChanged(double)));
|
|
||||||
QWidget::connect(cooldownTime, SIGNAL(UnitChanged(DurationUnit)), this,
|
|
||||||
SLOT(CooldownUnitChanged(DurationUnit)));
|
|
||||||
|
|
||||||
ui->verboseLogging->setChecked(switcher->verbose);
|
|
||||||
ui->saveWindowGeo->setChecked(switcher->saveWindowGeo);
|
|
||||||
ui->showTrayNotifications->setChecked(
|
|
||||||
switcher->showSystemTrayNotifications);
|
|
||||||
ui->uiHintsDisable->setChecked(switcher->disableHints);
|
|
||||||
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
|
|
||||||
|
|
||||||
for (int p : switcher->functionNamesByPriority) {
|
for (int p : switcher->functionNamesByPriority) {
|
||||||
std::string s = "";
|
std::string s = "";
|
||||||
switch (p) {
|
switch (p) {
|
||||||
@@ -1016,26 +906,114 @@ void AdvSceneSwitcher::setupGeneralTab()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
QString text(s.c_str());
|
QString text(s.c_str());
|
||||||
QListWidgetItem *item =
|
QListWidgetItem *item = new QListWidgetItem(text, list);
|
||||||
new QListWidgetItem(text, ui->priorityList);
|
|
||||||
item->setData(Qt::UserRole, text);
|
item->setData(Qt::UserRole, text);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void populateThreadPriorityList(QComboBox *list)
|
||||||
|
{
|
||||||
for (int i = 0; i < (int)switcher->threadPriorities.size(); ++i) {
|
for (int i = 0; i < (int)switcher->threadPriorities.size(); ++i) {
|
||||||
ui->threadPriority->addItem(
|
list->addItem(switcher->threadPriorities[i].name.c_str());
|
||||||
switcher->threadPriorities[i].name.c_str());
|
list->setItemData(
|
||||||
ui->threadPriority->setItemData(
|
|
||||||
i, switcher->threadPriorities[i].description.c_str(),
|
i, switcher->threadPriorities[i].description.c_str(),
|
||||||
Qt::ToolTipRole);
|
Qt::ToolTipRole);
|
||||||
if (switcher->threadPriority ==
|
if (switcher->threadPriority ==
|
||||||
switcher->threadPriorities[i].value) {
|
switcher->threadPriorities[i].value) {
|
||||||
ui->threadPriority->setCurrentText(
|
list->setCurrentText(
|
||||||
switcher->threadPriorities[i].name.c_str());
|
switcher->threadPriorities[i].name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isGeneralTab(const QString &name)
|
||||||
|
{
|
||||||
|
return name == obs_module_text("AdvSceneSwitcher.generalTab.title");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getGeneralTabIdx(QTabWidget *tabWidget)
|
||||||
|
{
|
||||||
|
for (int idx = 0; idx < tabWidget->count(); idx++) {
|
||||||
|
if (isGeneralTab(tabWidget->tabText(idx))) {
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setupGeneralTabInactiveWarning(QTabWidget *tabs)
|
||||||
|
{
|
||||||
|
auto callback = [tabs]() {
|
||||||
|
const bool isRunning = switcher && switcher->th &&
|
||||||
|
switcher->th->isRunning();
|
||||||
|
auto idx = getGeneralTabIdx(tabs);
|
||||||
|
tabs->setTabIcon(
|
||||||
|
idx,
|
||||||
|
isRunning ? QIcon()
|
||||||
|
: QIcon::fromTheme(
|
||||||
|
"obs",
|
||||||
|
QIcon(":/res/images/warning.svg")));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto inactiveTimer = new QTimer(tabs);
|
||||||
|
inactiveTimer->setInterval(1000);
|
||||||
|
QObject::connect(inactiveTimer, &QTimer::timeout, callback);
|
||||||
|
inactiveTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::SetupGeneralTab()
|
||||||
|
{
|
||||||
|
PopulateSceneSelection(ui->noMatchSwitchScene, false);
|
||||||
|
|
||||||
|
if (switcher->switchIfNotMatching == SwitcherData::NoMatch::SWITCH) {
|
||||||
|
ui->noMatchSwitch->setChecked(true);
|
||||||
|
ui->noMatchSwitchScene->setEnabled(true);
|
||||||
|
} else if (switcher->switchIfNotMatching ==
|
||||||
|
SwitcherData::NoMatch::NO_SWITCH) {
|
||||||
|
ui->noMatchDontSwitch->setChecked(true);
|
||||||
|
ui->noMatchSwitchScene->setEnabled(false);
|
||||||
|
} else {
|
||||||
|
ui->noMatchRandomSwitch->setChecked(true);
|
||||||
|
ui->noMatchSwitchScene->setEnabled(false);
|
||||||
|
}
|
||||||
|
ui->noMatchSwitchScene->setCurrentText(
|
||||||
|
GetWeakSourceName(switcher->nonMatchingScene).c_str());
|
||||||
|
|
||||||
|
DurationSelection *noMatchDelay = new DurationSelection();
|
||||||
|
noMatchDelay->SetDuration(switcher->noMatchDelay);
|
||||||
|
noMatchDelay->setToolTip(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip"));
|
||||||
|
ui->noMatchLayout->addWidget(noMatchDelay);
|
||||||
|
QWidget::connect(noMatchDelay,
|
||||||
|
SIGNAL(DurationChanged(const Duration &)), this,
|
||||||
|
SLOT(NoMatchDelayDurationChanged(const Duration &)));
|
||||||
|
|
||||||
|
ui->checkInterval->setValue(switcher->interval);
|
||||||
|
|
||||||
|
DurationSelection *cooldownTime = new DurationSelection();
|
||||||
|
cooldownTime->SetDuration(switcher->cooldown);
|
||||||
|
cooldownTime->setToolTip(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint"));
|
||||||
|
ui->cooldownLayout->addWidget(cooldownTime);
|
||||||
|
ui->cooldownLayout->addStretch();
|
||||||
|
QWidget::connect(cooldownTime,
|
||||||
|
SIGNAL(DurationChanged(const Duration &)), this,
|
||||||
|
SLOT(CooldownDurationChanged(const Duration &)));
|
||||||
|
|
||||||
|
ui->verboseLogging->setChecked(switcher->verbose);
|
||||||
|
ui->saveWindowGeo->setChecked(switcher->saveWindowGeo);
|
||||||
|
ui->showTrayNotifications->setChecked(
|
||||||
|
switcher->showSystemTrayNotifications);
|
||||||
|
ui->uiHintsDisable->setChecked(switcher->disableHints);
|
||||||
|
ui->warnPluginLoadFailure->setChecked(switcher->warnPluginLoadFailure);
|
||||||
|
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
|
||||||
|
|
||||||
|
populatePriorityFunctionList(ui->priorityList);
|
||||||
|
populateThreadPriorityList(ui->threadPriority);
|
||||||
|
|
||||||
populateStartupBehavior(ui->startupBehavior);
|
populateStartupBehavior(ui->startupBehavior);
|
||||||
ui->startupBehavior->setCurrentIndex(switcher->startupBehavior);
|
ui->startupBehavior->setCurrentIndex(
|
||||||
|
static_cast<int>(switcher->startupBehavior));
|
||||||
|
|
||||||
populateAutoStartEventSelection(ui->autoStartEvent);
|
populateAutoStartEventSelection(ui->autoStartEvent);
|
||||||
ui->autoStartEvent->setCurrentIndex(
|
ui->autoStartEvent->setCurrentIndex(
|
||||||
@@ -1052,6 +1030,10 @@ void AdvSceneSwitcher::setupGeneralTab()
|
|||||||
// Hide the now empty invisible shell of the statusControl widget
|
// Hide the now empty invisible shell of the statusControl widget
|
||||||
// as otherwise it could block user input
|
// as otherwise it could block user input
|
||||||
statusControl->hide();
|
statusControl->hide();
|
||||||
|
setupGeneralTabInactiveWarning(ui->tabWidget);
|
||||||
|
|
||||||
|
MinimizeSizeOfColumn(ui->statusLayout, 0);
|
||||||
setWindowTitle(windowTitle() + " - " + g_GIT_TAG);
|
setWindowTitle(windowTitle() + " - " + g_GIT_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
#include "hotkey.hpp"
|
#include "hotkey.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
#include <obs-module.h>
|
#include <obs-module.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
std::vector<std::weak_ptr<Hotkey>> Hotkey::_registeredHotkeys = {};
|
std::vector<std::weak_ptr<Hotkey>> Hotkey::_registeredHotkeys = {};
|
||||||
uint32_t Hotkey::_hotkeyCounter = 1;
|
uint32_t Hotkey::_hotkeyCounter = 1;
|
||||||
|
|
||||||
@@ -117,7 +120,7 @@ void Hotkey::ClearAllHotkeys()
|
|||||||
_registeredHotkeys.clear();
|
_registeredHotkeys.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void startHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
static void startHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
||||||
{
|
{
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
if (!(switcher->th && switcher->th->isRunning())) {
|
if (!(switcher->th && switcher->th->isRunning())) {
|
||||||
@@ -126,7 +129,7 @@ void startHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
static void stopHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
||||||
{
|
{
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
if (switcher->th && switcher->th->isRunning()) {
|
if (switcher->th && switcher->th->isRunning()) {
|
||||||
@@ -135,8 +138,8 @@ void stopHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void startStopToggleHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
static void startStopToggleHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||||
bool pressed)
|
bool pressed)
|
||||||
{
|
{
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
if (switcher->th && switcher->th->isRunning()) {
|
if (switcher->th && switcher->th->isRunning()) {
|
||||||
@@ -147,8 +150,8 @@ void startStopToggleHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void upMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
static void upMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||||
bool pressed)
|
bool pressed)
|
||||||
{
|
{
|
||||||
if (pressed && switcher->settingsWindowOpened &&
|
if (pressed && switcher->settingsWindowOpened &&
|
||||||
AdvSceneSwitcher::window) {
|
AdvSceneSwitcher::window) {
|
||||||
@@ -158,8 +161,8 @@ void upMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void downMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
static void downMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||||
bool pressed)
|
bool pressed)
|
||||||
{
|
{
|
||||||
if (pressed && switcher->settingsWindowOpened &&
|
if (pressed && switcher->settingsWindowOpened &&
|
||||||
AdvSceneSwitcher::window) {
|
AdvSceneSwitcher::window) {
|
||||||
@@ -169,8 +172,8 @@ void downMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
static void removeMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||||
bool pressed)
|
bool pressed)
|
||||||
{
|
{
|
||||||
if (pressed && switcher->settingsWindowOpened &&
|
if (pressed && switcher->settingsWindowOpened &&
|
||||||
AdvSceneSwitcher::window) {
|
AdvSceneSwitcher::window) {
|
||||||
@@ -180,7 +183,7 @@ void removeMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerHotkeys()
|
static void registerHotkeys()
|
||||||
{
|
{
|
||||||
switcher->startHotkey = obs_hotkey_register_frontend(
|
switcher->startHotkey = obs_hotkey_register_frontend(
|
||||||
"startSwitcherHotkey",
|
"startSwitcherHotkey",
|
||||||
@@ -213,14 +216,14 @@ void registerHotkeys()
|
|||||||
switcher->hotkeysRegistered = true;
|
switcher->hotkeysRegistered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveHotkey(obs_data_t *obj, obs_hotkey_id id, const char *name)
|
static void saveHotkey(obs_data_t *obj, obs_hotkey_id id, const char *name)
|
||||||
{
|
{
|
||||||
obs_data_array_t *a = obs_hotkey_save(id);
|
obs_data_array_t *a = obs_hotkey_save(id);
|
||||||
obs_data_set_array(obj, name, a);
|
obs_data_set_array(obj, name, a);
|
||||||
obs_data_array_release(a);
|
obs_data_array_release(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::saveHotkeys(obs_data_t *obj)
|
void SwitcherData::SaveHotkeys(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
saveHotkey(obj, startHotkey, "startHotkey");
|
saveHotkey(obj, startHotkey, "startHotkey");
|
||||||
saveHotkey(obj, stopHotkey, "stopHotkey");
|
saveHotkey(obj, stopHotkey, "stopHotkey");
|
||||||
@@ -230,14 +233,14 @@ void SwitcherData::saveHotkeys(obs_data_t *obj)
|
|||||||
saveHotkey(obj, removeMacroSegment, "removeMacroSegmentHotkey");
|
saveHotkey(obj, removeMacroSegment, "removeMacroSegmentHotkey");
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadHotkey(obs_data_t *obj, obs_hotkey_id id, const char *name)
|
static void loadHotkey(obs_data_t *obj, obs_hotkey_id id, const char *name)
|
||||||
{
|
{
|
||||||
obs_data_array_t *a = obs_data_get_array(obj, name);
|
obs_data_array_t *a = obs_data_get_array(obj, name);
|
||||||
obs_hotkey_load(id, a);
|
obs_hotkey_load(id, a);
|
||||||
obs_data_array_release(a);
|
obs_data_array_release(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::loadHotkeys(obs_data_t *obj)
|
void SwitcherData::LoadHotkeys(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
if (!hotkeysRegistered) {
|
if (!hotkeysRegistered) {
|
||||||
registerHotkeys();
|
registerHotkeys();
|
||||||
@@ -249,3 +252,5 @@ void SwitcherData::loadHotkeys(obs_data_t *obj)
|
|||||||
loadHotkey(obj, downMacroSegment, "downMacroSegmentHotkey");
|
loadHotkey(obj, downMacroSegment, "downMacroSegmentHotkey");
|
||||||
loadHotkey(obj, removeMacroSegment, "removeMacroSegmentHotkey");
|
loadHotkey(obj, removeMacroSegment, "removeMacroSegmentHotkey");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
extern bool canSimulateKeyPresses;
|
extern bool canSimulateKeyPresses;
|
||||||
|
|
||||||
class Hotkey {
|
class Hotkey {
|
||||||
@@ -161,4 +163,4 @@ enum class HotkeyType {
|
|||||||
Key_NumpadEnter
|
Key_NumpadEnter
|
||||||
};
|
};
|
||||||
|
|
||||||
void registerHotkeys();
|
} // namespace advss
|
||||||
|
|||||||
@@ -3,9 +3,12 @@
|
|||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
#include "name-dialog.hpp"
|
#include "name-dialog.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
SceneGroupEditWidget *typeEdit = nullptr;
|
SceneGroupEditWidget *typeEdit = nullptr;
|
||||||
|
|
||||||
@@ -487,9 +490,9 @@ void SwitcherData::loadSceneGroups(obs_data_t *obj)
|
|||||||
obs_data_array_release(sceneGroupArray);
|
obs_data_array_release(sceneGroupArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupSceneGroupTab()
|
void AdvSceneSwitcher::SetupSceneGroupTab()
|
||||||
{
|
{
|
||||||
populateSceneSelection(ui->sceneGroupSceneSelection);
|
PopulateSceneSelection(ui->sceneGroupSceneSelection);
|
||||||
|
|
||||||
for (auto &sg : switcher->sceneGroups) {
|
for (auto &sg : switcher->sceneGroups) {
|
||||||
QString text = QString::fromStdString(sg.name);
|
QString text = QString::fromStdString(sg.name);
|
||||||
@@ -538,7 +541,7 @@ SceneGroupEditWidget::SceneGroupEditWidget()
|
|||||||
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{type}}", type}};
|
{"{{type}}", type}};
|
||||||
placeWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.sceneGroupTab.edit.type"),
|
obs_module_text("AdvSceneSwitcher.sceneGroupTab.edit.type"),
|
||||||
typeLayout, widgetPlaceholders);
|
typeLayout, widgetPlaceholders);
|
||||||
|
|
||||||
@@ -555,7 +558,7 @@ SceneGroupEditWidget::SceneGroupEditWidget()
|
|||||||
countLayout->setContentsMargins(0, 0, 0, 0);
|
countLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
widgetPlaceholders = {{"{{count}}", count}};
|
widgetPlaceholders = {{"{{count}}", count}};
|
||||||
placeWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.sceneGroupTab.edit.count"),
|
obs_module_text("AdvSceneSwitcher.sceneGroupTab.edit.count"),
|
||||||
countLayout, widgetPlaceholders);
|
countLayout, widgetPlaceholders);
|
||||||
|
|
||||||
@@ -573,7 +576,7 @@ SceneGroupEditWidget::SceneGroupEditWidget()
|
|||||||
timeLayout->setContentsMargins(0, 0, 0, 0);
|
timeLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
widgetPlaceholders = {{"{{time}}", time}};
|
widgetPlaceholders = {{"{{time}}", time}};
|
||||||
placeWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.sceneGroupTab.edit.time"),
|
obs_module_text("AdvSceneSwitcher.sceneGroupTab.edit.time"),
|
||||||
timeLayout, widgetPlaceholders);
|
timeLayout, widgetPlaceholders);
|
||||||
|
|
||||||
@@ -705,3 +708,5 @@ SceneGroup *GetSceneGroupByQString(const QString &name)
|
|||||||
{
|
{
|
||||||
return GetSceneGroupByName(name.toUtf8().constData());
|
return GetSceneGroupByName(name.toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <obs.hpp>
|
#include <obs.hpp>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
auto constexpr invalid_scene_group_name = "invalid-scene-group";
|
auto constexpr invalid_scene_group_name = "invalid-scene-group";
|
||||||
|
|
||||||
enum class AdvanceCondition {
|
enum class AdvanceCondition {
|
||||||
@@ -85,3 +87,5 @@ private:
|
|||||||
|
|
||||||
SceneGroup *GetSceneGroupByName(const char *name);
|
SceneGroup *GetSceneGroupByName(const char *name);
|
||||||
SceneGroup *GetSceneGroupByQString(const QString &name);
|
SceneGroup *GetSceneGroupByQString(const QString &name);
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
namespace advss {
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
bool SceneTrigger::pause = false;
|
bool SceneTrigger::pause = false;
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
@@ -156,7 +159,7 @@ void SceneTrigger::logMatch()
|
|||||||
blog(LOG_INFO,
|
blog(LOG_INFO,
|
||||||
"scene '%s' in status '%s' triggering action '%s' after %f seconds",
|
"scene '%s' in status '%s' triggering action '%s' after %f seconds",
|
||||||
GetWeakSourceName(scene).c_str(), statusName.c_str(),
|
GetWeakSourceName(scene).c_str(), statusName.c_str(),
|
||||||
actionName.c_str(), duration.seconds);
|
actionName.c_str(), duration.Seconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
void frontEndActionThread(sceneTriggerAction action, double delay)
|
void frontEndActionThread(sceneTriggerAction action, double delay)
|
||||||
@@ -266,14 +269,14 @@ void SceneTrigger::performAction()
|
|||||||
|
|
||||||
if (isFrontendAction(triggerAction)) {
|
if (isFrontendAction(triggerAction)) {
|
||||||
t = std::thread(frontEndActionThread, triggerAction,
|
t = std::thread(frontEndActionThread, triggerAction,
|
||||||
duration.seconds);
|
duration.Seconds());
|
||||||
} else if (isAudioAction(triggerAction)) {
|
} else if (isAudioAction(triggerAction)) {
|
||||||
bool mute = triggerAction == sceneTriggerAction::MUTE_SOURCE;
|
bool mute = triggerAction == sceneTriggerAction::MUTE_SOURCE;
|
||||||
t = std::thread(muteThread, audioSource, duration.seconds,
|
t = std::thread(muteThread, audioSource, duration.Seconds(),
|
||||||
mute);
|
mute);
|
||||||
} else if (isSwitcherStatusAction(triggerAction)) {
|
} else if (isSwitcherStatusAction(triggerAction)) {
|
||||||
bool stop = triggerAction == sceneTriggerAction::STOP_SWITCHER;
|
bool stop = triggerAction == sceneTriggerAction::STOP_SWITCHER;
|
||||||
t = std::thread(statusThread, duration.seconds, stop);
|
t = std::thread(statusThread, duration.Seconds(), stop);
|
||||||
} else {
|
} else {
|
||||||
blog(LOG_WARNING, "ignoring unknown action '%d'",
|
blog(LOG_WARNING, "ignoring unknown action '%d'",
|
||||||
static_cast<int>(triggerAction));
|
static_cast<int>(triggerAction));
|
||||||
@@ -349,7 +352,7 @@ void SwitcherData::loadSceneTriggers(obs_data_t *obj)
|
|||||||
obs_data_array_release(triggerArray);
|
obs_data_array_release(triggerArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupTriggerTab()
|
void AdvSceneSwitcher::SetupTriggerTab()
|
||||||
{
|
{
|
||||||
for (auto &s : switcher->sceneTriggers) {
|
for (auto &s : switcher->sceneTriggers) {
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
@@ -398,7 +401,7 @@ void SceneTrigger::load(obs_data_t *obj)
|
|||||||
|
|
||||||
static inline void populateTriggers(QComboBox *list)
|
static inline void populateTriggers(QComboBox *list)
|
||||||
{
|
{
|
||||||
addSelectionEntry(
|
AddSelectionEntry(
|
||||||
list,
|
list,
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none"));
|
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none"));
|
||||||
@@ -413,7 +416,7 @@ static inline void populateTriggers(QComboBox *list)
|
|||||||
|
|
||||||
inline void populateActions(QComboBox *list)
|
inline void populateActions(QComboBox *list)
|
||||||
{
|
{
|
||||||
addSelectionEntry(
|
AddSelectionEntry(
|
||||||
list,
|
list,
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none"));
|
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none"));
|
||||||
@@ -460,17 +463,15 @@ SceneTriggerWidget::SceneTriggerWidget(QWidget *parent, SceneTrigger *s)
|
|||||||
SLOT(TriggerTypeChanged(int)));
|
SLOT(TriggerTypeChanged(int)));
|
||||||
QWidget::connect(actions, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(actions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(TriggerActionChanged(int)));
|
SLOT(TriggerActionChanged(int)));
|
||||||
QWidget::connect(duration, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(duration, SIGNAL(DurationChanged(const Duration &)),
|
||||||
SLOT(DurationChanged(double)));
|
this, SLOT(DurationChanged(const Duration &)));
|
||||||
QWidget::connect(duration, SIGNAL(UnitChanged(DurationUnit)), this,
|
|
||||||
SLOT(DurationUnitChanged(DurationUnit)));
|
|
||||||
QWidget::connect(audioSources,
|
QWidget::connect(audioSources,
|
||||||
SIGNAL(currentTextChanged(const QString &)), this,
|
SIGNAL(currentTextChanged(const QString &)), this,
|
||||||
SLOT(AudioSourceChanged(const QString &)));
|
SLOT(AudioSourceChanged(const QString &)));
|
||||||
|
|
||||||
populateTriggers(triggers);
|
populateTriggers(triggers);
|
||||||
populateActions(actions);
|
populateActions(actions);
|
||||||
populateAudioSelection(audioSources);
|
PopulateAudioSelection(audioSources);
|
||||||
|
|
||||||
if (s) {
|
if (s) {
|
||||||
triggers->setCurrentIndex(static_cast<int>(s->triggerType));
|
triggers->setCurrentIndex(static_cast<int>(s->triggerType));
|
||||||
@@ -494,7 +495,7 @@ SceneTriggerWidget::SceneTriggerWidget(QWidget *parent, SceneTrigger *s)
|
|||||||
{"{{audioSources}}", audioSources},
|
{"{{audioSources}}", audioSources},
|
||||||
{"{{duration}}", duration},
|
{"{{duration}}", duration},
|
||||||
{"{{scenes}}", scenes}};
|
{"{{scenes}}", scenes}};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.sceneTriggerTab.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.sceneTriggerTab.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -552,24 +553,14 @@ void SceneTriggerWidget::TriggerActionChanged(int index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneTriggerWidget::DurationChanged(double seconds)
|
void SceneTriggerWidget::DurationChanged(const Duration &duration)
|
||||||
{
|
{
|
||||||
if (loading || !switchData) {
|
if (loading || !switchData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->duration.seconds = seconds;
|
switchData->duration = duration;
|
||||||
}
|
|
||||||
|
|
||||||
void SceneTriggerWidget::DurationUnitChanged(DurationUnit unit)
|
|
||||||
{
|
|
||||||
if (loading || !switchData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switchData->duration.displayUnit = unit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneTriggerWidget::AudioSourceChanged(const QString &text)
|
void SceneTriggerWidget::AudioSourceChanged(const QString &text)
|
||||||
@@ -581,3 +572,5 @@ void SceneTriggerWidget::AudioSourceChanged(const QString &text)
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->audioSource = GetWeakSourceByQString(text);
|
switchData->audioSource = GetWeakSourceByQString(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
enum class sceneTriggerType {
|
enum class sceneTriggerType {
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
SCENE_ACTIVE = 1,
|
SCENE_ACTIVE = 1,
|
||||||
@@ -71,8 +73,7 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void TriggerTypeChanged(int index);
|
void TriggerTypeChanged(int index);
|
||||||
void TriggerActionChanged(int index);
|
void TriggerActionChanged(int index);
|
||||||
void DurationChanged(double seconds);
|
void DurationChanged(const Duration &);
|
||||||
void DurationUnitChanged(DurationUnit unit);
|
|
||||||
void AudioSourceChanged(const QString &text);
|
void AudioSourceChanged(const QString &text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -83,3 +84,5 @@ private:
|
|||||||
|
|
||||||
SceneTrigger *switchData;
|
SceneTrigger *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
#include <float.h>
|
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
#include "volume-control.hpp"
|
#include "volume-control.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
bool AudioSwitch::pause = false;
|
bool AudioSwitch::pause = false;
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
|
|
||||||
@@ -212,7 +215,7 @@ void SwitcherData::loadAudioSwitches(obs_data_t *obj)
|
|||||||
audioFallback.load(obj);
|
audioFallback.load(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupAudioTab()
|
void AdvSceneSwitcher::SetupAudioTab()
|
||||||
{
|
{
|
||||||
for (auto &s : switcher->audioSwitches) {
|
for (auto &s : switcher->audioSwitches) {
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
@@ -438,15 +441,15 @@ AudioSwitchWidget::AudioSwitchWidget(QWidget *parent, AudioSwitch *s)
|
|||||||
SLOT(VolumeThresholdChanged(int)));
|
SLOT(VolumeThresholdChanged(int)));
|
||||||
QWidget::connect(condition, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(condition, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ConditionChanged(int)));
|
SLOT(ConditionChanged(int)));
|
||||||
QWidget::connect(duration, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(duration, SIGNAL(DurationChanged(const Duration &)),
|
||||||
SLOT(DurationChanged(double)));
|
this, SLOT(DurationChanged(const Duration &)));
|
||||||
QWidget::connect(audioSources,
|
QWidget::connect(audioSources,
|
||||||
SIGNAL(currentTextChanged(const QString &)), this,
|
SIGNAL(currentTextChanged(const QString &)), this,
|
||||||
SLOT(SourceChanged(const QString &)));
|
SLOT(SourceChanged(const QString &)));
|
||||||
QWidget::connect(ignoreInactiveSource, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(ignoreInactiveSource, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(IgnoreInactiveChanged(int)));
|
SLOT(IgnoreInactiveChanged(int)));
|
||||||
|
|
||||||
populateAudioSelection(audioSources);
|
PopulateAudioSelection(audioSources);
|
||||||
populateConditionSelection(condition);
|
populateConditionSelection(condition);
|
||||||
|
|
||||||
if (s) {
|
if (s) {
|
||||||
@@ -467,7 +470,7 @@ AudioSwitchWidget::AudioSwitchWidget(QWidget *parent, AudioSwitch *s)
|
|||||||
{"{{ignoreInactiveSource}}", ignoreInactiveSource},
|
{"{{ignoreInactiveSource}}", ignoreInactiveSource},
|
||||||
{"{{scenes}}", scenes},
|
{"{{scenes}}", scenes},
|
||||||
{"{{transitions}}", transitions}};
|
{"{{transitions}}", transitions}};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.audioTab.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.audioTab.entry"),
|
||||||
switchLayout, widgetPlaceholders);
|
switchLayout, widgetPlaceholders);
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
@@ -554,14 +557,14 @@ void AudioSwitchWidget::ConditionChanged(int cond)
|
|||||||
switchData->condition = (audioCondition)cond;
|
switchData->condition = (audioCondition)cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSwitchWidget::DurationChanged(double sec)
|
void AudioSwitchWidget::DurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (loading || !switchData) {
|
if (loading || !switchData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->duration.seconds = sec;
|
switchData->duration = dur;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSwitchWidget::IgnoreInactiveChanged(int state)
|
void AudioSwitchWidget::IgnoreInactiveChanged(int state)
|
||||||
@@ -580,8 +583,8 @@ AudioSwitchFallbackWidget::AudioSwitchFallbackWidget(QWidget *parent,
|
|||||||
{
|
{
|
||||||
duration = new DurationSelection(this, false);
|
duration = new DurationSelection(this, false);
|
||||||
|
|
||||||
QWidget::connect(duration, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(duration, SIGNAL(DurationChanged(const Duration &)),
|
||||||
SLOT(DurationChanged(double)));
|
this, SLOT(DurationChanged(const Duration &)));
|
||||||
|
|
||||||
if (s) {
|
if (s) {
|
||||||
duration->SetDuration(s->duration);
|
duration->SetDuration(s->duration);
|
||||||
@@ -592,7 +595,7 @@ AudioSwitchFallbackWidget::AudioSwitchFallbackWidget(QWidget *parent,
|
|||||||
{"{{scenes}}", scenes},
|
{"{{scenes}}", scenes},
|
||||||
{"{{duration}}", duration},
|
{"{{duration}}", duration},
|
||||||
{"{{transitions}}", transitions}};
|
{"{{transitions}}", transitions}};
|
||||||
placeWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.audioTab.multiMatchfallback"),
|
obs_module_text("AdvSceneSwitcher.audioTab.multiMatchfallback"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
@@ -602,12 +605,14 @@ AudioSwitchFallbackWidget::AudioSwitchFallbackWidget(QWidget *parent,
|
|||||||
loading = false;
|
loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSwitchFallbackWidget::DurationChanged(double sec)
|
void AudioSwitchFallbackWidget::DurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (loading || !switchData) {
|
if (loading || !switchData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->duration.seconds = sec;
|
switchData->duration = dur;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
#include "volume-control.hpp"
|
#include "volume-control.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
constexpr auto audio_func = 8;
|
constexpr auto audio_func = 8;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -75,7 +77,7 @@ private slots:
|
|||||||
void SourceChanged(const QString &text);
|
void SourceChanged(const QString &text);
|
||||||
void VolumeThresholdChanged(int vol);
|
void VolumeThresholdChanged(int vol);
|
||||||
void ConditionChanged(int cond);
|
void ConditionChanged(int cond);
|
||||||
void DurationChanged(double dur);
|
void DurationChanged(const Duration &);
|
||||||
void IgnoreInactiveChanged(int state);
|
void IgnoreInactiveChanged(int state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -96,10 +98,12 @@ public:
|
|||||||
AudioSwitchFallbackWidget(QWidget *parent, AudioSwitchFallback *s);
|
AudioSwitchFallbackWidget(QWidget *parent, AudioSwitchFallback *s);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void DurationChanged(double dur);
|
void DurationChanged(const Duration &dur);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DurationSelection *duration;
|
DurationSelection *duration;
|
||||||
|
|
||||||
AudioSwitchFallback *switchData;
|
AudioSwitchFallback *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
|
#include "platform-funcs.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
bool ExecutableSwitch::pause = false;
|
bool ExecutableSwitch::pause = false;
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
|
|
||||||
@@ -99,7 +103,7 @@ bool SwitcherData::checkExeSwitch(OBSWeakSource &scene,
|
|||||||
bool equals = runningProcesses.contains(s.exe);
|
bool equals = runningProcesses.contains(s.exe);
|
||||||
bool matches = (runningProcesses.indexOf(
|
bool matches = (runningProcesses.indexOf(
|
||||||
QRegularExpression(s.exe)) != -1);
|
QRegularExpression(s.exe)) != -1);
|
||||||
bool focus = (!s.inFocus || isInFocus(s.exe));
|
bool focus = (!s.inFocus || IsInFocus(s.exe));
|
||||||
|
|
||||||
// True if current window is ignored AND switch equals OR matches last window
|
// True if current window is ignored AND switch equals OR matches last window
|
||||||
bool ignore =
|
bool ignore =
|
||||||
@@ -156,7 +160,7 @@ void SwitcherData::loadExecutableSwitches(obs_data_t *obj)
|
|||||||
obs_data_array_release(executableArray);
|
obs_data_array_release(executableArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupExecutableTab()
|
void AdvSceneSwitcher::SetupExecutableTab()
|
||||||
{
|
{
|
||||||
for (auto &s : switcher->executableSwitches) {
|
for (auto &s : switcher->executableSwitches) {
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
@@ -208,7 +212,7 @@ ExecutableSwitchWidget::ExecutableSwitchWidget(QWidget *parent,
|
|||||||
QWidget::connect(requiresFocus, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(requiresFocus, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(FocusChanged(int)));
|
SLOT(FocusChanged(int)));
|
||||||
|
|
||||||
populateProcessSelection(processes);
|
PopulateProcessSelection(processes);
|
||||||
|
|
||||||
processes->setEditable(true);
|
processes->setEditable(true);
|
||||||
processes->setMaxVisibleItems(20);
|
processes->setMaxVisibleItems(20);
|
||||||
@@ -224,7 +228,7 @@ ExecutableSwitchWidget::ExecutableSwitchWidget(QWidget *parent,
|
|||||||
{"{{requiresFocus}}", requiresFocus},
|
{"{{requiresFocus}}", requiresFocus},
|
||||||
{"{{scenes}}", scenes},
|
{"{{scenes}}", scenes},
|
||||||
{"{{transitions}}", transitions}};
|
{"{{transitions}}", transitions}};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.executableTab.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.executableTab.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -272,3 +276,5 @@ void ExecutableSwitchWidget::FocusChanged(int state)
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->inFocus = state;
|
switchData->inFocus = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
constexpr auto exe_func = 3;
|
constexpr auto exe_func = 3;
|
||||||
|
|
||||||
struct ExecutableSwitch : SceneSwitcherEntry {
|
struct ExecutableSwitch : SceneSwitcherEntry {
|
||||||
@@ -42,3 +44,5 @@ private:
|
|||||||
|
|
||||||
ExecutableSwitch *switchData;
|
ExecutableSwitch *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
|
#include "curl-helper.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
@@ -6,9 +11,7 @@
|
|||||||
#include <regex>
|
#include <regex>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
namespace advss {
|
||||||
#include "curl-helper.hpp"
|
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
bool FileSwitch::pause = false;
|
bool FileSwitch::pause = false;
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
@@ -209,7 +212,7 @@ bool matchFileContent(QString &filedata, FileSwitch &s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString text = QString::fromStdString(s.text);
|
QString text = QString::fromStdString(s.text);
|
||||||
return compareIgnoringLineEnding(text, filedata);
|
return CompareIgnoringLineEnding(text, filedata);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkRemoteFileContent(FileSwitch &s)
|
bool checkRemoteFileContent(FileSwitch &s)
|
||||||
@@ -411,7 +414,7 @@ void SwitcherData::loadFileSwitches(obs_data_t *obj)
|
|||||||
fileIO.writePath = obs_data_get_string(obj, "writePath");
|
fileIO.writePath = obs_data_get_string(obj, "writePath");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupFileTab()
|
void AdvSceneSwitcher::SetupFileTab()
|
||||||
{
|
{
|
||||||
ui->remoteFileWarningLabel->setText(
|
ui->remoteFileWarningLabel->setText(
|
||||||
obs_module_text("AdvSceneSwitcher.fileTab.remoteFileWarning1") +
|
obs_module_text("AdvSceneSwitcher.fileTab.remoteFileWarning1") +
|
||||||
@@ -542,11 +545,11 @@ FileSwitchWidget::FileSwitchWidget(QWidget *parent, FileSwitch *s)
|
|||||||
QHBoxLayout *line1Layout = new QHBoxLayout;
|
QHBoxLayout *line1Layout = new QHBoxLayout;
|
||||||
QHBoxLayout *line2Layout = new QHBoxLayout;
|
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||||
QHBoxLayout *line3Layout = new QHBoxLayout;
|
QHBoxLayout *line3Layout = new QHBoxLayout;
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry"),
|
||||||
line1Layout, widgetPlaceholders);
|
line1Layout, widgetPlaceholders);
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry2"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry2"),
|
||||||
line2Layout, widgetPlaceholders, false);
|
line2Layout, widgetPlaceholders, false);
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry3"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry3"),
|
||||||
line3Layout, widgetPlaceholders);
|
line3Layout, widgetPlaceholders);
|
||||||
mainLayout->addLayout(line1Layout);
|
mainLayout->addLayout(line1Layout);
|
||||||
mainLayout->addLayout(line2Layout);
|
mainLayout->addLayout(line2Layout);
|
||||||
@@ -665,3 +668,5 @@ void FileSwitchWidget::CheckFileContentChanged(int state)
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->onlyMatchIfChanged = state;
|
switchData->onlyMatchIfChanged = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -8,8 +8,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
|
#include <QDateTime>
|
||||||
#include <obs-module.h>
|
#include <obs-module.h>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
constexpr auto read_file_func = 0;
|
constexpr auto read_file_func = 0;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -77,3 +80,5 @@ static inline QString MakeFileSwitchName(const QString &scene,
|
|||||||
const QString &fileName,
|
const QString &fileName,
|
||||||
const QString &text, bool useRegex,
|
const QString &text, bool useRegex,
|
||||||
bool useTime, bool onlyMatchIfChanged);
|
bool useTime, bool onlyMatchIfChanged);
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
constexpr auto previous_scene_name = "Previous Scene";
|
||||||
|
constexpr auto current_transition_name = "Current Transition";
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
static inline bool SceneGroupValid(SceneGroup *group)
|
static inline bool SceneGroupValid(SceneGroup *group)
|
||||||
{
|
{
|
||||||
if (group) {
|
if (group) {
|
||||||
@@ -208,9 +214,9 @@ SwitchWidget::SwitchWidget(QWidget *parent, SceneSwitcherEntry *s,
|
|||||||
SIGNAL(SceneGroupRenamed(const QString &, const QString &)),
|
SIGNAL(SceneGroupRenamed(const QString &, const QString &)),
|
||||||
this, SLOT(SceneGroupRename(const QString &, const QString &)));
|
this, SLOT(SceneGroupRename(const QString &, const QString &)));
|
||||||
|
|
||||||
populateSceneSelection(scenes, usePreviousScene, false, false,
|
PopulateSceneSelection(scenes, usePreviousScene, false, false,
|
||||||
addSceneGroup, &switcher->sceneGroups);
|
addSceneGroup, &switcher->sceneGroups);
|
||||||
populateTransitionSelection(transitions, addCurrentTransition);
|
PopulateTransitionSelection(transitions, addCurrentTransition);
|
||||||
|
|
||||||
switchData = s;
|
switchData = s;
|
||||||
showSwitchData();
|
showSwitchData();
|
||||||
@@ -300,3 +306,5 @@ void SwitchWidget::TransitionChanged(const QString &text)
|
|||||||
switchData->transition = GetWeakTransitionByQString(text);
|
switchData->transition = GetWeakTransitionByQString(text);
|
||||||
switchData->useCurrentTransition = switchData->transition == nullptr;
|
switchData->useCurrentTransition = switchData->transition == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "scene-group.hpp"
|
#include "scene-group.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
enum class SwitchTargetType {
|
enum class SwitchTargetType {
|
||||||
Scene,
|
Scene,
|
||||||
SceneGroup,
|
SceneGroup,
|
||||||
@@ -95,3 +97,5 @@ protected:
|
|||||||
|
|
||||||
SceneSwitcherEntry *switchData;
|
SceneSwitcherEntry *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
|
#include "platform-funcs.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
namespace advss {
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
bool IdleData::pause = false;
|
bool IdleData::pause = false;
|
||||||
IdleWidget *idleWidget = nullptr;
|
IdleWidget *idleWidget = nullptr;
|
||||||
@@ -38,7 +42,7 @@ bool SwitcherData::checkIdleSwitch(OBSWeakSource &scene,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ignoreIdle && secondsSinceLastInput() > idleData.time) {
|
if (!ignoreIdle && SecondsSinceLastInput() > idleData.time) {
|
||||||
if (idleData.alreadySwitched) {
|
if (idleData.alreadySwitched) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -205,9 +209,9 @@ void SwitcherData::loadIdleSwitches(obs_data_t *obj)
|
|||||||
idleData.load(obj);
|
idleData.load(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupIdleTab()
|
void AdvSceneSwitcher::SetupIdleTab()
|
||||||
{
|
{
|
||||||
populateWindowSelection(ui->ignoreIdleWindowsWindows);
|
PopulateWindowSelection(ui->ignoreIdleWindowsWindows);
|
||||||
|
|
||||||
for (auto &window : switcher->ignoreIdleWindows) {
|
for (auto &window : switcher->ignoreIdleWindows) {
|
||||||
QString text = QString::fromStdString(window);
|
QString text = QString::fromStdString(window);
|
||||||
@@ -267,7 +271,7 @@ IdleWidget::IdleWidget(QWidget *parent, IdleData *s)
|
|||||||
{"{{duration}}", duration},
|
{"{{duration}}", duration},
|
||||||
{"{{scenes}}", scenes},
|
{"{{scenes}}", scenes},
|
||||||
{"{{transitions}}", transitions}};
|
{"{{transitions}}", transitions}};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.idleTab.idleswitch"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.idleTab.idleswitch"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -285,3 +289,5 @@ void IdleWidget::DurationChanged(int dur)
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->idleData.time = dur;
|
switcher->idleData.time = dur;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
constexpr auto default_idle_time = 60;
|
constexpr auto default_idle_time = 60;
|
||||||
constexpr auto idle_func = 2;
|
constexpr auto idle_func = 2;
|
||||||
|
|
||||||
@@ -36,3 +38,5 @@ private:
|
|||||||
|
|
||||||
IdleData *switchData;
|
IdleData *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
bool MediaSwitch::pause = false;
|
bool MediaSwitch::pause = false;
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
|
|
||||||
@@ -232,7 +235,7 @@ void SwitcherData::loadMediaSwitches(obs_data_t *obj)
|
|||||||
obs_data_array_release(mediaArray);
|
obs_data_array_release(mediaArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupMediaTab()
|
void AdvSceneSwitcher::SetupMediaTab()
|
||||||
{
|
{
|
||||||
for (auto &s : switcher->mediaSwitches) {
|
for (auto &s : switcher->mediaSwitches) {
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
@@ -460,7 +463,7 @@ MediaSwitchWidget::MediaSwitchWidget(QWidget *parent, MediaSwitch *s)
|
|||||||
QWidget::connect(time, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(time, SIGNAL(valueChanged(int)), this,
|
||||||
SLOT(TimeChanged(int)));
|
SLOT(TimeChanged(int)));
|
||||||
|
|
||||||
populateMediaSelection(mediaSources);
|
PopulateMediaSelection(mediaSources);
|
||||||
populateMediaStates(states);
|
populateMediaStates(states);
|
||||||
populateTimeRestrictions(timeRestrictions);
|
populateTimeRestrictions(timeRestrictions);
|
||||||
|
|
||||||
@@ -483,7 +486,7 @@ MediaSwitchWidget::MediaSwitchWidget(QWidget *parent, MediaSwitch *s)
|
|||||||
{"{{time}}", time},
|
{"{{time}}", time},
|
||||||
{"{{scenes}}", scenes},
|
{"{{scenes}}", scenes},
|
||||||
{"{{transitions}}", transitions}};
|
{"{{transitions}}", transitions}};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.mediaTab.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.mediaTab.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -560,3 +563,5 @@ void MediaSwitchWidget::TimeChanged(int time)
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->time = time;
|
switchData->time = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
constexpr auto media_func = 6;
|
constexpr auto media_func = 6;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -83,3 +85,5 @@ private:
|
|||||||
|
|
||||||
MediaSwitch *switchData;
|
MediaSwitch *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -7,8 +7,12 @@ Most of this code is based on https://github.com/Palakis/obs-websocket
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
|
#include "scene-switch-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
#define PARAM_SERVER_ENABLE "ServerEnabled"
|
#define PARAM_SERVER_ENABLE "ServerEnabled"
|
||||||
#define PARAM_SERVER_PORT "ServerPort"
|
#define PARAM_SERVER_PORT "ServerPort"
|
||||||
#define PARAM_LOCKTOIPV4 "LockToIPv4"
|
#define PARAM_LOCKTOIPV4 "LockToIPv4"
|
||||||
@@ -124,10 +128,9 @@ WSServer::WSServer() : QObject(nullptr), _connections(), _clMutex()
|
|||||||
_server.set_reuse_addr(true);
|
_server.set_reuse_addr(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_server.set_open_handler(bind(&WSServer::onOpen, this, ::_1));
|
_server.set_open_handler(bind(&WSServer::onOpen, this, _1));
|
||||||
_server.set_close_handler(bind(&WSServer::onClose, this, ::_1));
|
_server.set_close_handler(bind(&WSServer::onClose, this, _1));
|
||||||
_server.set_message_handler(
|
_server.set_message_handler(bind(&WSServer::onMessage, this, _1, _2));
|
||||||
bind(&WSServer::onMessage, this, ::_1, ::_2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WSServer::~WSServer()
|
WSServer::~WSServer()
|
||||||
@@ -221,7 +224,7 @@ void WSServer::stop()
|
|||||||
blog(LOG_INFO, "server stopped successfully");
|
blog(LOG_INFO, "server stopped successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSServer::sendMessage(sceneSwitchInfo sceneSwitch, bool preview)
|
void WSServer::sendMessage(SceneSwitchInfo sceneSwitch, bool preview)
|
||||||
{
|
{
|
||||||
if (!sceneSwitch.scene) {
|
if (!sceneSwitch.scene) {
|
||||||
return;
|
return;
|
||||||
@@ -305,9 +308,9 @@ std::string processMessage(std::string payload)
|
|||||||
"'";
|
"'";
|
||||||
}
|
}
|
||||||
if (preview) {
|
if (preview) {
|
||||||
switchPreviewScene(scene);
|
SwitchPreviewScene(scene);
|
||||||
} else {
|
} else {
|
||||||
switchScene({scene, transition, duration});
|
SwitchScene({scene, transition, duration});
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -361,11 +364,10 @@ WSClient::WSClient() : QObject(nullptr)
|
|||||||
_client.set_reuse_addr(true);
|
_client.set_reuse_addr(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_client.set_open_handler(bind(&WSClient::onOpen, this, ::_1));
|
_client.set_open_handler(bind(&WSClient::onOpen, this, _1));
|
||||||
_client.set_fail_handler(bind(&WSClient::onFail, this, ::_1));
|
_client.set_fail_handler(bind(&WSClient::onFail, this, _1));
|
||||||
_client.set_message_handler(
|
_client.set_message_handler(bind(&WSClient::onMessage, this, _1, _2));
|
||||||
bind(&WSClient::onMessage, this, ::_1, ::_2));
|
_client.set_close_handler(bind(&WSClient::onClose, this, _1));
|
||||||
_client.set_close_handler(bind(&WSClient::onClose, this, ::_1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WSClient::~WSClient()
|
WSClient::~WSClient()
|
||||||
@@ -501,7 +503,7 @@ void SwitcherData::saveNetworkSwitches(obs_data_t *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupNetworkTab()
|
void AdvSceneSwitcher::SetupNetworkTab()
|
||||||
{
|
{
|
||||||
ui->serverSettings->setChecked(switcher->networkConfig.ServerEnabled);
|
ui->serverSettings->setChecked(switcher->networkConfig.ServerEnabled);
|
||||||
ui->serverPort->setValue(switcher->networkConfig.ServerPort);
|
ui->serverPort->setValue(switcher->networkConfig.ServerPort);
|
||||||
@@ -519,9 +521,9 @@ void AdvSceneSwitcher::setupNetworkTab()
|
|||||||
|
|
||||||
QTimer *statusTimer = new QTimer(this);
|
QTimer *statusTimer = new QTimer(this);
|
||||||
connect(statusTimer, SIGNAL(timeout()), this,
|
connect(statusTimer, SIGNAL(timeout()), this,
|
||||||
SLOT(updateClientStatus()));
|
SLOT(UpdateClientStatus()));
|
||||||
connect(statusTimer, SIGNAL(timeout()), this,
|
connect(statusTimer, SIGNAL(timeout()), this,
|
||||||
SLOT(updateServerStatus()));
|
SLOT(UpdateServerStatus()));
|
||||||
statusTimer->start(500);
|
statusTimer->start(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -572,7 +574,7 @@ void AdvSceneSwitcher::on_serverRestart_clicked()
|
|||||||
switcher->networkConfig.LockToIPv4);
|
switcher->networkConfig.LockToIPv4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::updateServerStatus()
|
void AdvSceneSwitcher::UpdateServerStatus()
|
||||||
{
|
{
|
||||||
switch (switcher->serverStatus) {
|
switch (switcher->serverStatus) {
|
||||||
case ServerStatus::NOT_RUNNING:
|
case ServerStatus::NOT_RUNNING:
|
||||||
@@ -670,7 +672,7 @@ void AdvSceneSwitcher::on_clientReconnect_clicked()
|
|||||||
switcher->client.connect(switcher->networkConfig.GetClientUri());
|
switcher->client.connect(switcher->networkConfig.GetClientUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::updateClientStatus()
|
void AdvSceneSwitcher::UpdateClientStatus()
|
||||||
{
|
{
|
||||||
switch (switcher->clientStatus) {
|
switch (switcher->clientStatus) {
|
||||||
case ClientStatus::DISCONNECTED:
|
case ClientStatus::DISCONNECTED:
|
||||||
@@ -709,3 +711,5 @@ Compatability::StdFunctionRunnable::StdFunctionRunnable(
|
|||||||
: cb(std::move(func))
|
: cb(std::move(func))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -19,11 +19,13 @@ Most of this code is based on https://github.com/Palakis/obs-websocket
|
|||||||
#include <websocketpp/server.hpp>
|
#include <websocketpp/server.hpp>
|
||||||
#include <websocketpp/client.hpp>
|
#include <websocketpp/client.hpp>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
using websocketpp::connection_hdl;
|
using websocketpp::connection_hdl;
|
||||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||||
|
|
||||||
struct sceneSwitchInfo;
|
struct SceneSwitchInfo;
|
||||||
|
|
||||||
class NetworkConfig {
|
class NetworkConfig {
|
||||||
public:
|
public:
|
||||||
@@ -60,7 +62,7 @@ public:
|
|||||||
virtual ~WSServer();
|
virtual ~WSServer();
|
||||||
void start(quint16 port, bool lockToIPv4);
|
void start(quint16 port, bool lockToIPv4);
|
||||||
void stop();
|
void stop();
|
||||||
void sendMessage(sceneSwitchInfo sceneSwitch, bool preview = false);
|
void sendMessage(SceneSwitchInfo sceneSwitch, bool preview = false);
|
||||||
QThreadPool *threadPool() { return &_threadPool; }
|
QThreadPool *threadPool() { return &_threadPool; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -131,3 +133,5 @@ public:
|
|||||||
|
|
||||||
QRunnable *CreateFunctionRunnable(std::function<void()> func);
|
QRunnable *CreateFunctionRunnable(std::function<void()> func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
namespace advss {
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
|
|
||||||
@@ -244,7 +247,7 @@ void SwitcherData::loadPauseSwitches(obs_data_t *obj)
|
|||||||
obs_data_array_release(pauseArray);
|
obs_data_array_release(pauseArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupPauseTab()
|
void AdvSceneSwitcher::SetupPauseTab()
|
||||||
{
|
{
|
||||||
for (auto &s : switcher->pauseEntries) {
|
for (auto &s : switcher->pauseEntries) {
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
@@ -309,7 +312,7 @@ PauseEntryWidget::PauseEntryWidget(QWidget *parent, PauseEntry *s)
|
|||||||
|
|
||||||
populatePauseTypes(pauseTypes);
|
populatePauseTypes(pauseTypes);
|
||||||
populatePauseTargets(pauseTargets);
|
populatePauseTargets(pauseTargets);
|
||||||
populateWindowSelection(windows);
|
PopulateWindowSelection(windows);
|
||||||
|
|
||||||
windows->setEditable(true);
|
windows->setEditable(true);
|
||||||
windows->setMaxVisibleItems(20);
|
windows->setMaxVisibleItems(20);
|
||||||
@@ -335,7 +338,7 @@ PauseEntryWidget::PauseEntryWidget(QWidget *parent, PauseEntry *s)
|
|||||||
{"{{pauseTargets}}", pauseTargets},
|
{"{{pauseTargets}}", pauseTargets},
|
||||||
{"{{windows}}", windows}};
|
{"{{windows}}", windows}};
|
||||||
|
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.pauseTab.pauseEntry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.pauseTab.pauseEntry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -410,3 +413,5 @@ bool PauseEntry::valid()
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
enum class PauseType {
|
enum class PauseType {
|
||||||
Scene,
|
Scene,
|
||||||
Window,
|
Window,
|
||||||
@@ -70,3 +72,5 @@ private:
|
|||||||
|
|
||||||
PauseEntry *switchData;
|
PauseEntry *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_threadPriority_currentTextChanged(const QString &text)
|
|
||||||
{
|
|
||||||
if (loading || ui->threadPriority->count() !=
|
|
||||||
(int)switcher->threadPriorities.size())
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
|
|
||||||
for (auto p : switcher->threadPriorities) {
|
|
||||||
if (p.name == text.toUtf8().constData()) {
|
|
||||||
switcher->threadPriority = p.value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_priorityUp_clicked()
|
|
||||||
{
|
|
||||||
int currentIndex = ui->priorityList->currentRow();
|
|
||||||
if (currentIndex != -1 && currentIndex != 0) {
|
|
||||||
ui->priorityList->insertItem(
|
|
||||||
currentIndex - 1,
|
|
||||||
ui->priorityList->takeItem(currentIndex));
|
|
||||||
ui->priorityList->setCurrentRow(currentIndex - 1);
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
|
|
||||||
iter_swap(switcher->functionNamesByPriority.begin() +
|
|
||||||
currentIndex,
|
|
||||||
switcher->functionNamesByPriority.begin() +
|
|
||||||
currentIndex - 1);
|
|
||||||
}
|
|
||||||
ui->macroPriorityWarning->setVisible(
|
|
||||||
switcher->functionNamesByPriority[0] != macro_func);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_priorityDown_clicked()
|
|
||||||
{
|
|
||||||
int currentIndex = ui->priorityList->currentRow();
|
|
||||||
if (currentIndex != -1 &&
|
|
||||||
currentIndex != ui->priorityList->count() - 1) {
|
|
||||||
ui->priorityList->insertItem(
|
|
||||||
currentIndex + 1,
|
|
||||||
ui->priorityList->takeItem(currentIndex));
|
|
||||||
ui->priorityList->setCurrentRow(currentIndex + 1);
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
|
|
||||||
iter_swap(switcher->functionNamesByPriority.begin() +
|
|
||||||
currentIndex,
|
|
||||||
switcher->functionNamesByPriority.begin() +
|
|
||||||
currentIndex + 1);
|
|
||||||
}
|
|
||||||
ui->macroPriorityWarning->setVisible(
|
|
||||||
switcher->functionNamesByPriority[0] != macro_func);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SwitcherData::prioFuncsValid()
|
|
||||||
{
|
|
||||||
auto fNBPCopy = functionNamesByPriority;
|
|
||||||
|
|
||||||
std::sort(fNBPCopy.begin(), fNBPCopy.end());
|
|
||||||
auto it = std::unique(fNBPCopy.begin(), fNBPCopy.end());
|
|
||||||
bool wasUnique = (it == fNBPCopy.end());
|
|
||||||
|
|
||||||
if (!wasUnique) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int p : functionNamesByPriority) {
|
|
||||||
if (p < 0 || p > 10) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
namespace advss {
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
bool RandomSwitch::pause = false;
|
bool RandomSwitch::pause = false;
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
@@ -113,7 +116,7 @@ void SwitcherData::loadRandomSwitches(obs_data_t *obj)
|
|||||||
obs_data_array_release(randomArray);
|
obs_data_array_release(randomArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupRandomTab()
|
void AdvSceneSwitcher::SetupRandomTab()
|
||||||
{
|
{
|
||||||
for (auto &s : switcher->randomSwitches) {
|
for (auto &s : switcher->randomSwitches) {
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
@@ -140,7 +143,8 @@ void AdvSceneSwitcher::setupRandomTab()
|
|||||||
border-radius: 7px; \
|
border-radius: 7px; \
|
||||||
border-color: rgb(0,0,0,0) \
|
border-color: rgb(0,0,0,0) \
|
||||||
}");
|
}");
|
||||||
if (switcher->switchIfNotMatching != RANDOM_SWITCH) {
|
if (switcher->switchIfNotMatching !=
|
||||||
|
SwitcherData::NoMatch::RANDOM_SWITCH) {
|
||||||
if (!switcher->disableHints) {
|
if (!switcher->disableHints) {
|
||||||
PulseWidget(ui->randomDisabledWarning, QColor(Qt::red),
|
PulseWidget(ui->randomDisabledWarning, QColor(Qt::red),
|
||||||
QColor(0, 0, 0, 0));
|
QColor(0, 0, 0, 0));
|
||||||
@@ -182,7 +186,7 @@ RandomSwitchWidget::RandomSwitchWidget(QWidget *parent, RandomSwitch *s)
|
|||||||
{"{{scenes}}", scenes},
|
{"{{scenes}}", scenes},
|
||||||
{"{{transitions}}", transitions},
|
{"{{transitions}}", transitions},
|
||||||
{"{{delay}}", delay}};
|
{"{{delay}}", delay}};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.randomTab.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.randomTab.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -220,3 +224,5 @@ void RandomSwitchWidget::DelayChanged(double d)
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->delay = d;
|
switchData->delay = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
struct RandomSwitch : SceneSwitcherEntry {
|
struct RandomSwitch : SceneSwitcherEntry {
|
||||||
static bool pause;
|
static bool pause;
|
||||||
double delay = 0.0;
|
double delay = 0.0;
|
||||||
@@ -36,3 +38,5 @@ private:
|
|||||||
|
|
||||||
RandomSwitch *switchData;
|
RandomSwitch *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
namespace advss {
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
bool ScreenRegionSwitch::pause = false;
|
bool ScreenRegionSwitch::pause = false;
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
|
|
||||||
void AdvSceneSwitcher::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 =
|
||||||
@@ -48,7 +51,7 @@ void AdvSceneSwitcher::on_showFrame_clicked()
|
|||||||
showCurrentFrame(ui->screenRegionSwitches);
|
showCurrentFrame(ui->screenRegionSwitches);
|
||||||
} else {
|
} else {
|
||||||
SetShowFrames();
|
SetShowFrames();
|
||||||
clearFrames(ui->screenRegionSwitches);
|
ClearFrames(ui->screenRegionSwitches);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +62,7 @@ void AdvSceneSwitcher::on_screenRegionSwitches_currentRowChanged(int idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (switcher->showFrame) {
|
if (switcher->showFrame) {
|
||||||
clearFrames(ui->screenRegionSwitches);
|
ClearFrames(ui->screenRegionSwitches);
|
||||||
showCurrentFrame(ui->screenRegionSwitches);
|
showCurrentFrame(ui->screenRegionSwitches);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +156,7 @@ bool SwitcherData::checkScreenRegionSwitch(OBSWeakSource &scene,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<int, int> cursorPos = getCursorPos();
|
std::pair<int, int> cursorPos = GetCursorPos();
|
||||||
int minRegionSize = 99999;
|
int minRegionSize = 99999;
|
||||||
bool match = false;
|
bool match = false;
|
||||||
|
|
||||||
@@ -188,7 +191,7 @@ bool SwitcherData::checkScreenRegionSwitch(OBSWeakSource &scene,
|
|||||||
|
|
||||||
void AdvSceneSwitcher::updateScreenRegionCursorPos()
|
void AdvSceneSwitcher::updateScreenRegionCursorPos()
|
||||||
{
|
{
|
||||||
std::pair<int, int> position = getCursorPos();
|
std::pair<int, int> position = GetCursorPos();
|
||||||
ui->cursorXPosition->setText(QString::number(position.first));
|
ui->cursorXPosition->setText(QString::number(position.first));
|
||||||
ui->cursorYPosition->setText(QString::number(position.second));
|
ui->cursorYPosition->setText(QString::number(position.second));
|
||||||
}
|
}
|
||||||
@@ -228,7 +231,7 @@ void SwitcherData::loadScreenRegionSwitches(obs_data_t *obj)
|
|||||||
obs_data_array_release(screenRegionArray);
|
obs_data_array_release(screenRegionArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupRegionTab()
|
void AdvSceneSwitcher::SetupRegionTab()
|
||||||
{
|
{
|
||||||
for (auto &s : switcher->screenRegionSwitches) {
|
for (auto &s : switcher->screenRegionSwitches) {
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
@@ -318,7 +321,7 @@ ScreenRegionWidget::ScreenRegionWidget(QWidget *parent, ScreenRegionSwitch *s)
|
|||||||
QWidget::connect(maxY, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(maxY, SIGNAL(valueChanged(int)), this,
|
||||||
SLOT(MaxYChanged(int)));
|
SLOT(MaxYChanged(int)));
|
||||||
|
|
||||||
populateSceneSelection(
|
PopulateSceneSelection(
|
||||||
excludeScenes, false, false, false, false, nullptr, true,
|
excludeScenes, false, false, false, false, nullptr, true,
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.screenRegionTab.excludeScenes.None"),
|
"AdvSceneSwitcher.screenRegionTab.excludeScenes.None"),
|
||||||
@@ -342,7 +345,7 @@ ScreenRegionWidget::ScreenRegionWidget(QWidget *parent, ScreenRegionSwitch *s)
|
|||||||
{"{{scenes}}", scenes},
|
{"{{scenes}}", scenes},
|
||||||
{"{{transitions}}", transitions},
|
{"{{transitions}}", transitions},
|
||||||
{"{{excludeScenes}}", excludeScenes}};
|
{"{{excludeScenes}}", excludeScenes}};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.screenRegionTab.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.screenRegionTab.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -455,3 +458,5 @@ void ScreenRegionWidget::drawFrame()
|
|||||||
switchData->maxY - switchData->minY);
|
switchData->maxY - switchData->minY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
constexpr auto screen_region_func = 4;
|
constexpr auto screen_region_func = 4;
|
||||||
|
|
||||||
struct ScreenRegionSwitch : SceneSwitcherEntry {
|
struct ScreenRegionSwitch : SceneSwitcherEntry {
|
||||||
@@ -55,3 +57,5 @@ private:
|
|||||||
|
|
||||||
void drawFrame();
|
void drawFrame();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
namespace advss {
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
constexpr auto max_extend_text_size = 150;
|
constexpr auto max_extend_text_size = 150;
|
||||||
|
|
||||||
@@ -278,7 +281,7 @@ void SwitcherData::loadSceneSequenceSwitches(obs_data_t *obj)
|
|||||||
obs_data_array_release(sceneSequenceArray);
|
obs_data_array_release(sceneSequenceArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupSequenceTab()
|
void AdvSceneSwitcher::SetupSequenceTab()
|
||||||
{
|
{
|
||||||
for (auto &s : switcher->sceneSequenceSwitches) {
|
for (auto &s : switcher->sceneSequenceSwitches) {
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
@@ -455,7 +458,7 @@ bool SceneSequenceSwitch::checkDurationMatchInterruptible()
|
|||||||
|
|
||||||
void SceneSequenceSwitch::prepareUninterruptibleMatch(int &linger)
|
void SceneSequenceSwitch::prepareUninterruptibleMatch(int &linger)
|
||||||
{
|
{
|
||||||
int dur = delay.seconds * 1000;
|
int dur = delay.Milliseconds();
|
||||||
if (dur > 0) {
|
if (dur > 0) {
|
||||||
linger = dur;
|
linger = dur;
|
||||||
}
|
}
|
||||||
@@ -588,10 +591,8 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s,
|
|||||||
QWidget::connect(scenes, SIGNAL(currentTextChanged(const QString &)),
|
QWidget::connect(scenes, SIGNAL(currentTextChanged(const QString &)),
|
||||||
this, SLOT(SceneChanged(const QString &)));
|
this, SLOT(SceneChanged(const QString &)));
|
||||||
|
|
||||||
QWidget::connect(delay, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(delay, SIGNAL(DurationChanged(const Duration &)), this,
|
||||||
SLOT(DelayChanged(double)));
|
SLOT(DelayChanged(const Duration &)));
|
||||||
QWidget::connect(delay, SIGNAL(UnitChanged(DurationUnit)), this,
|
|
||||||
SLOT(DelayUnitsChanged(DurationUnit)));
|
|
||||||
QWidget::connect(startScenes,
|
QWidget::connect(startScenes,
|
||||||
SIGNAL(currentTextChanged(const QString &)), this,
|
SIGNAL(currentTextChanged(const QString &)), this,
|
||||||
SLOT(StartSceneChanged(const QString &)));
|
SLOT(StartSceneChanged(const QString &)));
|
||||||
@@ -603,7 +604,7 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s,
|
|||||||
QWidget::connect(reduce, SIGNAL(clicked()), this,
|
QWidget::connect(reduce, SIGNAL(clicked()), this,
|
||||||
SLOT(ReduceClicked()));
|
SLOT(ReduceClicked()));
|
||||||
|
|
||||||
populateSceneSelection(startScenes);
|
PopulateSceneSelection(startScenes);
|
||||||
interruptible->setToolTip(obs_module_text(
|
interruptible->setToolTip(obs_module_text(
|
||||||
"AdvSceneSwitcher.sceneSequenceTab.interruptibleHint"));
|
"AdvSceneSwitcher.sceneSequenceTab.interruptibleHint"));
|
||||||
|
|
||||||
@@ -615,7 +616,7 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s,
|
|||||||
{"{{scenes}}", scenes},
|
{"{{scenes}}", scenes},
|
||||||
{"{{delay}}", delay},
|
{"{{delay}}", delay},
|
||||||
{"{{transitions}}", transitions}};
|
{"{{transitions}}", transitions}};
|
||||||
placeWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.sceneSequenceTab.extendEntry"),
|
"AdvSceneSwitcher.sceneSequenceTab.extendEntry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
@@ -628,7 +629,7 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s,
|
|||||||
{"{{delay}}", delay},
|
{"{{delay}}", delay},
|
||||||
{"{{transitions}}", transitions},
|
{"{{transitions}}", transitions},
|
||||||
{"{{interruptible}}", interruptible}};
|
{"{{interruptible}}", interruptible}};
|
||||||
placeWidgets(obs_module_text(
|
PlaceWidgets(obs_module_text(
|
||||||
"AdvSceneSwitcher.sceneSequenceTab.entry"),
|
"AdvSceneSwitcher.sceneSequenceTab.entry"),
|
||||||
startSequence, widgetPlaceholders);
|
startSequence, widgetPlaceholders);
|
||||||
|
|
||||||
@@ -689,24 +690,14 @@ void SequenceWidget::swapSwitchData(SequenceWidget *s1, SequenceWidget *s2)
|
|||||||
s2->setSwitchData(t);
|
s2->setSwitchData(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SequenceWidget::DelayChanged(double sec)
|
void SequenceWidget::DelayChanged(const Duration &delay)
|
||||||
{
|
{
|
||||||
if (loading || !switchData) {
|
if (loading || !switchData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->delay.seconds = sec;
|
switchData->delay = delay;
|
||||||
}
|
|
||||||
|
|
||||||
void SequenceWidget::DelayUnitsChanged(DurationUnit unit)
|
|
||||||
{
|
|
||||||
if (loading || !switchData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switchData->delay.displayUnit = unit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SequenceWidget::setExtendedSequenceStartScene()
|
void SequenceWidget::setExtendedSequenceStartScene()
|
||||||
@@ -805,3 +796,5 @@ void SequenceWidget::ReduceClicked()
|
|||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
constexpr auto round_trip_func = 1;
|
constexpr auto round_trip_func = 1;
|
||||||
|
|
||||||
struct SceneSequenceSwitch : SceneSwitcherEntry {
|
struct SceneSequenceSwitch : SceneSwitcherEntry {
|
||||||
@@ -59,8 +61,7 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void SceneChanged(const QString &text);
|
void SceneChanged(const QString &text);
|
||||||
void DelayChanged(double delay);
|
void DelayChanged(const Duration &delay);
|
||||||
void DelayUnitsChanged(DurationUnit);
|
|
||||||
void StartSceneChanged(const QString &text);
|
void StartSceneChanged(const QString &text);
|
||||||
void InterruptibleChanged(int state);
|
void InterruptibleChanged(int state);
|
||||||
void ExtendClicked();
|
void ExtendClicked();
|
||||||
@@ -83,3 +84,5 @@ protected:
|
|||||||
|
|
||||||
SceneSequenceSwitch *switchData;
|
SceneSequenceSwitch *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
bool TimeSwitch::pause = false;
|
bool TimeSwitch::pause = false;
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
|
|
||||||
@@ -179,7 +182,7 @@ void SwitcherData::loadTimeSwitches(obs_data_t *obj)
|
|||||||
obs_data_array_release(timeArray);
|
obs_data_array_release(timeArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupTimeTab()
|
void AdvSceneSwitcher::SetupTimeTab()
|
||||||
{
|
{
|
||||||
for (auto &s : switcher->timeSwitches) {
|
for (auto &s : switcher->timeSwitches) {
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
@@ -258,7 +261,7 @@ TimeSwitchWidget::TimeSwitchWidget(QWidget *parent, TimeSwitch *s)
|
|||||||
{"{{time}}", time},
|
{"{{time}}", time},
|
||||||
{"{{scenes}}", scenes},
|
{"{{scenes}}", scenes},
|
||||||
{"{{transitions}}", transitions}};
|
{"{{transitions}}", transitions}};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.timeTab.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.timeTab.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -306,3 +309,5 @@ void TimeSwitchWidget::TimeChanged(const QTime &time)
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->time = time;
|
switchData->time = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
constexpr auto time_func = 7;
|
constexpr auto time_func = 7;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -54,3 +56,5 @@ private:
|
|||||||
|
|
||||||
TimeSwitch *switchData;
|
TimeSwitch *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
namespace advss {
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
constexpr auto default_def_transition_dealy = 300;
|
constexpr auto default_def_transition_dealy = 300;
|
||||||
bool DefaultSceneTransition::pause = false;
|
bool DefaultSceneTransition::pause = false;
|
||||||
@@ -169,7 +172,7 @@ void SwitcherData::checkDefaultSceneTransitions()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::defTransitionDelayValueChanged(int value)
|
void AdvSceneSwitcher::DefTransitionDelayValueChanged(int value)
|
||||||
{
|
{
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return;
|
return;
|
||||||
@@ -179,104 +182,6 @@ void AdvSceneSwitcher::defTransitionDelayValueChanged(int value)
|
|||||||
DefaultSceneTransition::delay = value;
|
DefaultSceneTransition::delay = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<obs_weak_source_t *, int> getNextTransition(obs_weak_source_t *scene1,
|
|
||||||
obs_weak_source_t *scene2)
|
|
||||||
{
|
|
||||||
obs_weak_source_t *ws = nullptr;
|
|
||||||
int duration = 0;
|
|
||||||
if (scene1 && scene2) {
|
|
||||||
for (SceneTransition &t : switcher->sceneTransitions) {
|
|
||||||
if (!t.initialized()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t.scene == scene1 && t.scene2 == scene2) {
|
|
||||||
ws = t.transition;
|
|
||||||
duration = t.duration * 1000;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_pair(ws, duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
void overwriteTransitionOverride(const sceneSwitchInfo &ssi, transitionData &td)
|
|
||||||
{
|
|
||||||
obs_source_t *scene = obs_weak_source_get_source(ssi.scene);
|
|
||||||
obs_data_t *data = obs_source_get_private_settings(scene);
|
|
||||||
|
|
||||||
td.name = obs_data_get_string(data, "transition");
|
|
||||||
td.duration = obs_data_get_int(data, "transition_duration");
|
|
||||||
|
|
||||||
std::string name = GetWeakSourceName(ssi.transition);
|
|
||||||
|
|
||||||
obs_data_set_string(data, "transition", name.c_str());
|
|
||||||
obs_data_set_int(data, "transition_duration", ssi.duration);
|
|
||||||
|
|
||||||
obs_data_release(data);
|
|
||||||
obs_source_release(scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
void restoreTransitionOverride(obs_source_t *scene, const transitionData &td)
|
|
||||||
{
|
|
||||||
obs_data_t *data = obs_source_get_private_settings(scene);
|
|
||||||
|
|
||||||
obs_data_set_string(data, "transition", td.name.c_str());
|
|
||||||
obs_data_set_int(data, "transition_duration", td.duration);
|
|
||||||
|
|
||||||
obs_data_release(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setNextTransition(const sceneSwitchInfo &sceneSwitch,
|
|
||||||
obs_source_t *currentSource, transitionData &td)
|
|
||||||
{
|
|
||||||
// Priority:
|
|
||||||
// 1. Transition tab
|
|
||||||
// 2. Individual switcher entry
|
|
||||||
// 3. Current transition settings
|
|
||||||
|
|
||||||
// Transition Tab
|
|
||||||
obs_weak_source_t *currentScene =
|
|
||||||
obs_source_get_weak_source(currentSource);
|
|
||||||
auto tinfo = getNextTransition(currentScene, sceneSwitch.scene);
|
|
||||||
obs_weak_source_release(currentScene);
|
|
||||||
|
|
||||||
OBSWeakSource nextTransition = tinfo.first;
|
|
||||||
int nextTransitionDuration = tinfo.second;
|
|
||||||
|
|
||||||
// Individual switcher entry
|
|
||||||
if (!nextTransition) {
|
|
||||||
nextTransition = sceneSwitch.transition;
|
|
||||||
}
|
|
||||||
if (!nextTransitionDuration) {
|
|
||||||
nextTransitionDuration = sceneSwitch.duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Current transition settings
|
|
||||||
if (!nextTransition) {
|
|
||||||
auto ct = obs_frontend_get_current_transition();
|
|
||||||
nextTransition = obs_source_get_weak_source(ct);
|
|
||||||
obs_weak_source_release(nextTransition);
|
|
||||||
obs_source_release(ct);
|
|
||||||
}
|
|
||||||
if (!nextTransitionDuration) {
|
|
||||||
nextTransitionDuration = obs_frontend_get_transition_duration();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switcher->adjustActiveTransitionType) {
|
|
||||||
obs_frontend_set_transition_duration(nextTransitionDuration);
|
|
||||||
auto t = obs_weak_source_get_source(nextTransition);
|
|
||||||
obs_frontend_set_current_transition(t);
|
|
||||||
obs_source_release(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switcher->transitionOverrideOverride) {
|
|
||||||
overwriteTransitionOverride({sceneSwitch.scene, nextTransition,
|
|
||||||
nextTransitionDuration},
|
|
||||||
td);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitcherData::saveSceneTransitions(obs_data_t *obj)
|
void SwitcherData::saveSceneTransitions(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
obs_data_array_t *sceneTransitionsArray = obs_data_array_create();
|
obs_data_array_t *sceneTransitionsArray = obs_data_array_create();
|
||||||
@@ -349,7 +254,7 @@ void SwitcherData::loadSceneTransitions(obs_data_t *obj)
|
|||||||
obs_data_get_int(obj, "defTransitionDelay");
|
obs_data_get_int(obj, "defTransitionDelay");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupTransitionsTab()
|
void AdvSceneSwitcher::SetupTransitionsTab()
|
||||||
{
|
{
|
||||||
for (auto &s : switcher->sceneTransitions) {
|
for (auto &s : switcher->sceneTransitions) {
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
@@ -397,11 +302,11 @@ void AdvSceneSwitcher::setupTransitionsTab()
|
|||||||
"AdvSceneSwitcher.transitionTab.defaultTransition.delay.help"));
|
"AdvSceneSwitcher.transitionTab.defaultTransition.delay.help"));
|
||||||
|
|
||||||
QWidget::connect(defTransitionDelay, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(defTransitionDelay, SIGNAL(valueChanged(int)), this,
|
||||||
SLOT(defTransitionDelayValueChanged(int)));
|
SLOT(DefTransitionDelayValueChanged(int)));
|
||||||
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{defTransitionDelay}}", defTransitionDelay}};
|
{"{{defTransitionDelay}}", defTransitionDelay}};
|
||||||
placeWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.transitionTab.defaultTransition.delay"),
|
"AdvSceneSwitcher.transitionTab.defaultTransition.delay"),
|
||||||
ui->defTransitionDelayLayout, widgetPlaceholders);
|
ui->defTransitionDelayLayout, widgetPlaceholders);
|
||||||
@@ -449,7 +354,7 @@ TransitionSwitchWidget::TransitionSwitchWidget(QWidget *parent,
|
|||||||
QWidget::connect(duration, SIGNAL(valueChanged(double)), this,
|
QWidget::connect(duration, SIGNAL(valueChanged(double)), this,
|
||||||
SLOT(DurationChanged(double)));
|
SLOT(DurationChanged(double)));
|
||||||
|
|
||||||
populateSceneSelection(scenes2);
|
PopulateSceneSelection(scenes2);
|
||||||
|
|
||||||
if (s) {
|
if (s) {
|
||||||
scenes2->setCurrentText(GetWeakSourceName(s->scene2).c_str());
|
scenes2->setCurrentText(GetWeakSourceName(s->scene2).c_str());
|
||||||
@@ -462,7 +367,7 @@ TransitionSwitchWidget::TransitionSwitchWidget(QWidget *parent,
|
|||||||
{"{{scenes2}}", scenes2},
|
{"{{scenes2}}", scenes2},
|
||||||
{"{{duration}}", duration},
|
{"{{duration}}", duration},
|
||||||
{"{{transitions}}", transitions}};
|
{"{{transitions}}", transitions}};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.transitionTab.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.transitionTab.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -518,7 +423,7 @@ DefTransitionSwitchWidget::DefTransitionSwitchWidget(QWidget *parent,
|
|||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{scenes}}", scenes}, {"{{transitions}}", transitions}};
|
{"{{scenes}}", scenes}, {"{{transitions}}", transitions}};
|
||||||
placeWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.transitionTab.defaultTransitionEntry"),
|
"AdvSceneSwitcher.transitionTab.defaultTransitionEntry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
@@ -592,3 +497,5 @@ void DefaultSceneTransition::setTransition()
|
|||||||
t = std::thread(setTransitionDelayed, transition, delay);
|
t = std::thread(setTransitionDelayed, transition, delay);
|
||||||
t.detach();
|
t.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
struct SceneTransition : SceneSwitcherEntry {
|
struct SceneTransition : SceneSwitcherEntry {
|
||||||
OBSWeakSource scene2 = nullptr;
|
OBSWeakSource scene2 = nullptr;
|
||||||
double duration = 0.3;
|
double duration = 0.3;
|
||||||
@@ -77,3 +79,5 @@ public:
|
|||||||
private:
|
private:
|
||||||
DefaultSceneTransition *switchData;
|
DefaultSceneTransition *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
#include <QToolTip>
|
#include <QToolTip>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
namespace advss {
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
bool VideoSwitch::pause = false;
|
bool VideoSwitch::pause = false;
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
@@ -182,7 +185,7 @@ void SwitcherData::loadVideoSwitches(obs_data_t *obj)
|
|||||||
obs_data_array_release(videoArray);
|
obs_data_array_release(videoArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupVideoTab()
|
void AdvSceneSwitcher::SetupVideoTab()
|
||||||
{
|
{
|
||||||
for (auto &s : switcher->videoSwitches) {
|
for (auto &s : switcher->videoSwitches) {
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
@@ -428,7 +431,7 @@ VideoSwitchWidget::VideoSwitchWidget(QWidget *parent, VideoSwitch *s)
|
|||||||
{"{{ignoreInactiveSource}}", ignoreInactiveSource},
|
{"{{ignoreInactiveSource}}", ignoreInactiveSource},
|
||||||
{"{{scenes}}", scenes},
|
{"{{scenes}}", scenes},
|
||||||
{"{{transitions}}", transitions}};
|
{"{{transitions}}", transitions}};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.videoTab.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.videoTab.entry"),
|
||||||
switchLayout, widgetPlaceholders);
|
switchLayout, widgetPlaceholders);
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
@@ -577,3 +580,5 @@ void VideoSwitchWidget::IgnoreInactiveChanged(int state)
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->ignoreInactiveSource = state;
|
switchData->ignoreInactiveSource = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
#include "screenshot-helper.hpp"
|
#include "screenshot-helper.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
constexpr auto video_func = 9;
|
constexpr auto video_func = 9;
|
||||||
|
|
||||||
enum class videoSwitchType {
|
enum class videoSwitchType {
|
||||||
@@ -80,3 +82,5 @@ private:
|
|||||||
|
|
||||||
VideoSwitch *switchData;
|
VideoSwitch *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
|
#include "platform-funcs.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
namespace advss {
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
bool WindowSwitch::pause = false;
|
bool WindowSwitch::pause = false;
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
@@ -177,8 +181,8 @@ void checkWindowTitleSwitchDirect(WindowSwitch &s,
|
|||||||
OBSWeakSource &transition)
|
OBSWeakSource &transition)
|
||||||
{
|
{
|
||||||
bool focus = (!s.focus || s.window == currentWindowTitle);
|
bool focus = (!s.focus || s.window == currentWindowTitle);
|
||||||
bool fullscreen = (!s.fullscreen || isFullscreen(s.window));
|
bool fullscreen = (!s.fullscreen || IsFullscreen(s.window));
|
||||||
bool max = (!s.maximized || isMaximized(s.window));
|
bool max = (!s.maximized || IsMaximized(s.window));
|
||||||
|
|
||||||
if (focus && fullscreen && max) {
|
if (focus && fullscreen && max) {
|
||||||
match = true;
|
match = true;
|
||||||
@@ -203,8 +207,8 @@ void checkWindowTitleSwitchRegex(WindowSwitch &s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool focus = (!s.focus || window == currentWindowTitle);
|
bool focus = (!s.focus || window == currentWindowTitle);
|
||||||
bool fullscreen = (!s.fullscreen || isFullscreen(window));
|
bool fullscreen = (!s.fullscreen || IsFullscreen(window));
|
||||||
bool max = (!s.maximized || isMaximized(window));
|
bool max = (!s.maximized || IsMaximized(window));
|
||||||
|
|
||||||
if (focus && fullscreen && max) {
|
if (focus && fullscreen && max) {
|
||||||
match = true;
|
match = true;
|
||||||
@@ -315,7 +319,7 @@ void SwitcherData::loadWindowTitleSwitches(obs_data_t *obj)
|
|||||||
obs_data_array_release(ignoreWindowsArray);
|
obs_data_array_release(ignoreWindowsArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupTitleTab()
|
void AdvSceneSwitcher::SetupTitleTab()
|
||||||
{
|
{
|
||||||
for (auto &s : switcher->windowSwitches) {
|
for (auto &s : switcher->windowSwitches) {
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
@@ -336,7 +340,7 @@ void AdvSceneSwitcher::setupTitleTab()
|
|||||||
ui->windowHelp->setVisible(false);
|
ui->windowHelp->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
populateWindowSelection(ui->ignoreWindowsWindows);
|
PopulateWindowSelection(ui->ignoreWindowsWindows);
|
||||||
|
|
||||||
for (auto &window : switcher->ignoreWindowsSwitches) {
|
for (auto &window : switcher->ignoreWindowsSwitches) {
|
||||||
QString text = QString::fromStdString(window);
|
QString text = QString::fromStdString(window);
|
||||||
@@ -394,7 +398,7 @@ WindowSwitchWidget::WindowSwitchWidget(QWidget *parent, WindowSwitch *s)
|
|||||||
QWidget::connect(focused, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(focused, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(FocusChanged(int)));
|
SLOT(FocusChanged(int)));
|
||||||
|
|
||||||
populateWindowSelection(windows);
|
PopulateWindowSelection(windows);
|
||||||
|
|
||||||
windows->setEditable(true);
|
windows->setEditable(true);
|
||||||
windows->setMaxVisibleItems(20);
|
windows->setMaxVisibleItems(20);
|
||||||
@@ -414,7 +418,7 @@ WindowSwitchWidget::WindowSwitchWidget(QWidget *parent, WindowSwitch *s)
|
|||||||
{"{{fullscreen}}", fullscreen},
|
{"{{fullscreen}}", fullscreen},
|
||||||
{"{{maximized}}", maximized},
|
{"{{maximized}}", maximized},
|
||||||
{"{{focused}}", focused}};
|
{"{{focused}}", focused}};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.windowTitleTab.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.windowTitleTab.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -482,3 +486,5 @@ void WindowSwitchWidget::FocusChanged(int state)
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->focus = state;
|
switchData->focus = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "switch-generic.hpp"
|
#include "switch-generic.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
constexpr auto window_title_func = 5;
|
constexpr auto window_title_func = 5;
|
||||||
|
|
||||||
struct WindowSwitch : SceneSwitcherEntry {
|
struct WindowSwitch : SceneSwitcherEntry {
|
||||||
@@ -47,3 +49,5 @@ private:
|
|||||||
|
|
||||||
WindowSwitch *switchData;
|
WindowSwitch *switchData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
static Display *xdisplay = 0;
|
static Display *xdisplay = 0;
|
||||||
|
|
||||||
static QLibrary *libXtstHandle = nullptr;
|
static QLibrary *libXtstHandle = nullptr;
|
||||||
@@ -315,7 +317,7 @@ bool windowStatesAreSet(const std::string &windowTitle,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMaximized(const std::string &title)
|
bool IsMaximized(const std::string &title)
|
||||||
{
|
{
|
||||||
std::vector<QString> states;
|
std::vector<QString> states;
|
||||||
states.emplace_back("_NET_WM_STATE_MAXIMIZED_VERT");
|
states.emplace_back("_NET_WM_STATE_MAXIMIZED_VERT");
|
||||||
@@ -323,13 +325,19 @@ bool isMaximized(const std::string &title)
|
|||||||
return windowStatesAreSet(title, states);
|
return windowStatesAreSet(title, states);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFullscreen(const std::string &title)
|
bool IsFullscreen(const std::string &title)
|
||||||
{
|
{
|
||||||
std::vector<QString> states;
|
std::vector<QString> states;
|
||||||
states.emplace_back("_NET_WM_STATE_FULLSCREEN");
|
states.emplace_back("_NET_WM_STATE_FULLSCREEN");
|
||||||
return windowStatesAreSet(title, states);
|
return windowStatesAreSet(title, states);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> GetTextInWindow(const std::string &window)
|
||||||
|
{
|
||||||
|
// Not implemented
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_PROCPS
|
#ifdef USE_PROCPS
|
||||||
void GetProcessList(QStringList &processes)
|
void GetProcessList(QStringList &processes)
|
||||||
{
|
{
|
||||||
@@ -428,7 +436,7 @@ void GetForegroundProcessName(std::string &proc)
|
|||||||
proc = getProcNameFromPid(pid);
|
proc = getProcNameFromPid(pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isInFocus(const QString &executable)
|
bool IsInFocus(const QString &executable)
|
||||||
{
|
{
|
||||||
std::string current;
|
std::string current;
|
||||||
GetForegroundProcessName(current);
|
GetForegroundProcessName(current);
|
||||||
@@ -442,7 +450,7 @@ bool isInFocus(const QString &executable)
|
|||||||
return (equals || matches);
|
return (equals || matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
int secondsSinceLastInput()
|
int SecondsSinceLastInput()
|
||||||
{
|
{
|
||||||
if (!canGetIdleTime) {
|
if (!canGetIdleTime) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -659,3 +667,5 @@ void PlatformCleanup()
|
|||||||
}
|
}
|
||||||
cleanupDisplay();
|
cleanupDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#include "macro-action-audio.hpp"
|
#include "macro-action-audio.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "switcher-data.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
constexpr int64_t nsPerMs = 1000000;
|
constexpr int64_t nsPerMs = 1000000;
|
||||||
const std::string MacroActionAudio::id = "audio";
|
const std::string MacroActionAudio::id = "audio";
|
||||||
|
|
||||||
@@ -114,7 +116,7 @@ void MacroActionAudio::FadeVolume()
|
|||||||
int nrSteps = 0;
|
int nrSteps = 0;
|
||||||
float volStep = 0.;
|
float volStep = 0.;
|
||||||
if (_fadeType == FadeType::DURATION) {
|
if (_fadeType == FadeType::DURATION) {
|
||||||
nrSteps = _duration.seconds * 1000 / fadeInterval.count();
|
nrSteps = _duration.Milliseconds() / fadeInterval.count();
|
||||||
volStep = volDiff / nrSteps;
|
volStep = volDiff / nrSteps;
|
||||||
} else {
|
} else {
|
||||||
volStep = _rate / 1000.0f;
|
volStep = _rate / 1000.0f;
|
||||||
@@ -212,7 +214,7 @@ void MacroActionAudio::LogAction() const
|
|||||||
vblog(LOG_INFO,
|
vblog(LOG_INFO,
|
||||||
"performed action \"%s\" for source \"%s\" with volume %d with fade %d %f",
|
"performed action \"%s\" for source \"%s\" with volume %d with fade %d %f",
|
||||||
it->second.c_str(), _audioSource.ToString(true).c_str(),
|
it->second.c_str(), _audioSource.ToString(true).c_str(),
|
||||||
_volume, _fade, _duration.seconds);
|
_volume.GetValue(), _fade, _duration.Seconds());
|
||||||
} else {
|
} else {
|
||||||
blog(LOG_WARNING, "ignored unknown audio action %d",
|
blog(LOG_WARNING, "ignored unknown audio action %d",
|
||||||
static_cast<int>(_action));
|
static_cast<int>(_action));
|
||||||
@@ -225,15 +227,16 @@ bool MacroActionAudio::Save(obs_data_t *obj) const
|
|||||||
_duration.Save(obj);
|
_duration.Save(obj);
|
||||||
_audioSource.Save(obj, "audioSource");
|
_audioSource.Save(obj, "audioSource");
|
||||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||||
obs_data_set_int(obj, "syncOffset", _syncOffset);
|
|
||||||
obs_data_set_int(obj, "monitor", _monitorType);
|
obs_data_set_int(obj, "monitor", _monitorType);
|
||||||
obs_data_set_double(obj, "balance", _balance);
|
_syncOffset.Save(obj, "syncOffset");
|
||||||
obs_data_set_int(obj, "volume", _volume);
|
_balance.Save(obj, "balance");
|
||||||
obs_data_set_double(obj, "rate", _rate);
|
_volume.Save(obj, "volume");
|
||||||
|
_rate.Save(obj, "rate");
|
||||||
obs_data_set_bool(obj, "fade", _fade);
|
obs_data_set_bool(obj, "fade", _fade);
|
||||||
obs_data_set_int(obj, "fadeType", static_cast<int>(_fadeType));
|
obs_data_set_int(obj, "fadeType", static_cast<int>(_fadeType));
|
||||||
obs_data_set_bool(obj, "wait", _wait);
|
obs_data_set_bool(obj, "wait", _wait);
|
||||||
obs_data_set_bool(obj, "abortActiveFade", _abortActiveFade);
|
obs_data_set_bool(obj, "abortActiveFade", _abortActiveFade);
|
||||||
|
obs_data_set_int(obj, "version", 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,12 +246,19 @@ bool MacroActionAudio::Load(obs_data_t *obj)
|
|||||||
_duration.Load(obj);
|
_duration.Load(obj);
|
||||||
_audioSource.Load(obj, "audioSource");
|
_audioSource.Load(obj, "audioSource");
|
||||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||||
_syncOffset = obs_data_get_int(obj, "syncOffset");
|
|
||||||
_monitorType = static_cast<obs_monitoring_type>(
|
_monitorType = static_cast<obs_monitoring_type>(
|
||||||
obs_data_get_int(obj, "monitor"));
|
obs_data_get_int(obj, "monitor"));
|
||||||
_balance = obs_data_get_double(obj, "balance");
|
if (!obs_data_has_user_value(obj, "version")) {
|
||||||
_volume = obs_data_get_int(obj, "volume");
|
_syncOffset = obs_data_get_int(obj, "syncOffset");
|
||||||
_rate = obs_data_get_double(obj, "rate");
|
_balance = obs_data_get_double(obj, "balance");
|
||||||
|
_volume = obs_data_get_int(obj, "volume");
|
||||||
|
_rate = obs_data_get_double(obj, "rate");
|
||||||
|
} else {
|
||||||
|
_syncOffset.Load(obj, "syncOffset");
|
||||||
|
_balance.Load(obj, "balance");
|
||||||
|
_volume.Load(obj, "volume");
|
||||||
|
_rate.Load(obj, "rate");
|
||||||
|
}
|
||||||
_fade = obs_data_get_bool(obj, "fade");
|
_fade = obs_data_get_bool(obj, "fade");
|
||||||
if (obs_data_has_user_value(obj, "wait")) {
|
if (obs_data_has_user_value(obj, "wait")) {
|
||||||
_wait = obs_data_get_bool(obj, "wait");
|
_wait = obs_data_get_bool(obj, "wait");
|
||||||
@@ -302,16 +312,16 @@ MacroActionAudioEdit::MacroActionAudioEdit(
|
|||||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||||
_actions(new QComboBox),
|
_actions(new QComboBox),
|
||||||
_fadeTypes(new QComboBox),
|
_fadeTypes(new QComboBox),
|
||||||
_syncOffset(new QSpinBox),
|
_syncOffset(new VariableSpinBox),
|
||||||
_monitorTypes(new QComboBox),
|
_monitorTypes(new QComboBox),
|
||||||
_balance(new SliderSpinBox(
|
_balance(new SliderSpinBox(
|
||||||
0., 1., "",
|
0., 1., "",
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.action.audio.balance.description"))),
|
"AdvSceneSwitcher.action.audio.balance.description"))),
|
||||||
_volumePercent(new QSpinBox),
|
_volumePercent(new VariableSpinBox),
|
||||||
_fade(new QCheckBox),
|
_fade(new QCheckBox),
|
||||||
_duration(new DurationSelection(parent, false)),
|
_duration(new DurationSelection(parent, false)),
|
||||||
_rate(new QDoubleSpinBox),
|
_rate(new VariableDoubleSpinBox),
|
||||||
_wait(new QCheckBox(
|
_wait(new QCheckBox(
|
||||||
obs_module_text("AdvSceneSwitcher.action.audio.fade.wait"))),
|
obs_module_text("AdvSceneSwitcher.action.audio.fade.wait"))),
|
||||||
_abortActiveFade(new QCheckBox(
|
_abortActiveFade(new QCheckBox(
|
||||||
@@ -336,27 +346,35 @@ MacroActionAudioEdit::MacroActionAudioEdit(
|
|||||||
sources.sort();
|
sources.sort();
|
||||||
_sources->SetSourceNameList(sources);
|
_sources->SetSourceNameList(sources);
|
||||||
populateFadeTypeSelection(_fadeTypes);
|
populateFadeTypeSelection(_fadeTypes);
|
||||||
populateMonitorTypeSelection(_monitorTypes);
|
PopulateMonitorTypeSelection(_monitorTypes);
|
||||||
|
|
||||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ActionChanged(int)));
|
SLOT(ActionChanged(int)));
|
||||||
QWidget::connect(_sources,
|
QWidget::connect(_sources,
|
||||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||||
SLOT(SourceChanged(const SourceSelection &)));
|
SLOT(SourceChanged(const SourceSelection &)));
|
||||||
QWidget::connect(_syncOffset, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(
|
||||||
SLOT(SyncOffsetChanged(int)));
|
_syncOffset,
|
||||||
QWidget::connect(_balance, SIGNAL(DoubleValueChanged(double)), this,
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
SLOT(BalanceChanged(double)));
|
this, SLOT(SyncOffsetChanged(const NumberVariable<int> &)));
|
||||||
|
QWidget::connect(
|
||||||
|
_balance,
|
||||||
|
SIGNAL(DoubleValueChanged(const NumberVariable<double> &)),
|
||||||
|
this, SLOT(BalanceChanged(const NumberVariable<double> &)));
|
||||||
QWidget::connect(_monitorTypes, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_monitorTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(MonitorTypeChanged(int)));
|
SLOT(MonitorTypeChanged(int)));
|
||||||
QWidget::connect(_volumePercent, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(
|
||||||
SLOT(VolumeChanged(int)));
|
_volumePercent,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
|
this, SLOT(VolumeChanged(const NumberVariable<int> &)));
|
||||||
QWidget::connect(_fade, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_fade, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(FadeChanged(int)));
|
SLOT(FadeChanged(int)));
|
||||||
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)),
|
||||||
SLOT(DurationChanged(double)));
|
this, SLOT(DurationChanged(const Duration &)));
|
||||||
QWidget::connect(_rate, SIGNAL(valueChanged(double)), this,
|
QWidget::connect(
|
||||||
SLOT(RateChanged(double)));
|
_rate,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
|
||||||
|
this, SLOT(RateChanged(const NumberVariable<double> &)));
|
||||||
QWidget::connect(_wait, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_wait, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(WaitChanged(int)));
|
SLOT(WaitChanged(int)));
|
||||||
QWidget::connect(_abortActiveFade, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_abortActiveFade, SIGNAL(stateChanged(int)), this,
|
||||||
@@ -379,10 +397,10 @@ MacroActionAudioEdit::MacroActionAudioEdit(
|
|||||||
{"{{fadeTypes}}", _fadeTypes},
|
{"{{fadeTypes}}", _fadeTypes},
|
||||||
};
|
};
|
||||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.audio.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.audio.entry"),
|
||||||
entryLayout, widgetPlaceholders);
|
entryLayout, widgetPlaceholders);
|
||||||
_fadeTypeLayout = new QHBoxLayout;
|
_fadeTypeLayout = new QHBoxLayout;
|
||||||
placeWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.action.audio.fade.duration"),
|
obs_module_text("AdvSceneSwitcher.action.audio.fade.duration"),
|
||||||
_fadeTypeLayout, widgetPlaceholders);
|
_fadeTypeLayout, widgetPlaceholders);
|
||||||
|
|
||||||
@@ -401,7 +419,7 @@ MacroActionAudioEdit::MacroActionAudioEdit(
|
|||||||
_loading = false;
|
_loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasVolumeControl(MacroActionAudio::Action action)
|
static bool hasVolumeControl(MacroActionAudio::Action action)
|
||||||
{
|
{
|
||||||
return action == MacroActionAudio::Action::SOURCE_VOLUME ||
|
return action == MacroActionAudio::Action::SOURCE_VOLUME ||
|
||||||
action == MacroActionAudio::Action::MASTER_VOLUME;
|
action == MacroActionAudio::Action::MASTER_VOLUME;
|
||||||
@@ -429,7 +447,7 @@ void MacroActionAudioEdit::SetWidgetVisibility()
|
|||||||
_fadeTypeLayout->removeWidget(_fadeTypes);
|
_fadeTypeLayout->removeWidget(_fadeTypes);
|
||||||
_fadeTypeLayout->removeWidget(_duration);
|
_fadeTypeLayout->removeWidget(_duration);
|
||||||
_fadeTypeLayout->removeWidget(_rate);
|
_fadeTypeLayout->removeWidget(_rate);
|
||||||
clearLayout(_fadeTypeLayout);
|
ClearLayout(_fadeTypeLayout);
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{fade}}", _fade},
|
{"{{fade}}", _fade},
|
||||||
{"{{duration}}", _duration},
|
{"{{duration}}", _duration},
|
||||||
@@ -437,12 +455,12 @@ void MacroActionAudioEdit::SetWidgetVisibility()
|
|||||||
{"{{fadeTypes}}", _fadeTypes},
|
{"{{fadeTypes}}", _fadeTypes},
|
||||||
};
|
};
|
||||||
if (_entryData->_fadeType == MacroActionAudio::FadeType::DURATION) {
|
if (_entryData->_fadeType == MacroActionAudio::FadeType::DURATION) {
|
||||||
placeWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.action.audio.fade.duration"),
|
"AdvSceneSwitcher.action.audio.fade.duration"),
|
||||||
_fadeTypeLayout, widgetPlaceholders);
|
_fadeTypeLayout, widgetPlaceholders);
|
||||||
} else {
|
} else {
|
||||||
placeWidgets(obs_module_text(
|
PlaceWidgets(obs_module_text(
|
||||||
"AdvSceneSwitcher.action.audio.fade.rate"),
|
"AdvSceneSwitcher.action.audio.fade.rate"),
|
||||||
_fadeTypeLayout, widgetPlaceholders);
|
_fadeTypeLayout, widgetPlaceholders);
|
||||||
}
|
}
|
||||||
@@ -452,9 +470,9 @@ void MacroActionAudioEdit::SetWidgetVisibility()
|
|||||||
_rate->setVisible(_entryData->_fadeType ==
|
_rate->setVisible(_entryData->_fadeType ==
|
||||||
MacroActionAudio::FadeType::RATE);
|
MacroActionAudio::FadeType::RATE);
|
||||||
|
|
||||||
setLayoutVisible(_fadeTypeLayout,
|
SetLayoutVisible(_fadeTypeLayout,
|
||||||
hasVolumeControl(_entryData->_action));
|
hasVolumeControl(_entryData->_action));
|
||||||
setLayoutVisible(_fadeOptionsLayout,
|
SetLayoutVisible(_fadeOptionsLayout,
|
||||||
hasVolumeControl(_entryData->_action));
|
hasVolumeControl(_entryData->_action));
|
||||||
adjustSize();
|
adjustSize();
|
||||||
}
|
}
|
||||||
@@ -468,13 +486,13 @@ void MacroActionAudioEdit::UpdateEntryData()
|
|||||||
_sources->SetSource(_entryData->_audioSource);
|
_sources->SetSource(_entryData->_audioSource);
|
||||||
_actions->setCurrentIndex(
|
_actions->setCurrentIndex(
|
||||||
_actions->findData(static_cast<int>(_entryData->_action)));
|
_actions->findData(static_cast<int>(_entryData->_action)));
|
||||||
_syncOffset->setValue(_entryData->_syncOffset);
|
_syncOffset->SetValue(_entryData->_syncOffset);
|
||||||
_monitorTypes->setCurrentIndex(_entryData->_monitorType);
|
_monitorTypes->setCurrentIndex(_entryData->_monitorType);
|
||||||
_balance->SetDoubleValue(_entryData->_balance);
|
_balance->SetDoubleValue(_entryData->_balance);
|
||||||
_volumePercent->setValue(_entryData->_volume);
|
_volumePercent->SetValue(_entryData->_volume);
|
||||||
_fade->setChecked(_entryData->_fade);
|
_fade->setChecked(_entryData->_fade);
|
||||||
_duration->SetDuration(_entryData->_duration);
|
_duration->SetDuration(_entryData->_duration);
|
||||||
_rate->setValue(_entryData->_rate);
|
_rate->SetValue(_entryData->_rate);
|
||||||
_wait->setChecked(_entryData->_wait);
|
_wait->setChecked(_entryData->_wait);
|
||||||
_abortActiveFade->setChecked(_entryData->_abortActiveFade);
|
_abortActiveFade->setChecked(_entryData->_abortActiveFade);
|
||||||
_fadeTypes->setCurrentIndex(static_cast<int>(_entryData->_fadeType));
|
_fadeTypes->setCurrentIndex(static_cast<int>(_entryData->_fadeType));
|
||||||
@@ -487,7 +505,7 @@ void MacroActionAudioEdit::SourceChanged(const SourceSelection &source)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_audioSource = source;
|
_entryData->_audioSource = source;
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
@@ -499,19 +517,19 @@ void MacroActionAudioEdit::ActionChanged(int idx)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_action = static_cast<MacroActionAudio::Action>(
|
_entryData->_action = static_cast<MacroActionAudio::Action>(
|
||||||
_actions->itemData(idx).toInt());
|
_actions->itemData(idx).toInt());
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionAudioEdit::SyncOffsetChanged(int value)
|
void MacroActionAudioEdit::SyncOffsetChanged(const NumberVariable<int> &value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_syncOffset = value;
|
_entryData->_syncOffset = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,27 +539,27 @@ void MacroActionAudioEdit::MonitorTypeChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_monitorType = static_cast<obs_monitoring_type>(value);
|
_entryData->_monitorType = static_cast<obs_monitoring_type>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionAudioEdit::BalanceChanged(double value)
|
void MacroActionAudioEdit::BalanceChanged(const NumberVariable<double> &value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_balance = value;
|
_entryData->_balance = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionAudioEdit::VolumeChanged(int value)
|
void MacroActionAudioEdit::VolumeChanged(const NumberVariable<int> &value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_volume = value;
|
_entryData->_volume = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,28 +569,28 @@ void MacroActionAudioEdit::FadeChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_fade = value;
|
_entryData->_fade = value;
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionAudioEdit::DurationChanged(double seconds)
|
void MacroActionAudioEdit::DurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_duration.seconds = seconds;
|
_entryData->_duration = dur;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionAudioEdit::RateChanged(double value)
|
void MacroActionAudioEdit::RateChanged(const NumberVariable<double> &value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_rate = value;
|
_entryData->_rate = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,7 +600,7 @@ void MacroActionAudioEdit::WaitChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_wait = value;
|
_entryData->_wait = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -592,7 +610,7 @@ void MacroActionAudioEdit::AbortActiveFadeChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_abortActiveFade = value;
|
_entryData->_abortActiveFade = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,7 +620,9 @@ void MacroActionAudioEdit::FadeTypeChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_fadeType = static_cast<MacroActionAudio::FadeType>(value);
|
_entryData->_fadeType = static_cast<MacroActionAudio::FadeType>(value);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
class MacroActionAudio : public MacroAction {
|
class MacroActionAudio : public MacroAction {
|
||||||
public:
|
public:
|
||||||
MacroActionAudio(Macro *m) : MacroAction(m) {}
|
MacroActionAudio(Macro *m) : MacroAction(m) {}
|
||||||
@@ -42,13 +44,13 @@ public:
|
|||||||
|
|
||||||
Action _action = Action::MUTE;
|
Action _action = Action::MUTE;
|
||||||
FadeType _fadeType = FadeType::DURATION;
|
FadeType _fadeType = FadeType::DURATION;
|
||||||
int64_t _syncOffset = 0;
|
NumberVariable<int> _syncOffset = 0;
|
||||||
obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE;
|
obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE;
|
||||||
double _balance = 0.5;
|
NumberVariable<double> _balance = 0.5;
|
||||||
int _volume = 0;
|
NumberVariable<int> _volume = 0;
|
||||||
bool _fade = false;
|
bool _fade = false;
|
||||||
Duration _duration;
|
Duration _duration;
|
||||||
double _rate = 100.;
|
NumberVariable<double> _rate = 100.;
|
||||||
bool _wait = false;
|
bool _wait = false;
|
||||||
bool _abortActiveFade = false;
|
bool _abortActiveFade = false;
|
||||||
|
|
||||||
@@ -84,13 +86,13 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void SourceChanged(const SourceSelection &);
|
void SourceChanged(const SourceSelection &);
|
||||||
void ActionChanged(int value);
|
void ActionChanged(int value);
|
||||||
void SyncOffsetChanged(int value);
|
void SyncOffsetChanged(const NumberVariable<int> &value);
|
||||||
void MonitorTypeChanged(int value);
|
void MonitorTypeChanged(int value);
|
||||||
void BalanceChanged(double value);
|
void BalanceChanged(const NumberVariable<double> &value);
|
||||||
void VolumeChanged(int value);
|
void VolumeChanged(const NumberVariable<int> &value);
|
||||||
void FadeChanged(int value);
|
void FadeChanged(int value);
|
||||||
void DurationChanged(double seconds);
|
void DurationChanged(const Duration &seconds);
|
||||||
void RateChanged(double value);
|
void RateChanged(const NumberVariable<double> &value);
|
||||||
void WaitChanged(int value);
|
void WaitChanged(int value);
|
||||||
void AbortActiveFadeChanged(int value);
|
void AbortActiveFadeChanged(int value);
|
||||||
void FadeTypeChanged(int value);
|
void FadeTypeChanged(int value);
|
||||||
@@ -101,13 +103,13 @@ protected:
|
|||||||
SourceSelectionWidget *_sources;
|
SourceSelectionWidget *_sources;
|
||||||
QComboBox *_actions;
|
QComboBox *_actions;
|
||||||
QComboBox *_fadeTypes;
|
QComboBox *_fadeTypes;
|
||||||
QSpinBox *_syncOffset;
|
VariableSpinBox *_syncOffset;
|
||||||
QComboBox *_monitorTypes;
|
QComboBox *_monitorTypes;
|
||||||
SliderSpinBox *_balance;
|
SliderSpinBox *_balance;
|
||||||
QSpinBox *_volumePercent;
|
VariableSpinBox *_volumePercent;
|
||||||
QCheckBox *_fade;
|
QCheckBox *_fade;
|
||||||
DurationSelection *_duration;
|
DurationSelection *_duration;
|
||||||
QDoubleSpinBox *_rate;
|
VariableDoubleSpinBox *_rate;
|
||||||
QCheckBox *_wait;
|
QCheckBox *_wait;
|
||||||
QCheckBox *_abortActiveFade;
|
QCheckBox *_abortActiveFade;
|
||||||
QHBoxLayout *_fadeTypeLayout;
|
QHBoxLayout *_fadeTypeLayout;
|
||||||
@@ -119,3 +121,5 @@ private:
|
|||||||
|
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
#include "macro-action-scene-switch.hpp"
|
#include "macro-action-scene-switch.hpp"
|
||||||
#include "section.hpp"
|
#include "section.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
std::map<std::string, MacroActionInfo> &MacroActionFactory::GetMap()
|
std::map<std::string, MacroActionInfo> &MacroActionFactory::GetMap()
|
||||||
{
|
{
|
||||||
static std::map<std::string, MacroActionInfo> _methods;
|
static std::map<std::string, MacroActionInfo> _methods;
|
||||||
@@ -154,7 +157,7 @@ std::shared_ptr<MacroSegment> MacroActionEdit::Data()
|
|||||||
|
|
||||||
void AdvSceneSwitcher::AddMacroAction(int idx)
|
void AdvSceneSwitcher::AddMacroAction(int idx)
|
||||||
{
|
{
|
||||||
auto macro = getSelectedMacro();
|
auto macro = GetSelectedMacro();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -193,7 +196,7 @@ void AdvSceneSwitcher::AddMacroAction(int idx)
|
|||||||
|
|
||||||
void AdvSceneSwitcher::on_actionAdd_clicked()
|
void AdvSceneSwitcher::on_actionAdd_clicked()
|
||||||
{
|
{
|
||||||
auto macro = getSelectedMacro();
|
auto macro = GetSelectedMacro();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -211,7 +214,7 @@ void AdvSceneSwitcher::on_actionAdd_clicked()
|
|||||||
|
|
||||||
void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
||||||
{
|
{
|
||||||
auto macro = getSelectedMacro();
|
auto macro = GetSelectedMacro();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -237,7 +240,7 @@ void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
|||||||
void AdvSceneSwitcher::on_actionRemove_clicked()
|
void AdvSceneSwitcher::on_actionRemove_clicked()
|
||||||
{
|
{
|
||||||
if (currentActionIdx == -1) {
|
if (currentActionIdx == -1) {
|
||||||
auto macro = getSelectedMacro();
|
auto macro = GetSelectedMacro();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -289,7 +292,7 @@ void AdvSceneSwitcher::SwapActions(Macro *m, int pos1, int pos2)
|
|||||||
|
|
||||||
void AdvSceneSwitcher::MoveMacroActionUp(int idx)
|
void AdvSceneSwitcher::MoveMacroActionUp(int idx)
|
||||||
{
|
{
|
||||||
auto macro = getSelectedMacro();
|
auto macro = GetSelectedMacro();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -304,7 +307,7 @@ void AdvSceneSwitcher::MoveMacroActionUp(int idx)
|
|||||||
|
|
||||||
void AdvSceneSwitcher::MoveMacroActionDown(int idx)
|
void AdvSceneSwitcher::MoveMacroActionDown(int idx)
|
||||||
{
|
{
|
||||||
auto macro = getSelectedMacro();
|
auto macro = GetSelectedMacro();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -319,7 +322,7 @@ void AdvSceneSwitcher::MoveMacroActionDown(int idx)
|
|||||||
|
|
||||||
void AdvSceneSwitcher::MacroActionSelectionChanged(int idx)
|
void AdvSceneSwitcher::MacroActionSelectionChanged(int idx)
|
||||||
{
|
{
|
||||||
auto macro = getSelectedMacro();
|
auto macro = GetSelectedMacro();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -339,7 +342,7 @@ void AdvSceneSwitcher::MacroActionSelectionChanged(int idx)
|
|||||||
|
|
||||||
void AdvSceneSwitcher::MacroActionReorder(int to, int from)
|
void AdvSceneSwitcher::MacroActionReorder(int to, int from)
|
||||||
{
|
{
|
||||||
auto macro = getSelectedMacro();
|
auto macro = GetSelectedMacro();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -361,3 +364,5 @@ void AdvSceneSwitcher::MacroActionReorder(int to, int from)
|
|||||||
HighlightAction(to);
|
HighlightAction(to);
|
||||||
emit(MacroSegmentOrderChanged());
|
emit(MacroSegmentOrderChanged());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
struct MacroActionInfo {
|
struct MacroActionInfo {
|
||||||
using TCreateMethod = std::shared_ptr<MacroAction> (*)(Macro *m);
|
using TCreateMethod = std::shared_ptr<MacroAction> (*)(Macro *m);
|
||||||
using TCreateWidgetMethod = QWidget *(*)(QWidget *parent,
|
using TCreateWidgetMethod = QWidget *(*)(QWidget *parent,
|
||||||
@@ -51,3 +53,5 @@ private:
|
|||||||
std::shared_ptr<MacroAction> *_entryData;
|
std::shared_ptr<MacroAction> *_entryData;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#include "macro-action-file.hpp"
|
#include "macro-action-file.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
const std::string MacroActionFile::id = "file";
|
const std::string MacroActionFile::id = "file";
|
||||||
|
|
||||||
bool MacroActionFile::_registered = MacroActionFactory::Register(
|
bool MacroActionFile::_registered = MacroActionFactory::Register(
|
||||||
@@ -55,7 +56,7 @@ void MacroActionFile::LogAction() const
|
|||||||
bool MacroActionFile::Save(obs_data_t *obj) const
|
bool MacroActionFile::Save(obs_data_t *obj) const
|
||||||
{
|
{
|
||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
obs_data_set_string(obj, "file", _file.c_str());
|
_file.Save(obj, "file");
|
||||||
_text.Save(obj, "text");
|
_text.Save(obj, "text");
|
||||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||||
return true;
|
return true;
|
||||||
@@ -64,7 +65,7 @@ bool MacroActionFile::Save(obs_data_t *obj) const
|
|||||||
bool MacroActionFile::Load(obs_data_t *obj)
|
bool MacroActionFile::Load(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
_file = obs_data_get_string(obj, "file");
|
_file.Load(obj, "file");
|
||||||
_text.Load(obj, "text");
|
_text.Load(obj, "text");
|
||||||
_action = static_cast<FileAction>(obs_data_get_int(obj, "action"));
|
_action = static_cast<FileAction>(obs_data_get_int(obj, "action"));
|
||||||
return true;
|
return true;
|
||||||
@@ -72,7 +73,7 @@ bool MacroActionFile::Load(obs_data_t *obj)
|
|||||||
|
|
||||||
std::string MacroActionFile::GetShortDesc() const
|
std::string MacroActionFile::GetShortDesc() const
|
||||||
{
|
{
|
||||||
return _file;
|
return _file.UnresolvedValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void populateActionSelection(QComboBox *list)
|
static inline void populateActionSelection(QComboBox *list)
|
||||||
@@ -106,7 +107,7 @@ MacroActionFileEdit::MacroActionFileEdit(
|
|||||||
{"{{matchText}}", _text},
|
{"{{matchText}}", _text},
|
||||||
{"{{actions}}", _actions},
|
{"{{actions}}", _actions},
|
||||||
};
|
};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.file.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.file.entry"),
|
||||||
entryLayout, widgetPlaceholders);
|
entryLayout, widgetPlaceholders);
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
@@ -139,7 +140,7 @@ void MacroActionFileEdit::PathChanged(const QString &text)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_file = text.toUtf8().constData();
|
_entryData->_file = text.toUtf8().constData();
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
@@ -151,7 +152,7 @@ void MacroActionFileEdit::TextChanged()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_text = _text->toPlainText().toStdString();
|
_entryData->_text = _text->toPlainText().toStdString();
|
||||||
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
@@ -164,6 +165,8 @@ void MacroActionFileEdit::ActionChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_action = static_cast<FileAction>(value);
|
_entryData->_action = static_cast<FileAction>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
enum class FileAction {
|
enum class FileAction {
|
||||||
WRITE,
|
WRITE,
|
||||||
APPEND,
|
APPEND,
|
||||||
@@ -24,9 +26,8 @@ public:
|
|||||||
return std::make_shared<MacroActionFile>(m);
|
return std::make_shared<MacroActionFile>(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
StringVariable _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||||
VariableResolvingString _text =
|
StringVariable _text = obs_module_text("AdvSceneSwitcher.enterText");
|
||||||
obs_module_text("AdvSceneSwitcher.enterText");
|
|
||||||
FileAction _action = FileAction::WRITE;
|
FileAction _action = FileAction::WRITE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -66,3 +67,5 @@ protected:
|
|||||||
private:
|
private:
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#include "macro-action-filter.hpp"
|
#include "macro-action-filter.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
const std::string MacroActionFilter::id = "filter";
|
const std::string MacroActionFilter::id = "filter";
|
||||||
|
|
||||||
bool MacroActionFilter::_registered = MacroActionFactory::Register(
|
bool MacroActionFilter::_registered = MacroActionFactory::Register(
|
||||||
@@ -18,24 +19,9 @@ const static std::map<MacroActionFilter::Action, std::string> actionTypes = {
|
|||||||
"AdvSceneSwitcher.action.filter.type.settings"},
|
"AdvSceneSwitcher.action.filter.type.settings"},
|
||||||
};
|
};
|
||||||
|
|
||||||
void MacroActionFilter::ResolveVariables()
|
|
||||||
{
|
|
||||||
if (_source.GetType() == SourceSelection::Type::SOURCE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string name = GetWeakSourceName(_filter);
|
|
||||||
if (!name.empty()) {
|
|
||||||
_filterName = name;
|
|
||||||
}
|
|
||||||
_filter = GetWeakFilterByName(_source.GetSource(), _filterName.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroActionFilter::PerformAction()
|
bool MacroActionFilter::PerformAction()
|
||||||
{
|
{
|
||||||
ResolveVariables();
|
auto s = obs_weak_source_get_source(_filter.GetFilter(_source));
|
||||||
|
|
||||||
auto s = obs_weak_source_get_source(_filter);
|
|
||||||
switch (_action) {
|
switch (_action) {
|
||||||
case Action::ENABLE:
|
case Action::ENABLE:
|
||||||
obs_source_set_enabled(s, true);
|
obs_source_set_enabled(s, true);
|
||||||
@@ -44,7 +30,7 @@ bool MacroActionFilter::PerformAction()
|
|||||||
obs_source_set_enabled(s, false);
|
obs_source_set_enabled(s, false);
|
||||||
break;
|
break;
|
||||||
case Action::SETTINGS:
|
case Action::SETTINGS:
|
||||||
setSourceSettings(s, _settings);
|
SetSourceSettings(s, _settings);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -59,7 +45,7 @@ void MacroActionFilter::LogAction() const
|
|||||||
if (it != actionTypes.end()) {
|
if (it != actionTypes.end()) {
|
||||||
vblog(LOG_INFO,
|
vblog(LOG_INFO,
|
||||||
"performed action \"%s\" for filter \"%s\" on source \"%s\"",
|
"performed action \"%s\" for filter \"%s\" on source \"%s\"",
|
||||||
it->second.c_str(), GetWeakSourceName(_filter).c_str(),
|
it->second.c_str(), _filter.ToString().c_str(),
|
||||||
_source.ToString(true).c_str());
|
_source.ToString(true).c_str());
|
||||||
} else {
|
} else {
|
||||||
blog(LOG_WARNING, "ignored unknown filter action %d",
|
blog(LOG_WARNING, "ignored unknown filter action %d",
|
||||||
@@ -71,7 +57,7 @@ bool MacroActionFilter::Save(obs_data_t *obj) const
|
|||||||
{
|
{
|
||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
_source.Save(obj);
|
_source.Save(obj);
|
||||||
obs_data_set_string(obj, "filter", _filterName.c_str());
|
_filter.Save(obj, "filter");
|
||||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||||
_settings.Save(obj, "settings");
|
_settings.Save(obj, "settings");
|
||||||
return true;
|
return true;
|
||||||
@@ -81,9 +67,7 @@ bool MacroActionFilter::Load(obs_data_t *obj)
|
|||||||
{
|
{
|
||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
_source.Load(obj);
|
_source.Load(obj);
|
||||||
_filterName = obs_data_get_string(obj, "filter");
|
_filter.Load(obj, _source, "filter");
|
||||||
_filter = GetWeakFilterByQString(_source.GetSource(),
|
|
||||||
_filterName.c_str());
|
|
||||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||||
_settings.Load(obj, "settings");
|
_settings.Load(obj, "settings");
|
||||||
return true;
|
return true;
|
||||||
@@ -91,8 +75,8 @@ bool MacroActionFilter::Load(obs_data_t *obj)
|
|||||||
|
|
||||||
std::string MacroActionFilter::GetShortDesc() const
|
std::string MacroActionFilter::GetShortDesc() const
|
||||||
{
|
{
|
||||||
if (_filter && !_source.ToString().empty()) {
|
if (!_filter.ToString().empty() && !_source.ToString().empty()) {
|
||||||
return _source.ToString() + " - " + GetWeakSourceName(_filter);
|
return _source.ToString() + " - " + _filter.ToString();
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -108,7 +92,7 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
|||||||
QWidget *parent, std::shared_ptr<MacroActionFilter> entryData)
|
QWidget *parent, std::shared_ptr<MacroActionFilter> entryData)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||||
_filters(new QComboBox()),
|
_filters(new FilterSelectionWidget(this, _sources, true)),
|
||||||
_actions(new QComboBox()),
|
_actions(new QComboBox()),
|
||||||
_getSettings(new QPushButton(obs_module_text(
|
_getSettings(new QPushButton(obs_module_text(
|
||||||
"AdvSceneSwitcher.action.filter.getSettings"))),
|
"AdvSceneSwitcher.action.filter.getSettings"))),
|
||||||
@@ -126,8 +110,9 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
|||||||
QWidget::connect(_sources,
|
QWidget::connect(_sources,
|
||||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||||
SLOT(SourceChanged(const SourceSelection &)));
|
SLOT(SourceChanged(const SourceSelection &)));
|
||||||
QWidget::connect(_filters, SIGNAL(currentTextChanged(const QString &)),
|
QWidget::connect(_filters,
|
||||||
this, SLOT(FilterChanged(const QString &)));
|
SIGNAL(FilterChanged(const FilterSelection &)), this,
|
||||||
|
SLOT(FilterChanged(const FilterSelection &)));
|
||||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||||
SLOT(GetSettingsClicked()));
|
SLOT(GetSettingsClicked()));
|
||||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||||
@@ -140,12 +125,13 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
|||||||
{"{{actions}}", _actions}, {"{{settings}}", _settings},
|
{"{{actions}}", _actions}, {"{{settings}}", _settings},
|
||||||
{"{{getSettings}}", _getSettings},
|
{"{{getSettings}}", _getSettings},
|
||||||
};
|
};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.filter.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.filter.entry"),
|
||||||
entryLayout, widgetPlaceholders);
|
entryLayout, widgetPlaceholders);
|
||||||
|
|
||||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||||
buttonLayout->addWidget(_getSettings);
|
buttonLayout->addWidget(_getSettings);
|
||||||
buttonLayout->addStretch();
|
buttonLayout->addStretch();
|
||||||
|
buttonLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
mainLayout->addLayout(entryLayout);
|
mainLayout->addLayout(entryLayout);
|
||||||
@@ -166,9 +152,7 @@ void MacroActionFilterEdit::UpdateEntryData()
|
|||||||
|
|
||||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||||
_sources->SetSource(_entryData->_source);
|
_sources->SetSource(_entryData->_source);
|
||||||
populateFilterSelection(_filters, _entryData->_source.GetSource());
|
_filters->SetFilter(_entryData->_source, _entryData->_filter);
|
||||||
_filters->setCurrentText(
|
|
||||||
GetWeakSourceName(_entryData->_filter).c_str());
|
|
||||||
_settings->setPlainText(_entryData->_settings);
|
_settings->setPlainText(_entryData->_settings);
|
||||||
SetWidgetVisibility(_entryData->_action ==
|
SetWidgetVisibility(_entryData->_action ==
|
||||||
MacroActionFilter::Action::SETTINGS);
|
MacroActionFilter::Action::SETTINGS);
|
||||||
@@ -182,25 +166,19 @@ void MacroActionFilterEdit::SourceChanged(const SourceSelection &source)
|
|||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_source = source;
|
_entryData->_source = source;
|
||||||
}
|
|
||||||
_filters->clear();
|
|
||||||
populateFilterSelection(_filters, _entryData->_source.GetSource());
|
|
||||||
_filters->adjustSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionFilterEdit::FilterChanged(const QString &text)
|
void MacroActionFilterEdit::FilterChanged(const FilterSelection &filter)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_filterName = text.toStdString();
|
_entryData->_filter = filter;
|
||||||
_entryData->_filter =
|
|
||||||
GetWeakFilterByQString(_entryData->_source.GetSource(), text);
|
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
@@ -211,7 +189,7 @@ void MacroActionFilterEdit::ActionChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_action = static_cast<MacroActionFilter::Action>(value);
|
_entryData->_action = static_cast<MacroActionFilter::Action>(value);
|
||||||
SetWidgetVisibility(_entryData->_action ==
|
SetWidgetVisibility(_entryData->_action ==
|
||||||
MacroActionFilter::Action::SETTINGS);
|
MacroActionFilter::Action::SETTINGS);
|
||||||
@@ -219,13 +197,13 @@ void MacroActionFilterEdit::ActionChanged(int value)
|
|||||||
|
|
||||||
void MacroActionFilterEdit::GetSettingsClicked()
|
void MacroActionFilterEdit::GetSettingsClicked()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData || !_entryData->_source.GetSource() ||
|
if (_loading || !_entryData ||
|
||||||
!_entryData->_filter) {
|
!_entryData->_filter.GetFilter(_entryData->_source)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_settings->setPlainText(
|
_settings->setPlainText(FormatJsonString(GetSourceSettings(
|
||||||
formatJsonString(getSourceSettings(_entryData->_filter)));
|
_entryData->_filter.GetFilter(_entryData->_source))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionFilterEdit::SettingsChanged()
|
void MacroActionFilterEdit::SettingsChanged()
|
||||||
@@ -234,7 +212,7 @@ void MacroActionFilterEdit::SettingsChanged()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_settings = _settings->toPlainText().toStdString();
|
_entryData->_settings = _settings->toPlainText().toStdString();
|
||||||
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
@@ -246,4 +224,7 @@ void MacroActionFilterEdit::SetWidgetVisibility(bool showSettings)
|
|||||||
_settings->setVisible(showSettings);
|
_settings->setVisible(showSettings);
|
||||||
_getSettings->setVisible(showSettings);
|
_getSettings->setVisible(showSettings);
|
||||||
adjustSize();
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -2,11 +2,14 @@
|
|||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
#include "variable-text-edit.hpp"
|
#include "variable-text-edit.hpp"
|
||||||
#include "source-selection.hpp"
|
#include "source-selection.hpp"
|
||||||
|
#include "filter-selection.hpp"
|
||||||
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
class MacroActionFilter : public MacroAction {
|
class MacroActionFilter : public MacroAction {
|
||||||
public:
|
public:
|
||||||
MacroActionFilter(Macro *m) : MacroAction(m) {}
|
MacroActionFilter(Macro *m) : MacroAction(m) {}
|
||||||
@@ -28,18 +31,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
SourceSelection _source;
|
SourceSelection _source;
|
||||||
OBSWeakSource _filter;
|
FilterSelection _filter;
|
||||||
Action _action = Action::ENABLE;
|
Action _action = Action::ENABLE;
|
||||||
VariableResolvingString _settings = "";
|
StringVariable _settings = "";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ResolveVariables();
|
|
||||||
std::string _filterName = "";
|
|
||||||
|
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
static const std::string id;
|
static const std::string id;
|
||||||
|
|
||||||
friend class MacroActionFilterEdit;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacroActionFilterEdit : public QWidget {
|
class MacroActionFilterEdit : public QWidget {
|
||||||
@@ -60,7 +58,7 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void SourceChanged(const SourceSelection &);
|
void SourceChanged(const SourceSelection &);
|
||||||
void FilterChanged(const QString &);
|
void FilterChanged(const FilterSelection &);
|
||||||
void ActionChanged(int value);
|
void ActionChanged(int value);
|
||||||
void GetSettingsClicked();
|
void GetSettingsClicked();
|
||||||
void SettingsChanged();
|
void SettingsChanged();
|
||||||
@@ -69,7 +67,7 @@ signals:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
SourceSelectionWidget *_sources;
|
SourceSelectionWidget *_sources;
|
||||||
QComboBox *_filters;
|
FilterSelectionWidget *_filters;
|
||||||
QComboBox *_actions;
|
QComboBox *_actions;
|
||||||
QPushButton *_getSettings;
|
QPushButton *_getSettings;
|
||||||
VariableTextEdit *_settings;
|
VariableTextEdit *_settings;
|
||||||
@@ -79,3 +77,5 @@ private:
|
|||||||
void SetWidgetVisibility(bool);
|
void SetWidgetVisibility(bool);
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#include "macro-action-hotkey.hpp"
|
#include "macro-action-hotkey.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "platform-funcs.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <obs-interaction.h>
|
#include <obs-interaction.h>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
const std::string MacroActionHotkey::id = "hotkey";
|
const std::string MacroActionHotkey::id = "hotkey";
|
||||||
|
|
||||||
bool MacroActionHotkey::_registered = MacroActionFactory::Register(
|
bool MacroActionHotkey::_registered = MacroActionFactory::Register(
|
||||||
@@ -130,7 +133,8 @@ static std::unordered_map<HotkeyType, long> keyTable = {
|
|||||||
//{HotkeyType::Key_NumpadEnter, ???},
|
//{HotkeyType::Key_NumpadEnter, ???},
|
||||||
};
|
};
|
||||||
|
|
||||||
obs_key_combination keysToOBSKeycombo(const std::vector<HotkeyType> &keys)
|
static obs_key_combination
|
||||||
|
keysToOBSKeycombo(const std::vector<HotkeyType> &keys)
|
||||||
{
|
{
|
||||||
obs_key_combination combo{};
|
obs_key_combination combo{};
|
||||||
auto it = keyTable.find(keys.back());
|
auto it = keyTable.find(keys.back());
|
||||||
@@ -178,7 +182,7 @@ obs_key_combination keysToOBSKeycombo(const std::vector<HotkeyType> &keys)
|
|||||||
return combo;
|
return combo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectKeys(const std::vector<HotkeyType> &keys, int duration)
|
static void InjectKeys(const std::vector<HotkeyType> &keys, int duration)
|
||||||
{
|
{
|
||||||
auto combo = keysToOBSKeycombo(keys);
|
auto combo = keysToOBSKeycombo(keys);
|
||||||
if (obs_key_combination_is_empty(combo)) {
|
if (obs_key_combination_is_empty(combo)) {
|
||||||
@@ -224,7 +228,7 @@ bool MacroActionHotkey::PerformAction()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!keys.empty()) {
|
if (!keys.empty()) {
|
||||||
int dur = _duration;
|
int dur = _duration.Milliseconds();
|
||||||
if (_onlySendToObs || !canSimulateKeyPresses) {
|
if (_onlySendToObs || !canSimulateKeyPresses) {
|
||||||
std::thread t([keys, dur]() { InjectKeys(keys, dur); });
|
std::thread t([keys, dur]() { InjectKeys(keys, dur); });
|
||||||
t.detach();
|
t.detach();
|
||||||
@@ -254,8 +258,9 @@ bool MacroActionHotkey::Save(obs_data_t *obj) const
|
|||||||
obs_data_set_bool(obj, "right_alt", _rightAlt);
|
obs_data_set_bool(obj, "right_alt", _rightAlt);
|
||||||
obs_data_set_bool(obj, "left_meta", _leftMeta);
|
obs_data_set_bool(obj, "left_meta", _leftMeta);
|
||||||
obs_data_set_bool(obj, "right_meta", _rightMeta);
|
obs_data_set_bool(obj, "right_meta", _rightMeta);
|
||||||
obs_data_set_int(obj, "duration", _duration);
|
_duration.Save(obj);
|
||||||
obs_data_set_bool(obj, "onlyOBS", _onlySendToObs);
|
obs_data_set_bool(obj, "onlyOBS", _onlySendToObs);
|
||||||
|
obs_data_set_int(obj, "version", 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +276,11 @@ bool MacroActionHotkey::Load(obs_data_t *obj)
|
|||||||
_rightAlt = obs_data_get_bool(obj, "right_alt");
|
_rightAlt = obs_data_get_bool(obj, "right_alt");
|
||||||
_leftMeta = obs_data_get_bool(obj, "left_meta");
|
_leftMeta = obs_data_get_bool(obj, "left_meta");
|
||||||
_rightMeta = obs_data_get_bool(obj, "right_meta");
|
_rightMeta = obs_data_get_bool(obj, "right_meta");
|
||||||
_duration = obs_data_get_int(obj, "duration");
|
if (!obs_data_has_user_value(obj, "version")) {
|
||||||
|
_duration = obs_data_get_int(obj, "duration") / 1000.0;
|
||||||
|
} else {
|
||||||
|
_duration.Load(obj);
|
||||||
|
}
|
||||||
_onlySendToObs = obs_data_get_bool(obj, "onlyOBS");
|
_onlySendToObs = obs_data_get_bool(obj, "onlyOBS");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -388,32 +397,30 @@ static inline void populateKeySelection(QComboBox *list)
|
|||||||
|
|
||||||
MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroActionHotkey> entryData)
|
QWidget *parent, std::shared_ptr<MacroActionHotkey> entryData)
|
||||||
: QWidget(parent)
|
: QWidget(parent),
|
||||||
|
_keys(new QComboBox()),
|
||||||
|
_leftShift(new QCheckBox(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.hotkey.leftShift"))),
|
||||||
|
_rightShift(new QCheckBox(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.hotkey.rightShift"))),
|
||||||
|
_leftCtrl(new QCheckBox(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.hotkey.leftCtrl"))),
|
||||||
|
_rightCtrl(new QCheckBox(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.hotkey.rightCtrl"))),
|
||||||
|
_leftAlt(new QCheckBox(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.hotkey.leftAlt"))),
|
||||||
|
_rightAlt(new QCheckBox(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.hotkey.rightAlt"))),
|
||||||
|
_leftMeta(new QCheckBox(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.hotkey.leftMeta"))),
|
||||||
|
_rightMeta(new QCheckBox(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.hotkey.rightMeta"))),
|
||||||
|
_duration(new DurationSelection(this, false)),
|
||||||
|
_onlySendToOBS(new QCheckBox(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.hotkey.onlyOBS"))),
|
||||||
|
_noKeyPressSimulationWarning(new QLabel(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.hotkey.disabled")))
|
||||||
{
|
{
|
||||||
_keys = new QComboBox();
|
|
||||||
_leftShift = new QCheckBox(
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftShift"));
|
|
||||||
_rightShift = new QCheckBox(
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightShift"));
|
|
||||||
_leftCtrl = new QCheckBox(
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftCtrl"));
|
|
||||||
_rightCtrl = new QCheckBox(
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightCtrl"));
|
|
||||||
_leftAlt = new QCheckBox(
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftAlt"));
|
|
||||||
_rightAlt = new QCheckBox(
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightAlt"));
|
|
||||||
_leftMeta = new QCheckBox(
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftMeta"));
|
|
||||||
_rightMeta = new QCheckBox(
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightMeta"));
|
|
||||||
_duration = new QSpinBox();
|
|
||||||
_duration->setMaximum(5000);
|
|
||||||
_onlySendToOBS = new QCheckBox(
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.hotkey.onlyOBS"));
|
|
||||||
_noKeyPressSimulationWarning = new QLabel(
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.hotkey.disabled"));
|
|
||||||
|
|
||||||
populateKeySelection(_keys);
|
populateKeySelection(_keys);
|
||||||
|
|
||||||
QWidget::connect(_keys, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_keys, SIGNAL(currentIndexChanged(int)), this,
|
||||||
@@ -434,8 +441,8 @@ MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
|||||||
SLOT(LMetaChanged(int)));
|
SLOT(LMetaChanged(int)));
|
||||||
QWidget::connect(_rightMeta, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_rightMeta, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(RMetaChanged(int)));
|
SLOT(RMetaChanged(int)));
|
||||||
QWidget::connect(_duration, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)),
|
||||||
SLOT(DurationChanged(int)));
|
this, SLOT(DurationChanged(const Duration &)));
|
||||||
QWidget::connect(_onlySendToOBS, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_onlySendToOBS, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(OnlySendToOBSChanged(int)));
|
SLOT(OnlySendToOBSChanged(int)));
|
||||||
|
|
||||||
@@ -444,7 +451,7 @@ MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
|||||||
{"{{keys}}", _keys},
|
{"{{keys}}", _keys},
|
||||||
{"{{duration}}", _duration},
|
{"{{duration}}", _duration},
|
||||||
};
|
};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.hotkey.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.hotkey.entry"),
|
||||||
line1Layout, widgetPlaceholders);
|
line1Layout, widgetPlaceholders);
|
||||||
|
|
||||||
QHBoxLayout *line2Layout = new QHBoxLayout;
|
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||||
@@ -493,7 +500,7 @@ void MacroActionHotkeyEdit::UpdateEntryData()
|
|||||||
_rightAlt->setChecked(_entryData->_rightAlt);
|
_rightAlt->setChecked(_entryData->_rightAlt);
|
||||||
_leftMeta->setChecked(_entryData->_leftMeta);
|
_leftMeta->setChecked(_entryData->_leftMeta);
|
||||||
_rightMeta->setChecked(_entryData->_rightMeta);
|
_rightMeta->setChecked(_entryData->_rightMeta);
|
||||||
_duration->setValue(_entryData->_duration);
|
_duration->SetDuration(_entryData->_duration);
|
||||||
_onlySendToOBS->setChecked(_entryData->_onlySendToObs ||
|
_onlySendToOBS->setChecked(_entryData->_onlySendToObs ||
|
||||||
!canSimulateKeyPresses);
|
!canSimulateKeyPresses);
|
||||||
SetWarningVisibility();
|
SetWarningVisibility();
|
||||||
@@ -505,7 +512,7 @@ void MacroActionHotkeyEdit::LShiftChanged(int state)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_leftShift = state;
|
_entryData->_leftShift = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,7 +522,7 @@ void MacroActionHotkeyEdit::RShiftChanged(int state)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_rightShift = state;
|
_entryData->_rightShift = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,7 +532,7 @@ void MacroActionHotkeyEdit::LCtrlChanged(int state)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_leftCtrl = state;
|
_entryData->_leftCtrl = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,7 +542,7 @@ void MacroActionHotkeyEdit::RCtrlChanged(int state)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_rightCtrl = state;
|
_entryData->_rightCtrl = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,7 +552,7 @@ void MacroActionHotkeyEdit::LAltChanged(int state)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_leftAlt = state;
|
_entryData->_leftAlt = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,7 +562,7 @@ void MacroActionHotkeyEdit::RAltChanged(int state)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_rightAlt = state;
|
_entryData->_rightAlt = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,7 +572,7 @@ void MacroActionHotkeyEdit::LMetaChanged(int state)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_leftMeta = state;
|
_entryData->_leftMeta = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,18 +582,18 @@ void MacroActionHotkeyEdit::RMetaChanged(int state)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_rightMeta = state;
|
_entryData->_rightMeta = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionHotkeyEdit::DurationChanged(int ms)
|
void MacroActionHotkeyEdit::DurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_duration = ms;
|
_entryData->_duration = dur;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionHotkeyEdit::OnlySendToOBSChanged(int state)
|
void MacroActionHotkeyEdit::OnlySendToOBSChanged(int state)
|
||||||
@@ -595,7 +602,7 @@ void MacroActionHotkeyEdit::OnlySendToOBSChanged(int state)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_onlySendToObs = state;
|
_entryData->_onlySendToObs = state;
|
||||||
SetWarningVisibility();
|
SetWarningVisibility();
|
||||||
}
|
}
|
||||||
@@ -606,6 +613,8 @@ void MacroActionHotkeyEdit::KeyChanged(int key)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_key = static_cast<HotkeyType>(key);
|
_entryData->_key = static_cast<HotkeyType>(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
#include "hotkey.hpp"
|
#include "hotkey.hpp"
|
||||||
|
#include "duration-control.hpp"
|
||||||
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
class MacroActionHotkey : public MacroAction {
|
class MacroActionHotkey : public MacroAction {
|
||||||
public:
|
public:
|
||||||
MacroActionHotkey(Macro *m) : MacroAction(m) {}
|
MacroActionHotkey(Macro *m) : MacroAction(m) {}
|
||||||
@@ -30,7 +33,7 @@ public:
|
|||||||
bool _rightAlt = false;
|
bool _rightAlt = false;
|
||||||
bool _leftMeta = false;
|
bool _leftMeta = false;
|
||||||
bool _rightMeta = false;
|
bool _rightMeta = false;
|
||||||
int _duration = 300; // in ms
|
Duration _duration = 0.3;
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
bool _onlySendToObs = true;
|
bool _onlySendToObs = true;
|
||||||
#else
|
#else
|
||||||
@@ -68,7 +71,7 @@ private slots:
|
|||||||
void RAltChanged(int state);
|
void RAltChanged(int state);
|
||||||
void LMetaChanged(int state);
|
void LMetaChanged(int state);
|
||||||
void RMetaChanged(int state);
|
void RMetaChanged(int state);
|
||||||
void DurationChanged(int ms);
|
void DurationChanged(const Duration &);
|
||||||
void OnlySendToOBSChanged(int state);
|
void OnlySendToOBSChanged(int state);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -81,7 +84,7 @@ protected:
|
|||||||
QCheckBox *_rightAlt;
|
QCheckBox *_rightAlt;
|
||||||
QCheckBox *_leftMeta;
|
QCheckBox *_leftMeta;
|
||||||
QCheckBox *_rightMeta;
|
QCheckBox *_rightMeta;
|
||||||
QSpinBox *_duration;
|
DurationSelection *_duration;
|
||||||
QCheckBox *_onlySendToOBS;
|
QCheckBox *_onlySendToOBS;
|
||||||
QLabel *_noKeyPressSimulationWarning;
|
QLabel *_noKeyPressSimulationWarning;
|
||||||
|
|
||||||
@@ -92,3 +95,5 @@ private:
|
|||||||
QHBoxLayout *_mainLayout;
|
QHBoxLayout *_mainLayout;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#include "macro-action-http.hpp"
|
#include "macro-action-http.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "switcher-data.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "curl-helper.hpp"
|
#include "curl-helper.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
const std::string MacroActionHttp::id = "http";
|
const std::string MacroActionHttp::id = "http";
|
||||||
|
|
||||||
bool MacroActionHttp::_registered = MacroActionFactory::Register(
|
bool MacroActionHttp::_registered = MacroActionFactory::Register(
|
||||||
@@ -16,22 +18,37 @@ const static std::map<MacroActionHttp::Method, std::string> methods = {
|
|||||||
"AdvSceneSwitcher.action.http.type.post"},
|
"AdvSceneSwitcher.action.http.type.post"},
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t DropCB(void *, size_t size, size_t nmemb, std::string *)
|
static size_t DropCB(void *, size_t size, size_t nmemb, std::string *)
|
||||||
{
|
{
|
||||||
return size * nmemb;
|
return size * nmemb;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t WriteCB(void *ptr, size_t size, size_t nmemb, std::string *buffer)
|
static size_t WriteCB(void *ptr, size_t size, size_t nmemb, std::string *buffer)
|
||||||
{
|
{
|
||||||
buffer->append((char *)ptr, nmemb);
|
buffer->append((char *)ptr, nmemb);
|
||||||
return size * nmemb;
|
return size * nmemb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionHttp::SetupHeaders()
|
||||||
|
{
|
||||||
|
if (!_setHeaders) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct curl_slist *headers = nullptr;
|
||||||
|
for (auto &header : _headers) {
|
||||||
|
headers = switcher->curl.SlistAppend(headers, header.c_str());
|
||||||
|
}
|
||||||
|
if (!_headers.empty()) {
|
||||||
|
switcher->curl.SetOpt(CURLOPT_HTTPHEADER, headers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MacroActionHttp::Get()
|
void MacroActionHttp::Get()
|
||||||
{
|
{
|
||||||
switcher->curl.SetOpt(CURLOPT_URL, _url.c_str());
|
switcher->curl.SetOpt(CURLOPT_URL, _url.c_str());
|
||||||
switcher->curl.SetOpt(CURLOPT_HTTPGET, 1L);
|
switcher->curl.SetOpt(CURLOPT_HTTPGET, 1L);
|
||||||
switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.seconds * 1000);
|
switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.Milliseconds());
|
||||||
|
SetupHeaders();
|
||||||
|
|
||||||
std::string response;
|
std::string response;
|
||||||
if (IsReferencedInVars()) {
|
if (IsReferencedInVars()) {
|
||||||
@@ -49,7 +66,8 @@ void MacroActionHttp::Post()
|
|||||||
{
|
{
|
||||||
switcher->curl.SetOpt(CURLOPT_URL, _url.c_str());
|
switcher->curl.SetOpt(CURLOPT_URL, _url.c_str());
|
||||||
switcher->curl.SetOpt(CURLOPT_POSTFIELDS, _data.c_str());
|
switcher->curl.SetOpt(CURLOPT_POSTFIELDS, _data.c_str());
|
||||||
switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.seconds * 1000);
|
switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.Milliseconds());
|
||||||
|
SetupHeaders();
|
||||||
switcher->curl.Perform();
|
switcher->curl.Perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,8 +108,10 @@ void MacroActionHttp::LogAction() const
|
|||||||
bool MacroActionHttp::Save(obs_data_t *obj) const
|
bool MacroActionHttp::Save(obs_data_t *obj) const
|
||||||
{
|
{
|
||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
obs_data_set_string(obj, "url", _url.c_str());
|
_url.Save(obj, "url");
|
||||||
_data.Save(obj, "data");
|
_data.Save(obj, "data");
|
||||||
|
obs_data_set_bool(obj, "setHeaders", _setHeaders);
|
||||||
|
_headers.Save(obj, "headers", "header");
|
||||||
obs_data_set_int(obj, "method", static_cast<int>(_method));
|
obs_data_set_int(obj, "method", static_cast<int>(_method));
|
||||||
_timeout.Save(obj);
|
_timeout.Save(obj);
|
||||||
return true;
|
return true;
|
||||||
@@ -100,8 +120,10 @@ bool MacroActionHttp::Save(obs_data_t *obj) const
|
|||||||
bool MacroActionHttp::Load(obs_data_t *obj)
|
bool MacroActionHttp::Load(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
_url = obs_data_get_string(obj, "url");
|
_url.Load(obj, "url");
|
||||||
_data.Load(obj, "data");
|
_data.Load(obj, "data");
|
||||||
|
_setHeaders = obs_data_get_bool(obj, "setHeaders");
|
||||||
|
_headers.Load(obj, "headers", "header");
|
||||||
_method = static_cast<Method>(obs_data_get_int(obj, "method"));
|
_method = static_cast<Method>(obs_data_get_int(obj, "method"));
|
||||||
_timeout.Load(obj);
|
_timeout.Load(obj);
|
||||||
return true;
|
return true;
|
||||||
@@ -109,7 +131,7 @@ bool MacroActionHttp::Load(obs_data_t *obj)
|
|||||||
|
|
||||||
std::string MacroActionHttp::GetShortDesc() const
|
std::string MacroActionHttp::GetShortDesc() const
|
||||||
{
|
{
|
||||||
return _url;
|
return _url.UnresolvedValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void populateMethodSelection(QComboBox *list)
|
static inline void populateMethodSelection(QComboBox *list)
|
||||||
@@ -122,9 +144,15 @@ static inline void populateMethodSelection(QComboBox *list)
|
|||||||
MacroActionHttpEdit::MacroActionHttpEdit(
|
MacroActionHttpEdit::MacroActionHttpEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroActionHttp> entryData)
|
QWidget *parent, std::shared_ptr<MacroActionHttp> entryData)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
_url(new QLineEdit()),
|
_url(new VariableLineEdit(this)),
|
||||||
_methods(new QComboBox()),
|
_methods(new QComboBox()),
|
||||||
_data(new VariableTextEdit(this)),
|
_data(new VariableTextEdit(this)),
|
||||||
|
_setHeaders(new QCheckBox(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.http.setHeaders"))),
|
||||||
|
_headerListLayout(new QVBoxLayout()),
|
||||||
|
_headerList(new StringListEdit(
|
||||||
|
this, obs_module_text("AdvSceneSwitcher.action.http.headers"),
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.http.addHeader"))),
|
||||||
_timeout(new DurationSelection(this, false))
|
_timeout(new DurationSelection(this, false))
|
||||||
{
|
{
|
||||||
populateMethodSelection(_methods);
|
populateMethodSelection(_methods);
|
||||||
@@ -135,8 +163,13 @@ MacroActionHttpEdit::MacroActionHttpEdit(
|
|||||||
SLOT(DataChanged()));
|
SLOT(DataChanged()));
|
||||||
QWidget::connect(_methods, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_methods, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(MethodChanged(int)));
|
SLOT(MethodChanged(int)));
|
||||||
QWidget::connect(_timeout, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(_setHeaders, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(TimeoutChanged(double)));
|
SLOT(SetHeadersChanged(int)));
|
||||||
|
QWidget::connect(_headerList,
|
||||||
|
SIGNAL(StringListChanged(const StringList &)), this,
|
||||||
|
SLOT(HeadersChanged(const StringList &)));
|
||||||
|
QWidget::connect(_timeout, SIGNAL(DurationChanged(const Duration &)),
|
||||||
|
this, SLOT(TimeoutChanged(const Duration &)));
|
||||||
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{url}}", _url},
|
{"{{url}}", _url},
|
||||||
@@ -145,16 +178,22 @@ MacroActionHttpEdit::MacroActionHttpEdit(
|
|||||||
{"{{timeout}}", _timeout},
|
{"{{timeout}}", _timeout},
|
||||||
};
|
};
|
||||||
auto *actionLayout = new QHBoxLayout;
|
auto *actionLayout = new QHBoxLayout;
|
||||||
placeWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.action.http.entry.line1"),
|
obs_module_text("AdvSceneSwitcher.action.http.entry.line1"),
|
||||||
actionLayout, widgetPlaceholders);
|
actionLayout, widgetPlaceholders);
|
||||||
auto *timeoutLayout = new QHBoxLayout;
|
auto *timeoutLayout = new QHBoxLayout;
|
||||||
placeWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.action.http.entry.line2"),
|
obs_module_text("AdvSceneSwitcher.action.http.entry.line2"),
|
||||||
timeoutLayout, widgetPlaceholders);
|
timeoutLayout, widgetPlaceholders);
|
||||||
|
|
||||||
|
_headerListLayout->addWidget(new QLabel(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.http.headers")));
|
||||||
|
_headerListLayout->addWidget(_headerList);
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
mainLayout->addLayout(actionLayout);
|
mainLayout->addLayout(actionLayout);
|
||||||
|
mainLayout->addWidget(_setHeaders);
|
||||||
|
mainLayout->addLayout(_headerListLayout);
|
||||||
mainLayout->addWidget(_data);
|
mainLayout->addWidget(_data);
|
||||||
mainLayout->addLayout(timeoutLayout);
|
mainLayout->addLayout(timeoutLayout);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
@@ -170,8 +209,10 @@ void MacroActionHttpEdit::UpdateEntryData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_url->setText(QString::fromStdString(_entryData->_url));
|
_url->setText(_entryData->_url);
|
||||||
_data->setPlainText(_entryData->_data);
|
_data->setPlainText(_entryData->_data);
|
||||||
|
_setHeaders->setChecked(_entryData->_setHeaders);
|
||||||
|
_headerList->SetStringList(_entryData->_headers);
|
||||||
_methods->setCurrentIndex(static_cast<int>(_entryData->_method));
|
_methods->setCurrentIndex(static_cast<int>(_entryData->_method));
|
||||||
_timeout->SetDuration(_entryData->_timeout);
|
_timeout->SetDuration(_entryData->_timeout);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
@@ -183,7 +224,7 @@ void MacroActionHttpEdit::URLChanged()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_url = _url->text().toStdString();
|
_entryData->_url = _url->text().toStdString();
|
||||||
emit(HeaderInfoChanged(_url->text()));
|
emit(HeaderInfoChanged(_url->text()));
|
||||||
}
|
}
|
||||||
@@ -194,33 +235,48 @@ void MacroActionHttpEdit::MethodChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_method = static_cast<MacroActionHttp::Method>(value);
|
_entryData->_method = static_cast<MacroActionHttp::Method>(value);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionHttpEdit::TimeoutChanged(double seconds)
|
void MacroActionHttpEdit::TimeoutChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_timeout.seconds = seconds;
|
_entryData->_timeout = dur;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionHttpEdit::SetHeadersChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_setHeaders = value;
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionHttpEdit::HeadersChanged(const StringList &headers)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_headers = headers;
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionHttpEdit::SetWidgetVisibility()
|
void MacroActionHttpEdit::SetWidgetVisibility()
|
||||||
{
|
{
|
||||||
switch (_entryData->_method) {
|
_data->setVisible(_entryData->_method == MacroActionHttp::Method::POST);
|
||||||
case MacroActionHttp::Method::GET:
|
SetLayoutVisible(_headerListLayout, _entryData->_setHeaders);
|
||||||
_data->hide();
|
|
||||||
break;
|
|
||||||
case MacroActionHttp::Method::POST:
|
|
||||||
_data->show();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
@@ -232,9 +288,11 @@ void MacroActionHttpEdit::DataChanged()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_data = _data->toPlainText().toUtf8().constData();
|
_entryData->_data = _data->toPlainText().toUtf8().constData();
|
||||||
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
#include "variable-text-edit.hpp"
|
#include "variable-text-edit.hpp"
|
||||||
|
#include "variable-line-edit.hpp"
|
||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
|
#include "string-list.hpp"
|
||||||
|
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QCheckBox>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
class MacroActionHttp : public MacroAction {
|
class MacroActionHttp : public MacroAction {
|
||||||
public:
|
public:
|
||||||
@@ -25,13 +30,15 @@ public:
|
|||||||
POST,
|
POST,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string _url = obs_module_text("AdvSceneSwitcher.enterURL");
|
StringVariable _url = obs_module_text("AdvSceneSwitcher.enterURL");
|
||||||
VariableResolvingString _data =
|
StringVariable _data = obs_module_text("AdvSceneSwitcher.enterText");
|
||||||
obs_module_text("AdvSceneSwitcher.enterText");
|
bool _setHeaders = false;
|
||||||
|
StringList _headers;
|
||||||
Method _method = Method::GET;
|
Method _method = Method::GET;
|
||||||
Duration _timeout;
|
Duration _timeout = Duration(1.0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void SetupHeaders();
|
||||||
void Get();
|
void Get();
|
||||||
void Post();
|
void Post();
|
||||||
|
|
||||||
@@ -59,7 +66,9 @@ private slots:
|
|||||||
void DataChanged();
|
void DataChanged();
|
||||||
void URLChanged();
|
void URLChanged();
|
||||||
void MethodChanged(int);
|
void MethodChanged(int);
|
||||||
void TimeoutChanged(double seconds);
|
void TimeoutChanged(const Duration &seconds);
|
||||||
|
void SetHeadersChanged(int);
|
||||||
|
void HeadersChanged(const StringList &);
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
@@ -69,9 +78,14 @@ protected:
|
|||||||
private:
|
private:
|
||||||
void SetWidgetVisibility();
|
void SetWidgetVisibility();
|
||||||
|
|
||||||
QLineEdit *_url;
|
VariableLineEdit *_url;
|
||||||
QComboBox *_methods;
|
QComboBox *_methods;
|
||||||
VariableTextEdit *_data;
|
VariableTextEdit *_data;
|
||||||
|
QCheckBox *_setHeaders;
|
||||||
|
QVBoxLayout *_headerListLayout;
|
||||||
|
StringListEdit *_headerList;
|
||||||
DurationSelection *_timeout;
|
DurationSelection *_timeout;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#include "macro-action-macro.hpp"
|
#include "macro-action-macro.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "macro.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
const std::string MacroActionMacro::id = "macro";
|
const std::string MacroActionMacro::id = "macro";
|
||||||
|
|
||||||
bool MacroActionMacro::_registered = MacroActionFactory::Register(
|
bool MacroActionMacro::_registered = MacroActionFactory::Register(
|
||||||
@@ -21,27 +23,28 @@ const static std::map<PerformMacroAction, std::string> actionTypes = {
|
|||||||
|
|
||||||
bool MacroActionMacro::PerformAction()
|
bool MacroActionMacro::PerformAction()
|
||||||
{
|
{
|
||||||
if (!_macro.get()) {
|
auto macro = _macro.GetMacro();
|
||||||
|
if (!macro) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_action) {
|
switch (_action) {
|
||||||
case PerformMacroAction::PAUSE:
|
case PerformMacroAction::PAUSE:
|
||||||
_macro->SetPaused();
|
macro->SetPaused();
|
||||||
break;
|
break;
|
||||||
case PerformMacroAction::UNPAUSE:
|
case PerformMacroAction::UNPAUSE:
|
||||||
_macro->SetPaused(false);
|
macro->SetPaused(false);
|
||||||
break;
|
break;
|
||||||
case PerformMacroAction::RESET_COUNTER:
|
case PerformMacroAction::RESET_COUNTER:
|
||||||
_macro->ResetRunCount();
|
macro->ResetRunCount();
|
||||||
break;
|
break;
|
||||||
case PerformMacroAction::RUN:
|
case PerformMacroAction::RUN:
|
||||||
if (!_macro->Paused()) {
|
if (!macro->Paused()) {
|
||||||
_macro->PerformActions();
|
macro->PerformActions();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PerformMacroAction::STOP:
|
case PerformMacroAction::STOP:
|
||||||
_macro->Stop();
|
macro->Stop();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -51,26 +54,27 @@ bool MacroActionMacro::PerformAction()
|
|||||||
|
|
||||||
void MacroActionMacro::LogAction() const
|
void MacroActionMacro::LogAction() const
|
||||||
{
|
{
|
||||||
if (!_macro.get()) {
|
auto macro = _macro.GetMacro();
|
||||||
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (_action) {
|
switch (_action) {
|
||||||
case PerformMacroAction::PAUSE:
|
case PerformMacroAction::PAUSE:
|
||||||
vblog(LOG_INFO, "paused \"%s\"", _macro->Name().c_str());
|
vblog(LOG_INFO, "paused \"%s\"", macro->Name().c_str());
|
||||||
break;
|
break;
|
||||||
case PerformMacroAction::UNPAUSE:
|
case PerformMacroAction::UNPAUSE:
|
||||||
vblog(LOG_INFO, "unpaused \"%s\"", _macro->Name().c_str());
|
vblog(LOG_INFO, "unpaused \"%s\"", macro->Name().c_str());
|
||||||
break;
|
break;
|
||||||
case PerformMacroAction::RESET_COUNTER:
|
case PerformMacroAction::RESET_COUNTER:
|
||||||
vblog(LOG_INFO, "reset counter for \"%s\"",
|
vblog(LOG_INFO, "reset counter for \"%s\"",
|
||||||
_macro->Name().c_str());
|
macro->Name().c_str());
|
||||||
break;
|
break;
|
||||||
case PerformMacroAction::RUN:
|
case PerformMacroAction::RUN:
|
||||||
vblog(LOG_INFO, "run nested macro \"%s\"",
|
vblog(LOG_INFO, "run nested macro \"%s\"",
|
||||||
_macro->Name().c_str());
|
macro->Name().c_str());
|
||||||
break;
|
break;
|
||||||
case PerformMacroAction::STOP:
|
case PerformMacroAction::STOP:
|
||||||
vblog(LOG_INFO, "stopped macro \"%s\"", _macro->Name().c_str());
|
vblog(LOG_INFO, "stopped macro \"%s\"", macro->Name().c_str());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -96,10 +100,7 @@ bool MacroActionMacro::Load(obs_data_t *obj)
|
|||||||
|
|
||||||
std::string MacroActionMacro::GetShortDesc() const
|
std::string MacroActionMacro::GetShortDesc() const
|
||||||
{
|
{
|
||||||
if (_macro.get()) {
|
return _macro.Name();
|
||||||
return _macro->Name();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void populateActionSelection(QComboBox *list)
|
static inline void populateActionSelection(QComboBox *list)
|
||||||
@@ -120,8 +121,6 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
|||||||
|
|
||||||
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
|
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
|
||||||
this, SLOT(MacroChanged(const QString &)));
|
this, SLOT(MacroChanged(const QString &)));
|
||||||
QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this,
|
|
||||||
SLOT(MacroRemove(const QString &)));
|
|
||||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ActionChanged(int)));
|
SLOT(ActionChanged(int)));
|
||||||
|
|
||||||
@@ -130,7 +129,7 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
|||||||
{"{{actions}}", _actions},
|
{"{{actions}}", _actions},
|
||||||
{"{{macros}}", _macros},
|
{"{{macros}}", _macros},
|
||||||
};
|
};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.macro.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.macro.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -145,7 +144,7 @@ void MacroActionMacroEdit::UpdateEntryData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||||
_macros->SetCurrentMacro(_entryData->_macro.get());
|
_macros->SetCurrentMacro(_entryData->_macro);
|
||||||
if (_entryData->_action == PerformMacroAction::RUN ||
|
if (_entryData->_action == PerformMacroAction::RUN ||
|
||||||
_entryData->_action == PerformMacroAction::STOP) {
|
_entryData->_action == PerformMacroAction::STOP) {
|
||||||
_macros->HideSelectedMacro();
|
_macros->HideSelectedMacro();
|
||||||
@@ -158,8 +157,8 @@ void MacroActionMacroEdit::MacroChanged(const QString &text)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_macro.UpdateRef(text);
|
_entryData->_macro = text;
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
@@ -170,7 +169,7 @@ void MacroActionMacroEdit::ActionChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_action = static_cast<PerformMacroAction>(value);
|
_entryData->_action = static_cast<PerformMacroAction>(value);
|
||||||
|
|
||||||
if (_entryData->_action == PerformMacroAction::RUN ||
|
if (_entryData->_action == PerformMacroAction::RUN ||
|
||||||
@@ -181,9 +180,4 @@ void MacroActionMacroEdit::ActionChanged(int value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionMacroEdit::MacroRemove(const QString &)
|
} // namespace advss
|
||||||
{
|
|
||||||
if (_entryData) {
|
|
||||||
_entryData->_macro.UpdateRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
enum class PerformMacroAction {
|
enum class PerformMacroAction {
|
||||||
PAUSE,
|
PAUSE,
|
||||||
UNPAUSE,
|
UNPAUSE,
|
||||||
@@ -51,7 +53,6 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void MacroChanged(const QString &text);
|
void MacroChanged(const QString &text);
|
||||||
void MacroRemove(const QString &name);
|
|
||||||
void ActionChanged(int value);
|
void ActionChanged(int value);
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
@@ -65,3 +66,5 @@ private:
|
|||||||
QHBoxLayout *_mainLayout;
|
QHBoxLayout *_mainLayout;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#include "macro-action-media.hpp"
|
#include "macro-action-media.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
const std::string MacroActionMedia::id = "media";
|
const std::string MacroActionMedia::id = "media";
|
||||||
|
|
||||||
bool MacroActionMedia::_registered = MacroActionFactory::Register(
|
bool MacroActionMedia::_registered = MacroActionFactory::Register(
|
||||||
@@ -48,7 +49,7 @@ bool MacroActionMedia::PerformAction()
|
|||||||
obs_source_media_previous(source);
|
obs_source_media_previous(source);
|
||||||
break;
|
break;
|
||||||
case MediaAction::SEEK:
|
case MediaAction::SEEK:
|
||||||
obs_source_media_set_time(source, _seek.seconds * 1000);
|
obs_source_media_set_time(source, _seek.Milliseconds());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -116,10 +117,8 @@ MacroActionMediaEdit::MacroActionMediaEdit(
|
|||||||
QWidget::connect(_sources,
|
QWidget::connect(_sources,
|
||||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||||
SLOT(SourceChanged(const SourceSelection &)));
|
SLOT(SourceChanged(const SourceSelection &)));
|
||||||
QWidget::connect(_seek, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(_seek, SIGNAL(DurationChanged(const Duration &)), this,
|
||||||
SLOT(DurationChanged(double)));
|
SLOT(DurationChanged(const Duration &)));
|
||||||
QWidget::connect(_seek, SIGNAL(UnitChanged(DurationUnit)), this,
|
|
||||||
SLOT(DurationUnitChanged(DurationUnit)));
|
|
||||||
|
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
@@ -127,7 +126,7 @@ MacroActionMediaEdit::MacroActionMediaEdit(
|
|||||||
{"{{actions}}", _actions},
|
{"{{actions}}", _actions},
|
||||||
{"{{duration}}", _seek},
|
{"{{duration}}", _seek},
|
||||||
};
|
};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.media.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.media.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -154,7 +153,7 @@ void MacroActionMediaEdit::SourceChanged(const SourceSelection &source)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_mediaSource = source;
|
_entryData->_mediaSource = source;
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
@@ -166,29 +165,19 @@ void MacroActionMediaEdit::ActionChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_action = static_cast<MediaAction>(value);
|
_entryData->_action = static_cast<MediaAction>(value);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionMediaEdit::DurationChanged(double seconds)
|
void MacroActionMediaEdit::DurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_seek.seconds = seconds;
|
_entryData->_seek = dur;
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionMediaEdit::DurationUnitChanged(DurationUnit unit)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_seek.displayUnit = unit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionMediaEdit::SetWidgetVisibility()
|
void MacroActionMediaEdit::SetWidgetVisibility()
|
||||||
@@ -199,3 +188,5 @@ void MacroActionMediaEdit::SetWidgetVisibility()
|
|||||||
_seek->setVisible(_entryData->_action == MediaAction::SEEK);
|
_seek->setVisible(_entryData->_action == MediaAction::SEEK);
|
||||||
adjustSize();
|
adjustSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
enum class MediaAction {
|
enum class MediaAction {
|
||||||
PLAY,
|
PLAY,
|
||||||
PAUSE,
|
PAUSE,
|
||||||
@@ -58,8 +60,7 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void SourceChanged(const SourceSelection &);
|
void SourceChanged(const SourceSelection &);
|
||||||
void ActionChanged(int value);
|
void ActionChanged(int value);
|
||||||
void DurationChanged(double value);
|
void DurationChanged(const Duration &value);
|
||||||
void DurationUnitChanged(DurationUnit unit);
|
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
@@ -75,3 +76,5 @@ private:
|
|||||||
QHBoxLayout *_mainLayout;
|
QHBoxLayout *_mainLayout;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
318
src/macro-core/macro-action-osc.cpp
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
#include "macro-action-osc.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
#include <system_error>
|
||||||
|
#include <QGroupBox>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
const std::string MacroActionOSC::id = "osc";
|
||||||
|
|
||||||
|
bool MacroActionOSC::_registered = MacroActionFactory::Register(
|
||||||
|
MacroActionOSC::id, {MacroActionOSC::Create, MacroActionOSCEdit::Create,
|
||||||
|
"AdvSceneSwitcher.action.osc"});
|
||||||
|
|
||||||
|
MacroActionOSC::MacroActionOSC(Macro *m)
|
||||||
|
: MacroAction(m),
|
||||||
|
_ctx(asio::io_context()),
|
||||||
|
_tcpSocket(asio::ip::tcp::socket(_ctx)),
|
||||||
|
_udpSocket(asio::ip::udp::socket(_ctx))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSC::SendOSCTCPMessage(const asio::mutable_buffer &buffer)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
asio::write(_tcpSocket, asio::buffer(buffer));
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"failed to send OSC message \"%s\" via TCP %s %d: %s",
|
||||||
|
_message.ToString().c_str(), _ip.c_str(), _port.GetValue(),
|
||||||
|
e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSC::SendOSCUDPMessage(const asio::mutable_buffer &buffer)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
_udpSocket.send_to(buffer, _updEndpoint);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"failed to send OSC message \"%s\" via UDP %s %d: %s",
|
||||||
|
_message.ToString().c_str(), _ip.c_str(), _port.GetValue(),
|
||||||
|
e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSC::UDPReconnect()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
asio::ip::udp::resolver resolver(_ctx);
|
||||||
|
auto endpoints = resolver.resolve(asio::ip::udp::v4(), _ip.c_str(),
|
||||||
|
std::to_string(_port.GetValue()), ec);
|
||||||
|
if (ec) {
|
||||||
|
endpoints = resolver.resolve(asio::ip::udp::v6(), _ip.c_str(),
|
||||||
|
std::to_string(_port.GetValue()),
|
||||||
|
ec);
|
||||||
|
}
|
||||||
|
if (ec) {
|
||||||
|
blog(LOG_WARNING, "failed to get IP for \"%s\": %s",
|
||||||
|
_ip.c_str(), ec.message().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
_updEndpoint = endpoints.begin()->endpoint();
|
||||||
|
_udpSocket = asio::ip::udp::socket(_ctx);
|
||||||
|
_udpSocket.open(endpoints.begin()->endpoint().protocol());
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
blog(LOG_WARNING, "failed to connect to UDP %s %d: %s",
|
||||||
|
_ip.c_str(), _port.GetValue(), e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSC::TCPReconnect()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
asio::ip::tcp::resolver resolver(_ctx);
|
||||||
|
auto endpoints = resolver.resolve(asio::ip::tcp::v4(), _ip.c_str(),
|
||||||
|
std::to_string(_port.GetValue()), ec);
|
||||||
|
if (ec) {
|
||||||
|
endpoints = resolver.resolve(asio::ip::tcp::v6(), _ip.c_str(),
|
||||||
|
std::to_string(_port.GetValue()),
|
||||||
|
ec);
|
||||||
|
}
|
||||||
|
if (ec) {
|
||||||
|
blog(LOG_WARNING, "failed to get IP for \"%s\": %s",
|
||||||
|
_ip.c_str(), ec.message().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
_tcpSocket = asio::ip::tcp::socket(_ctx);
|
||||||
|
_tcpSocket.connect(endpoints.begin()->endpoint());
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
blog(LOG_WARNING, "failed to connect to TCP %s %d: %s",
|
||||||
|
_ip.c_str(), _port.GetValue(), e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSC::CheckReconnect()
|
||||||
|
{
|
||||||
|
if (_protocol == Protocol::TCP &&
|
||||||
|
(_reconnect || !_tcpSocket.is_open())) {
|
||||||
|
TCPReconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_protocol == Protocol::UDP &&
|
||||||
|
(_reconnect || !_udpSocket.is_open())) {
|
||||||
|
UDPReconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionOSC::PerformAction()
|
||||||
|
{
|
||||||
|
auto buffer = _message.GetBuffer();
|
||||||
|
if (!buffer.has_value()) {
|
||||||
|
blog(LOG_WARNING, "failed to create or fill OSC buffer!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckReconnect();
|
||||||
|
|
||||||
|
if (_protocol == Protocol::TCP &&
|
||||||
|
(_reconnect || !_tcpSocket.is_open())) {
|
||||||
|
TCPReconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_protocol == Protocol::UDP &&
|
||||||
|
(_reconnect || !_udpSocket.is_open())) {
|
||||||
|
UDPReconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rawMessage = asio::buffer(*buffer);
|
||||||
|
|
||||||
|
switch (_protocol) {
|
||||||
|
case MacroActionOSC::Protocol::TCP:
|
||||||
|
SendOSCTCPMessage(rawMessage);
|
||||||
|
break;
|
||||||
|
case MacroActionOSC::Protocol::UDP:
|
||||||
|
SendOSCUDPMessage(rawMessage);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSC::LogAction() const
|
||||||
|
{
|
||||||
|
vblog(LOG_INFO, "sending OSC message '%s' to %s %s %d",
|
||||||
|
_message.ToString().c_str(),
|
||||||
|
_protocol == Protocol::UDP ? "UDP" : "TCP", _ip.c_str(),
|
||||||
|
_port.GetValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionOSC::Save(obs_data_t *obj) const
|
||||||
|
{
|
||||||
|
MacroAction::Save(obj);
|
||||||
|
obs_data_set_int(obj, "protocol", static_cast<int>(_protocol));
|
||||||
|
_ip.Save(obj, "ip");
|
||||||
|
_port.Save(obj, "port");
|
||||||
|
_message.Save(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionOSC::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroAction::Load(obj);
|
||||||
|
_protocol = static_cast<Protocol>(obs_data_get_int(obj, "protocol"));
|
||||||
|
_ip.Load(obj, "ip");
|
||||||
|
_port.Load(obj, "port");
|
||||||
|
_message.Load(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSC::SetProtocol(Protocol p)
|
||||||
|
{
|
||||||
|
_protocol = p;
|
||||||
|
_reconnect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSC::SetIP(const std::string &ip)
|
||||||
|
{
|
||||||
|
_ip = ip;
|
||||||
|
_reconnect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSC::SetPortNr(IntVariable port)
|
||||||
|
{
|
||||||
|
_port = port;
|
||||||
|
_reconnect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void populateProtocolSelection(QComboBox *list)
|
||||||
|
{
|
||||||
|
list->addItem("TCP");
|
||||||
|
list->addItem("UDP");
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroActionOSCEdit::MacroActionOSCEdit(
|
||||||
|
QWidget *parent, std::shared_ptr<MacroActionOSC> entryData)
|
||||||
|
: QWidget(parent),
|
||||||
|
_protocol(new QComboBox(this)),
|
||||||
|
_ip(new VariableLineEdit(this)),
|
||||||
|
_port(new VariableSpinBox(this)),
|
||||||
|
_message(new OSCMessageEdit(this))
|
||||||
|
{
|
||||||
|
populateProtocolSelection(_protocol);
|
||||||
|
_port->setMaximum(65535);
|
||||||
|
|
||||||
|
auto networkGroup =
|
||||||
|
new QGroupBox(obs_module_text("AdvSceneSwitcher.osc.network"));
|
||||||
|
auto networkLayout = new QGridLayout;
|
||||||
|
int row = 0;
|
||||||
|
networkLayout->addWidget(
|
||||||
|
new QLabel(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.osc.network.protocol")),
|
||||||
|
row, 0);
|
||||||
|
networkLayout->addWidget(_protocol, row, 1);
|
||||||
|
++row;
|
||||||
|
networkLayout->addWidget(
|
||||||
|
new QLabel(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.osc.network.address")),
|
||||||
|
row, 0);
|
||||||
|
networkLayout->addWidget(_ip, row, 1);
|
||||||
|
++row;
|
||||||
|
networkLayout->addWidget(new QLabel(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.osc.network.port")),
|
||||||
|
row, 0);
|
||||||
|
networkLayout->addWidget(_port, row, 1);
|
||||||
|
networkGroup->setLayout(networkLayout);
|
||||||
|
|
||||||
|
auto messageGroup =
|
||||||
|
new QGroupBox(obs_module_text("AdvSceneSwitcher.osc.message"));
|
||||||
|
auto messageLayout = new QHBoxLayout();
|
||||||
|
messageLayout->addWidget(_message);
|
||||||
|
messageGroup->setLayout(messageLayout);
|
||||||
|
|
||||||
|
auto mainLayout = new QVBoxLayout;
|
||||||
|
mainLayout->addWidget(networkGroup);
|
||||||
|
mainLayout->addWidget(messageGroup);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
QWidget::connect(_ip, SIGNAL(editingFinished()), this,
|
||||||
|
SLOT(IpChanged()));
|
||||||
|
QWidget::connect(_protocol, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(ProtocolChanged(int)));
|
||||||
|
QWidget::connect(
|
||||||
|
_port,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
|
this, SLOT(PortChanged(const NumberVariable<int> &)));
|
||||||
|
QWidget::connect(_message, SIGNAL(MessageChanged(const OSCMessage &)),
|
||||||
|
this, SLOT(MessageChanged(const OSCMessage &)));
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
|
UpdateEntryData();
|
||||||
|
_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSCEdit::UpdateEntryData()
|
||||||
|
{
|
||||||
|
if (!_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_protocol->setCurrentIndex(static_cast<int>(_entryData->GetProtocol()));
|
||||||
|
_ip->setText(_entryData->GetIP());
|
||||||
|
_port->SetValue(_entryData->GetPortNr());
|
||||||
|
_message->SetMessage(_entryData->_message);
|
||||||
|
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSCEdit::IpChanged()
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->SetIP(_ip->text().toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSCEdit::ProtocolChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->SetProtocol(static_cast<MacroActionOSC::Protocol>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSCEdit::PortChanged(const NumberVariable<int> &value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->SetPortNr(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionOSCEdit::MessageChanged(const OSCMessage &m)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_message = m;
|
||||||
|
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
94
src/macro-core/macro-action-osc.hpp
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "osc-helpers.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <asio.hpp>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
class MacroActionOSC : public MacroAction {
|
||||||
|
public:
|
||||||
|
MacroActionOSC(Macro *m);
|
||||||
|
bool PerformAction();
|
||||||
|
void LogAction() const;
|
||||||
|
bool Save(obs_data_t *obj) const;
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetId() const { return id; };
|
||||||
|
static std::shared_ptr<MacroAction> Create(Macro *m)
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroActionOSC>(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Protocol {
|
||||||
|
TCP,
|
||||||
|
UDP,
|
||||||
|
};
|
||||||
|
|
||||||
|
void SetProtocol(Protocol);
|
||||||
|
Protocol GetProtocol() const { return _protocol; }
|
||||||
|
void SetIP(const std::string &);
|
||||||
|
StringVariable GetIP() const { return _ip; }
|
||||||
|
void SetPortNr(IntVariable);
|
||||||
|
IntVariable GetPortNr() { return _port; }
|
||||||
|
|
||||||
|
OSCMessage _message;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SendOSCTCPMessage(const asio::mutable_buffer &);
|
||||||
|
void SendOSCUDPMessage(const asio::mutable_buffer &);
|
||||||
|
|
||||||
|
void CheckReconnect();
|
||||||
|
void TCPReconnect();
|
||||||
|
void UDPReconnect();
|
||||||
|
|
||||||
|
Protocol _protocol = Protocol::UDP;
|
||||||
|
StringVariable _ip = "localhost";
|
||||||
|
IntVariable _port = 12345;
|
||||||
|
bool _reconnect = true;
|
||||||
|
|
||||||
|
asio::io_context _ctx;
|
||||||
|
asio::ip::tcp::socket _tcpSocket;
|
||||||
|
asio::ip::udp::socket _udpSocket;
|
||||||
|
asio::ip::udp::endpoint _updEndpoint;
|
||||||
|
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroActionOSCEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroActionOSCEdit(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroActionOSC> entryData = nullptr);
|
||||||
|
void UpdateEntryData();
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroAction> action)
|
||||||
|
{
|
||||||
|
return new MacroActionOSCEdit(
|
||||||
|
parent,
|
||||||
|
std::dynamic_pointer_cast<MacroActionOSC>(action));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void IpChanged();
|
||||||
|
void MessageChanged(const OSCMessage &);
|
||||||
|
void ProtocolChanged(int);
|
||||||
|
void PortChanged(const NumberVariable<int> &value);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<MacroActionOSC> _entryData;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QComboBox *_protocol;
|
||||||
|
VariableLineEdit *_ip;
|
||||||
|
VariableSpinBox *_port;
|
||||||
|
OSCMessageEdit *_message;
|
||||||
|
bool _loading = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -1,15 +1,20 @@
|
|||||||
#include "macro-action-plugin-state.hpp"
|
#include "macro-action-plugin-state.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "switcher-data.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <QMainWindow>
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
const std::string MacroActionPluginState::id = "plugin_state";
|
const std::string MacroActionPluginState::id = "plugin_state";
|
||||||
|
|
||||||
bool MacroActionPluginState::_registered = MacroActionFactory::Register(
|
bool MacroActionPluginState::_registered = MacroActionFactory::Register(
|
||||||
MacroActionPluginState::id,
|
MacroActionPluginState::id,
|
||||||
{MacroActionPluginState::Create, MacroActionPluginStateEdit::Create,
|
{MacroActionPluginState::Create, MacroActionPluginStateEdit::Create,
|
||||||
"AdvSceneSwitcher.action.PluginState"});
|
"AdvSceneSwitcher.action.pluginState"});
|
||||||
|
|
||||||
const static std::map<PluginStateAction, std::string> actionTypes = {
|
const static std::map<PluginStateAction, std::string> actionTypes = {
|
||||||
{PluginStateAction::STOP,
|
{PluginStateAction::STOP,
|
||||||
@@ -18,24 +23,26 @@ const static std::map<PluginStateAction, std::string> actionTypes = {
|
|||||||
"AdvSceneSwitcher.action.pluginState.type.noMatch"},
|
"AdvSceneSwitcher.action.pluginState.type.noMatch"},
|
||||||
{PluginStateAction::IMPORT_SETTINGS,
|
{PluginStateAction::IMPORT_SETTINGS,
|
||||||
"AdvSceneSwitcher.action.pluginState.type.import"},
|
"AdvSceneSwitcher.action.pluginState.type.import"},
|
||||||
|
{PluginStateAction::TERMINATE,
|
||||||
|
"AdvSceneSwitcher.action.pluginState.type.terminate"},
|
||||||
};
|
};
|
||||||
|
|
||||||
const static std::map<NoMatch, std::string> noMatchValues = {
|
const static std::map<SwitcherData::NoMatch, std::string> noMatchValues = {
|
||||||
{NO_SWITCH,
|
{SwitcherData::NoMatch::NO_SWITCH,
|
||||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch"},
|
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch"},
|
||||||
{SWITCH,
|
{SwitcherData::NoMatch::SWITCH,
|
||||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo"},
|
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo"},
|
||||||
{RANDOM_SWITCH,
|
{SwitcherData::NoMatch::RANDOM_SWITCH,
|
||||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom"},
|
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom"},
|
||||||
};
|
};
|
||||||
|
|
||||||
void stopPlugin()
|
static void stopPlugin()
|
||||||
{
|
{
|
||||||
std::thread t([]() { switcher->Stop(); });
|
std::thread t([]() { switcher->Stop(); });
|
||||||
t.detach();
|
t.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
void importSettings(const std::string &path)
|
static void importSettings(const std::string &path)
|
||||||
{
|
{
|
||||||
if (switcher->settingsWindowOpened) {
|
if (switcher->settingsWindowOpened) {
|
||||||
return;
|
return;
|
||||||
@@ -44,18 +51,91 @@ void importSettings(const std::string &path)
|
|||||||
if (!obj) {
|
if (!obj) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switcher->loadSettings(obj);
|
switcher->LoadSettings(obj);
|
||||||
obs_data_release(obj);
|
obs_data_release(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNoMatchBehaviour(int value, OBSWeakSource &scene)
|
static void setNoMatchBehaviour(int value, OBSWeakSource &scene)
|
||||||
{
|
{
|
||||||
switcher->switchIfNotMatching = static_cast<NoMatch>(value);
|
switcher->switchIfNotMatching =
|
||||||
if (switcher->switchIfNotMatching == SWITCH) {
|
static_cast<SwitcherData::NoMatch>(value);
|
||||||
|
if (switcher->switchIfNotMatching == SwitcherData::NoMatch::SWITCH) {
|
||||||
switcher->nonMatchingScene = scene;
|
switcher->nonMatchingScene = scene;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void closeOBSWindow()
|
||||||
|
{
|
||||||
|
blog(LOG_WARNING, "closing OBS window now!");
|
||||||
|
auto obsWindow =
|
||||||
|
static_cast<QMainWindow *>(obs_frontend_get_main_window());
|
||||||
|
if (obsWindow) {
|
||||||
|
obsWindow->close();
|
||||||
|
} else {
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"OBS shutdown was aborted - failed to get QMainWindow");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void terminateOBS(void *)
|
||||||
|
{
|
||||||
|
static std::mutex mtx;
|
||||||
|
static std::mutex waitMutex;
|
||||||
|
static std::condition_variable cv;
|
||||||
|
static bool abortTerminate;
|
||||||
|
static bool stopWaiting;
|
||||||
|
static std::chrono::high_resolution_clock::time_point
|
||||||
|
lastShutdownAttempt{};
|
||||||
|
|
||||||
|
// Don't allow multiple simultaneous instances of the shutdown dialog
|
||||||
|
std::unique_lock<std::mutex> lock(mtx, std::try_to_lock);
|
||||||
|
if (!lock.owns_lock()) {
|
||||||
|
blog(LOG_INFO,
|
||||||
|
"OBS shutdown dialog already triggered - ignoring additional request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent the user from locking himself out of controlling OBS by
|
||||||
|
// continuously opening the shutdown dialog
|
||||||
|
auto now = std::chrono::high_resolution_clock::now();
|
||||||
|
if (lastShutdownAttempt + 5s > now) {
|
||||||
|
blog(LOG_INFO,
|
||||||
|
"OBS shutdown dialog already triggered recently - ignoring request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastShutdownAttempt = now;
|
||||||
|
|
||||||
|
abortTerminate = false;
|
||||||
|
stopWaiting = false;
|
||||||
|
|
||||||
|
// Give the user a 10s grace period during which the shutdown can be aborted
|
||||||
|
std::thread thread([]() {
|
||||||
|
std::unique_lock<std::mutex> lock(waitMutex);
|
||||||
|
if (cv.wait_for(lock, 10s, [] { return stopWaiting; })) {
|
||||||
|
if (abortTerminate) {
|
||||||
|
blog(LOG_INFO, "OBS shutdown was aborted");
|
||||||
|
} else {
|
||||||
|
closeOBSWindow();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
closeOBSWindow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.detach();
|
||||||
|
|
||||||
|
// Ask the user how to proceed
|
||||||
|
abortTerminate = !DisplayMessage(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.pluginState.terminateConfirm"),
|
||||||
|
true, false);
|
||||||
|
stopWaiting = true;
|
||||||
|
|
||||||
|
// This closes OBS immediately if shutdown was confirmed
|
||||||
|
cv.notify_all();
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroActionPluginState::PerformAction()
|
bool MacroActionPluginState::PerformAction()
|
||||||
{
|
{
|
||||||
switch (_action) {
|
switch (_action) {
|
||||||
@@ -70,6 +150,14 @@ bool MacroActionPluginState::PerformAction()
|
|||||||
// There is no point in continuing
|
// There is no point in continuing
|
||||||
// The settings will be invalid
|
// The settings will be invalid
|
||||||
return false;
|
return false;
|
||||||
|
case PluginStateAction::TERMINATE: {
|
||||||
|
std::thread thread([]() {
|
||||||
|
obs_queue_task(OBS_TASK_UI, terminateOBS, nullptr,
|
||||||
|
false);
|
||||||
|
});
|
||||||
|
thread.detach();
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -89,6 +177,9 @@ void MacroActionPluginState::LogAction() const
|
|||||||
vblog(LOG_INFO, "importing settings from %s",
|
vblog(LOG_INFO, "importing settings from %s",
|
||||||
_settingsPath.c_str());
|
_settingsPath.c_str());
|
||||||
break;
|
break;
|
||||||
|
case PluginStateAction::TERMINATE:
|
||||||
|
vblog(LOG_INFO, "sending terminate signal to OBS in 10s");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
blog(LOG_WARNING, "ignored unknown pluginState action %d",
|
blog(LOG_WARNING, "ignored unknown pluginState action %d",
|
||||||
static_cast<int>(_action));
|
static_cast<int>(_action));
|
||||||
@@ -102,7 +193,7 @@ bool MacroActionPluginState::Save(obs_data_t *obj) const
|
|||||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||||
obs_data_set_int(obj, "value", _value);
|
obs_data_set_int(obj, "value", _value);
|
||||||
obs_data_set_string(obj, "scene", GetWeakSourceName(_scene).c_str());
|
obs_data_set_string(obj, "scene", GetWeakSourceName(_scene).c_str());
|
||||||
obs_data_set_string(obj, "settingsPath", _settingsPath.c_str());
|
_settingsPath.Save(obj, "settingsPath");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +205,7 @@ bool MacroActionPluginState::Load(obs_data_t *obj)
|
|||||||
_value = obs_data_get_int(obj, "value");
|
_value = obs_data_get_int(obj, "value");
|
||||||
const char *sceneName = obs_data_get_string(obj, "scene");
|
const char *sceneName = obs_data_get_string(obj, "scene");
|
||||||
_scene = GetWeakSourceByName(sceneName);
|
_scene = GetWeakSourceByName(sceneName);
|
||||||
_settingsPath = obs_data_get_string(obj, "settingsPath");
|
_settingsPath.Load(obj, "settingsPath");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +238,7 @@ MacroActionPluginStateEdit::MacroActionPluginStateEdit(
|
|||||||
"AdvSceneSwitcher.action.pluginState.importWarning"));
|
"AdvSceneSwitcher.action.pluginState.importWarning"));
|
||||||
|
|
||||||
populateActionSelection(_actions);
|
populateActionSelection(_actions);
|
||||||
populateSceneSelection(_scenes);
|
PopulateSceneSelection(_scenes);
|
||||||
|
|
||||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ActionChanged(int)));
|
SLOT(ActionChanged(int)));
|
||||||
@@ -166,7 +257,7 @@ MacroActionPluginStateEdit::MacroActionPluginStateEdit(
|
|||||||
{"{{settings}}", _settings},
|
{"{{settings}}", _settings},
|
||||||
{"{{settingsWarning}}", _settingsWarning},
|
{"{{settingsWarning}}", _settingsWarning},
|
||||||
};
|
};
|
||||||
placeWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.action.pluginState.entry"),
|
obs_module_text("AdvSceneSwitcher.action.pluginState.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
@@ -185,7 +276,7 @@ void MacroActionPluginStateEdit::UpdateEntryData()
|
|||||||
populateValueSelection(_values, _entryData->_action);
|
populateValueSelection(_values, _entryData->_action);
|
||||||
_values->setCurrentIndex(_entryData->_value);
|
_values->setCurrentIndex(_entryData->_value);
|
||||||
_scenes->setCurrentText(GetWeakSourceName(_entryData->_scene).c_str());
|
_scenes->setCurrentText(GetWeakSourceName(_entryData->_scene).c_str());
|
||||||
_settings->SetPath(QString::fromStdString(_entryData->_settingsPath));
|
_settings->SetPath(_entryData->_settingsPath);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +287,7 @@ void MacroActionPluginStateEdit::ActionChanged(int value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_action = static_cast<PluginStateAction>(value);
|
_entryData->_action = static_cast<PluginStateAction>(value);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
@@ -211,7 +302,7 @@ void MacroActionPluginStateEdit::ValueChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_value = value;
|
_entryData->_value = value;
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
@@ -222,7 +313,7 @@ void MacroActionPluginStateEdit::SceneChanged(const QString &text)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_scene = GetWeakSourceByQString(text);
|
_entryData->_scene = GetWeakSourceByQString(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +323,7 @@ void MacroActionPluginStateEdit::PathChanged(const QString &text)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_settingsPath = text.toStdString();
|
_entryData->_settingsPath = text.toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +342,8 @@ void MacroActionPluginStateEdit::SetWidgetVisibility()
|
|||||||
break;
|
break;
|
||||||
case PluginStateAction::NO_MATCH_BEHAVIOUR:
|
case PluginStateAction::NO_MATCH_BEHAVIOUR:
|
||||||
_values->show();
|
_values->show();
|
||||||
if ((NoMatch)_entryData->_value == SWITCH) {
|
if (static_cast<SwitcherData::NoMatch>(_entryData->_value) ==
|
||||||
|
SwitcherData::NoMatch::SWITCH) {
|
||||||
_scenes->show();
|
_scenes->show();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -263,3 +355,5 @@ void MacroActionPluginStateEdit::SetWidgetVisibility()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -5,10 +5,13 @@
|
|||||||
#include <QDoubleSpinBox>
|
#include <QDoubleSpinBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
enum class PluginStateAction {
|
enum class PluginStateAction {
|
||||||
STOP,
|
STOP,
|
||||||
NO_MATCH_BEHAVIOUR,
|
NO_MATCH_BEHAVIOUR,
|
||||||
IMPORT_SETTINGS,
|
IMPORT_SETTINGS,
|
||||||
|
TERMINATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacroActionPluginState : public MacroAction {
|
class MacroActionPluginState : public MacroAction {
|
||||||
@@ -26,7 +29,7 @@ public:
|
|||||||
|
|
||||||
PluginStateAction _action = PluginStateAction::STOP;
|
PluginStateAction _action = PluginStateAction::STOP;
|
||||||
int _value = 0;
|
int _value = 0;
|
||||||
std::string _settingsPath;
|
StringVariable _settingsPath;
|
||||||
OBSWeakSource _scene;
|
OBSWeakSource _scene;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -69,3 +72,5 @@ private:
|
|||||||
void SetWidgetVisibility();
|
void SetWidgetVisibility();
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#include "macro-action-profile.hpp"
|
#include "macro-action-profile.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
const std::string MacroActionProfile::id = "profile";
|
const std::string MacroActionProfile::id = "profile";
|
||||||
|
|
||||||
bool MacroActionProfile::_registered = MacroActionFactory::Register(
|
bool MacroActionProfile::_registered = MacroActionFactory::Register(
|
||||||
@@ -44,7 +45,7 @@ MacroActionProfileEdit::MacroActionProfileEdit(
|
|||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
_profiles = new QComboBox();
|
_profiles = new QComboBox();
|
||||||
populateProfileSelection(_profiles);
|
PopulateProfileSelection(_profiles);
|
||||||
QWidget::connect(_profiles, SIGNAL(currentTextChanged(const QString &)),
|
QWidget::connect(_profiles, SIGNAL(currentTextChanged(const QString &)),
|
||||||
this, SLOT(ProfileChanged(const QString &)));
|
this, SLOT(ProfileChanged(const QString &)));
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@ MacroActionProfileEdit::MacroActionProfileEdit(
|
|||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{profiles}}", _profiles},
|
{"{{profiles}}", _profiles},
|
||||||
};
|
};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.profile.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.profile.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -76,8 +77,10 @@ void MacroActionProfileEdit::ProfileChanged(const QString &text)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_profile = text.toStdString();
|
_entryData->_profile = text.toStdString();
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
class MacroActionProfile : public MacroAction {
|
class MacroActionProfile : public MacroAction {
|
||||||
public:
|
public:
|
||||||
MacroActionProfile(Macro *m) : MacroAction(m) {}
|
MacroActionProfile(Macro *m) : MacroAction(m) {}
|
||||||
@@ -52,3 +54,5 @@ protected:
|
|||||||
private:
|
private:
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
254
src/macro-core/macro-action-projector.cpp
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
#include "macro-action-projector.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QScreen>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
const std::string MacroActionProjector::id = "projector";
|
||||||
|
|
||||||
|
bool MacroActionProjector::_registered = MacroActionFactory::Register(
|
||||||
|
MacroActionProjector::id,
|
||||||
|
{MacroActionProjector::Create, MacroActionProjectorEdit::Create,
|
||||||
|
"AdvSceneSwitcher.action.projector"});
|
||||||
|
|
||||||
|
const static std::map<MacroActionProjector::Type, std::string> selectionTypes = {
|
||||||
|
{MacroActionProjector::Type::SOURCE,
|
||||||
|
"AdvSceneSwitcher.action.projector.type.source"},
|
||||||
|
{MacroActionProjector::Type::SCENE,
|
||||||
|
"AdvSceneSwitcher.action.projector.type.scene"},
|
||||||
|
{MacroActionProjector::Type::PREVIEW,
|
||||||
|
"AdvSceneSwitcher.action.projector.type.preview"},
|
||||||
|
{MacroActionProjector::Type::PROGRAM,
|
||||||
|
"AdvSceneSwitcher.action.projector.type.program"},
|
||||||
|
{MacroActionProjector::Type::MULTIVIEW,
|
||||||
|
"AdvSceneSwitcher.action.projector.type.multiview"},
|
||||||
|
};
|
||||||
|
|
||||||
|
bool MacroActionProjector::PerformAction()
|
||||||
|
{
|
||||||
|
std::string name = "";
|
||||||
|
const char *type = "";
|
||||||
|
|
||||||
|
switch (_type) {
|
||||||
|
case MacroActionProjector::Type::SOURCE:
|
||||||
|
type = "Source";
|
||||||
|
name = GetWeakSourceName(_source.GetSource());
|
||||||
|
if (name.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MacroActionProjector::Type::SCENE:
|
||||||
|
type = "Scene";
|
||||||
|
name = GetWeakSourceName(_scene.GetScene());
|
||||||
|
if (name.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MacroActionProjector::Type::PREVIEW:
|
||||||
|
type = "Preview";
|
||||||
|
break;
|
||||||
|
case MacroActionProjector::Type::PROGRAM:
|
||||||
|
type = "StudioProgram";
|
||||||
|
break;
|
||||||
|
case MacroActionProjector::Type::MULTIVIEW:
|
||||||
|
type = "Multiview";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_frontend_open_projector(type, _fullscreen ? _monitor : -1, "",
|
||||||
|
name.c_str());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjector::LogAction() const
|
||||||
|
{
|
||||||
|
auto it = selectionTypes.find(_type);
|
||||||
|
if (it != selectionTypes.end()) {
|
||||||
|
vblog(LOG_INFO,
|
||||||
|
"performed projector action \"%s\" with"
|
||||||
|
"source \"%s\","
|
||||||
|
"scene \"%s\","
|
||||||
|
"monitor %d",
|
||||||
|
it->second.c_str(), _source.ToString(true).c_str(),
|
||||||
|
_scene.ToString(true).c_str(), _monitor);
|
||||||
|
} else {
|
||||||
|
blog(LOG_WARNING, "ignored unknown projector action %d",
|
||||||
|
static_cast<int>(_type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionProjector::Save(obs_data_t *obj) const
|
||||||
|
{
|
||||||
|
MacroAction::Save(obj);
|
||||||
|
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
||||||
|
obs_data_set_int(obj, "monitor", _monitor);
|
||||||
|
obs_data_set_bool(obj, "fullscreen", _fullscreen);
|
||||||
|
_scene.Save(obj);
|
||||||
|
_source.Save(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionProjector::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroAction::Load(obj);
|
||||||
|
_type = static_cast<Type>(obs_data_get_int(obj, "type"));
|
||||||
|
_monitor = obs_data_get_int(obj, "monitor");
|
||||||
|
_fullscreen = obs_data_get_bool(obj, "fullscreen");
|
||||||
|
_scene.Load(obj);
|
||||||
|
_source.Load(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void populateSelectionTypes(QComboBox *list)
|
||||||
|
{
|
||||||
|
for (auto entry : selectionTypes) {
|
||||||
|
list->addItem(obs_module_text(entry.second.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void populateWindowTypes(QComboBox *list)
|
||||||
|
{
|
||||||
|
list->addItem(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.projector.windowed"));
|
||||||
|
list->addItem(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.projector.fullscreen"));
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroActionProjectorEdit::MacroActionProjectorEdit(
|
||||||
|
QWidget *parent, std::shared_ptr<MacroActionProjector> entryData)
|
||||||
|
: QWidget(parent),
|
||||||
|
_windowTypes(new QComboBox()),
|
||||||
|
_types(new QComboBox()),
|
||||||
|
_scenes(new SceneSelectionWidget(window(), true, false, true, true,
|
||||||
|
true)),
|
||||||
|
_sources(new SourceSelectionWidget(window(), QStringList(), true)),
|
||||||
|
_monitorSelection(new QHBoxLayout()),
|
||||||
|
_monitors(new QComboBox())
|
||||||
|
{
|
||||||
|
populateWindowTypes(_windowTypes);
|
||||||
|
populateSelectionTypes(_types);
|
||||||
|
auto sources = GetSourceNames();
|
||||||
|
sources.sort();
|
||||||
|
_sources->SetSourceNameList(sources);
|
||||||
|
_monitors->addItems(GetMonitorNames());
|
||||||
|
|
||||||
|
QWidget::connect(_windowTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(WindowTypeChanged(int)));
|
||||||
|
QWidget::connect(_types, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(TypeChanged(int)));
|
||||||
|
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||||
|
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||||
|
QWidget::connect(_sources,
|
||||||
|
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||||
|
SLOT(SourceChanged(const SourceSelection &)));
|
||||||
|
QWidget::connect(_monitors, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(MonitorChanged(int)));
|
||||||
|
|
||||||
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
|
{"{{windowTypes}}", _windowTypes}, {"{{types}}", _types},
|
||||||
|
{"{{scenes}}", _scenes}, {"{{sources}}", _sources},
|
||||||
|
{"{{monitors}}", _monitors},
|
||||||
|
};
|
||||||
|
|
||||||
|
PlaceWidgets(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.projector.entry.monitor"),
|
||||||
|
_monitorSelection, widgetPlaceholders);
|
||||||
|
|
||||||
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.projector.entry"),
|
||||||
|
mainLayout, widgetPlaceholders);
|
||||||
|
mainLayout->insertLayout(mainLayout->count() - 1, _monitorSelection);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
|
UpdateEntryData();
|
||||||
|
_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::UpdateEntryData()
|
||||||
|
{
|
||||||
|
if (!_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_windowTypes->setCurrentIndex(_entryData->_fullscreen ? 1 : 0);
|
||||||
|
_types->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||||
|
_scenes->SetScene(_entryData->_scene);
|
||||||
|
_sources->SetSource(_entryData->_source);
|
||||||
|
_monitors->setCurrentIndex(_entryData->_monitor);
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::SceneChanged(const SceneSelection &s)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_scene = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::SourceChanged(const SourceSelection &source)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::MonitorChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_monitor = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::WindowTypeChanged(int)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_fullscreen =
|
||||||
|
_windowTypes->currentText() ==
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.projector.fullscreen");
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::TypeChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_type = static_cast<MacroActionProjector::Type>(value);
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::SetWidgetVisibility()
|
||||||
|
{
|
||||||
|
if (!_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_scenes->setVisible(_entryData->_type ==
|
||||||
|
MacroActionProjector::Type::SCENE);
|
||||||
|
_sources->setVisible(_entryData->_type ==
|
||||||
|
MacroActionProjector::Type::SOURCE);
|
||||||
|
SetLayoutVisible(_monitorSelection, _entryData->_fullscreen);
|
||||||
|
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
77
src/macro-core/macro-action-projector.hpp
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "scene-selection.hpp"
|
||||||
|
#include "source-selection.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
class MacroActionProjector : public MacroAction {
|
||||||
|
public:
|
||||||
|
MacroActionProjector(Macro *m) : MacroAction(m) {}
|
||||||
|
bool PerformAction();
|
||||||
|
void LogAction() const;
|
||||||
|
bool Save(obs_data_t *obj) const;
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetId() const { return id; };
|
||||||
|
static std::shared_ptr<MacroAction> Create(Macro *m)
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroActionProjector>(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Type {
|
||||||
|
SOURCE,
|
||||||
|
SCENE,
|
||||||
|
PREVIEW,
|
||||||
|
PROGRAM,
|
||||||
|
MULTIVIEW,
|
||||||
|
};
|
||||||
|
|
||||||
|
Type _type = Type::SCENE;
|
||||||
|
SourceSelection _source;
|
||||||
|
SceneSelection _scene;
|
||||||
|
int _monitor = 0;
|
||||||
|
bool _fullscreen = true;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroActionProjectorEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroActionProjectorEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroActionProjector> entryData = nullptr);
|
||||||
|
void UpdateEntryData();
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroAction> action)
|
||||||
|
{
|
||||||
|
return new MacroActionProjectorEdit(
|
||||||
|
parent, std::dynamic_pointer_cast<MacroActionProjector>(
|
||||||
|
action));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void WindowTypeChanged(int value);
|
||||||
|
void TypeChanged(int value);
|
||||||
|
void SceneChanged(const SceneSelection &);
|
||||||
|
void SourceChanged(const SourceSelection &);
|
||||||
|
void MonitorChanged(int value);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QComboBox *_windowTypes;
|
||||||
|
QComboBox *_types;
|
||||||
|
SceneSelectionWidget *_scenes;
|
||||||
|
SourceSelectionWidget *_sources;
|
||||||
|
QHBoxLayout *_monitorSelection;
|
||||||
|
QComboBox *_monitors;
|
||||||
|
std::shared_ptr<MacroActionProjector> _entryData;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetWidgetVisibility();
|
||||||
|
bool _loading = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
#include "macro-action-random.hpp"
|
#include "macro-action-random.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "macro.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
const std::string MacroActionRandom::id = "random";
|
const std::string MacroActionRandom::id = "random";
|
||||||
|
|
||||||
bool MacroActionRandom::_registered = MacroActionFactory::Register(
|
bool MacroActionRandom::_registered = MacroActionFactory::Register(
|
||||||
@@ -11,22 +13,30 @@ bool MacroActionRandom::_registered = MacroActionFactory::Register(
|
|||||||
{MacroActionRandom::Create, MacroActionRandomEdit::Create,
|
{MacroActionRandom::Create, MacroActionRandomEdit::Create,
|
||||||
"AdvSceneSwitcher.action.random"});
|
"AdvSceneSwitcher.action.random"});
|
||||||
|
|
||||||
std::vector<MacroRef> getNextMacros(std::vector<MacroRef> ¯os,
|
static bool validNextMacro(const std::shared_ptr<Macro> ¯o)
|
||||||
MacroRef &lastRandomMacro, bool allowRepeat)
|
|
||||||
{
|
{
|
||||||
std::vector<MacroRef> res;
|
return macro && !macro->Paused();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::shared_ptr<Macro>>
|
||||||
|
getNextMacros(std::vector<MacroRef> ¯os, MacroRef &lastRandomMacroRef,
|
||||||
|
bool allowRepeat)
|
||||||
|
{
|
||||||
|
std::vector<std::shared_ptr<Macro>> res;
|
||||||
if (macros.size() == 1) {
|
if (macros.size() == 1) {
|
||||||
if (!macros[0].get() || macros[0]->Paused()) {
|
auto macro = macros[0].GetMacro();
|
||||||
return res;
|
if (validNextMacro(macro)) {
|
||||||
} else {
|
res.push_back(macro);
|
||||||
return macros;
|
|
||||||
}
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto lastRandomMacro = lastRandomMacroRef.GetMacro();
|
||||||
for (auto &m : macros) {
|
for (auto &m : macros) {
|
||||||
if (m.get() && !m->Paused() &&
|
auto macro = m.GetMacro();
|
||||||
(allowRepeat || (lastRandomMacro.get() != m.get()))) {
|
if (validNextMacro(macro) &&
|
||||||
res.push_back(m);
|
(allowRepeat || (lastRandomMacro != macro))) {
|
||||||
|
res.push_back(macro);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
@@ -42,7 +52,7 @@ bool MacroActionRandom::PerformAction()
|
|||||||
if (macros.size() == 0) {
|
if (macros.size() == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (macros.size() == 1 && macros[0].get()) {
|
if (macros.size() == 1) {
|
||||||
lastRandomMacro = macros[0];
|
lastRandomMacro = macros[0];
|
||||||
return macros[0]->PerformActions();
|
return macros[0]->PerformActions();
|
||||||
}
|
}
|
||||||
@@ -92,7 +102,7 @@ MacroActionRandomEdit::MacroActionRandomEdit(
|
|||||||
|
|
||||||
auto *entryLayout = new QHBoxLayout;
|
auto *entryLayout = new QHBoxLayout;
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {};
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.random.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.random.entry"),
|
||||||
entryLayout, widgetPlaceholders);
|
entryLayout, widgetPlaceholders);
|
||||||
|
|
||||||
auto *mainLayout = new QVBoxLayout;
|
auto *mainLayout = new QVBoxLayout;
|
||||||
@@ -126,8 +136,7 @@ void MacroActionRandomEdit::MacroRemove(const QString &)
|
|||||||
|
|
||||||
auto it = _entryData->_macros.begin();
|
auto it = _entryData->_macros.begin();
|
||||||
while (it != _entryData->_macros.end()) {
|
while (it != _entryData->_macros.end()) {
|
||||||
it->UpdateRef();
|
if (!it->GetMacro()) {
|
||||||
if (it->get() == nullptr) {
|
|
||||||
it = _entryData->_macros.erase(it);
|
it = _entryData->_macros.erase(it);
|
||||||
} else {
|
} else {
|
||||||
++it;
|
++it;
|
||||||
@@ -142,7 +151,7 @@ void MacroActionRandomEdit::Add(const std::string &name)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
MacroRef macro(name);
|
MacroRef macro(name);
|
||||||
_entryData->_macros.push_back(macro);
|
_entryData->_macros.push_back(macro);
|
||||||
_allowRepeat->setVisible(ShouldShowAllowRepeat());
|
_allowRepeat->setVisible(ShouldShowAllowRepeat());
|
||||||
@@ -155,7 +164,7 @@ void MacroActionRandomEdit::Remove(int idx)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_macros.erase(std::next(_entryData->_macros.begin(), idx));
|
_entryData->_macros.erase(std::next(_entryData->_macros.begin(), idx));
|
||||||
_allowRepeat->setVisible(ShouldShowAllowRepeat());
|
_allowRepeat->setVisible(ShouldShowAllowRepeat());
|
||||||
adjustSize();
|
adjustSize();
|
||||||
@@ -168,7 +177,7 @@ void MacroActionRandomEdit::Replace(int idx, const std::string &name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MacroRef macro(name);
|
MacroRef macro(name);
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_macros[idx] = macro;
|
_entryData->_macros[idx] = macro;
|
||||||
adjustSize();
|
adjustSize();
|
||||||
}
|
}
|
||||||
@@ -179,7 +188,7 @@ void MacroActionRandomEdit::AllowRepeatChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_allowRepeat = value;
|
_entryData->_allowRepeat = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,11 +197,13 @@ bool MacroActionRandomEdit::ShouldShowAllowRepeat()
|
|||||||
if (_entryData->_macros.size() <= 1) {
|
if (_entryData->_macros.size() <= 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto macro = _entryData->_macros[0];
|
const auto macro = _entryData->_macros[0].GetMacro();
|
||||||
for (const auto &m : _entryData->_macros) {
|
for (const auto &m : _entryData->_macros) {
|
||||||
if (macro.get() != m.get()) {
|
if (macro != m.GetMacro()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
class MacroActionRandom : public MultiMacroRefAction {
|
class MacroActionRandom : public MultiMacroRefAction {
|
||||||
public:
|
public:
|
||||||
MacroActionRandom(Macro *m) : MacroAction(m), MultiMacroRefAction(m) {}
|
MacroActionRandom(Macro *m) : MacroAction(m), MultiMacroRefAction(m) {}
|
||||||
@@ -60,3 +62,5 @@ private:
|
|||||||
QCheckBox *_allowRepeat;
|
QCheckBox *_allowRepeat;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#include "macro-action-recording.hpp"
|
#include "macro-action-recording.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
#include <util/config-file.h>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
const std::string MacroActionRecord::id = "recording";
|
const std::string MacroActionRecord::id = "recording";
|
||||||
|
|
||||||
bool MacroActionRecord::_registered = MacroActionFactory::Register(
|
bool MacroActionRecord::_registered = MacroActionFactory::Register(
|
||||||
@@ -9,45 +12,80 @@ bool MacroActionRecord::_registered = MacroActionFactory::Register(
|
|||||||
{MacroActionRecord::Create, MacroActionRecordEdit::Create,
|
{MacroActionRecord::Create, MacroActionRecordEdit::Create,
|
||||||
"AdvSceneSwitcher.action.recording"});
|
"AdvSceneSwitcher.action.recording"});
|
||||||
|
|
||||||
const static std::map<RecordAction, std::string> actionTypes = {
|
const static std::map<MacroActionRecord::Action, std::string> actionTypes = {
|
||||||
{RecordAction::STOP, "AdvSceneSwitcher.action.recording.type.stop"},
|
{MacroActionRecord::Action::STOP,
|
||||||
{RecordAction::START, "AdvSceneSwitcher.action.recording.type.start"},
|
"AdvSceneSwitcher.action.recording.type.stop"},
|
||||||
{RecordAction::PAUSE, "AdvSceneSwitcher.action.recording.type.pause"},
|
{MacroActionRecord::Action::START,
|
||||||
{RecordAction::UNPAUSE,
|
"AdvSceneSwitcher.action.recording.type.start"},
|
||||||
|
{MacroActionRecord::Action::PAUSE,
|
||||||
|
"AdvSceneSwitcher.action.recording.type.pause"},
|
||||||
|
{MacroActionRecord::Action::UNPAUSE,
|
||||||
"AdvSceneSwitcher.action.recording.type.unpause"},
|
"AdvSceneSwitcher.action.recording.type.unpause"},
|
||||||
{RecordAction::SPLIT, "AdvSceneSwitcher.action.recording.type.split"},
|
{MacroActionRecord::Action::SPLIT,
|
||||||
|
"AdvSceneSwitcher.action.recording.type.split"},
|
||||||
|
{MacroActionRecord::Action::FOLDER,
|
||||||
|
"AdvSceneSwitcher.action.recording.type.changeOutputFolder"},
|
||||||
|
{MacroActionRecord::Action::FILE_FORMAT,
|
||||||
|
"AdvSceneSwitcher.action.recording.type.changeOutputFileFormat"},
|
||||||
};
|
};
|
||||||
|
|
||||||
bool MacroActionRecord::PerformAction()
|
bool MacroActionRecord::PerformAction()
|
||||||
{
|
{
|
||||||
switch (_action) {
|
switch (_action) {
|
||||||
case RecordAction::STOP:
|
case Action::STOP:
|
||||||
if (obs_frontend_recording_active()) {
|
if (obs_frontend_recording_active()) {
|
||||||
obs_frontend_recording_stop();
|
obs_frontend_recording_stop();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RecordAction::START:
|
case Action::START:
|
||||||
if (!obs_frontend_recording_active()) {
|
if (!obs_frontend_recording_active()) {
|
||||||
obs_frontend_recording_start();
|
obs_frontend_recording_start();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RecordAction::PAUSE:
|
case Action::PAUSE:
|
||||||
if (obs_frontend_recording_active() &&
|
if (obs_frontend_recording_active() &&
|
||||||
!obs_frontend_recording_paused()) {
|
!obs_frontend_recording_paused()) {
|
||||||
obs_frontend_recording_pause(true);
|
obs_frontend_recording_pause(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RecordAction::UNPAUSE:
|
case Action::UNPAUSE:
|
||||||
if (obs_frontend_recording_active() &&
|
if (obs_frontend_recording_active() &&
|
||||||
obs_frontend_recording_paused()) {
|
obs_frontend_recording_paused()) {
|
||||||
obs_frontend_recording_pause(false);
|
obs_frontend_recording_pause(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(28, 0, 0)
|
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(28, 0, 0)
|
||||||
case RecordAction::SPLIT:
|
case Action::SPLIT:
|
||||||
obs_frontend_recording_split_file();
|
obs_frontend_recording_split_file();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case Action::FOLDER: {
|
||||||
|
std::string folder = _folder; // Trigger variable resolve
|
||||||
|
|
||||||
|
auto conf = obs_frontend_get_profile_config();
|
||||||
|
config_set_string(conf, "SimpleOutput", "FilePath",
|
||||||
|
folder.c_str());
|
||||||
|
config_set_string(conf, "AdvOut", "FFFilePath", folder.c_str());
|
||||||
|
config_set_string(conf, "AdvOut", "RecFilePath",
|
||||||
|
folder.c_str());
|
||||||
|
if (config_save(conf) != CONFIG_SUCCESS) {
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"failed to set recoding output folder");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Action::FILE_FORMAT: {
|
||||||
|
std::string format = _fileFormat; // Trigger variable resolve
|
||||||
|
|
||||||
|
auto conf = obs_frontend_get_profile_config();
|
||||||
|
config_set_string(conf, "Output", "FilenameFormatting",
|
||||||
|
format.c_str());
|
||||||
|
if (config_save(conf) != CONFIG_SUCCESS) {
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"failed to set recoding file format string");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -69,13 +107,17 @@ bool MacroActionRecord::Save(obs_data_t *obj) const
|
|||||||
{
|
{
|
||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||||
|
_folder.Save(obj, "folder");
|
||||||
|
_fileFormat.Save(obj, "format");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroActionRecord::Load(obs_data_t *obj)
|
bool MacroActionRecord::Load(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
_action = static_cast<RecordAction>(obs_data_get_int(obj, "action"));
|
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||||
|
_folder.Load(obj, "folder");
|
||||||
|
_fileFormat.Load(obj, "format");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,21 +135,27 @@ MacroActionRecordEdit::MacroActionRecordEdit(
|
|||||||
_pauseHint(new QLabel(obs_module_text(
|
_pauseHint(new QLabel(obs_module_text(
|
||||||
"AdvSceneSwitcher.action.recording.pause.hint"))),
|
"AdvSceneSwitcher.action.recording.pause.hint"))),
|
||||||
_splitHint(new QLabel(obs_module_text(
|
_splitHint(new QLabel(obs_module_text(
|
||||||
"AdvSceneSwitcher.action.recording.split.hint")))
|
"AdvSceneSwitcher.action.recording.split.hint"))),
|
||||||
|
_recordFolder(new FileSelection(FileSelection::Type::FOLDER, this)),
|
||||||
|
_recordFileFormat(new VariableLineEdit(this))
|
||||||
{
|
{
|
||||||
populateActionSelection(_actions);
|
populateActionSelection(_actions);
|
||||||
|
|
||||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ActionChanged(int)));
|
SLOT(ActionChanged(int)));
|
||||||
|
QWidget::connect(_recordFolder, SIGNAL(PathChanged(const QString &)),
|
||||||
|
this, SLOT(FolderChanged(const QString &)));
|
||||||
|
QWidget::connect(_recordFileFormat, SIGNAL(editingFinished()), this,
|
||||||
|
SLOT(FormatStringChanged()));
|
||||||
|
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
auto mainLayout = new QHBoxLayout;
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.recording.entry"),
|
||||||
{"{{actions}}", _actions},
|
mainLayout,
|
||||||
{"{{pauseHint}}", _pauseHint},
|
{{"{{actions}}", _actions},
|
||||||
{"{{splitHint}}", _splitHint},
|
{"{{pauseHint}}", _pauseHint},
|
||||||
};
|
{"{{splitHint}}", _splitHint},
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.recording.entry"),
|
{"{{recordFolder}}", _recordFolder},
|
||||||
mainLayout, widgetPlaceholders);
|
{"{{recordFileFormat}}", _recordFileFormat}});
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
@@ -121,18 +169,46 @@ void MacroActionRecordEdit::UpdateEntryData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||||
SetLabelVisibility();
|
_recordFolder->SetPath(_entryData->_folder);
|
||||||
|
_recordFileFormat->setText(_entryData->_fileFormat);
|
||||||
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPauseAction(RecordAction a)
|
static bool isPauseAction(MacroActionRecord::Action a)
|
||||||
{
|
{
|
||||||
return a == RecordAction::PAUSE || a == RecordAction::UNPAUSE;
|
return a == MacroActionRecord::Action::PAUSE ||
|
||||||
|
a == MacroActionRecord::Action::UNPAUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionRecordEdit::SetLabelVisibility()
|
void MacroActionRecordEdit::FolderChanged(const QString &folder)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_folder = folder.toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionRecordEdit::FormatStringChanged()
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_fileFormat = _recordFileFormat->text().toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionRecordEdit::SetWidgetVisibility()
|
||||||
{
|
{
|
||||||
_pauseHint->setVisible(isPauseAction(_entryData->_action));
|
_pauseHint->setVisible(isPauseAction(_entryData->_action));
|
||||||
_splitHint->setVisible(_entryData->_action == RecordAction::SPLIT);
|
_splitHint->setVisible(_entryData->_action ==
|
||||||
|
MacroActionRecord::Action::SPLIT);
|
||||||
|
_recordFolder->setVisible(_entryData->_action ==
|
||||||
|
MacroActionRecord::Action::FOLDER);
|
||||||
|
_recordFileFormat->setVisible(_entryData->_action ==
|
||||||
|
MacroActionRecord::Action::FILE_FORMAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionRecordEdit::ActionChanged(int value)
|
void MacroActionRecordEdit::ActionChanged(int value)
|
||||||
@@ -141,7 +217,9 @@ void MacroActionRecordEdit::ActionChanged(int value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->_action = static_cast<RecordAction>(value);
|
_entryData->_action = static_cast<MacroActionRecord::Action>(value);
|
||||||
SetLabelVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "file-selection.hpp"
|
||||||
|
#include "variable-line-edit.hpp"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
enum class RecordAction {
|
namespace advss {
|
||||||
STOP,
|
|
||||||
START,
|
|
||||||
PAUSE,
|
|
||||||
UNPAUSE,
|
|
||||||
SPLIT,
|
|
||||||
};
|
|
||||||
|
|
||||||
class MacroActionRecord : public MacroAction {
|
class MacroActionRecord : public MacroAction {
|
||||||
public:
|
public:
|
||||||
@@ -25,7 +22,19 @@ public:
|
|||||||
return std::make_shared<MacroActionRecord>(m);
|
return std::make_shared<MacroActionRecord>(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordAction _action = RecordAction::STOP;
|
enum class Action {
|
||||||
|
STOP,
|
||||||
|
START,
|
||||||
|
PAUSE,
|
||||||
|
UNPAUSE,
|
||||||
|
SPLIT,
|
||||||
|
FOLDER,
|
||||||
|
FILE_FORMAT,
|
||||||
|
};
|
||||||
|
Action _action = Action::STOP;
|
||||||
|
|
||||||
|
StringVariable _folder = QDir::homePath().toStdString() + "/Videos";
|
||||||
|
StringVariable _fileFormat = "%CCYY-%MM-%DD %hh-%mm-%ss";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
@@ -50,16 +59,22 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ActionChanged(int value);
|
void ActionChanged(int value);
|
||||||
|
void FolderChanged(const QString &);
|
||||||
|
void FormatStringChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QComboBox *_actions;
|
QComboBox *_actions;
|
||||||
QLabel *_pauseHint;
|
QLabel *_pauseHint;
|
||||||
QLabel *_splitHint;
|
QLabel *_splitHint;
|
||||||
|
FileSelection *_recordFolder;
|
||||||
|
VariableLineEdit *_recordFileFormat;
|
||||||
std::shared_ptr<MacroActionRecord> _entryData;
|
std::shared_ptr<MacroActionRecord> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetLabelVisibility();
|
void SetWidgetVisibility();
|
||||||
|
|
||||||
QHBoxLayout *_mainLayout;
|
QHBoxLayout *_mainLayout;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|||||||