Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
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
|
||||||
|
|||||||
6
.gitmodules
vendored
@@ -10,3 +10,9 @@
|
|||||||
[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
|
||||||
|
|||||||
@@ -113,6 +113,8 @@ target_sources(
|
|||||||
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
|
||||||
@@ -189,6 +191,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 +221,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
|
||||||
@@ -248,8 +254,15 @@ target_sources(
|
|||||||
src/utils/file-selection.hpp
|
src/utils/file-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/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
|
||||||
@@ -266,12 +279,24 @@ 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/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 +343,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 +355,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 +473,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,542 @@ 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}}"
|
||||||
|
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}}{{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}}"
|
||||||
|
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.systray.entry="Benachrichtigung anzeigen: {{message}}"
|
||||||
|
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 +651,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 +725,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 +756,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 +823,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,33 @@ 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.macroDock.pause="Pause"
|
||||||
|
AdvSceneSwitcher.macroDock.unpause="Unpause"
|
||||||
|
AdvSceneSwitcher.macroDock.run="Run"
|
||||||
|
|
||||||
; Macro List
|
; Macro List
|
||||||
AdvSceneSwitcher.macroList.deleted="deleted"
|
AdvSceneSwitcher.macroList.deleted="deleted"
|
||||||
@@ -174,6 +189,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 +200,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 +219,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 +240,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"
|
||||||
@@ -393,6 +427,9 @@ 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}}"
|
||||||
|
|
||||||
; Macro Actions
|
; Macro Actions
|
||||||
AdvSceneSwitcher.action.switchScene="Switch scene"
|
AdvSceneSwitcher.action.switchScene="Switch scene"
|
||||||
@@ -440,11 +477,6 @@ AdvSceneSwitcher.action.streaming.type.stop="Stop streaming"
|
|||||||
AdvSceneSwitcher.action.streaming.type.start="Start streaming"
|
AdvSceneSwitcher.action.streaming.type.start="Start streaming"
|
||||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
||||||
AdvSceneSwitcher.action.run="Run"
|
AdvSceneSwitcher.action.run="Run"
|
||||||
AdvSceneSwitcher.action.run.arguments="Arguments:"
|
|
||||||
AdvSceneSwitcher.action.run.addArgument="Add argument"
|
|
||||||
AdvSceneSwitcher.action.run.addArgumentDescription="Add new argument:"
|
|
||||||
AdvSceneSwitcher.action.run.entry="Run {{filePath}}"
|
|
||||||
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"
|
||||||
@@ -506,7 +538,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"
|
||||||
@@ -571,6 +603,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,11 +618,34 @@ 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}}"
|
||||||
|
|
||||||
|
|
||||||
; Transition Tab
|
; Transition Tab
|
||||||
@@ -881,6 +939,15 @@ 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.selectScene="--select scene--"
|
AdvSceneSwitcher.selectScene="--select scene--"
|
||||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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="下移"
|
||||||
@@ -541,7 +541,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 |
@@ -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 |
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/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>
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
const char *obs_module_text(const char *text)
|
const char *obs_module_text(const char *text)
|
||||||
{
|
{
|
||||||
|
if (!switcher) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
return switcher->translate(text);
|
return switcher->translate(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,9 +43,7 @@ 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();
|
||||||
}
|
}
|
||||||
@@ -55,26 +56,51 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DisplayMissingDependencyWarning()
|
||||||
|
{
|
||||||
|
if (!switcher->warnPluginLoadFailure ||
|
||||||
|
switcher->loadFailureLibs.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString failedLibsString = "<ul>";
|
||||||
|
for (const auto &lib : switcher->loadFailureLibs) {
|
||||||
|
failedLibsString += "<li>" + lib + "</li>";
|
||||||
|
}
|
||||||
|
failedLibsString += "</ul>";
|
||||||
|
QString warning(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage"));
|
||||||
|
DisplayMessage(warning.arg(failedLibsString));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DisplayMissingDataDirWarning()
|
||||||
|
{
|
||||||
|
if (translationAvailable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
void AdvSceneSwitcher::loadUI()
|
||||||
{
|
{
|
||||||
if (!translationAvailable()) {
|
DisplayMissingDataDirWarning();
|
||||||
QString msg = "Failed to find plug-in's 'data' directory.\n"
|
DisplayMissingDependencyWarning();
|
||||||
"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());
|
|
||||||
(void)DisplayMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
setupGeneralTab();
|
setupGeneralTab();
|
||||||
setupTitleTab();
|
setupTitleTab();
|
||||||
@@ -155,6 +181,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;
|
||||||
@@ -230,19 +257,6 @@ void SwitcherData::Thread()
|
|||||||
|
|
||||||
ClearWebsocketMessages();
|
ClearWebsocketMessages();
|
||||||
|
|
||||||
// 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();
|
||||||
@@ -256,6 +270,7 @@ void SwitcherData::Thread()
|
|||||||
switcher->firstIntervalAfterStop = false;
|
switcher->firstIntervalAfterStop = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainLoopLock = nullptr;
|
||||||
blog(LOG_INFO, "stopped");
|
blog(LOG_INFO, "stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -695,6 +710,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,10 @@ public:
|
|||||||
|
|
||||||
bool addNewMacro(std::shared_ptr<Macro> &res, std::string &name,
|
bool addNewMacro(std::shared_ptr<Macro> &res, std::string &name,
|
||||||
std::string format = "");
|
std::string format = "");
|
||||||
|
void RemoveMacro(std::shared_ptr<Macro> &);
|
||||||
|
void RenameMacro(std::shared_ptr<Macro> &, const QString &name);
|
||||||
std::shared_ptr<Macro> getSelectedMacro();
|
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));
|
||||||
@@ -109,10 +112,8 @@ public slots:
|
|||||||
void on_noMatchDontSwitch_clicked();
|
void on_noMatchDontSwitch_clicked();
|
||||||
void on_noMatchSwitch_clicked();
|
void on_noMatchSwitch_clicked();
|
||||||
void on_noMatchRandomSwitch_clicked();
|
void on_noMatchRandomSwitch_clicked();
|
||||||
void NoMatchDelayDurationChanged(double);
|
void NoMatchDelayDurationChanged(const Duration &);
|
||||||
void NoMatchDelayUnitChanged(DurationUnit);
|
void CooldownDurationChanged(const Duration &);
|
||||||
void CooldownDurationChanged(double);
|
|
||||||
void CooldownUnitChanged(DurationUnit);
|
|
||||||
void on_startupBehavior_currentIndexChanged(int index);
|
void on_startupBehavior_currentIndexChanged(int index);
|
||||||
void on_autoStartEvent_currentIndexChanged(int index);
|
void on_autoStartEvent_currentIndexChanged(int index);
|
||||||
void on_noMatchSwitchScene_currentTextChanged(const QString &text);
|
void on_noMatchSwitchScene_currentTextChanged(const QString &text);
|
||||||
@@ -145,6 +146,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();
|
||||||
@@ -200,6 +202,7 @@ public slots:
|
|||||||
void on_saveWindowGeo_stateChanged(int state);
|
void on_saveWindowGeo_stateChanged(int state);
|
||||||
void on_showTrayNotifications_stateChanged(int state);
|
void on_showTrayNotifications_stateChanged(int state);
|
||||||
void on_uiHintsDisable_stateChanged(int state);
|
void on_uiHintsDisable_stateChanged(int state);
|
||||||
|
void on_warnPluginLoadFailure_stateChanged(int state);
|
||||||
void on_hideLegacyTabs_stateChanged(int state);
|
void on_hideLegacyTabs_stateChanged(int state);
|
||||||
|
|
||||||
void on_exportSettings_clicked();
|
void on_exportSettings_clicked();
|
||||||
|
|||||||
105
src/general.cpp
@@ -60,44 +60,24 @@ void AdvSceneSwitcher::on_noMatchRandomSwitch_clicked()
|
|||||||
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)
|
||||||
@@ -192,6 +172,15 @@ void AdvSceneSwitcher::on_uiHintsDisable_stateChanged(int state)
|
|||||||
switcher->disableHints = state;
|
switcher->disableHints = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::on_warnPluginLoadFailure_stateChanged(int state)
|
||||||
|
{
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switcher->warnPluginLoadFailure = state;
|
||||||
|
}
|
||||||
|
|
||||||
bool isLegacyTab(const QString &name)
|
bool isLegacyTab(const QString &name)
|
||||||
{
|
{
|
||||||
return name == obs_module_text(
|
return name == obs_module_text(
|
||||||
@@ -255,11 +244,28 @@ QString getDefaultSaveLocation()
|
|||||||
{
|
{
|
||||||
QString desktopPath = QStandardPaths::writableLocation(
|
QString desktopPath = QStandardPaths::writableLocation(
|
||||||
QStandardPaths::DesktopLocation);
|
QStandardPaths::DesktopLocation);
|
||||||
|
|
||||||
auto scName = obs_frontend_get_current_scene_collection();
|
auto scName = obs_frontend_get_current_scene_collection();
|
||||||
QString sceneCollectionName(scName);
|
QString sceneCollectionName(scName);
|
||||||
bfree(scName);
|
bfree(scName);
|
||||||
|
|
||||||
auto timestamp = QDateTime::currentDateTime();
|
auto timestamp = QDateTime::currentDateTime();
|
||||||
return desktopPath + "/adv-ss-" + sceneCollectionName + "-" +
|
auto path = desktopPath + "/adv-ss-" + sceneCollectionName + "-" +
|
||||||
|
timestamp.toString("yyyy.MM.dd.hh.mm.ss");
|
||||||
|
|
||||||
|
// Check if scene collection name contains invalid path characters
|
||||||
|
QFile file(path);
|
||||||
|
if (file.exists()) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validPath = file.open(QIODevice::WriteOnly);
|
||||||
|
if (validPath) {
|
||||||
|
file.remove();
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return desktopPath + "/adv-ss-" +
|
||||||
timestamp.toString("yyyy.MM.dd.hh.mm.ss");
|
timestamp.toString("yyyy.MM.dd.hh.mm.ss");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,8 +547,8 @@ void SwitcherData::loadSettings(obs_data_t *obj)
|
|||||||
// 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);
|
||||||
@@ -605,9 +611,9 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
|||||||
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", switchIfNotMatching);
|
||||||
noMatchDelay.Save(obj, "noMatchDelay", "noMatchDelayUnit");
|
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;
|
||||||
@@ -620,6 +626,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,12 +643,11 @@ 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());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -656,9 +662,9 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
|||||||
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 =
|
||||||
@@ -677,6 +683,8 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
|||||||
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");
|
||||||
|
|
||||||
@@ -719,11 +727,23 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
|||||||
QThread::NormalPriority);
|
QThread::NormalPriority);
|
||||||
threadPriority = obs_data_get_int(obj, "threadPriority");
|
threadPriority = obs_data_get_int(obj, "threadPriority");
|
||||||
|
|
||||||
transitionOverrideOverride =
|
// TODO: Remove this fallback in future version
|
||||||
obs_data_get_bool(obj, "tansitionOverrideOverride");
|
if (obs_data_has_user_value(obj, "tansitionOverrideOverride")) {
|
||||||
|
transitionOverrideOverride =
|
||||||
|
obs_data_get_bool(obj, "tansitionOverrideOverride");
|
||||||
|
} else {
|
||||||
|
transitionOverrideOverride =
|
||||||
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -942,10 +962,9 @@ void AdvSceneSwitcher::setupGeneralTab()
|
|||||||
noMatchDelay->setToolTip(obs_module_text(
|
noMatchDelay->setToolTip(obs_module_text(
|
||||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip"));
|
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip"));
|
||||||
ui->noMatchLayout->addWidget(noMatchDelay);
|
ui->noMatchLayout->addWidget(noMatchDelay);
|
||||||
QWidget::connect(noMatchDelay, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(noMatchDelay,
|
||||||
SLOT(NoMatchDelayDurationChanged(double)));
|
SIGNAL(DurationChanged(const Duration &)), this,
|
||||||
QWidget::connect(noMatchDelay, SIGNAL(UnitChanged(DurationUnit)), this,
|
SLOT(NoMatchDelayDurationChanged(const Duration &)));
|
||||||
SLOT(NoMatchDelayUnitChanged(DurationUnit)));
|
|
||||||
|
|
||||||
ui->checkInterval->setValue(switcher->interval);
|
ui->checkInterval->setValue(switcher->interval);
|
||||||
|
|
||||||
@@ -955,16 +974,16 @@ void AdvSceneSwitcher::setupGeneralTab()
|
|||||||
"AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint"));
|
"AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint"));
|
||||||
ui->cooldownLayout->addWidget(cooldownTime);
|
ui->cooldownLayout->addWidget(cooldownTime);
|
||||||
ui->cooldownLayout->addStretch();
|
ui->cooldownLayout->addStretch();
|
||||||
QWidget::connect(cooldownTime, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(cooldownTime,
|
||||||
SLOT(CooldownDurationChanged(double)));
|
SIGNAL(DurationChanged(const Duration &)), this,
|
||||||
QWidget::connect(cooldownTime, SIGNAL(UnitChanged(DurationUnit)), this,
|
SLOT(CooldownDurationChanged(const Duration &)));
|
||||||
SLOT(CooldownUnitChanged(DurationUnit)));
|
|
||||||
|
|
||||||
ui->verboseLogging->setChecked(switcher->verbose);
|
ui->verboseLogging->setChecked(switcher->verbose);
|
||||||
ui->saveWindowGeo->setChecked(switcher->saveWindowGeo);
|
ui->saveWindowGeo->setChecked(switcher->saveWindowGeo);
|
||||||
ui->showTrayNotifications->setChecked(
|
ui->showTrayNotifications->setChecked(
|
||||||
switcher->showSystemTrayNotifications);
|
switcher->showSystemTrayNotifications);
|
||||||
ui->uiHintsDisable->setChecked(switcher->disableHints);
|
ui->uiHintsDisable->setChecked(switcher->disableHints);
|
||||||
|
ui->warnPluginLoadFailure->setChecked(switcher->warnPluginLoadFailure);
|
||||||
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
|
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
|
||||||
|
|
||||||
for (int p : switcher->functionNamesByPriority) {
|
for (int p : switcher->functionNamesByPriority) {
|
||||||
|
|||||||
@@ -156,7 +156,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 +266,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));
|
||||||
@@ -460,10 +460,8 @@ 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 &)));
|
||||||
@@ -552,24 +550,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)
|
||||||
|
|||||||
@@ -71,8 +71,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:
|
||||||
|
|||||||
@@ -438,8 +438,8 @@ 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 &)));
|
||||||
@@ -554,14 +554,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 +580,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);
|
||||||
@@ -602,12 +602,12 @@ 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,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,7 +96,7 @@ 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;
|
||||||
|
|||||||
@@ -455,7 +455,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 +588,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 &)));
|
||||||
@@ -689,24 +687,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()
|
||||||
|
|||||||
@@ -59,8 +59,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();
|
||||||
|
|||||||
@@ -114,7 +114,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 +212,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 +225,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 +244,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 +310,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(
|
||||||
@@ -343,20 +351,28 @@ MacroActionAudioEdit::MacroActionAudioEdit(
|
|||||||
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,
|
||||||
@@ -468,13 +484,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));
|
||||||
@@ -505,7 +521,7 @@ void MacroActionAudioEdit::ActionChanged(int idx)
|
|||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionAudioEdit::SyncOffsetChanged(int value)
|
void MacroActionAudioEdit::SyncOffsetChanged(const NumberVariable<int> &value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
@@ -525,7 +541,7 @@ void MacroActionAudioEdit::MonitorTypeChanged(int value)
|
|||||||
_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;
|
||||||
@@ -535,7 +551,7 @@ void MacroActionAudioEdit::BalanceChanged(double value)
|
|||||||
_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;
|
||||||
@@ -556,17 +572,17 @@ void MacroActionAudioEdit::FadeChanged(int 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);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_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;
|
||||||
|
|||||||
@@ -42,13 +42,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 +84,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 +101,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;
|
||||||
|
|||||||
@@ -55,7 +55,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 +64,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 +72,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)
|
||||||
|
|||||||
@@ -24,9 +24,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:
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public:
|
|||||||
SourceSelection _source;
|
SourceSelection _source;
|
||||||
OBSWeakSource _filter;
|
OBSWeakSource _filter;
|
||||||
Action _action = Action::ENABLE;
|
Action _action = Action::ENABLE;
|
||||||
VariableResolvingString _settings = "";
|
StringVariable _settings = "";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ResolveVariables();
|
void ResolveVariables();
|
||||||
|
|||||||
@@ -224,7 +224,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 +254,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 +272,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 +393,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 +437,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)));
|
||||||
|
|
||||||
@@ -493,7 +496,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();
|
||||||
@@ -579,14 +582,14 @@ void MacroActionHotkeyEdit::RMetaChanged(int state)
|
|||||||
_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);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_duration = ms;
|
_entryData->_duration = dur;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionHotkeyEdit::OnlySendToOBSChanged(int state)
|
void MacroActionHotkeyEdit::OnlySendToOBSChanged(int state)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#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>
|
||||||
@@ -30,7 +31,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 +69,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 +82,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;
|
||||||
|
|
||||||
|
|||||||
@@ -27,11 +27,26 @@ size_t WriteCB(void *ptr, size_t size, size_t nmemb, std::string *buffer)
|
|||||||
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 +64,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 +106,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 +118,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 +129,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 +142,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 +161,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},
|
||||||
@@ -153,8 +184,14 @@ MacroActionHttpEdit::MacroActionHttpEdit(
|
|||||||
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 +207,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();
|
||||||
@@ -199,28 +238,43 @@ void MacroActionHttpEdit::MethodChanged(int 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);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_timeout.seconds = seconds;
|
_entryData->_timeout = dur;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionHttpEdit::SetHeadersChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_setHeaders = value;
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionHttpEdit::HeadersChanged(const StringList &headers)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_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();
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
#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>
|
||||||
|
|
||||||
class MacroActionHttp : public MacroAction {
|
class MacroActionHttp : public MacroAction {
|
||||||
public:
|
public:
|
||||||
@@ -25,13 +28,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 +64,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 +76,12 @@ 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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,27 +21,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 +52,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 +98,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 +119,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)));
|
||||||
|
|
||||||
@@ -145,7 +142,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();
|
||||||
@@ -159,7 +156,7 @@ void MacroActionMacroEdit::MacroChanged(const QString &text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_macro.UpdateRef(text);
|
_entryData->_macro = text;
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
@@ -180,10 +177,3 @@ void MacroActionMacroEdit::ActionChanged(int value)
|
|||||||
_macros->ShowAllMacros();
|
_macros->ShowAllMacros();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionMacroEdit::MacroRemove(const QString &)
|
|
||||||
{
|
|
||||||
if (_entryData) {
|
|
||||||
_entryData->_macro.UpdateRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -51,7 +51,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 &);
|
||||||
|
|||||||
@@ -48,7 +48,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 +116,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 = {
|
||||||
@@ -171,24 +169,14 @@ void MacroActionMediaEdit::ActionChanged(int 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);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_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()
|
||||||
|
|||||||
@@ -58,8 +58,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 &);
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,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 +114,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +185,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,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:
|
||||||
|
|||||||
290
src/macro-core/macro-action-projector.cpp
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
#include "macro-action-projector.hpp"
|
||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
#include <QScreen>
|
||||||
|
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static QStringList getMonitorNames()
|
||||||
|
{
|
||||||
|
QStringList monitorNames;
|
||||||
|
QList<QScreen *> screens = QGuiApplication::screens();
|
||||||
|
for (int i = 0; i < screens.size(); i++) {
|
||||||
|
QScreen *screen = screens[i];
|
||||||
|
QRect screenGeometry = screen->geometry();
|
||||||
|
qreal ratio = screen->devicePixelRatio();
|
||||||
|
QString name = "";
|
||||||
|
#if defined(__APPLE__) || defined(_WIN32)
|
||||||
|
name = screen->name();
|
||||||
|
#else
|
||||||
|
name = screen->model().simplified();
|
||||||
|
if (name.length() > 1 && name.endsWith("-")) {
|
||||||
|
name.chop(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
name = name.simplified();
|
||||||
|
|
||||||
|
if (name.length() == 0) {
|
||||||
|
name = QString("%1 %2")
|
||||||
|
.arg(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.projector.display"))
|
||||||
|
.arg(QString::number(i + 1));
|
||||||
|
}
|
||||||
|
QString str =
|
||||||
|
QString("%1: %2x%3 @ %4,%5")
|
||||||
|
.arg(name,
|
||||||
|
QString::number(screenGeometry.width() *
|
||||||
|
ratio),
|
||||||
|
QString::number(screenGeometry.height() *
|
||||||
|
ratio),
|
||||||
|
QString::number(screenGeometry.x()),
|
||||||
|
QString::number(screenGeometry.y()));
|
||||||
|
|
||||||
|
monitorNames << str;
|
||||||
|
}
|
||||||
|
return monitorNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_scene = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::SourceChanged(const SourceSelection &source)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::MonitorChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_monitor = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::WindowTypeChanged(int)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_fullscreen =
|
||||||
|
_windowTypes->currentText() ==
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.projector.fullscreen");
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::TypeChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_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();
|
||||||
|
}
|
||||||
73
src/macro-core/macro-action-projector.hpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "scene-selection.hpp"
|
||||||
|
#include "source-selection.hpp"
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
@@ -11,22 +11,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 +50,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();
|
||||||
}
|
}
|
||||||
@@ -126,8 +134,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;
|
||||||
@@ -188,9 +195,9 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
#include "macro-action-run.hpp"
|
#include "macro-action-run.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "name-dialog.hpp"
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
|
||||||
const std::string MacroActionRun::id = "run";
|
const std::string MacroActionRun::id = "run";
|
||||||
@@ -15,137 +13,53 @@ bool MacroActionRun::_registered = MacroActionFactory::Register(
|
|||||||
|
|
||||||
bool MacroActionRun::PerformAction()
|
bool MacroActionRun::PerformAction()
|
||||||
{
|
{
|
||||||
if (!QProcess::startDetached(
|
bool procStarted = QProcess::startDetached(
|
||||||
QString::fromStdString(_path), _args,
|
QString::fromStdString(_procConfig.Path()), _procConfig.Args(),
|
||||||
QString::fromStdString(_workingDirectory)) &&
|
QString::fromStdString(_procConfig.WorkingDir()));
|
||||||
_args.empty()) {
|
if (!procStarted && _procConfig.Args().empty()) {
|
||||||
vblog(LOG_INFO, "run \"%s\" using QDesktopServices",
|
vblog(LOG_INFO, "run \"%s\" using QDesktopServices",
|
||||||
_path.c_str());
|
_procConfig.Path().c_str());
|
||||||
QDesktopServices::openUrl(
|
QDesktopServices::openUrl(QUrl::fromLocalFile(
|
||||||
QUrl::fromLocalFile(QString::fromStdString(_path)));
|
QString::fromStdString(_procConfig.Path())));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionRun::LogAction() const
|
void MacroActionRun::LogAction() const
|
||||||
{
|
{
|
||||||
vblog(LOG_INFO, "run \"%s\"", _path.c_str());
|
vblog(LOG_INFO, "run \"%s\"", _procConfig.UnresolvedPath().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroActionRun::Save(obs_data_t *obj) const
|
bool MacroActionRun::Save(obs_data_t *obj) const
|
||||||
{
|
{
|
||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
obs_data_set_string(obj, "path", _path.c_str());
|
_procConfig.Save(obj);
|
||||||
obs_data_set_string(obj, "workingDirectory", _workingDirectory.c_str());
|
|
||||||
obs_data_array_t *args = obs_data_array_create();
|
|
||||||
for (auto &arg : _args) {
|
|
||||||
obs_data_t *array_obj = obs_data_create();
|
|
||||||
obs_data_set_string(array_obj, "arg",
|
|
||||||
arg.toStdString().c_str());
|
|
||||||
obs_data_array_push_back(args, array_obj);
|
|
||||||
obs_data_release(array_obj);
|
|
||||||
}
|
|
||||||
obs_data_set_array(obj, "args", args);
|
|
||||||
obs_data_array_release(args);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroActionRun::Load(obs_data_t *obj)
|
bool MacroActionRun::Load(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
_path = obs_data_get_string(obj, "path");
|
_procConfig.Load(obj);
|
||||||
_workingDirectory = obs_data_get_string(obj, "workingDirectory");
|
|
||||||
obs_data_array_t *args = obs_data_get_array(obj, "args");
|
|
||||||
size_t count = obs_data_array_count(args);
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
obs_data_t *array_obj = obs_data_array_item(args, i);
|
|
||||||
_args << QString::fromStdString(
|
|
||||||
obs_data_get_string(array_obj, "arg"));
|
|
||||||
obs_data_release(array_obj);
|
|
||||||
}
|
|
||||||
obs_data_array_release(args);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MacroActionRun::GetShortDesc() const
|
std::string MacroActionRun::GetShortDesc() const
|
||||||
{
|
{
|
||||||
return _path;
|
return _procConfig.UnresolvedPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroActionRunEdit::MacroActionRunEdit(
|
MacroActionRunEdit::MacroActionRunEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroActionRun> entryData)
|
QWidget *parent, std::shared_ptr<MacroActionRun> entryData)
|
||||||
: QWidget(parent),
|
: QWidget(parent), _procConfig(new ProcessConfigEdit(this))
|
||||||
_filePath(new FileSelection()),
|
|
||||||
_argList(new QListWidget()),
|
|
||||||
_addArg(new QPushButton()),
|
|
||||||
_removeArg(new QPushButton()),
|
|
||||||
_argUp(new QPushButton()),
|
|
||||||
_argDown(new QPushButton()),
|
|
||||||
_workingDirectory(new FileSelection(FileSelection::Type::FOLDER))
|
|
||||||
{
|
{
|
||||||
_addArg->setMaximumWidth(22);
|
QWidget::connect(_procConfig,
|
||||||
_addArg->setProperty("themeID",
|
SIGNAL(ConfigChanged(const ProcessConfig &)), this,
|
||||||
QVariant(QString::fromUtf8("addIconSmall")));
|
SLOT(ProcessConfigChanged(const ProcessConfig &)));
|
||||||
_addArg->setFlat(true);
|
|
||||||
_removeArg->setMaximumWidth(22);
|
|
||||||
_removeArg->setProperty("themeID",
|
|
||||||
QVariant(QString::fromUtf8("removeIconSmall")));
|
|
||||||
_removeArg->setFlat(true);
|
|
||||||
_argUp->setMaximumWidth(22);
|
|
||||||
_argUp->setProperty("themeID",
|
|
||||||
QVariant(QString::fromUtf8("upArrowIconSmall")));
|
|
||||||
_argUp->setFlat(true);
|
|
||||||
_argDown->setMaximumWidth(22);
|
|
||||||
_argDown->setProperty(
|
|
||||||
"themeID", QVariant(QString::fromUtf8("downArrowIconSmall")));
|
|
||||||
_argDown->setFlat(true);
|
|
||||||
|
|
||||||
QWidget::connect(_filePath, SIGNAL(PathChanged(const QString &)), this,
|
auto *layout = new QVBoxLayout;
|
||||||
SLOT(PathChanged(const QString &)));
|
layout->addWidget(_procConfig);
|
||||||
QWidget::connect(_addArg, SIGNAL(clicked()), this, SLOT(AddArg()));
|
setLayout(layout);
|
||||||
QWidget::connect(_removeArg, SIGNAL(clicked()), this,
|
|
||||||
SLOT(RemoveArg()));
|
|
||||||
QWidget::connect(_argUp, SIGNAL(clicked()), this, SLOT(ArgUp()));
|
|
||||||
QWidget::connect(_argDown, SIGNAL(clicked()), this, SLOT(ArgDown()));
|
|
||||||
QWidget::connect(_argList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
|
|
||||||
this, SLOT(ArgItemClicked(QListWidgetItem *)));
|
|
||||||
QWidget::connect(_workingDirectory,
|
|
||||||
SIGNAL(PathChanged(const QString &)), this,
|
|
||||||
SLOT(WorkingDirectoryChanged(const QString &)));
|
|
||||||
|
|
||||||
auto *entryLayout = new QHBoxLayout;
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
|
||||||
{"{{filePath}}", _filePath},
|
|
||||||
{"{{workingDirectory}}", _workingDirectory},
|
|
||||||
};
|
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.run.entry"),
|
|
||||||
entryLayout, widgetPlaceholders, false);
|
|
||||||
|
|
||||||
auto argButtonLayout = new QHBoxLayout;
|
|
||||||
argButtonLayout->addWidget(_addArg);
|
|
||||||
argButtonLayout->addWidget(_removeArg);
|
|
||||||
QFrame *line = new QFrame();
|
|
||||||
line->setFrameShape(QFrame::VLine);
|
|
||||||
line->setFrameShadow(QFrame::Sunken);
|
|
||||||
argButtonLayout->addWidget(line);
|
|
||||||
argButtonLayout->addWidget(_argUp);
|
|
||||||
argButtonLayout->addWidget(_argDown);
|
|
||||||
argButtonLayout->addStretch();
|
|
||||||
|
|
||||||
auto workingDirectoryLayout = new QHBoxLayout;
|
|
||||||
placeWidgets(
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.action.run.entry.workingDirectory"),
|
|
||||||
workingDirectoryLayout, widgetPlaceholders, false);
|
|
||||||
|
|
||||||
auto *mainLayout = new QVBoxLayout;
|
|
||||||
mainLayout->addLayout(entryLayout);
|
|
||||||
mainLayout->addWidget(new QLabel(
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.run.arguments")));
|
|
||||||
mainLayout->addWidget(_argList);
|
|
||||||
mainLayout->addLayout(argButtonLayout);
|
|
||||||
mainLayout->addLayout(workingDirectoryLayout);
|
|
||||||
setLayout(mainLayout);
|
|
||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
UpdateEntryData();
|
UpdateEntryData();
|
||||||
@@ -157,142 +71,19 @@ void MacroActionRunEdit::UpdateEntryData()
|
|||||||
if (!_entryData) {
|
if (!_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_filePath->SetPath(QString::fromStdString(_entryData->_path));
|
_procConfig->SetProcessConfig(_entryData->_procConfig);
|
||||||
for (auto &arg : _entryData->_args) {
|
|
||||||
QListWidgetItem *item = new QListWidgetItem(arg, _argList);
|
|
||||||
item->setData(Qt::UserRole, arg);
|
|
||||||
}
|
|
||||||
_workingDirectory->SetPath(
|
|
||||||
QString::fromStdString(_entryData->_workingDirectory));
|
|
||||||
SetArgListSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionRunEdit::PathChanged(const QString &text)
|
void MacroActionRunEdit::ProcessConfigChanged(const ProcessConfig &conf)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_path = text.toUtf8().constData();
|
_entryData->_procConfig = conf;
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionRunEdit::AddArg()
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
bool accepted = AdvSSNameDialog::AskForName(
|
|
||||||
this,
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.run.addArgument"),
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.action.run.addArgumentDescription"),
|
|
||||||
name, "", 170, false);
|
|
||||||
|
|
||||||
if (!accepted || name.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto arg = QString::fromStdString(name);
|
|
||||||
QVariant v = QVariant::fromValue(arg);
|
|
||||||
QListWidgetItem *item = new QListWidgetItem(arg, _argList);
|
|
||||||
item->setData(Qt::UserRole, arg);
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_args << arg;
|
|
||||||
SetArgListSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionRunEdit::RemoveArg()
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
int idx = _argList->currentRow();
|
|
||||||
if (idx == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_entryData->_args.removeAt(idx);
|
|
||||||
|
|
||||||
QListWidgetItem *item = _argList->currentItem();
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
delete item;
|
|
||||||
SetArgListSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionRunEdit::ArgUp()
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int idx = _argList->currentRow();
|
|
||||||
if (idx != -1 && idx != 0) {
|
|
||||||
_argList->insertItem(idx - 1, _argList->takeItem(idx));
|
|
||||||
_argList->setCurrentRow(idx - 1);
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_args.move(idx, idx - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionRunEdit::ArgDown()
|
|
||||||
{
|
|
||||||
int idx = _argList->currentRow();
|
|
||||||
if (idx != -1 && idx != _argList->count() - 1) {
|
|
||||||
_argList->insertItem(idx + 1, _argList->takeItem(idx));
|
|
||||||
_argList->setCurrentRow(idx + 1);
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_args.move(idx, idx + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionRunEdit::ArgItemClicked(QListWidgetItem *item)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
bool accepted = AdvSSNameDialog::AskForName(
|
|
||||||
this,
|
|
||||||
obs_module_text("AdvSceneSwitcher.action.run.addArgument"),
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.action.run.addArgumentDescription"),
|
|
||||||
name, item->text(), 170, false);
|
|
||||||
|
|
||||||
if (!accepted || name.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto arg = QString::fromStdString(name);
|
|
||||||
QVariant v = QVariant::fromValue(arg);
|
|
||||||
item->setText(arg);
|
|
||||||
item->setData(Qt::UserRole, arg);
|
|
||||||
int idx = _argList->currentRow();
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_args[idx] = arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionRunEdit::WorkingDirectoryChanged(const QString &path)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_entryData->_workingDirectory = path.toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionRunEdit::SetArgListSize()
|
|
||||||
{
|
|
||||||
setHeightToContentHeight(_argList);
|
|
||||||
adjustSize();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
#include "file-selection.hpp"
|
#include "process-config.hpp"
|
||||||
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QListWidget>
|
|
||||||
#include <QStringList>
|
|
||||||
|
|
||||||
class MacroActionRun : public MacroAction {
|
class MacroActionRun : public MacroAction {
|
||||||
public:
|
public:
|
||||||
@@ -21,9 +16,7 @@ public:
|
|||||||
return std::make_shared<MacroActionRun>(m);
|
return std::make_shared<MacroActionRun>(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string _path = obs_module_text("AdvSceneSwitcher.enterPath");
|
ProcessConfig _procConfig;
|
||||||
std::string _workingDirectory = "";
|
|
||||||
QStringList _args;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
@@ -46,13 +39,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void PathChanged(const QString &text);
|
void ProcessConfigChanged(const ProcessConfig &);
|
||||||
void AddArg();
|
|
||||||
void RemoveArg();
|
|
||||||
void ArgUp();
|
|
||||||
void ArgDown();
|
|
||||||
void ArgItemClicked(QListWidgetItem *);
|
|
||||||
void WorkingDirectoryChanged(const QString &text);
|
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
@@ -60,14 +47,6 @@ protected:
|
|||||||
std::shared_ptr<MacroActionRun> _entryData;
|
std::shared_ptr<MacroActionRun> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetArgListSize();
|
ProcessConfigEdit *_procConfig;
|
||||||
|
|
||||||
FileSelection *_filePath;
|
|
||||||
QListWidget *_argList;
|
|
||||||
QPushButton *_addArg;
|
|
||||||
QPushButton *_removeArg;
|
|
||||||
QPushButton *_argUp;
|
|
||||||
QPushButton *_argDown;
|
|
||||||
FileSelection *_workingDirectory;
|
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,37 +11,39 @@ bool MacroActionSwitchScene::_registered = MacroActionFactory::Register(
|
|||||||
{MacroActionSwitchScene::Create, MacroActionSwitchSceneEdit::Create,
|
{MacroActionSwitchScene::Create, MacroActionSwitchSceneEdit::Create,
|
||||||
"AdvSceneSwitcher.action.switchScene"});
|
"AdvSceneSwitcher.action.switchScene"});
|
||||||
|
|
||||||
void waitForTransitionChange(OBSWeakSource &transition)
|
static void waitForTransitionChange(OBSWeakSource &transition,
|
||||||
|
std::unique_lock<std::mutex> *lock,
|
||||||
|
Macro *macro)
|
||||||
{
|
{
|
||||||
const auto time = 100ms;
|
const auto time = 100ms;
|
||||||
obs_source_t *source = obs_weak_source_get_source(transition);
|
obs_source_t *source = obs_weak_source_get_source(transition);
|
||||||
std::unique_lock<std::mutex> lock(switcher->m);
|
|
||||||
bool stillTransitioning = true;
|
bool stillTransitioning = true;
|
||||||
while (stillTransitioning && !switcher->abortMacroWait) {
|
while (stillTransitioning && !switcher->abortMacroWait &&
|
||||||
switcher->macroTransitionCv.wait_for(lock, time);
|
!macro->GetStop()) {
|
||||||
|
switcher->macroTransitionCv.wait_for(*lock, time);
|
||||||
float t = obs_transition_get_time(source);
|
float t = obs_transition_get_time(source);
|
||||||
stillTransitioning = t < 1.0f && t > 0.0f;
|
stillTransitioning = t < 1.0f && t > 0.0f;
|
||||||
}
|
}
|
||||||
obs_source_release(source);
|
obs_source_release(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitForTransitionChangeFixedDuration(int duration)
|
static void waitForTransitionChangeFixedDuration(
|
||||||
|
int duration, std::unique_lock<std::mutex> *lock, Macro *macro)
|
||||||
{
|
{
|
||||||
duration += 200; // It seems to be necessary to add a small buffer
|
duration += 200; // It seems to be necessary to add a small buffer
|
||||||
auto time = std::chrono::high_resolution_clock::now() +
|
auto time = std::chrono::high_resolution_clock::now() +
|
||||||
std::chrono::milliseconds(duration);
|
std::chrono::milliseconds(duration);
|
||||||
|
|
||||||
switcher->abortMacroWait = false;
|
while (!switcher->abortMacroWait && !macro->GetStop()) {
|
||||||
std::unique_lock<std::mutex> lock(switcher->m);
|
if (switcher->macroTransitionCv.wait_until(*lock, time) ==
|
||||||
while (!switcher->abortMacroWait) {
|
|
||||||
if (switcher->macroTransitionCv.wait_until(lock, time) ==
|
|
||||||
std::cv_status::timeout) {
|
std::cv_status::timeout) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getTransitionOverrideDuration(OBSWeakSource &scene)
|
static int getTransitionOverrideDuration(OBSWeakSource &scene)
|
||||||
{
|
{
|
||||||
int duration = 0;
|
int duration = 0;
|
||||||
obs_source_t *source = obs_weak_source_get_source(scene);
|
obs_source_t *source = obs_weak_source_get_source(scene);
|
||||||
@@ -55,7 +57,7 @@ int getTransitionOverrideDuration(OBSWeakSource &scene)
|
|||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isUsingFixedLengthTransition(const OBSWeakSource &transition)
|
static bool isUsingFixedLengthTransition(const OBSWeakSource &transition)
|
||||||
{
|
{
|
||||||
obs_source_t *source = obs_weak_source_get_source(transition);
|
obs_source_t *source = obs_weak_source_get_source(transition);
|
||||||
bool ret = obs_transition_fixed(source);
|
bool ret = obs_transition_fixed(source);
|
||||||
@@ -63,7 +65,7 @@ bool isUsingFixedLengthTransition(const OBSWeakSource &transition)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSWeakSource getOverrideTransition(OBSWeakSource &scene)
|
static OBSWeakSource getOverrideTransition(OBSWeakSource &scene)
|
||||||
{
|
{
|
||||||
OBSWeakSource transition;
|
OBSWeakSource transition;
|
||||||
obs_source_t *source = obs_weak_source_get_source(scene);
|
obs_source_t *source = obs_weak_source_get_source(scene);
|
||||||
@@ -75,8 +77,8 @@ OBSWeakSource getOverrideTransition(OBSWeakSource &scene)
|
|||||||
return transition;
|
return transition;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getExpectedTransitionDuration(OBSWeakSource &scene, OBSWeakSource &t,
|
static int getExpectedTransitionDuration(OBSWeakSource &scene, OBSWeakSource &t,
|
||||||
double duration)
|
double duration)
|
||||||
{
|
{
|
||||||
OBSWeakSource transition = t;
|
OBSWeakSource transition = t;
|
||||||
if (!switcher->transitionOverrideOverride) {
|
if (!switcher->transitionOverrideOverride) {
|
||||||
@@ -97,23 +99,32 @@ int getExpectedTransitionDuration(OBSWeakSource &scene, OBSWeakSource &t,
|
|||||||
return obs_frontend_get_transition_duration();
|
return obs_frontend_get_transition_duration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MacroActionSwitchScene::WaitForTransition(OBSWeakSource &scene,
|
||||||
|
OBSWeakSource &transition)
|
||||||
|
{
|
||||||
|
const int expectedTransitionDuration = getExpectedTransitionDuration(
|
||||||
|
scene, transition, _duration.Seconds());
|
||||||
|
switcher->abortMacroWait = false;
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> lock(switcher->m);
|
||||||
|
if (expectedTransitionDuration < 0) {
|
||||||
|
waitForTransitionChange(transition, &lock, GetMacro());
|
||||||
|
} else {
|
||||||
|
waitForTransitionChangeFixedDuration(expectedTransitionDuration,
|
||||||
|
&lock, GetMacro());
|
||||||
|
}
|
||||||
|
|
||||||
|
return !switcher->abortMacroWait;
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroActionSwitchScene::PerformAction()
|
bool MacroActionSwitchScene::PerformAction()
|
||||||
{
|
{
|
||||||
auto scene = _scene.GetScene();
|
auto scene = _scene.GetScene();
|
||||||
auto transition = _transition.GetTransition();
|
auto transition = _transition.GetTransition();
|
||||||
switchScene({scene, transition, (int)(_duration.seconds * 1000)},
|
switchScene({scene, transition, (int)(_duration.Milliseconds())},
|
||||||
obs_frontend_preview_program_mode_active());
|
obs_frontend_preview_program_mode_active());
|
||||||
if (_blockUntilTransitionDone && scene) {
|
if (_blockUntilTransitionDone && scene) {
|
||||||
const int expectedTransitionDuration =
|
return WaitForTransition(scene, transition);
|
||||||
getExpectedTransitionDuration(scene, transition,
|
|
||||||
_duration.seconds);
|
|
||||||
if (expectedTransitionDuration < 0) {
|
|
||||||
waitForTransitionChange(transition);
|
|
||||||
} else {
|
|
||||||
waitForTransitionChangeFixedDuration(
|
|
||||||
expectedTransitionDuration);
|
|
||||||
}
|
|
||||||
return !switcher->abortMacroWait;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -185,8 +196,8 @@ MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
|
|||||||
SIGNAL(TransitionChanged(const TransitionSelection &)),
|
SIGNAL(TransitionChanged(const TransitionSelection &)),
|
||||||
this,
|
this,
|
||||||
SLOT(TransitionChanged(const TransitionSelection &)));
|
SLOT(TransitionChanged(const TransitionSelection &)));
|
||||||
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)),
|
||||||
SLOT(DurationChanged(double)));
|
this, SLOT(DurationChanged(const Duration &)));
|
||||||
QWidget::connect(_blockUntilTransitionDone, SIGNAL(stateChanged(int)),
|
QWidget::connect(_blockUntilTransitionDone, SIGNAL(stateChanged(int)),
|
||||||
this, SLOT(BlockUntilTransitionDoneChanged(int)));
|
this, SLOT(BlockUntilTransitionDoneChanged(int)));
|
||||||
|
|
||||||
@@ -214,14 +225,14 @@ MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
|
|||||||
_loading = false;
|
_loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSwitchSceneEdit::DurationChanged(double seconds)
|
void MacroActionSwitchSceneEdit::DurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_duration.seconds = seconds;
|
_entryData->_duration = dur;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSwitchSceneEdit::BlockUntilTransitionDoneChanged(int state)
|
void MacroActionSwitchSceneEdit::BlockUntilTransitionDoneChanged(int state)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public:
|
|||||||
bool _blockUntilTransitionDone = true;
|
bool _blockUntilTransitionDone = true;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *getType() { return "MacroActionSwitchScene"; }
|
bool WaitForTransition(OBSWeakSource &scene, OBSWeakSource &transition);
|
||||||
|
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
static const std::string id;
|
static const std::string id;
|
||||||
@@ -51,7 +51,7 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void SceneChanged(const SceneSelection &);
|
void SceneChanged(const SceneSelection &);
|
||||||
void TransitionChanged(const TransitionSelection &);
|
void TransitionChanged(const TransitionSelection &);
|
||||||
void DurationChanged(double seconds);
|
void DurationChanged(const Duration &seconds);
|
||||||
void BlockUntilTransitionDoneChanged(int state);
|
void BlockUntilTransitionDoneChanged(int state);
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public:
|
|||||||
|
|
||||||
SceneSelection _scene;
|
SceneSelection _scene;
|
||||||
SceneItemSelection _source;
|
SceneItemSelection _source;
|
||||||
VariableResolvingString _settings = "";
|
StringVariable _settings = "";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ApplySettings(const std::string &);
|
void ApplySettings(const std::string &);
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ bool MacroActionScreenshot::PerformAction()
|
|||||||
case MacroActionScreenshot::TargetType::SCENE:
|
case MacroActionScreenshot::TargetType::SCENE:
|
||||||
source = _scene.GetScene(false);
|
source = _scene.GetScene(false);
|
||||||
break;
|
break;
|
||||||
|
case MacroActionScreenshot::TargetType::MAIN_OUTPUT:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_saveType) {
|
switch (_saveType) {
|
||||||
@@ -73,8 +75,7 @@ void MacroActionScreenshot::LogAction() const
|
|||||||
_scene.ToString(true).c_str());
|
_scene.ToString(true).c_str());
|
||||||
break;
|
break;
|
||||||
case MacroActionScreenshot::TargetType::MAIN_OUTPUT:
|
case MacroActionScreenshot::TargetType::MAIN_OUTPUT:
|
||||||
vblog(LOG_INFO, "trigger screenshot of main output",
|
vblog(LOG_INFO, "trigger screenshot of main output");
|
||||||
_scene.ToString(true).c_str());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,7 +87,7 @@ bool MacroActionScreenshot::Save(obs_data_t *obj) const
|
|||||||
_source.Save(obj);
|
_source.Save(obj);
|
||||||
obs_data_set_int(obj, "saveType", static_cast<int>(_saveType));
|
obs_data_set_int(obj, "saveType", static_cast<int>(_saveType));
|
||||||
obs_data_set_int(obj, "targetType", static_cast<int>(_targetType));
|
obs_data_set_int(obj, "targetType", static_cast<int>(_targetType));
|
||||||
obs_data_set_string(obj, "savePath", _path.c_str());
|
_path.Save(obj, "savePath");
|
||||||
obs_data_set_int(obj, "version", _version);
|
obs_data_set_int(obj, "version", _version);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -99,7 +100,7 @@ bool MacroActionScreenshot::Load(obs_data_t *obj)
|
|||||||
_saveType = static_cast<SaveType>(obs_data_get_int(obj, "saveType"));
|
_saveType = static_cast<SaveType>(obs_data_get_int(obj, "saveType"));
|
||||||
_targetType =
|
_targetType =
|
||||||
static_cast<TargetType>(obs_data_get_int(obj, "targetType"));
|
static_cast<TargetType>(obs_data_get_int(obj, "targetType"));
|
||||||
_path = obs_data_get_string(obj, "savePath");
|
_path.Load(obj, "savePath");
|
||||||
|
|
||||||
// TODO: Remove fallback for older versions
|
// TODO: Remove fallback for older versions
|
||||||
if (!obs_data_has_user_value(obj, "version")) {
|
if (!obs_data_has_user_value(obj, "version")) {
|
||||||
@@ -199,7 +200,7 @@ void MacroActionScreenshotEdit::UpdateEntryData()
|
|||||||
_scenes->SetScene(_entryData->_scene);
|
_scenes->SetScene(_entryData->_scene);
|
||||||
_saveType->setCurrentIndex(static_cast<int>(_entryData->_saveType));
|
_saveType->setCurrentIndex(static_cast<int>(_entryData->_saveType));
|
||||||
_targetType->setCurrentIndex(static_cast<int>(_entryData->_targetType));
|
_targetType->setCurrentIndex(static_cast<int>(_entryData->_targetType));
|
||||||
_savePath->SetPath(QString::fromStdString(_entryData->_path));
|
_savePath->SetPath(_entryData->_path);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +243,7 @@ void MacroActionScreenshotEdit::PathChanged(const QString &text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_path = text.toUtf8().constData();
|
_entryData->_path = text.toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionScreenshotEdit::SourceChanged(const SourceSelection &source)
|
void MacroActionScreenshotEdit::SourceChanged(const SourceSelection &source)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public:
|
|||||||
TargetType _targetType = TargetType::SOURCE;
|
TargetType _targetType = TargetType::SOURCE;
|
||||||
SceneSelection _scene;
|
SceneSelection _scene;
|
||||||
SourceSelection _source;
|
SourceSelection _source;
|
||||||
std::string _path = obs_module_text("AdvSceneSwitcher.enterPath");
|
StringVariable _path = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void FrontendScreenshot(OBSWeakSource &);
|
void FrontendScreenshot(OBSWeakSource &);
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ bool MacroActionSequence::_registered = MacroActionFactory::Register(
|
|||||||
int getNextUnpausedMacroIdx(std::vector<MacroRef> ¯os, int startIdx)
|
int getNextUnpausedMacroIdx(std::vector<MacroRef> ¯os, int startIdx)
|
||||||
{
|
{
|
||||||
for (; (int)macros.size() > startIdx; ++startIdx) {
|
for (; (int)macros.size() > startIdx; ++startIdx) {
|
||||||
if (macros[startIdx].get() && !macros[startIdx]->Paused()) {
|
auto macro = macros[startIdx].GetMacro();
|
||||||
|
if (macro && !macro->Paused()) {
|
||||||
return startIdx;
|
return startIdx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,7 +59,7 @@ bool MacroActionSequence::PerformAction()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto macro = GetNextMacro();
|
auto macro = GetNextMacro().GetMacro();
|
||||||
if (!macro.get()) {
|
if (!macro.get()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -158,8 +159,8 @@ void MacroActionSequenceEdit::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->get() == nullptr) {
|
if (!it->GetMacro()) {
|
||||||
it = _entryData->_macros.erase(it);
|
it = _entryData->_macros.erase(it);
|
||||||
} else {
|
} else {
|
||||||
++it;
|
++it;
|
||||||
@@ -250,12 +251,11 @@ void MacroActionSequenceEdit::UpdateStatusLine()
|
|||||||
QString nextMacroName =
|
QString nextMacroName =
|
||||||
obs_module_text("AdvSceneSwitcher.action.sequence.status.none");
|
obs_module_text("AdvSceneSwitcher.action.sequence.status.none");
|
||||||
if (_entryData) {
|
if (_entryData) {
|
||||||
if (_entryData->_lastSequenceMacro.get()) {
|
if (auto macro = _entryData->_lastSequenceMacro.GetMacro()) {
|
||||||
lastMacroName = QString::fromStdString(
|
lastMacroName = QString::fromStdString(macro->Name());
|
||||||
_entryData->_lastSequenceMacro->Name());
|
|
||||||
}
|
}
|
||||||
auto next = _entryData->GetNextMacro(false);
|
auto next = _entryData->GetNextMacro(false).GetMacro();
|
||||||
if (next.get()) {
|
if (next) {
|
||||||
nextMacroName = QString::fromStdString(next->Name());
|
nextMacroName = QString::fromStdString(next->Name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public:
|
|||||||
|
|
||||||
SourceSelection _source;
|
SourceSelection _source;
|
||||||
SourceSettingButton _button;
|
SourceSettingButton _button;
|
||||||
VariableResolvingString _settings = "";
|
StringVariable _settings = "";
|
||||||
SourceAction _action = SourceAction::ENABLE;
|
SourceAction _action = SourceAction::ENABLE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -9,16 +9,6 @@ bool MacroActionSudioMode::_registered = MacroActionFactory::Register(
|
|||||||
{MacroActionSudioMode::Create, MacroActionSudioModeEdit::Create,
|
{MacroActionSudioMode::Create, MacroActionSudioModeEdit::Create,
|
||||||
"AdvSceneSwitcher.action.studioMode"});
|
"AdvSceneSwitcher.action.studioMode"});
|
||||||
|
|
||||||
// TODO: Remove in future version (backwards compatibility)
|
|
||||||
static const std::string idOld1 = "scene_swap";
|
|
||||||
static const std::string idOld2 = "preview_scene";
|
|
||||||
static bool oldRegisterd1 = MacroActionFactory::Register(
|
|
||||||
idOld1, {MacroActionSudioMode::Create, MacroActionSudioModeEdit::Create,
|
|
||||||
"AdvSceneSwitcher.action.studioMode"});
|
|
||||||
static bool oldRegisterd2 = MacroActionFactory::Register(
|
|
||||||
idOld2, {MacroActionSudioMode::Create, MacroActionSudioModeEdit::Create,
|
|
||||||
"AdvSceneSwitcher.action.studioMode"});
|
|
||||||
|
|
||||||
const static std::map<StudioModeAction, std::string> actionTypes = {
|
const static std::map<StudioModeAction, std::string> actionTypes = {
|
||||||
{StudioModeAction::SWAP_SCENE,
|
{StudioModeAction::SWAP_SCENE,
|
||||||
"AdvSceneSwitcher.action.studioMode.type.swap"},
|
"AdvSceneSwitcher.action.studioMode.type.swap"},
|
||||||
@@ -98,10 +88,6 @@ bool MacroActionSudioMode::Load(obs_data_t *obj)
|
|||||||
_action =
|
_action =
|
||||||
static_cast<StudioModeAction>(obs_data_get_int(obj, "action"));
|
static_cast<StudioModeAction>(obs_data_get_int(obj, "action"));
|
||||||
_scene.Load(obj);
|
_scene.Load(obj);
|
||||||
// TODO: Remove in future version (backwards compatibility)
|
|
||||||
if (obs_data_get_string(obj, "id") == idOld2) {
|
|
||||||
_action = StudioModeAction::SET_SCENE;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,10 +22,11 @@ static std::map<TimerAction, std::string> timerActions = {
|
|||||||
|
|
||||||
bool MacroActionTimer::PerformAction()
|
bool MacroActionTimer::PerformAction()
|
||||||
{
|
{
|
||||||
if (!_macro.get()) {
|
auto macro = _macro.GetMacro();
|
||||||
|
if (!macro) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (auto c : _macro->Conditions()) {
|
for (auto c : macro->Conditions()) {
|
||||||
if (c->GetId() != "timer") {
|
if (c->GetId() != "timer") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -47,7 +48,7 @@ bool MacroActionTimer::PerformAction()
|
|||||||
break;
|
break;
|
||||||
case TimerAction::SET_TIME_REMAINING:
|
case TimerAction::SET_TIME_REMAINING:
|
||||||
timerCondition->_duration.SetTimeRemaining(
|
timerCondition->_duration.SetTimeRemaining(
|
||||||
_duration.seconds);
|
_duration.Seconds());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -58,26 +59,27 @@ bool MacroActionTimer::PerformAction()
|
|||||||
|
|
||||||
void MacroActionTimer::LogAction() const
|
void MacroActionTimer::LogAction() const
|
||||||
{
|
{
|
||||||
if (!_macro.get()) {
|
auto macro = _macro.GetMacro();
|
||||||
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (_actionType) {
|
switch (_actionType) {
|
||||||
case TimerAction::PAUSE:
|
case TimerAction::PAUSE:
|
||||||
vblog(LOG_INFO, "paused timers on \"%s\"",
|
vblog(LOG_INFO, "paused timers on \"%s\"",
|
||||||
_macro->Name().c_str());
|
macro->Name().c_str());
|
||||||
break;
|
break;
|
||||||
case TimerAction::CONTINUE:
|
case TimerAction::CONTINUE:
|
||||||
vblog(LOG_INFO, "continued timers on \"%s\"",
|
vblog(LOG_INFO, "continued timers on \"%s\"",
|
||||||
_macro->Name().c_str());
|
macro->Name().c_str());
|
||||||
break;
|
break;
|
||||||
case TimerAction::RESET:
|
case TimerAction::RESET:
|
||||||
vblog(LOG_INFO, "reset timers on \"%s\"",
|
vblog(LOG_INFO, "reset timers on \"%s\"",
|
||||||
_macro->Name().c_str());
|
macro->Name().c_str());
|
||||||
break;
|
break;
|
||||||
case TimerAction::SET_TIME_REMAINING:
|
case TimerAction::SET_TIME_REMAINING:
|
||||||
vblog(LOG_INFO,
|
vblog(LOG_INFO,
|
||||||
"set time remaining of timers on \"%s\" to \"%s\"",
|
"set time remaining of timers on \"%s\" to \"%s\"",
|
||||||
_macro->Name().c_str(), _duration.ToString().c_str());
|
macro->Name().c_str(), _duration.ToString().c_str());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -105,10 +107,7 @@ bool MacroActionTimer::Load(obs_data_t *obj)
|
|||||||
|
|
||||||
std::string MacroActionTimer::GetShortDesc() const
|
std::string MacroActionTimer::GetShortDesc() const
|
||||||
{
|
{
|
||||||
if (_macro.get()) {
|
return _macro.Name();
|
||||||
return _macro->Name();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void populateTypeSelection(QComboBox *list)
|
static inline void populateTypeSelection(QComboBox *list)
|
||||||
@@ -130,12 +129,8 @@ MacroActionTimerEdit::MacroActionTimerEdit(
|
|||||||
|
|
||||||
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,
|
QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)),
|
||||||
SLOT(MacroRemove(const QString &)));
|
this, SLOT(DurationChanged(const Duration &)));
|
||||||
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
|
||||||
SLOT(DurationChanged(double)));
|
|
||||||
QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this,
|
|
||||||
SLOT(DurationUnitChanged(DurationUnit)));
|
|
||||||
QWidget::connect(_timerAction, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_timerAction, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ActionTypeChanged(int)));
|
SLOT(ActionTypeChanged(int)));
|
||||||
|
|
||||||
@@ -160,7 +155,7 @@ void MacroActionTimerEdit::UpdateEntryData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_macros->SetCurrentMacro(_entryData->_macro.get());
|
_macros->SetCurrentMacro(_entryData->_macro);
|
||||||
_duration->SetDuration(_entryData->_duration);
|
_duration->SetDuration(_entryData->_duration);
|
||||||
_timerAction->setCurrentIndex(
|
_timerAction->setCurrentIndex(
|
||||||
static_cast<int>(_entryData->_actionType));
|
static_cast<int>(_entryData->_actionType));
|
||||||
@@ -188,24 +183,14 @@ void MacroActionTimerEdit::SetWidgetVisibility()
|
|||||||
adjustSize();
|
adjustSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTimerEdit::DurationChanged(double seconds)
|
void MacroActionTimerEdit::DurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_duration.seconds = seconds;
|
_entryData->_duration = dur;
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionTimerEdit::DurationUnitChanged(DurationUnit unit)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_duration.displayUnit = unit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTimerEdit::MacroChanged(const QString &text)
|
void MacroActionTimerEdit::MacroChanged(const QString &text)
|
||||||
@@ -215,14 +200,7 @@ void MacroActionTimerEdit::MacroChanged(const QString &text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_macro.UpdateRef(text);
|
_entryData->_macro = text;
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTimerEdit::MacroRemove(const QString &)
|
|
||||||
{
|
|
||||||
if (_entryData) {
|
|
||||||
_entryData->_macro.UpdateRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -52,9 +52,7 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void MacroChanged(const QString &text);
|
void MacroChanged(const QString &text);
|
||||||
void MacroRemove(const QString &name);
|
void DurationChanged(const Duration &value);
|
||||||
void DurationChanged(double value);
|
|
||||||
void DurationUnitChanged(DurationUnit unit);
|
|
||||||
void ActionTypeChanged(int value);
|
void ActionTypeChanged(int value);
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ void MacroActionTransition::SetSceneTransition()
|
|||||||
obs_source_release(t);
|
obs_source_release(t);
|
||||||
}
|
}
|
||||||
if (_setDuration) {
|
if (_setDuration) {
|
||||||
obs_frontend_set_transition_duration(_duration.seconds * 1000);
|
obs_frontend_set_transition_duration(_duration.Seconds() *
|
||||||
|
1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ void MacroActionTransition::SetTransitionOverride()
|
|||||||
}
|
}
|
||||||
if (_setDuration) {
|
if (_setDuration) {
|
||||||
obs_data_set_int(data, "transition_duration",
|
obs_data_set_int(data, "transition_duration",
|
||||||
_duration.seconds * 1000);
|
_duration.Milliseconds());
|
||||||
}
|
}
|
||||||
obs_data_release(data);
|
obs_data_release(data);
|
||||||
obs_source_release(scene);
|
obs_source_release(scene);
|
||||||
@@ -91,7 +92,7 @@ void MacroActionTransition::SetSourceTransition(bool show)
|
|||||||
}
|
}
|
||||||
if (_setDuration) {
|
if (_setDuration) {
|
||||||
obs_sceneitem_set_transition_duration(
|
obs_sceneitem_set_transition_duration(
|
||||||
item, show, _duration.seconds * 1000);
|
item, show, _duration.Milliseconds());
|
||||||
}
|
}
|
||||||
obs_sceneitem_release(item);
|
obs_sceneitem_release(item);
|
||||||
}
|
}
|
||||||
@@ -230,8 +231,8 @@ MacroActionTransitionEdit::MacroActionTransitionEdit(
|
|||||||
SIGNAL(TransitionChanged(const TransitionSelection &)),
|
SIGNAL(TransitionChanged(const TransitionSelection &)),
|
||||||
this,
|
this,
|
||||||
SLOT(TransitionChanged(const TransitionSelection &)));
|
SLOT(TransitionChanged(const TransitionSelection &)));
|
||||||
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)),
|
||||||
SLOT(DurationChanged(double)));
|
this, SLOT(DurationChanged(const Duration &)));
|
||||||
QWidget::connect(_setTransition, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_setTransition, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(SetTransitionChanged(int)));
|
SLOT(SetTransitionChanged(int)));
|
||||||
QWidget::connect(_setDuration, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_setDuration, SIGNAL(stateChanged(int)), this,
|
||||||
@@ -334,14 +335,14 @@ void MacroActionTransitionEdit::TransitionChanged(const TransitionSelection &t)
|
|||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTransitionEdit::DurationChanged(double seconds)
|
void MacroActionTransitionEdit::DurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_duration.seconds = seconds;
|
_entryData->_duration = dur;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTransitionEdit::SetWidgetVisibility()
|
void MacroActionTransitionEdit::SetWidgetVisibility()
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ private slots:
|
|||||||
void SetTransitionChanged(int state);
|
void SetTransitionChanged(int state);
|
||||||
void SetDurationChanged(int state);
|
void SetDurationChanged(int state);
|
||||||
void TransitionChanged(const TransitionSelection &);
|
void TransitionChanged(const TransitionSelection &);
|
||||||
void DurationChanged(double seconds);
|
void DurationChanged(const Duration &seconds);
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "macro-action-variable.hpp"
|
#include "macro-action-variable.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "macro-condition-edit.hpp"
|
#include "macro-condition-edit.hpp"
|
||||||
|
#include "math-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
const std::string MacroActionVariable::id = "variable";
|
const std::string MacroActionVariable::id = "variable";
|
||||||
@@ -25,6 +26,14 @@ static std::map<MacroActionVariable::Type, std::string> actionTypes = {
|
|||||||
"AdvSceneSwitcher.action.variable.type.setConditionValue"},
|
"AdvSceneSwitcher.action.variable.type.setConditionValue"},
|
||||||
{MacroActionVariable::Type::SET_ACTION_VALUE,
|
{MacroActionVariable::Type::SET_ACTION_VALUE,
|
||||||
"AdvSceneSwitcher.action.variable.type.setActionValue"},
|
"AdvSceneSwitcher.action.variable.type.setActionValue"},
|
||||||
|
{MacroActionVariable::Type::ROUND_TO_INT,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.roundToInt"},
|
||||||
|
{MacroActionVariable::Type::SUBSTRING,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.subString"},
|
||||||
|
{MacroActionVariable::Type::FIND_AND_REPLACE,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.findAndReplace"},
|
||||||
|
{MacroActionVariable::Type::MATH_EXPRESSION,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.mathExpression"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void apppend(Variable &var, const std::string &value)
|
static void apppend(Variable &var, const std::string &value)
|
||||||
@@ -35,14 +44,14 @@ static void apppend(Variable &var, const std::string &value)
|
|||||||
|
|
||||||
static void modifyNumValue(Variable &var, double val, const bool increment)
|
static void modifyNumValue(Variable &var, double val, const bool increment)
|
||||||
{
|
{
|
||||||
double current;
|
auto current = var.DoubleValue();
|
||||||
if (!var.DoubleValue(current)) {
|
if (!current.has_value()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (increment) {
|
if (increment) {
|
||||||
var.SetValue(current + val);
|
var.SetValue(*current + val);
|
||||||
} else {
|
} else {
|
||||||
var.SetValue(current - val);
|
var.SetValue(*current - val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,9 +60,66 @@ MacroActionVariable::~MacroActionVariable()
|
|||||||
DecrementCurrentSegmentVariableRef();
|
DecrementCurrentSegmentVariableRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionVariable::HandleIndexSubString(Variable *var)
|
||||||
|
{
|
||||||
|
const auto curValue = var->Value();
|
||||||
|
try {
|
||||||
|
if (_subStringSize == 0) {
|
||||||
|
var->SetValue(curValue.substr(_subStringStart));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var->SetValue(curValue.substr(_subStringStart, _subStringSize));
|
||||||
|
} catch (const std::out_of_range &) {
|
||||||
|
vblog(LOG_WARNING,
|
||||||
|
"invalid start index \"%d\" selected for substring of \"%s\" of variable \"%s\"",
|
||||||
|
_subStringStart, curValue.c_str(), var->Name().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariable::HandleRegexSubString(Variable *var)
|
||||||
|
{
|
||||||
|
const auto curValue = var->Value();
|
||||||
|
auto regex = _regex.GetRegularExpression(_regexPattern);
|
||||||
|
if (!regex.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = regex.globalMatch(QString::fromStdString(curValue));
|
||||||
|
for (int idx = 0; idx < _regexMatchIdx; idx++) {
|
||||||
|
if (!it.hasNext()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
it.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!it.hasNext()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto match = it.next();
|
||||||
|
var->SetValue(match.captured(0).toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariable::HandleFindAndReplace(Variable *var)
|
||||||
|
{
|
||||||
|
auto value = var->Value();
|
||||||
|
replaceAll(value, _findStr, _replaceStr);
|
||||||
|
var->SetValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariable::HandleMathExpression(Variable *var)
|
||||||
|
{
|
||||||
|
auto result = EvalMathExpression(_mathExpression);
|
||||||
|
if (std::holds_alternative<std::string>(result)) {
|
||||||
|
blog(LOG_WARNING, "%s", std::get<std::string>(result).c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var->SetValue(std::get<double>(result));
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroActionVariable::PerformAction()
|
bool MacroActionVariable::PerformAction()
|
||||||
{
|
{
|
||||||
auto var = GetVariableByName(_variableName);
|
auto var = _variable.lock();
|
||||||
if (!var) {
|
if (!var) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -66,7 +132,7 @@ bool MacroActionVariable::PerformAction()
|
|||||||
apppend(*var, _strValue);
|
apppend(*var, _strValue);
|
||||||
break;
|
break;
|
||||||
case Type::APPEND_VAR: {
|
case Type::APPEND_VAR: {
|
||||||
auto var2 = GetVariableByName(_variable2Name);
|
auto var2 = _variable2.lock();
|
||||||
if (!var2) {
|
if (!var2) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -95,6 +161,30 @@ bool MacroActionVariable::PerformAction()
|
|||||||
var->SetValue(segment->GetVariableValue());
|
var->SetValue(segment->GetVariableValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Type::ROUND_TO_INT: {
|
||||||
|
auto curValue = var->DoubleValue();
|
||||||
|
if (!curValue.has_value()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var->SetValue(std::to_string(int(std::round(*curValue))));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case Type::SUBSTRING: {
|
||||||
|
if (_regex.Enabled()) {
|
||||||
|
HandleRegexSubString(var.get());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
HandleIndexSubString(var.get());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case Type::FIND_AND_REPLACE: {
|
||||||
|
HandleFindAndReplace(var.get());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case Type::MATH_EXPRESSION: {
|
||||||
|
HandleMathExpression(var.get());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -103,24 +193,44 @@ bool MacroActionVariable::PerformAction()
|
|||||||
bool MacroActionVariable::Save(obs_data_t *obj) const
|
bool MacroActionVariable::Save(obs_data_t *obj) const
|
||||||
{
|
{
|
||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
obs_data_set_string(obj, "variableName", _variableName.c_str());
|
obs_data_set_string(obj, "variableName",
|
||||||
obs_data_set_string(obj, "variable2Name", _variable2Name.c_str());
|
GetWeakVariableName(_variable).c_str());
|
||||||
|
obs_data_set_string(obj, "variable2Name",
|
||||||
|
GetWeakVariableName(_variable2).c_str());
|
||||||
obs_data_set_string(obj, "strValue", _strValue.c_str());
|
obs_data_set_string(obj, "strValue", _strValue.c_str());
|
||||||
obs_data_set_double(obj, "numValue", _numValue);
|
obs_data_set_double(obj, "numValue", _numValue);
|
||||||
obs_data_set_int(obj, "condition", static_cast<int>(_type));
|
obs_data_set_int(obj, "condition", static_cast<int>(_type));
|
||||||
obs_data_set_int(obj, "segmentIdx", GetSegmentIndexValue());
|
obs_data_set_int(obj, "segmentIdx", GetSegmentIndexValue());
|
||||||
|
obs_data_set_int(obj, "subStringStart", _subStringStart);
|
||||||
|
obs_data_set_int(obj, "subStringSize", _subStringSize);
|
||||||
|
obs_data_set_string(obj, "regexPattern", _regexPattern.c_str());
|
||||||
|
obs_data_set_int(obj, "regexMatchIdx", _regexMatchIdx);
|
||||||
|
obs_data_set_string(obj, "findStr", _findStr.c_str());
|
||||||
|
obs_data_set_string(obj, "replaceStr", _replaceStr.c_str());
|
||||||
|
_regex.Save(obj);
|
||||||
|
_mathExpression.Save(obj, "mathExpression");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroActionVariable::Load(obs_data_t *obj)
|
bool MacroActionVariable::Load(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
_variableName = obs_data_get_string(obj, "variableName");
|
_variable =
|
||||||
_variable2Name = obs_data_get_string(obj, "variable2Name");
|
GetWeakVariableByName(obs_data_get_string(obj, "variableName"));
|
||||||
|
_variable2 = GetWeakVariableByName(
|
||||||
|
obs_data_get_string(obj, "variable2Name"));
|
||||||
_strValue = obs_data_get_string(obj, "strValue");
|
_strValue = obs_data_get_string(obj, "strValue");
|
||||||
_numValue = obs_data_get_double(obj, "numValue");
|
_numValue = obs_data_get_double(obj, "numValue");
|
||||||
_type = static_cast<Type>(obs_data_get_int(obj, "condition"));
|
_type = static_cast<Type>(obs_data_get_int(obj, "condition"));
|
||||||
_segmentIdxLoadValue = obs_data_get_int(obj, "segmentIdx");
|
_segmentIdxLoadValue = obs_data_get_int(obj, "segmentIdx");
|
||||||
|
_subStringStart = obs_data_get_int(obj, "subStringStart");
|
||||||
|
_subStringSize = obs_data_get_int(obj, "subStringSize");
|
||||||
|
_regex.Load(obj);
|
||||||
|
_regexPattern = obs_data_get_string(obj, "regexPattern");
|
||||||
|
_regexMatchIdx = obs_data_get_int(obj, "regexMatchIdx");
|
||||||
|
_findStr = obs_data_get_string(obj, "findStr");
|
||||||
|
_replaceStr = obs_data_get_string(obj, "replaceStr");
|
||||||
|
_mathExpression.Load(obj, "mathExpression");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +242,7 @@ bool MacroActionVariable::PostLoad()
|
|||||||
|
|
||||||
std::string MacroActionVariable::GetShortDesc() const
|
std::string MacroActionVariable::GetShortDesc() const
|
||||||
{
|
{
|
||||||
return _variableName;
|
return GetWeakVariableName(_variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariable::SetSegmentIndexValue(int value)
|
void MacroActionVariable::SetSegmentIndexValue(int value)
|
||||||
@@ -152,11 +262,11 @@ void MacroActionVariable::SetSegmentIndexValue(int value)
|
|||||||
|
|
||||||
std::shared_ptr<MacroSegment> segment;
|
std::shared_ptr<MacroSegment> segment;
|
||||||
if (_type == Type::SET_CONDITION_VALUE) {
|
if (_type == Type::SET_CONDITION_VALUE) {
|
||||||
if (value < m->Conditions().size()) {
|
if (value < (int)m->Conditions().size()) {
|
||||||
segment = m->Conditions().at(value);
|
segment = m->Conditions().at(value);
|
||||||
}
|
}
|
||||||
} else if (_type == Type::SET_ACTION_VALUE) {
|
} else if (_type == Type::SET_ACTION_VALUE) {
|
||||||
if (value < m->Actions().size()) {
|
if (value < (int)m->Actions().size()) {
|
||||||
segment = m->Actions().at(value);
|
segment = m->Actions().at(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -225,7 +335,20 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_numValue(new QDoubleSpinBox()),
|
_numValue(new QDoubleSpinBox()),
|
||||||
_segmentIdx(new QSpinBox()),
|
_segmentIdx(new QSpinBox()),
|
||||||
_segmentValueStatus(new QLabel()),
|
_segmentValueStatus(new QLabel()),
|
||||||
_segmentValue(new ResizingPlainTextEdit(this, 10, 1, 1))
|
_segmentValue(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||||
|
_substringLayout(new QVBoxLayout()),
|
||||||
|
_subStringIndexEntryLayout(new QHBoxLayout()),
|
||||||
|
_subStringRegexEntryLayout(new QHBoxLayout()),
|
||||||
|
_subStringStart(new QSpinBox()),
|
||||||
|
_subStringSize(new QSpinBox()),
|
||||||
|
_regex(new RegexConfigWidget(parent)),
|
||||||
|
_regexPattern(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||||
|
_regexMatchIdx(new QSpinBox()),
|
||||||
|
_findReplaceLayout(new QHBoxLayout()),
|
||||||
|
_findStr(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||||
|
_replaceStr(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||||
|
_mathExpression(new VariableLineEdit(this)),
|
||||||
|
_mathExpressionResult(new QLabel())
|
||||||
{
|
{
|
||||||
_numValue->setMinimum(-9999999999);
|
_numValue->setMinimum(-9999999999);
|
||||||
_numValue->setMaximum(9999999999);
|
_numValue->setMaximum(9999999999);
|
||||||
@@ -233,6 +356,17 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_segmentIdx->setMaximum(99);
|
_segmentIdx->setMaximum(99);
|
||||||
_segmentIdx->setSpecialValueText("-");
|
_segmentIdx->setSpecialValueText("-");
|
||||||
_segmentValue->setReadOnly(true);
|
_segmentValue->setReadOnly(true);
|
||||||
|
_subStringStart->setMinimum(1);
|
||||||
|
_subStringStart->setMaximum(99999);
|
||||||
|
_subStringStart->setSpecialValueText(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.subString.begin"));
|
||||||
|
_subStringSize->setMinimum(0);
|
||||||
|
_subStringSize->setMaximum(99999);
|
||||||
|
_subStringSize->setSpecialValueText(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.subString.all"));
|
||||||
|
_regexMatchIdx->setMinimum(1);
|
||||||
|
_regexMatchIdx->setMaximum(999);
|
||||||
|
_regexMatchIdx->setSuffix(".");
|
||||||
populateTypeSelection(_actions);
|
populateTypeSelection(_actions);
|
||||||
|
|
||||||
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
||||||
@@ -249,6 +383,22 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
SLOT(SegmentIndexChanged(int)));
|
SLOT(SegmentIndexChanged(int)));
|
||||||
QWidget::connect(window(), SIGNAL(MacroSegmentOrderChanged()), this,
|
QWidget::connect(window(), SIGNAL(MacroSegmentOrderChanged()), this,
|
||||||
SLOT(MacroSegmentOrderChanged()));
|
SLOT(MacroSegmentOrderChanged()));
|
||||||
|
QWidget::connect(_subStringStart, SIGNAL(valueChanged(int)), this,
|
||||||
|
SLOT(SubStringStartChanged(int)));
|
||||||
|
QWidget::connect(_subStringSize, SIGNAL(valueChanged(int)), this,
|
||||||
|
SLOT(SubStringSizeChanged(int)));
|
||||||
|
QWidget::connect(_regex, SIGNAL(RegexConfigChanged(RegexConfig)), this,
|
||||||
|
SLOT(RegexChanged(RegexConfig)));
|
||||||
|
QWidget::connect(_regexPattern, SIGNAL(textChanged()), this,
|
||||||
|
SLOT(RegexPatternChanged()));
|
||||||
|
QWidget::connect(_regexMatchIdx, SIGNAL(valueChanged(int)), this,
|
||||||
|
SLOT(RegexMatchIdxChanged(int)));
|
||||||
|
QWidget::connect(_findStr, SIGNAL(textChanged()), this,
|
||||||
|
SLOT(FindStrValueChanged()));
|
||||||
|
QWidget::connect(_replaceStr, SIGNAL(textChanged()), this,
|
||||||
|
SLOT(ReplaceStrValueChanged()));
|
||||||
|
QWidget::connect(_mathExpression, SIGNAL(editingFinished()), this,
|
||||||
|
SLOT(MathExpressionChanged()));
|
||||||
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{variables}}", _variables},
|
{"{{variables}}", _variables},
|
||||||
@@ -257,15 +407,48 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
{"{{strValue}}", _strValue},
|
{"{{strValue}}", _strValue},
|
||||||
{"{{numValue}}", _numValue},
|
{"{{numValue}}", _numValue},
|
||||||
{"{{segmentIndex}}", _segmentIdx},
|
{"{{segmentIndex}}", _segmentIdx},
|
||||||
|
{"{{subStringStart}}", _subStringStart},
|
||||||
|
{"{{subStringSize}}", _subStringSize},
|
||||||
|
{"{{regexMatchIdx}}", _regexMatchIdx},
|
||||||
|
{"{{findStr}}", _findStr},
|
||||||
|
{"{{replaceStr}}", _replaceStr},
|
||||||
|
{"{{mathExpression}}", _mathExpression},
|
||||||
};
|
};
|
||||||
auto entryLayout = new QHBoxLayout;
|
auto entryLayout = new QHBoxLayout;
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.variable.entry"),
|
placeWidgets(obs_module_text("AdvSceneSwitcher.action.variable.entry"),
|
||||||
entryLayout, widgetPlaceholders);
|
entryLayout, widgetPlaceholders);
|
||||||
|
|
||||||
|
placeWidgets(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.entry.substringIndex"),
|
||||||
|
_subStringIndexEntryLayout, widgetPlaceholders);
|
||||||
|
|
||||||
|
placeWidgets(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.entry.substringRegex"),
|
||||||
|
_subStringRegexEntryLayout, widgetPlaceholders);
|
||||||
|
|
||||||
|
placeWidgets(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.entry.findAndReplace"),
|
||||||
|
_findReplaceLayout, widgetPlaceholders, false);
|
||||||
|
|
||||||
|
auto regexConfigLayout = new QHBoxLayout;
|
||||||
|
regexConfigLayout->addWidget(_regex);
|
||||||
|
regexConfigLayout->addStretch();
|
||||||
|
|
||||||
|
_substringLayout->addLayout(_subStringIndexEntryLayout);
|
||||||
|
_substringLayout->addLayout(_subStringRegexEntryLayout);
|
||||||
|
_substringLayout->addWidget(_regexPattern);
|
||||||
|
_substringLayout->addLayout(regexConfigLayout);
|
||||||
|
|
||||||
auto layout = new QVBoxLayout;
|
auto layout = new QVBoxLayout;
|
||||||
layout->addLayout(entryLayout);
|
layout->addLayout(entryLayout);
|
||||||
|
layout->addLayout(_substringLayout);
|
||||||
layout->addWidget(_segmentValueStatus);
|
layout->addWidget(_segmentValueStatus);
|
||||||
layout->addWidget(_segmentValue);
|
layout->addWidget(_segmentValue);
|
||||||
|
layout->addLayout(_findReplaceLayout);
|
||||||
|
layout->addWidget(_mathExpressionResult);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
@@ -284,12 +467,22 @@ void MacroActionVariableEdit::UpdateEntryData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_variables->SetVariable(_entryData->_variableName);
|
_variables->SetVariable(_entryData->_variable);
|
||||||
_variables2->SetVariable(_entryData->_variable2Name);
|
_variables2->SetVariable(_entryData->_variable2);
|
||||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_type));
|
_actions->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||||
_strValue->setPlainText(QString::fromStdString(_entryData->_strValue));
|
_strValue->setPlainText(QString::fromStdString(_entryData->_strValue));
|
||||||
_numValue->setValue(_entryData->_numValue);
|
_numValue->setValue(_entryData->_numValue);
|
||||||
_segmentIdx->setValue(_entryData->GetSegmentIndexValue() + 1);
|
_segmentIdx->setValue(_entryData->GetSegmentIndexValue() + 1);
|
||||||
|
_subStringStart->setValue(_entryData->_subStringStart + 1);
|
||||||
|
_subStringSize->setValue(_entryData->_subStringSize);
|
||||||
|
_regex->SetRegexConfig(_entryData->_regex);
|
||||||
|
_regexPattern->setPlainText(
|
||||||
|
QString::fromStdString(_entryData->_regexPattern));
|
||||||
|
_regexMatchIdx->setValue(_entryData->_regexMatchIdx + 1);
|
||||||
|
_findStr->setPlainText(QString::fromStdString(_entryData->_findStr));
|
||||||
|
_replaceStr->setPlainText(
|
||||||
|
QString::fromStdString(_entryData->_replaceStr));
|
||||||
|
_mathExpression->setText(_entryData->_mathExpression);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,7 +493,7 @@ void MacroActionVariableEdit::VariableChanged(const QString &text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_variableName = text.toStdString();
|
_entryData->_variable = GetWeakVariableByQString(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::Variable2Changed(const QString &text)
|
void MacroActionVariableEdit::Variable2Changed(const QString &text)
|
||||||
@@ -310,7 +503,7 @@ void MacroActionVariableEdit::Variable2Changed(const QString &text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_variable2Name = text.toStdString();
|
_entryData->_variable2 = GetWeakVariableByQString(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::ActionChanged(int value)
|
void MacroActionVariableEdit::ActionChanged(int value)
|
||||||
@@ -339,6 +532,7 @@ void MacroActionVariableEdit::StrValueChanged()
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_strValue = _strValue->toPlainText().toStdString();
|
_entryData->_strValue = _strValue->toPlainText().toStdString();
|
||||||
adjustSize();
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::NumValueChanged(double val)
|
void MacroActionVariableEdit::NumValueChanged(double val)
|
||||||
@@ -399,13 +593,13 @@ void MacroActionVariableEdit::UpdateSegmentVariableValue()
|
|||||||
std::shared_ptr<MacroSegment> segment;
|
std::shared_ptr<MacroSegment> segment;
|
||||||
if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE) {
|
if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE) {
|
||||||
const auto &actions = m->Actions();
|
const auto &actions = m->Actions();
|
||||||
if (index < actions.size()) {
|
if (index < (int)actions.size()) {
|
||||||
segment = actions.at(index);
|
segment = actions.at(index);
|
||||||
}
|
}
|
||||||
} else if (_entryData->_type ==
|
} else if (_entryData->_type ==
|
||||||
MacroActionVariable::Type::SET_CONDITION_VALUE) {
|
MacroActionVariable::Type::SET_CONDITION_VALUE) {
|
||||||
const auto &conditions = m->Conditions();
|
const auto &conditions = m->Conditions();
|
||||||
if (index < conditions.size()) {
|
if (index < (int)conditions.size()) {
|
||||||
segment = conditions.at(index);
|
segment = conditions.at(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -454,6 +648,106 @@ void MacroActionVariableEdit::MacroSegmentOrderChanged()
|
|||||||
_segmentIdx->setValue(_entryData->GetSegmentIndexValue() + 1);
|
_segmentIdx->setValue(_entryData->GetSegmentIndexValue() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::SubStringStartChanged(int val)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_subStringStart = val - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::SubStringSizeChanged(int val)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_subStringSize = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::RegexChanged(RegexConfig conf)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_regex = conf;
|
||||||
|
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::RegexPatternChanged()
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_regexPattern = _regexPattern->toPlainText().toStdString();
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::RegexMatchIdxChanged(int val)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_regexMatchIdx = val - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::FindStrValueChanged()
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_findStr = _findStr->toPlainText().toStdString();
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::ReplaceStrValueChanged()
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_replaceStr = _replaceStr->toPlainText().toStdString();
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::MathExpressionChanged()
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_mathExpression = _mathExpression->text().toStdString();
|
||||||
|
|
||||||
|
// In case of invalid expression display an error
|
||||||
|
auto result = EvalMathExpression(_entryData->_mathExpression);
|
||||||
|
auto hasError = std::holds_alternative<std::string>(result);
|
||||||
|
if (hasError) {
|
||||||
|
_mathExpressionResult->setText(
|
||||||
|
QString::fromStdString(std::get<std::string>(result)));
|
||||||
|
}
|
||||||
|
_mathExpressionResult->setVisible(hasError);
|
||||||
|
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::MarkSelectedSegment()
|
void MacroActionVariableEdit::MarkSelectedSegment()
|
||||||
{
|
{
|
||||||
if (switcher->disableHints) {
|
if (switcher->disableHints) {
|
||||||
@@ -472,14 +766,14 @@ void MacroActionVariableEdit::MarkSelectedSegment()
|
|||||||
|
|
||||||
if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE) {
|
if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE) {
|
||||||
const auto &actions = m->Actions();
|
const auto &actions = m->Actions();
|
||||||
if (index >= actions.size()) {
|
if (index >= (int)actions.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AdvSceneSwitcher::window->HighlightAction(
|
AdvSceneSwitcher::window->HighlightAction(
|
||||||
index, QColor(Qt::lightGray));
|
index, QColor(Qt::lightGray));
|
||||||
} else {
|
} else {
|
||||||
const auto &conditions = m->Conditions();
|
const auto &conditions = m->Conditions();
|
||||||
if (index >= conditions.size()) {
|
if (index >= (int)conditions.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AdvSceneSwitcher::window->HighlightCondition(
|
AdvSceneSwitcher::window->HighlightCondition(
|
||||||
@@ -520,6 +814,21 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
MacroActionVariable::Type::SET_ACTION_VALUE ||
|
MacroActionVariable::Type::SET_ACTION_VALUE ||
|
||||||
_entryData->_type ==
|
_entryData->_type ==
|
||||||
MacroActionVariable::Type::SET_CONDITION_VALUE);
|
MacroActionVariable::Type::SET_CONDITION_VALUE);
|
||||||
|
setLayoutVisible(_substringLayout,
|
||||||
|
_entryData->_type ==
|
||||||
|
MacroActionVariable::Type::SUBSTRING);
|
||||||
|
if (_entryData->_type == MacroActionVariable::Type::SUBSTRING) {
|
||||||
|
bool showRegex = _entryData->_regex.Enabled();
|
||||||
|
setLayoutVisible(_subStringIndexEntryLayout, !showRegex);
|
||||||
|
setLayoutVisible(_subStringRegexEntryLayout, showRegex);
|
||||||
|
_regexPattern->setVisible(showRegex);
|
||||||
|
}
|
||||||
|
setLayoutVisible(_findReplaceLayout,
|
||||||
|
_entryData->_type ==
|
||||||
|
MacroActionVariable::Type::FIND_AND_REPLACE);
|
||||||
|
_mathExpression->setVisible(_entryData->_type ==
|
||||||
|
MacroActionVariable::Type::MATH_EXPRESSION);
|
||||||
|
_mathExpressionResult->hide();
|
||||||
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "regex-config.hpp"
|
||||||
#include "resizing-text-edit.hpp"
|
#include "resizing-text-edit.hpp"
|
||||||
#include "variable.hpp"
|
#include "variable-line-edit.hpp"
|
||||||
|
|
||||||
class MacroActionVariable : public MacroAction {
|
class MacroActionVariable : public MacroAction {
|
||||||
public:
|
public:
|
||||||
@@ -28,16 +29,35 @@ public:
|
|||||||
DECREMENT,
|
DECREMENT,
|
||||||
SET_CONDITION_VALUE,
|
SET_CONDITION_VALUE,
|
||||||
SET_ACTION_VALUE,
|
SET_ACTION_VALUE,
|
||||||
|
ROUND_TO_INT,
|
||||||
|
SUBSTRING,
|
||||||
|
FIND_AND_REPLACE,
|
||||||
|
MATH_EXPRESSION,
|
||||||
};
|
};
|
||||||
|
|
||||||
Type _type = Type::SET_FIXED_VALUE;
|
Type _type = Type::SET_FIXED_VALUE;
|
||||||
std::string _variableName = "";
|
std::weak_ptr<Variable> _variable;
|
||||||
std::string _variable2Name = "";
|
std::weak_ptr<Variable> _variable2;
|
||||||
std::string _strValue = "";
|
std::string _strValue = "";
|
||||||
double _numValue = 0;
|
double _numValue = 0;
|
||||||
|
int _subStringStart = 0;
|
||||||
|
int _subStringSize = 0;
|
||||||
|
RegexConfig _regex = RegexConfig::PartialMatchRegexConfig();
|
||||||
|
std::string _regexPattern = ".*";
|
||||||
|
int _regexMatchIdx = 0;
|
||||||
|
std::string _findStr = obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.findAndReplace.find");
|
||||||
|
std::string _replaceStr = obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.findAndReplace.replace");
|
||||||
|
StringVariable _mathExpression = obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.mathExpression.example");
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DecrementCurrentSegmentVariableRef();
|
void DecrementCurrentSegmentVariableRef();
|
||||||
|
void HandleIndexSubString(Variable *);
|
||||||
|
void HandleRegexSubString(Variable *);
|
||||||
|
void HandleFindAndReplace(Variable *);
|
||||||
|
void HandleMathExpression(Variable *);
|
||||||
|
|
||||||
std::weak_ptr<MacroSegment> _macroSegment;
|
std::weak_ptr<MacroSegment> _macroSegment;
|
||||||
int _segmentIdxLoadValue = -1;
|
int _segmentIdxLoadValue = -1;
|
||||||
@@ -70,6 +90,14 @@ private slots:
|
|||||||
void SegmentIndexChanged(int val);
|
void SegmentIndexChanged(int val);
|
||||||
void UpdateSegmentVariableValue();
|
void UpdateSegmentVariableValue();
|
||||||
void MacroSegmentOrderChanged();
|
void MacroSegmentOrderChanged();
|
||||||
|
void SubStringStartChanged(int val);
|
||||||
|
void SubStringSizeChanged(int val);
|
||||||
|
void RegexChanged(RegexConfig conf);
|
||||||
|
void RegexPatternChanged();
|
||||||
|
void RegexMatchIdxChanged(int val);
|
||||||
|
void FindStrValueChanged();
|
||||||
|
void ReplaceStrValueChanged();
|
||||||
|
void MathExpressionChanged();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
@@ -79,10 +107,23 @@ protected:
|
|||||||
VariableSelection *_variables2;
|
VariableSelection *_variables2;
|
||||||
QComboBox *_actions;
|
QComboBox *_actions;
|
||||||
ResizingPlainTextEdit *_strValue;
|
ResizingPlainTextEdit *_strValue;
|
||||||
QSpinBox *_segmentIdx;
|
|
||||||
QDoubleSpinBox *_numValue;
|
QDoubleSpinBox *_numValue;
|
||||||
|
QSpinBox *_segmentIdx;
|
||||||
QLabel *_segmentValueStatus;
|
QLabel *_segmentValueStatus;
|
||||||
ResizingPlainTextEdit *_segmentValue;
|
ResizingPlainTextEdit *_segmentValue;
|
||||||
|
QVBoxLayout *_substringLayout;
|
||||||
|
QHBoxLayout *_subStringIndexEntryLayout;
|
||||||
|
QHBoxLayout *_subStringRegexEntryLayout;
|
||||||
|
QSpinBox *_subStringStart;
|
||||||
|
QSpinBox *_subStringSize;
|
||||||
|
RegexConfigWidget *_regex;
|
||||||
|
ResizingPlainTextEdit *_regexPattern;
|
||||||
|
QSpinBox *_regexMatchIdx;
|
||||||
|
QHBoxLayout *_findReplaceLayout;
|
||||||
|
ResizingPlainTextEdit *_findStr;
|
||||||
|
ResizingPlainTextEdit *_replaceStr;
|
||||||
|
VariableLineEdit *_mathExpression;
|
||||||
|
QLabel *_mathExpressionResult;
|
||||||
std::shared_ptr<MacroActionVariable> _entryData;
|
std::shared_ptr<MacroActionVariable> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -19,18 +19,29 @@ static std::map<WaitType, std::string> waitTypes = {
|
|||||||
static std::random_device rd;
|
static std::random_device rd;
|
||||||
static std::default_random_engine re(rd());
|
static std::default_random_engine re(rd());
|
||||||
|
|
||||||
|
static void waitHelper(std::unique_lock<std::mutex> *lock, Macro *macro,
|
||||||
|
std::chrono::high_resolution_clock::time_point &time)
|
||||||
|
{
|
||||||
|
while (!switcher->abortMacroWait && !macro->GetStop()) {
|
||||||
|
if (switcher->macroWaitCv.wait_until(*lock, time) ==
|
||||||
|
std::cv_status::timeout) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroActionWait::PerformAction()
|
bool MacroActionWait::PerformAction()
|
||||||
{
|
{
|
||||||
double sleepDuration;
|
double sleepDuration;
|
||||||
if (_waitType == WaitType::FIXED) {
|
if (_waitType == WaitType::FIXED) {
|
||||||
sleepDuration = _duration.seconds;
|
sleepDuration = _duration.Seconds();
|
||||||
} else {
|
} else {
|
||||||
double min = (_duration.seconds < _duration2.seconds)
|
double min = (_duration.Seconds() < _duration2.Seconds())
|
||||||
? _duration.seconds
|
? _duration.Seconds()
|
||||||
: _duration2.seconds;
|
: _duration2.Seconds();
|
||||||
double max = (_duration.seconds < _duration2.seconds)
|
double max = (_duration.Seconds() < _duration2.Seconds())
|
||||||
? _duration2.seconds
|
? _duration2.Seconds()
|
||||||
: _duration.seconds;
|
: _duration.Seconds();
|
||||||
std::uniform_real_distribution<double> unif(min, max);
|
std::uniform_real_distribution<double> unif(min, max);
|
||||||
sleepDuration = unif(re);
|
sleepDuration = unif(re);
|
||||||
}
|
}
|
||||||
@@ -39,15 +50,10 @@ bool MacroActionWait::PerformAction()
|
|||||||
|
|
||||||
auto time = std::chrono::high_resolution_clock::now() +
|
auto time = std::chrono::high_resolution_clock::now() +
|
||||||
std::chrono::milliseconds((int)(sleepDuration * 1000));
|
std::chrono::milliseconds((int)(sleepDuration * 1000));
|
||||||
auto macro = GetMacro();
|
|
||||||
switcher->abortMacroWait = false;
|
switcher->abortMacroWait = false;
|
||||||
std::unique_lock<std::mutex> lock(switcher->m);
|
std::unique_lock<std::mutex> lock(switcher->m);
|
||||||
while (!switcher->abortMacroWait && !macro->GetStop()) {
|
waitHelper(&lock, GetMacro(), time);
|
||||||
if (switcher->macroWaitCv.wait_until(lock, time) ==
|
|
||||||
std::cv_status::timeout) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return !switcher->abortMacroWait;
|
return !switcher->abortMacroWait;
|
||||||
}
|
}
|
||||||
@@ -56,8 +62,9 @@ bool MacroActionWait::Save(obs_data_t *obj) const
|
|||||||
{
|
{
|
||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
_duration.Save(obj);
|
_duration.Save(obj);
|
||||||
_duration2.Save(obj, "seconds2", "displayUnit2");
|
_duration2.Save(obj, "duration2");
|
||||||
obs_data_set_int(obj, "waitType", static_cast<int>(_waitType));
|
obs_data_set_int(obj, "waitType", static_cast<int>(_waitType));
|
||||||
|
obs_data_set_int(obj, "version", 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +72,14 @@ bool MacroActionWait::Load(obs_data_t *obj)
|
|||||||
{
|
{
|
||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
_duration.Load(obj);
|
_duration.Load(obj);
|
||||||
_duration2.Load(obj, "seconds2", "displayUnit2");
|
// TODO: remove this fallback
|
||||||
|
if (obs_data_get_int(obj, "version") == 1) {
|
||||||
|
_duration2.Load(obj, "duration2");
|
||||||
|
} else {
|
||||||
|
_duration2.Load(obj, "seconds2");
|
||||||
|
_duration2.SetUnit(static_cast<Duration::Unit>(
|
||||||
|
obs_data_get_int(obj, "displayUnit2")));
|
||||||
|
}
|
||||||
_waitType = static_cast<WaitType>(obs_data_get_int(obj, "waitType"));
|
_waitType = static_cast<WaitType>(obs_data_get_int(obj, "waitType"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -87,14 +101,10 @@ MacroActionWaitEdit::MacroActionWaitEdit(
|
|||||||
|
|
||||||
populateTypeSelection(_waitType);
|
populateTypeSelection(_waitType);
|
||||||
|
|
||||||
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,
|
QWidget::connect(_duration2, SIGNAL(DurationChanged(const Duration &)),
|
||||||
SLOT(DurationUnitChanged(DurationUnit)));
|
this, SLOT(Duration2Changed(const Duration &)));
|
||||||
QWidget::connect(_duration2, SIGNAL(DurationChanged(double)), this,
|
|
||||||
SLOT(Duration2Changed(double)));
|
|
||||||
QWidget::connect(_duration2, SIGNAL(UnitChanged(DurationUnit)), this,
|
|
||||||
SLOT(Duration2UnitChanged(DurationUnit)));
|
|
||||||
QWidget::connect(_waitType, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_waitType, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(TypeChanged(int)));
|
SLOT(TypeChanged(int)));
|
||||||
|
|
||||||
@@ -174,42 +184,22 @@ void MacroActionWaitEdit::TypeChanged(int value)
|
|||||||
_entryData->_waitType = type;
|
_entryData->_waitType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionWaitEdit::DurationChanged(double seconds)
|
void MacroActionWaitEdit::DurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_duration.seconds = seconds;
|
_entryData->_duration = dur;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionWaitEdit::DurationUnitChanged(DurationUnit unit)
|
void MacroActionWaitEdit::Duration2Changed(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_duration.displayUnit = unit;
|
_entryData->_duration2 = dur;
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionWaitEdit::Duration2Changed(double seconds)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_duration2.seconds = seconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionWaitEdit::Duration2UnitChanged(DurationUnit unit)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_duration2.displayUnit = unit;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,10 +49,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void DurationChanged(double value);
|
void DurationChanged(const Duration &value);
|
||||||
void DurationUnitChanged(DurationUnit unit);
|
void Duration2Changed(const Duration &value);
|
||||||
void Duration2Changed(double value);
|
|
||||||
void Duration2UnitChanged(DurationUnit unit);
|
|
||||||
void TypeChanged(int value);
|
void TypeChanged(int value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ static std::map<MacroActionWebsocket::Type, std::string> actionTypes = {
|
|||||||
|
|
||||||
void MacroActionWebsocket::SendRequest()
|
void MacroActionWebsocket::SendRequest()
|
||||||
{
|
{
|
||||||
auto connection = GetConnectionByName(_connection);
|
auto connection = _connection.lock();
|
||||||
if (!connection) {
|
if (!connection) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ void MacroActionWebsocket::LogAction() const
|
|||||||
switch (_type) {
|
switch (_type) {
|
||||||
case MacroActionWebsocket::Type::REQUEST:
|
case MacroActionWebsocket::Type::REQUEST:
|
||||||
vblog(LOG_INFO, "sent msg \"%s\" via \"%s\"", _message.c_str(),
|
vblog(LOG_INFO, "sent msg \"%s\" via \"%s\"", _message.c_str(),
|
||||||
_connection.c_str());
|
GetWeakConnectionName(_connection).c_str());
|
||||||
break;
|
break;
|
||||||
case MacroActionWebsocket::Type::EVENT:
|
case MacroActionWebsocket::Type::EVENT:
|
||||||
vblog(LOG_INFO, "sent event \"%s\" to connected clients",
|
vblog(LOG_INFO, "sent event \"%s\" to connected clients",
|
||||||
@@ -62,7 +62,8 @@ bool MacroActionWebsocket::Save(obs_data_t *obj) const
|
|||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
||||||
_message.Save(obj, "message");
|
_message.Save(obj, "message");
|
||||||
obs_data_set_string(obj, "connection", _connection.c_str());
|
obs_data_set_string(obj, "connection",
|
||||||
|
GetWeakConnectionName(_connection).c_str());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,14 +72,15 @@ bool MacroActionWebsocket::Load(obs_data_t *obj)
|
|||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
_type = static_cast<Type>(obs_data_get_int(obj, "type"));
|
_type = static_cast<Type>(obs_data_get_int(obj, "type"));
|
||||||
_message.Load(obj, "message");
|
_message.Load(obj, "message");
|
||||||
_connection = obs_data_get_string(obj, "connection");
|
_connection =
|
||||||
|
GetWeakConnectionByName(obs_data_get_string(obj, "connection"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MacroActionWebsocket::GetShortDesc() const
|
std::string MacroActionWebsocket::GetShortDesc() const
|
||||||
{
|
{
|
||||||
if (_type == Type::REQUEST) {
|
if (_type == Type::REQUEST) {
|
||||||
return _connection;
|
return GetWeakConnectionName(_connection);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -206,6 +208,6 @@ void MacroActionWebsocketEdit::ConnectionSelectionChanged(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_connection = connection.toStdString();
|
_entryData->_connection = GetWeakConnectionByQString(connection);
|
||||||
emit(HeaderInfoChanged(connection));
|
emit(HeaderInfoChanged(connection));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,9 +28,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Type _type = Type::REQUEST;
|
Type _type = Type::REQUEST;
|
||||||
VariableResolvingString _message =
|
StringVariable _message = obs_module_text("AdvSceneSwitcher.enterText");
|
||||||
obs_module_text("AdvSceneSwitcher.enterText");
|
std::weak_ptr<Connection> _connection;
|
||||||
std::string _connection;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SendRequest();
|
void SendRequest();
|
||||||
|
|||||||
@@ -29,9 +29,10 @@ MacroRefAction::MacroRefAction(Macro *m, bool supportsVariableValue)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroRefAction::ResolveMacroRef()
|
bool MacroRefAction::PostLoad()
|
||||||
{
|
{
|
||||||
_macro.UpdateRef();
|
_macro.PostLoad();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiMacroRefAction::MultiMacroRefAction(Macro *m, bool supportsVariableValue)
|
MultiMacroRefAction::MultiMacroRefAction(Macro *m, bool supportsVariableValue)
|
||||||
@@ -39,9 +40,10 @@ MultiMacroRefAction::MultiMacroRefAction(Macro *m, bool supportsVariableValue)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiMacroRefAction::ResolveMacroRef()
|
bool MultiMacroRefAction::PostLoad()
|
||||||
{
|
{
|
||||||
for (auto &m : _macros) {
|
for (auto ¯o : _macros) {
|
||||||
m.UpdateRef();
|
macro.PostLoad();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,15 @@ public:
|
|||||||
class MacroRefAction : virtual public MacroAction {
|
class MacroRefAction : virtual public MacroAction {
|
||||||
public:
|
public:
|
||||||
MacroRefAction(Macro *m, bool supportsVariableValue = false);
|
MacroRefAction(Macro *m, bool supportsVariableValue = false);
|
||||||
void ResolveMacroRef();
|
bool PostLoad() override;
|
||||||
|
|
||||||
MacroRef _macro;
|
MacroRef _macro;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MultiMacroRefAction : virtual public MacroAction {
|
class MultiMacroRefAction : virtual public MacroAction {
|
||||||
public:
|
public:
|
||||||
MultiMacroRefAction(Macro *m, bool supportsVariableValue = false);
|
MultiMacroRefAction(Macro *m, bool supportsVariableValue = false);
|
||||||
void ResolveMacroRef();
|
bool PostLoad() override;
|
||||||
|
|
||||||
std::vector<MacroRef> _macros;
|
std::vector<MacroRef> _macros;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -205,15 +205,16 @@ bool MacroConditionAudio::Save(obs_data_t *obj) const
|
|||||||
{
|
{
|
||||||
MacroCondition::Save(obj);
|
MacroCondition::Save(obj);
|
||||||
_audioSource.Save(obj, "audioSource");
|
_audioSource.Save(obj, "audioSource");
|
||||||
obs_data_set_int(obj, "volume", _volume);
|
|
||||||
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);
|
_volume.Save(obj, "volume");
|
||||||
|
_syncOffset.Save(obj, "syncOffset");
|
||||||
|
_balance.Save(obj, "balance");
|
||||||
obs_data_set_int(obj, "checkType", static_cast<int>(_checkType));
|
obs_data_set_int(obj, "checkType", static_cast<int>(_checkType));
|
||||||
obs_data_set_int(obj, "outputCondition",
|
obs_data_set_int(obj, "outputCondition",
|
||||||
static_cast<int>(_outputCondition));
|
static_cast<int>(_outputCondition));
|
||||||
obs_data_set_int(obj, "volumeCondition",
|
obs_data_set_int(obj, "volumeCondition",
|
||||||
static_cast<int>(_volumeCondition));
|
static_cast<int>(_volumeCondition));
|
||||||
|
obs_data_set_int(obj, "version", 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,11 +239,17 @@ bool MacroConditionAudio::Load(obs_data_t *obj)
|
|||||||
{
|
{
|
||||||
MacroCondition::Load(obj);
|
MacroCondition::Load(obj);
|
||||||
_audioSource.Load(obj, "audioSource");
|
_audioSource.Load(obj, "audioSource");
|
||||||
_volume = obs_data_get_int(obj, "volume");
|
|
||||||
_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");
|
||||||
|
_balance = obs_data_get_double(obj, "balance");
|
||||||
|
} else {
|
||||||
|
_volume.Load(obj, "volume");
|
||||||
|
_syncOffset.Load(obj, "syncOffset");
|
||||||
|
_balance.Load(obj, "balance");
|
||||||
|
}
|
||||||
_checkType = static_cast<Type>(obs_data_get_int(obj, "checkType"));
|
_checkType = static_cast<Type>(obs_data_get_int(obj, "checkType"));
|
||||||
_outputCondition = static_cast<OutputCondition>(
|
_outputCondition = static_cast<OutputCondition>(
|
||||||
obs_data_get_int(obj, "outputCondition"));
|
obs_data_get_int(obj, "outputCondition"));
|
||||||
@@ -320,8 +327,8 @@ MacroConditionAudioEdit::MacroConditionAudioEdit(
|
|||||||
_checkTypes(new QComboBox()),
|
_checkTypes(new QComboBox()),
|
||||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||||
_condition(new QComboBox()),
|
_condition(new QComboBox()),
|
||||||
_volume(new QSpinBox()),
|
_volume(new VariableSpinBox()),
|
||||||
_syncOffset(new QSpinBox()),
|
_syncOffset(new VariableSpinBox()),
|
||||||
_monitorTypes(new QComboBox),
|
_monitorTypes(new QComboBox),
|
||||||
_balance(new SliderSpinBox(0., 1., ""))
|
_balance(new SliderSpinBox(0., 1., ""))
|
||||||
{
|
{
|
||||||
@@ -339,14 +346,21 @@ MacroConditionAudioEdit::MacroConditionAudioEdit(
|
|||||||
|
|
||||||
QWidget::connect(_checkTypes, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_checkTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(CheckTypeChanged(int)));
|
SLOT(CheckTypeChanged(int)));
|
||||||
QWidget::connect(_volume, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(
|
||||||
SLOT(VolumeThresholdChanged(int)));
|
_volume,
|
||||||
QWidget::connect(_syncOffset, SIGNAL(valueChanged(int)), this,
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
SLOT(SyncOffsetChanged(int)));
|
this,
|
||||||
|
SLOT(VolumeThresholdChanged(const NumberVariable<int> &)));
|
||||||
|
QWidget::connect(
|
||||||
|
_syncOffset,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
|
this, SLOT(SyncOffsetChanged(const NumberVariable<int> &)));
|
||||||
QWidget::connect(_monitorTypes, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_monitorTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(MonitorTypeChanged(int)));
|
SLOT(MonitorTypeChanged(int)));
|
||||||
QWidget::connect(_balance, SIGNAL(DoubleValueChanged(double)), this,
|
QWidget::connect(
|
||||||
SLOT(BalanceChanged(double)));
|
_balance,
|
||||||
|
SIGNAL(DoubleValueChanged(const NumberVariable<double> &)),
|
||||||
|
this, SLOT(BalanceChanged(const NumberVariable<double> &)));
|
||||||
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ConditionChanged(int)));
|
SLOT(ConditionChanged(int)));
|
||||||
QWidget::connect(_sources,
|
QWidget::connect(_sources,
|
||||||
@@ -391,8 +405,8 @@ void MacroConditionAudioEdit::UpdateVolmeterSource()
|
|||||||
layout->addWidget(_volMeter);
|
layout->addWidget(_volMeter);
|
||||||
|
|
||||||
QWidget::connect(_volMeter->GetSlider(), SIGNAL(valueChanged(int)),
|
QWidget::connect(_volMeter->GetSlider(), SIGNAL(valueChanged(int)),
|
||||||
_volume, SLOT(setValue(int)));
|
_volume, SLOT(SetFixedValue(int)));
|
||||||
QWidget::connect(_volume, SIGNAL(valueChanged(int)),
|
QWidget::connect(_volume, SIGNAL(FixedValueChanged(int)),
|
||||||
_volMeter->GetSlider(), SLOT(setValue(int)));
|
_volMeter->GetSlider(), SLOT(setValue(int)));
|
||||||
|
|
||||||
// Slider will default to 0 so set it manually once
|
// Slider will default to 0 so set it manually once
|
||||||
@@ -405,16 +419,19 @@ void MacroConditionAudioEdit::SourceChanged(const SourceSelection &source)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
{
|
||||||
_entryData->_audioSource = source;
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->ResetVolmeter();
|
_entryData->_audioSource = source;
|
||||||
|
_entryData->ResetVolmeter();
|
||||||
|
}
|
||||||
UpdateVolmeterSource();
|
UpdateVolmeterSource();
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionAudioEdit::VolumeThresholdChanged(int vol)
|
void MacroConditionAudioEdit::VolumeThresholdChanged(
|
||||||
|
const NumberVariable<int> &vol)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
@@ -424,7 +441,7 @@ void MacroConditionAudioEdit::VolumeThresholdChanged(int vol)
|
|||||||
_entryData->_volume = vol;
|
_entryData->_volume = vol;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionAudioEdit::SyncOffsetChanged(int value)
|
void MacroConditionAudioEdit::SyncOffsetChanged(const NumberVariable<int> &value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
@@ -444,7 +461,7 @@ void MacroConditionAudioEdit::MonitorTypeChanged(int value)
|
|||||||
_entryData->_monitorType = static_cast<obs_monitoring_type>(value);
|
_entryData->_monitorType = static_cast<obs_monitoring_type>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionAudioEdit::BalanceChanged(double value)
|
void MacroConditionAudioEdit::BalanceChanged(const NumberVariable<double> &value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
@@ -504,8 +521,8 @@ void MacroConditionAudioEdit::UpdateEntryData()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_sources->SetSource(_entryData->_audioSource);
|
_sources->SetSource(_entryData->_audioSource);
|
||||||
_volume->setValue(_entryData->_volume);
|
_volume->SetValue(_entryData->_volume);
|
||||||
_syncOffset->setValue(_entryData->_syncOffset);
|
_syncOffset->SetValue(_entryData->_syncOffset);
|
||||||
_monitorTypes->setCurrentIndex(_entryData->_monitorType);
|
_monitorTypes->setCurrentIndex(_entryData->_monitorType);
|
||||||
_balance->SetDoubleValue(_entryData->_balance);
|
_balance->SetDoubleValue(_entryData->_balance);
|
||||||
_checkTypes->setCurrentIndex(_checkTypes->findData(
|
_checkTypes->setCurrentIndex(_checkTypes->findData(
|
||||||
|
|||||||
@@ -50,10 +50,10 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
SourceSelection _audioSource;
|
SourceSelection _audioSource;
|
||||||
int _volume = 0;
|
NumberVariable<int> _volume = 0;
|
||||||
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;
|
||||||
Type _checkType = Type::OUTPUT_VOLUME;
|
Type _checkType = Type::OUTPUT_VOLUME;
|
||||||
OutputCondition _outputCondition = OutputCondition::ABOVE;
|
OutputCondition _outputCondition = OutputCondition::ABOVE;
|
||||||
VolumeCondition _volumeCondition = VolumeCondition::ABOVE;
|
VolumeCondition _volumeCondition = VolumeCondition::ABOVE;
|
||||||
@@ -90,12 +90,12 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void SourceChanged(const SourceSelection &);
|
void SourceChanged(const SourceSelection &);
|
||||||
void VolumeThresholdChanged(int vol);
|
void VolumeThresholdChanged(const NumberVariable<int> &vol);
|
||||||
void ConditionChanged(int cond);
|
void ConditionChanged(int cond);
|
||||||
void CheckTypeChanged(int cond);
|
void CheckTypeChanged(int cond);
|
||||||
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);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
@@ -104,8 +104,8 @@ protected:
|
|||||||
QComboBox *_checkTypes;
|
QComboBox *_checkTypes;
|
||||||
SourceSelectionWidget *_sources;
|
SourceSelectionWidget *_sources;
|
||||||
QComboBox *_condition;
|
QComboBox *_condition;
|
||||||
QSpinBox *_volume;
|
VariableSpinBox *_volume;
|
||||||
QSpinBox *_syncOffset;
|
VariableSpinBox *_syncOffset;
|
||||||
QComboBox *_monitorTypes;
|
QComboBox *_monitorTypes;
|
||||||
SliderSpinBox *_balance;
|
SliderSpinBox *_balance;
|
||||||
VolControl *_volMeter = nullptr;
|
VolControl *_volMeter = nullptr;
|
||||||
|
|||||||
@@ -77,10 +77,11 @@ bool MacroConditionCursor::Save(obs_data_t *obj) const
|
|||||||
MacroCondition::Save(obj);
|
MacroCondition::Save(obj);
|
||||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||||
obs_data_set_int(obj, "button", static_cast<int>(_button));
|
obs_data_set_int(obj, "button", static_cast<int>(_button));
|
||||||
obs_data_set_int(obj, "minX", _minX);
|
_minX.Save(obj, "minX");
|
||||||
obs_data_set_int(obj, "minY", _minY);
|
_minY.Save(obj, "minY");
|
||||||
obs_data_set_int(obj, "maxX", _maxX);
|
_maxX.Save(obj, "maxX");
|
||||||
obs_data_set_int(obj, "maxY", _maxY);
|
_maxY.Save(obj, "maxY");
|
||||||
|
obs_data_set_int(obj, "version", 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,10 +90,17 @@ bool MacroConditionCursor::Load(obs_data_t *obj)
|
|||||||
MacroCondition::Load(obj);
|
MacroCondition::Load(obj);
|
||||||
_condition = static_cast<Condition>(obs_data_get_int(obj, "condition"));
|
_condition = static_cast<Condition>(obs_data_get_int(obj, "condition"));
|
||||||
_button = static_cast<Button>(obs_data_get_int(obj, "button"));
|
_button = static_cast<Button>(obs_data_get_int(obj, "button"));
|
||||||
_minX = obs_data_get_int(obj, "minX");
|
if (!obs_data_has_user_value(obj, "version")) {
|
||||||
_minY = obs_data_get_int(obj, "minY");
|
_minX = obs_data_get_int(obj, "minX");
|
||||||
_maxX = obs_data_get_int(obj, "maxX");
|
_minY = obs_data_get_int(obj, "minY");
|
||||||
_maxY = obs_data_get_int(obj, "maxY");
|
_maxX = obs_data_get_int(obj, "maxX");
|
||||||
|
_maxY = obs_data_get_int(obj, "maxY");
|
||||||
|
} else {
|
||||||
|
_minX.Load(obj, "minX");
|
||||||
|
_minY.Load(obj, "minY");
|
||||||
|
_maxX.Load(obj, "maxX");
|
||||||
|
_maxY.Load(obj, "maxY");
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,10 +123,10 @@ static inline void populateButtonSelection(QComboBox *list)
|
|||||||
MacroConditionCursorEdit::MacroConditionCursorEdit(
|
MacroConditionCursorEdit::MacroConditionCursorEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroConditionCursor> entryData)
|
QWidget *parent, std::shared_ptr<MacroConditionCursor> entryData)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
_minX(new QSpinBox()),
|
_minX(new VariableSpinBox()),
|
||||||
_minY(new QSpinBox()),
|
_minY(new VariableSpinBox()),
|
||||||
_maxX(new QSpinBox()),
|
_maxX(new VariableSpinBox()),
|
||||||
_maxY(new QSpinBox()),
|
_maxY(new VariableSpinBox()),
|
||||||
_conditions(new QComboBox()),
|
_conditions(new QComboBox()),
|
||||||
_buttons(new QComboBox()),
|
_buttons(new QComboBox()),
|
||||||
_frameToggle(new QPushButton(obs_module_text(
|
_frameToggle(new QPushButton(obs_module_text(
|
||||||
@@ -151,14 +159,22 @@ MacroConditionCursorEdit::MacroConditionCursorEdit(
|
|||||||
SLOT(ConditionChanged(int)));
|
SLOT(ConditionChanged(int)));
|
||||||
QWidget::connect(_buttons, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_buttons, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ButtonChanged(int)));
|
SLOT(ButtonChanged(int)));
|
||||||
QWidget::connect(_minX, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(
|
||||||
SLOT(MinXChanged(int)));
|
_minX,
|
||||||
QWidget::connect(_minY, SIGNAL(valueChanged(int)), this,
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
SLOT(MinYChanged(int)));
|
this, SLOT(MinXChanged(const NumberVariable<int> &)));
|
||||||
QWidget::connect(_maxX, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(
|
||||||
SLOT(MaxXChanged(int)));
|
_minY,
|
||||||
QWidget::connect(_maxY, SIGNAL(valueChanged(int)), this,
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
SLOT(MaxYChanged(int)));
|
this, SLOT(MinYChanged(const NumberVariable<int> &)));
|
||||||
|
QWidget::connect(
|
||||||
|
_maxX,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
|
this, SLOT(MaxXChanged(const NumberVariable<int> &)));
|
||||||
|
QWidget::connect(
|
||||||
|
_maxY,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
|
this, SLOT(MaxYChanged(const NumberVariable<int> &)));
|
||||||
QWidget::connect(_frameToggle, SIGNAL(clicked()), this,
|
QWidget::connect(_frameToggle, SIGNAL(clicked()), this,
|
||||||
SLOT(ToggleFrame()));
|
SLOT(ToggleFrame()));
|
||||||
|
|
||||||
@@ -217,7 +233,7 @@ void MacroConditionCursorEdit::ButtonChanged(int index)
|
|||||||
_buttons->itemData(index).toInt());
|
_buttons->itemData(index).toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionCursorEdit::MinXChanged(int pos)
|
void MacroConditionCursorEdit::MinXChanged(const NumberVariable<int> &pos)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
@@ -228,7 +244,7 @@ void MacroConditionCursorEdit::MinXChanged(int pos)
|
|||||||
SetupFrame();
|
SetupFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionCursorEdit::MinYChanged(int pos)
|
void MacroConditionCursorEdit::MinYChanged(const NumberVariable<int> &pos)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
@@ -239,7 +255,7 @@ void MacroConditionCursorEdit::MinYChanged(int pos)
|
|||||||
SetupFrame();
|
SetupFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionCursorEdit::MaxXChanged(int pos)
|
void MacroConditionCursorEdit::MaxXChanged(const NumberVariable<int> &pos)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
@@ -250,7 +266,7 @@ void MacroConditionCursorEdit::MaxXChanged(int pos)
|
|||||||
SetupFrame();
|
SetupFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionCursorEdit::MaxYChanged(int pos)
|
void MacroConditionCursorEdit::MaxYChanged(const NumberVariable<int> &pos)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
@@ -334,18 +350,20 @@ void MacroConditionCursorEdit::SetupFrame()
|
|||||||
Qt::WindowStaysOnTopHint);
|
Qt::WindowStaysOnTopHint);
|
||||||
_frame.setAttribute(Qt::WA_TranslucentBackground, true);
|
_frame.setAttribute(Qt::WA_TranslucentBackground, true);
|
||||||
|
|
||||||
if (_entryData) {
|
if (!_entryData) {
|
||||||
QRect rect(_entryData->_minX, _entryData->_minY,
|
return;
|
||||||
_entryData->_maxX - _entryData->_minX,
|
|
||||||
_entryData->_maxY - _entryData->_minY);
|
|
||||||
|
|
||||||
if (rect.size().height() == 0 || rect.size().width() == 0) {
|
|
||||||
_frame.setGeometry(0, 0, 1, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_frame.setGeometry(getScreenUnionRect().intersected(rect));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect rect(_entryData->_minX, _entryData->_minY,
|
||||||
|
_entryData->_maxX - _entryData->_minX,
|
||||||
|
_entryData->_maxY - _entryData->_minY);
|
||||||
|
|
||||||
|
if (rect.size().height() <= 0 || rect.size().width() <= 0) {
|
||||||
|
_frame.setGeometry(0, 0, 1, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_frame.setGeometry(getScreenUnionRect().intersected(rect));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionCursorEdit::UpdateEntryData()
|
void MacroConditionCursorEdit::UpdateEntryData()
|
||||||
@@ -356,9 +374,9 @@ void MacroConditionCursorEdit::UpdateEntryData()
|
|||||||
|
|
||||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||||
_buttons->setCurrentIndex(static_cast<int>(_entryData->_button));
|
_buttons->setCurrentIndex(static_cast<int>(_entryData->_button));
|
||||||
_minX->setValue(_entryData->_minX);
|
_minX->SetValue(_entryData->_minX);
|
||||||
_minY->setValue(_entryData->_minY);
|
_minY->SetValue(_entryData->_minY);
|
||||||
_maxX->setValue(_entryData->_maxX);
|
_maxX->SetValue(_entryData->_maxX);
|
||||||
_maxY->setValue(_entryData->_maxY);
|
_maxY->SetValue(_entryData->_maxY);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
|
#include "striped-frame.hpp"
|
||||||
|
#include "variable-spinbox.hpp"
|
||||||
|
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QFrame>
|
|
||||||
|
|
||||||
class MacroConditionCursor : public MacroCondition {
|
class MacroConditionCursor : public MacroCondition {
|
||||||
public:
|
public:
|
||||||
@@ -33,7 +34,7 @@ public:
|
|||||||
|
|
||||||
Condition _condition = Condition::REGION;
|
Condition _condition = Condition::REGION;
|
||||||
Button _button = Button::LEFT;
|
Button _button = Button::LEFT;
|
||||||
int _minX = 0, _minY = 0, _maxX = 0, _maxY = 0;
|
NumberVariable<int> _minX = 0, _minY = 0, _maxX = 0, _maxY = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CheckClick();
|
bool CheckClick();
|
||||||
@@ -62,18 +63,18 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void ConditionChanged(int idx);
|
void ConditionChanged(int idx);
|
||||||
void ButtonChanged(int idx);
|
void ButtonChanged(int idx);
|
||||||
void MinXChanged(int pos);
|
void MinXChanged(const NumberVariable<int> &pos);
|
||||||
void MinYChanged(int pos);
|
void MinYChanged(const NumberVariable<int> &pos);
|
||||||
void MaxXChanged(int pos);
|
void MaxXChanged(const NumberVariable<int> &pos);
|
||||||
void MaxYChanged(int pos);
|
void MaxYChanged(const NumberVariable<int> &pos);
|
||||||
void UpdateCursorPos();
|
void UpdateCursorPos();
|
||||||
void ToggleFrame();
|
void ToggleFrame();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QSpinBox *_minX;
|
VariableSpinBox *_minX;
|
||||||
QSpinBox *_minY;
|
VariableSpinBox *_minY;
|
||||||
QSpinBox *_maxX;
|
VariableSpinBox *_maxX;
|
||||||
QSpinBox *_maxY;
|
VariableSpinBox *_maxY;
|
||||||
QComboBox *_conditions;
|
QComboBox *_conditions;
|
||||||
QComboBox *_buttons;
|
QComboBox *_buttons;
|
||||||
QPushButton *_frameToggle;
|
QPushButton *_frameToggle;
|
||||||
@@ -86,6 +87,6 @@ private:
|
|||||||
void SetWidgetVisibility();
|
void SetWidgetVisibility();
|
||||||
void SetupFrame();
|
void SetupFrame();
|
||||||
QTimer _timer;
|
QTimer _timer;
|
||||||
QFrame _frame;
|
StripedFrame _frame;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -165,8 +165,8 @@ bool MacroConditionDate::CheckRegularDate(int64_t msSinceLastCheck)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (match && _repeat) {
|
if (match && _repeat) {
|
||||||
_dateTime = _dateTime.addSecs(_duration.seconds);
|
_dateTime = _dateTime.addSecs(_duration.Seconds());
|
||||||
_dateTime2 = _dateTime2.addSecs(_duration.seconds);
|
_dateTime2 = _dateTime2.addSecs(_duration.Seconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
return match;
|
return match;
|
||||||
@@ -398,10 +398,8 @@ MacroConditionDateEdit::MacroConditionDateEdit(
|
|||||||
SLOT(RepeatChanged(int)));
|
SLOT(RepeatChanged(int)));
|
||||||
QWidget::connect(_updateOnRepeat, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_updateOnRepeat, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(UpdateOnRepeatChanged(int)));
|
SLOT(UpdateOnRepeatChanged(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(_advancedSettingsTooggle, SIGNAL(clicked()), this,
|
QWidget::connect(_advancedSettingsTooggle, SIGNAL(clicked()), this,
|
||||||
SLOT(AdvancedSettingsToggleClicked()));
|
SLOT(AdvancedSettingsToggleClicked()));
|
||||||
QWidget::connect(_pattern, SIGNAL(editingFinished()), this,
|
QWidget::connect(_pattern, SIGNAL(editingFinished()), this,
|
||||||
@@ -589,24 +587,14 @@ void MacroConditionDateEdit::UpdateOnRepeatChanged(int state)
|
|||||||
_entryData->_updateOnRepeat = state;
|
_entryData->_updateOnRepeat = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionDateEdit::DurationChanged(double seconds)
|
void MacroConditionDateEdit::DurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_duration.seconds = seconds;
|
_entryData->_duration = dur;
|
||||||
}
|
|
||||||
|
|
||||||
void MacroConditionDateEdit::DurationUnitChanged(DurationUnit unit)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_duration.displayUnit = unit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionDateEdit::AdvancedSettingsToggleClicked()
|
void MacroConditionDateEdit::AdvancedSettingsToggleClicked()
|
||||||
|
|||||||
@@ -100,8 +100,7 @@ private slots:
|
|||||||
void IgnoreTimeChanged(int state);
|
void IgnoreTimeChanged(int state);
|
||||||
void RepeatChanged(int state);
|
void RepeatChanged(int state);
|
||||||
void UpdateOnRepeatChanged(int state);
|
void UpdateOnRepeatChanged(int state);
|
||||||
void DurationChanged(double seconds);
|
void DurationChanged(const Duration &seconds);
|
||||||
void DurationUnitChanged(DurationUnit unit);
|
|
||||||
void AdvancedSettingsToggleClicked();
|
void AdvancedSettingsToggleClicked();
|
||||||
void ShowNextMatch();
|
void ShowNextMatch();
|
||||||
void UpdateCurrentTime();
|
void UpdateCurrentTime();
|
||||||
|
|||||||
@@ -121,15 +121,14 @@ DurationModifierEdit::DurationModifierEdit(QWidget *parent)
|
|||||||
_duration = new DurationSelection(parent);
|
_duration = new DurationSelection(parent);
|
||||||
_toggle = new QPushButton(parent);
|
_toggle = new QPushButton(parent);
|
||||||
_toggle->setMaximumWidth(22);
|
_toggle->setMaximumWidth(22);
|
||||||
_toggle->setIcon(
|
const auto path = QString::fromStdString(getDataFilePath(
|
||||||
QIcon(QString::fromStdString(getDataFilePath("res/time.svg"))));
|
"res/images/" + GetThemeTypeName() + "Time.svg"));
|
||||||
|
_toggle->setIcon(QIcon(path));
|
||||||
populateDurationModifierTypes(_condition);
|
populateDurationModifierTypes(_condition);
|
||||||
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(_ModifierChanged(int)));
|
SLOT(_ModifierChanged(int)));
|
||||||
QObject::connect(_duration, &DurationSelection::DurationChanged, this,
|
QObject::connect(_duration, &DurationSelection::DurationChanged, this,
|
||||||
&DurationModifierEdit::DurationChanged);
|
&DurationModifierEdit::DurationChanged);
|
||||||
QObject::connect(_duration, &DurationSelection::UnitChanged, this,
|
|
||||||
&DurationModifierEdit::UnitChanged);
|
|
||||||
QWidget::connect(_toggle, SIGNAL(clicked()), this,
|
QWidget::connect(_toggle, SIGNAL(clicked()), this,
|
||||||
SLOT(ToggleClicked()));
|
SLOT(ToggleClicked()));
|
||||||
|
|
||||||
@@ -150,11 +149,6 @@ void DurationModifierEdit::SetValue(DurationModifier &value)
|
|||||||
_duration->setVisible(value.GetType() != DurationModifier::Type::NONE);
|
_duration->setVisible(value.GetType() != DurationModifier::Type::NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DurationModifierEdit::SetUnit(DurationUnit u)
|
|
||||||
{
|
|
||||||
_duration->SetUnit(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DurationModifierEdit::SetDuration(const Duration &d)
|
void DurationModifierEdit::SetDuration(const Duration &d)
|
||||||
{
|
{
|
||||||
_duration->SetDuration(d);
|
_duration->SetDuration(d);
|
||||||
@@ -195,10 +189,8 @@ MacroConditionEdit::MacroConditionEdit(
|
|||||||
QWidget::connect(_conditionSelection,
|
QWidget::connect(_conditionSelection,
|
||||||
SIGNAL(currentTextChanged(const QString &)), this,
|
SIGNAL(currentTextChanged(const QString &)), this,
|
||||||
SLOT(ConditionSelectionChanged(const QString &)));
|
SLOT(ConditionSelectionChanged(const QString &)));
|
||||||
QWidget::connect(_dur, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(_dur, SIGNAL(DurationChanged(const Duration &)), this,
|
||||||
SLOT(DurationChanged(double)));
|
SLOT(DurationChanged(const Duration &)));
|
||||||
QWidget::connect(_dur, SIGNAL(UnitChanged(DurationUnit)), this,
|
|
||||||
SLOT(DurationUnitChanged(DurationUnit)));
|
|
||||||
QWidget::connect(_dur, SIGNAL(ModifierChanged(DurationModifier::Type)),
|
QWidget::connect(_dur, SIGNAL(ModifierChanged(DurationModifier::Type)),
|
||||||
this,
|
this,
|
||||||
SLOT(DurationModifierChanged(DurationModifier::Type)));
|
SLOT(DurationModifierChanged(DurationModifier::Type)));
|
||||||
@@ -324,7 +316,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
|||||||
SetFocusPolicyOfWidgets();
|
SetFocusPolicyOfWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionEdit::DurationChanged(double seconds)
|
void MacroConditionEdit::DurationChanged(const Duration &seconds)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
@@ -344,16 +336,6 @@ void MacroConditionEdit::DurationModifierChanged(DurationModifier::Type m)
|
|||||||
(*_entryData)->SetDurationModifier(m);
|
(*_entryData)->SetDurationModifier(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionEdit::DurationUnitChanged(DurationUnit unit)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
(*_entryData)->SetDurationUnit(unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<MacroSegment> MacroConditionEdit::Data()
|
std::shared_ptr<MacroSegment> MacroConditionEdit::Data()
|
||||||
{
|
{
|
||||||
return *_entryData;
|
return *_entryData;
|
||||||
@@ -375,7 +357,7 @@ void AdvSceneSwitcher::AddMacroCondition(int idx)
|
|||||||
if (idx >= 1) {
|
if (idx >= 1) {
|
||||||
id = macro->Conditions().at(idx - 1)->GetId();
|
id = macro->Conditions().at(idx - 1)->GetId();
|
||||||
if (idx == 1) {
|
if (idx == 1) {
|
||||||
logic = LogicType::NONE;
|
logic = LogicType::OR;
|
||||||
} else {
|
} else {
|
||||||
logic = macro->Conditions().at(idx - 1)->GetLogicType();
|
logic = macro->Conditions().at(idx - 1)->GetLogicType();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,15 +35,13 @@ class DurationModifierEdit : public QWidget {
|
|||||||
public:
|
public:
|
||||||
DurationModifierEdit(QWidget *parent = nullptr);
|
DurationModifierEdit(QWidget *parent = nullptr);
|
||||||
void SetValue(DurationModifier &value);
|
void SetValue(DurationModifier &value);
|
||||||
void SetUnit(DurationUnit u);
|
|
||||||
void SetDuration(const Duration &d);
|
void SetDuration(const Duration &d);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void _ModifierChanged(int value);
|
void _ModifierChanged(int value);
|
||||||
void ToggleClicked();
|
void ToggleClicked();
|
||||||
signals:
|
signals:
|
||||||
void DurationChanged(double value);
|
void DurationChanged(const Duration &value);
|
||||||
void UnitChanged(DurationUnit u);
|
|
||||||
void ModifierChanged(DurationModifier::Type value);
|
void ModifierChanged(DurationModifier::Type value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -69,9 +67,8 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void LogicSelectionChanged(int idx);
|
void LogicSelectionChanged(int idx);
|
||||||
void ConditionSelectionChanged(const QString &text);
|
void ConditionSelectionChanged(const QString &text);
|
||||||
void DurationChanged(double seconds);
|
void DurationChanged(const Duration &value);
|
||||||
void DurationModifierChanged(DurationModifier::Type m);
|
void DurationModifierChanged(DurationModifier::Type m);
|
||||||
void DurationUnitChanged(DurationUnit unit);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetLogicSelection();
|
void SetLogicSelection();
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ bool MacroConditionFile::MatchFileContent(QString &filedata)
|
|||||||
|
|
||||||
bool MacroConditionFile::CheckRemoteFileContent()
|
bool MacroConditionFile::CheckRemoteFileContent()
|
||||||
{
|
{
|
||||||
std::string data = getRemoteData(_file);
|
std::string path = _file;
|
||||||
|
std::string data = getRemoteData(path);
|
||||||
SetVariableValue(data);
|
SetVariableValue(data);
|
||||||
QString qdata = QString::fromStdString(data);
|
QString qdata = QString::fromStdString(data);
|
||||||
return MatchFileContent(qdata);
|
return MatchFileContent(qdata);
|
||||||
@@ -99,7 +100,8 @@ bool MacroConditionFile::CheckChangeContent()
|
|||||||
QString filedata;
|
QString filedata;
|
||||||
switch (_fileType) {
|
switch (_fileType) {
|
||||||
case FileType::LOCAL: {
|
case FileType::LOCAL: {
|
||||||
QFile file(QString::fromStdString(_file));
|
std::string path = _file;
|
||||||
|
QFile file(QString::fromStdString(path));
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -107,7 +109,8 @@ bool MacroConditionFile::CheckChangeContent()
|
|||||||
file.close();
|
file.close();
|
||||||
} break;
|
} break;
|
||||||
case FileType::REMOTE: {
|
case FileType::REMOTE: {
|
||||||
std::string data = getRemoteData(_file);
|
std::string path = _file;
|
||||||
|
std::string data = getRemoteData(path);
|
||||||
QString filedata = QString::fromStdString(data);
|
QString filedata = QString::fromStdString(data);
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
@@ -166,7 +169,7 @@ bool MacroConditionFile::Save(obs_data_t *obj) const
|
|||||||
{
|
{
|
||||||
MacroCondition::Save(obj);
|
MacroCondition::Save(obj);
|
||||||
_regex.Save(obj);
|
_regex.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, "fileType", static_cast<int>(_fileType));
|
obs_data_set_int(obj, "fileType", static_cast<int>(_fileType));
|
||||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||||
@@ -184,7 +187,7 @@ bool MacroConditionFile::Load(obs_data_t *obj)
|
|||||||
_regex.CreateBackwardsCompatibleRegex(
|
_regex.CreateBackwardsCompatibleRegex(
|
||||||
obs_data_get_bool(obj, "useRegex"));
|
obs_data_get_bool(obj, "useRegex"));
|
||||||
}
|
}
|
||||||
_file = obs_data_get_string(obj, "file");
|
_file.Load(obj, "file");
|
||||||
_text.Load(obj, "text");
|
_text.Load(obj, "text");
|
||||||
_fileType = static_cast<FileType>(obs_data_get_int(obj, "fileType"));
|
_fileType = static_cast<FileType>(obs_data_get_int(obj, "fileType"));
|
||||||
_condition =
|
_condition =
|
||||||
@@ -196,7 +199,7 @@ bool MacroConditionFile::Load(obs_data_t *obj)
|
|||||||
|
|
||||||
std::string MacroConditionFile::GetShortDesc() const
|
std::string MacroConditionFile::GetShortDesc() const
|
||||||
{
|
{
|
||||||
return _file;
|
return _file.UnresolvedValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void populateFileTypes(QComboBox *list)
|
static void populateFileTypes(QComboBox *list)
|
||||||
@@ -292,7 +295,7 @@ void MacroConditionFileEdit::UpdateEntryData()
|
|||||||
|
|
||||||
_fileTypes->setCurrentIndex(static_cast<int>(_entryData->_fileType));
|
_fileTypes->setCurrentIndex(static_cast<int>(_entryData->_fileType));
|
||||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||||
_filePath->SetPath(QString::fromStdString(_entryData->_file));
|
_filePath->SetPath(_entryData->_file);
|
||||||
_matchText->setPlainText(_entryData->_text);
|
_matchText->setPlainText(_entryData->_text);
|
||||||
_regex->SetRegexConfig(_entryData->_regex);
|
_regex->SetRegexConfig(_entryData->_regex);
|
||||||
_checkModificationDate->setChecked(_entryData->_useTime);
|
_checkModificationDate->setChecked(_entryData->_useTime);
|
||||||
|
|||||||
@@ -35,9 +35,8 @@ public:
|
|||||||
DATE_CHANGE,
|
DATE_CHANGE,
|
||||||
};
|
};
|
||||||
|
|
||||||
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");
|
|
||||||
FileType _fileType = FileType::LOCAL;
|
FileType _fileType = FileType::LOCAL;
|
||||||
ConditionType _condition = ConditionType::MATCH;
|
ConditionType _condition = ConditionType::MATCH;
|
||||||
RegexConfig _regex;
|
RegexConfig _regex;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public:
|
|||||||
SourceSelection _source;
|
SourceSelection _source;
|
||||||
OBSWeakSource _filter;
|
OBSWeakSource _filter;
|
||||||
Condition _condition = Condition::ENABLED;
|
Condition _condition = Condition::ENABLED;
|
||||||
VariableResolvingString _settings = "";
|
StringVariable _settings = "";
|
||||||
RegexConfig _regex;
|
RegexConfig _regex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ bool MacroConditionIdle::CheckCondition()
|
|||||||
{
|
{
|
||||||
auto seconds = secondsSinceLastInput();
|
auto seconds = secondsSinceLastInput();
|
||||||
SetVariableValue(std::to_string(seconds));
|
SetVariableValue(std::to_string(seconds));
|
||||||
return seconds >= _duration.seconds;
|
return seconds >= _duration.Seconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionIdle::Save(obs_data_t *obj) const
|
bool MacroConditionIdle::Save(obs_data_t *obj) const
|
||||||
@@ -37,10 +37,8 @@ MacroConditionIdleEdit::MacroConditionIdleEdit(
|
|||||||
{
|
{
|
||||||
_duration = new DurationSelection();
|
_duration = new DurationSelection();
|
||||||
|
|
||||||
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)));
|
|
||||||
|
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
@@ -55,24 +53,14 @@ MacroConditionIdleEdit::MacroConditionIdleEdit(
|
|||||||
_loading = false;
|
_loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionIdleEdit::DurationChanged(double seconds)
|
void MacroConditionIdleEdit::DurationChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_duration.seconds = seconds;
|
_entryData->_duration = dur;
|
||||||
}
|
|
||||||
|
|
||||||
void MacroConditionIdleEdit::DurationUnitChanged(DurationUnit unit)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_duration.displayUnit = unit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionIdleEdit::UpdateEntryData()
|
void MacroConditionIdleEdit::UpdateEntryData()
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void DurationChanged(double seconds);
|
void DurationChanged(const Duration &seconds);
|
||||||
void DurationUnitChanged(DurationUnit unit);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DurationSelection *_duration;
|
DurationSelection *_duration;
|
||||||
|
|||||||
@@ -44,11 +44,12 @@ bool MacroConditionMacro::CheckStateCondition()
|
|||||||
// Note:
|
// Note:
|
||||||
// Depending on the order the macro conditions are checked Matched() might
|
// Depending on the order the macro conditions are checked Matched() might
|
||||||
// still return the state of the previous interval
|
// still return the state of the previous interval
|
||||||
if (!_macro.get()) {
|
auto macro = _macro.GetMacro();
|
||||||
|
if (!macro) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _macro->Matched();
|
return macro->Matched();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionMacro::CheckMultiStateCondition()
|
bool MacroConditionMacro::CheckMultiStateCondition()
|
||||||
@@ -57,8 +58,9 @@ bool MacroConditionMacro::CheckMultiStateCondition()
|
|||||||
// Depending on the order the macro conditions are checked Matched() might
|
// Depending on the order the macro conditions are checked Matched() might
|
||||||
// still return the state of the previous interval
|
// still return the state of the previous interval
|
||||||
int matchedCount = 0;
|
int matchedCount = 0;
|
||||||
for (const auto ¯o : _macros) {
|
for (const auto &m : _macros) {
|
||||||
if (!macro.get()) {
|
auto macro = m.GetMacro();
|
||||||
|
if (!macro) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (macro->Matched()) {
|
if (macro->Matched()) {
|
||||||
@@ -82,17 +84,18 @@ bool MacroConditionMacro::CheckMultiStateCondition()
|
|||||||
|
|
||||||
bool MacroConditionMacro::CheckCountCondition()
|
bool MacroConditionMacro::CheckCountCondition()
|
||||||
{
|
{
|
||||||
if (!_macro.get()) {
|
auto macro = _macro.GetMacro();
|
||||||
|
if (!macro) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_counterCondition) {
|
switch (_counterCondition) {
|
||||||
case CounterCondition::BELOW:
|
case CounterCondition::BELOW:
|
||||||
return _macro->RunCount() < _count;
|
return macro->RunCount() < _count;
|
||||||
case CounterCondition::ABOVE:
|
case CounterCondition::ABOVE:
|
||||||
return _macro->RunCount() > _count;
|
return macro->RunCount() > _count;
|
||||||
case CounterCondition::EQUAL:
|
case CounterCondition::EQUAL:
|
||||||
return _macro->RunCount() == _count;
|
return macro->RunCount() == _count;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -123,10 +126,11 @@ bool MacroConditionMacro::Save(obs_data_t *obj) const
|
|||||||
_macro.Save(obj);
|
_macro.Save(obj);
|
||||||
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
||||||
obs_data_set_int(obj, "condition", static_cast<int>(_counterCondition));
|
obs_data_set_int(obj, "condition", static_cast<int>(_counterCondition));
|
||||||
obs_data_set_int(obj, "count", _count);
|
_count.Save(obj, "count");
|
||||||
obs_data_set_int(obj, "multiStateCount", _multiSateCount);
|
_multiSateCount.Save(obj, "multiStateCount");
|
||||||
obs_data_set_int(obj, "multiStateCondition",
|
obs_data_set_int(obj, "multiStateCondition",
|
||||||
static_cast<int>(_multiSateCondition));
|
static_cast<int>(_multiSateCondition));
|
||||||
|
obs_data_set_int(obj, "version", 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,8 +142,6 @@ bool MacroConditionMacro::Load(obs_data_t *obj)
|
|||||||
_type = static_cast<Type>(obs_data_get_int(obj, "type"));
|
_type = static_cast<Type>(obs_data_get_int(obj, "type"));
|
||||||
_counterCondition = static_cast<CounterCondition>(
|
_counterCondition = static_cast<CounterCondition>(
|
||||||
obs_data_get_int(obj, "condition"));
|
obs_data_get_int(obj, "condition"));
|
||||||
_count = obs_data_get_int(obj, "count");
|
|
||||||
_multiSateCount = obs_data_get_int(obj, "multiStateCount");
|
|
||||||
// TODO: Remove this fallback in future version
|
// TODO: Remove this fallback in future version
|
||||||
if (!obs_data_has_user_value(obj, "multiStateCondition")) {
|
if (!obs_data_has_user_value(obj, "multiStateCondition")) {
|
||||||
_multiSateCondition = MultiStateCondition::ABOVE;
|
_multiSateCondition = MultiStateCondition::ABOVE;
|
||||||
@@ -147,15 +149,27 @@ bool MacroConditionMacro::Load(obs_data_t *obj)
|
|||||||
_multiSateCondition = static_cast<MultiStateCondition>(
|
_multiSateCondition = static_cast<MultiStateCondition>(
|
||||||
obs_data_get_int(obj, "multiStateCondition"));
|
obs_data_get_int(obj, "multiStateCondition"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!obs_data_has_user_value(obj, "version")) {
|
||||||
|
_count = obs_data_get_int(obj, "count");
|
||||||
|
_multiSateCount = obs_data_get_int(obj, "multiStateCount");
|
||||||
|
} else {
|
||||||
|
_count.Load(obj, "count");
|
||||||
|
_multiSateCount.Load(obj, "multiStateCount");
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MacroConditionMacro::PostLoad()
|
||||||
|
{
|
||||||
|
return MacroRefCondition::PostLoad() &&
|
||||||
|
MultiMacroRefCondtition::PostLoad();
|
||||||
|
}
|
||||||
|
|
||||||
std::string MacroConditionMacro::GetShortDesc() const
|
std::string MacroConditionMacro::GetShortDesc() const
|
||||||
{
|
{
|
||||||
if (_macro.get()) {
|
return _macro.Name();
|
||||||
return _macro->Name();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void populateTypeSelection(QComboBox *list)
|
static inline void populateTypeSelection(QComboBox *list)
|
||||||
@@ -183,19 +197,19 @@ MacroConditionMacroEdit::MacroConditionMacroEdit(
|
|||||||
QWidget *parent, std::shared_ptr<MacroConditionMacro> entryData)
|
QWidget *parent, std::shared_ptr<MacroConditionMacro> entryData)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
_macros(new MacroSelection(parent)),
|
_macros(new MacroSelection(parent)),
|
||||||
_types(new QComboBox(parent)),
|
_types(new QComboBox()),
|
||||||
_counterConditions(new QComboBox(parent)),
|
_counterConditions(new QComboBox()),
|
||||||
_count(new QSpinBox(parent)),
|
_count(new VariableSpinBox()),
|
||||||
_currentCount(new QLabel(parent)),
|
_currentCount(new QLabel()),
|
||||||
_pausedWarning(new QLabel(obs_module_text(
|
_pausedWarning(new QLabel(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.macro.pausedWarning"))),
|
"AdvSceneSwitcher.condition.macro.pausedWarning"))),
|
||||||
_resetCount(new QPushButton(obs_module_text(
|
_resetCount(new QPushButton(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.macro.count.reset"))),
|
"AdvSceneSwitcher.condition.macro.count.reset"))),
|
||||||
_settingsLine1(new QHBoxLayout),
|
_settingsLine1(new QHBoxLayout()),
|
||||||
_settingsLine2(new QHBoxLayout),
|
_settingsLine2(new QHBoxLayout()),
|
||||||
_macroList(new MacroList(this, false, false)),
|
_macroList(new MacroList(this, false, false)),
|
||||||
_multiStateConditions(new QComboBox(parent)),
|
_multiStateConditions(new QComboBox()),
|
||||||
_multiStateCount(new QSpinBox(parent))
|
_multiStateCount(new VariableSpinBox())
|
||||||
{
|
{
|
||||||
_count->setMaximum(10000000);
|
_count->setMaximum(10000000);
|
||||||
populateTypeSelection(_types);
|
populateTypeSelection(_types);
|
||||||
@@ -210,8 +224,10 @@ MacroConditionMacroEdit::MacroConditionMacroEdit(
|
|||||||
SLOT(TypeChanged(int)));
|
SLOT(TypeChanged(int)));
|
||||||
QWidget::connect(_counterConditions, SIGNAL(currentIndexChanged(int)),
|
QWidget::connect(_counterConditions, SIGNAL(currentIndexChanged(int)),
|
||||||
this, SLOT(CountConditionChanged(int)));
|
this, SLOT(CountConditionChanged(int)));
|
||||||
QWidget::connect(_count, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(
|
||||||
SLOT(CountChanged(int)));
|
_count,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
|
this, SLOT(CountChanged(const NumberVariable<int> &)));
|
||||||
QWidget::connect(_resetCount, SIGNAL(clicked()), this,
|
QWidget::connect(_resetCount, SIGNAL(clicked()), this,
|
||||||
SLOT(ResetClicked()));
|
SLOT(ResetClicked()));
|
||||||
QWidget::connect(_macroList, SIGNAL(Added(const std::string &)), this,
|
QWidget::connect(_macroList, SIGNAL(Added(const std::string &)), this,
|
||||||
@@ -223,10 +239,13 @@ MacroConditionMacroEdit::MacroConditionMacroEdit(
|
|||||||
QWidget::connect(_multiStateConditions,
|
QWidget::connect(_multiStateConditions,
|
||||||
SIGNAL(currentIndexChanged(int)), this,
|
SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(MultiStateConditionChanged(int)));
|
SLOT(MultiStateConditionChanged(int)));
|
||||||
QWidget::connect(_multiStateCount, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(
|
||||||
SLOT(MultiStateCountChanged(int)));
|
_multiStateCount,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
|
this,
|
||||||
|
SLOT(MultiStateCountChanged(const NumberVariable<int> &)));
|
||||||
|
|
||||||
auto typesLayout = new QHBoxLayout;
|
auto typesLayout = new QHBoxLayout();
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{types}}", _types},
|
{"{{types}}", _types},
|
||||||
};
|
};
|
||||||
@@ -234,7 +253,7 @@ MacroConditionMacroEdit::MacroConditionMacroEdit(
|
|||||||
"AdvSceneSwitcher.condition.macro.type.selection"),
|
"AdvSceneSwitcher.condition.macro.type.selection"),
|
||||||
typesLayout, widgetPlaceholders);
|
typesLayout, widgetPlaceholders);
|
||||||
|
|
||||||
auto mainLayout = new QVBoxLayout;
|
auto mainLayout = new QVBoxLayout(this);
|
||||||
mainLayout->addLayout(typesLayout);
|
mainLayout->addLayout(typesLayout);
|
||||||
mainLayout->addLayout(_settingsLine1);
|
mainLayout->addLayout(_settingsLine1);
|
||||||
mainLayout->addLayout(_settingsLine2);
|
mainLayout->addLayout(_settingsLine2);
|
||||||
@@ -244,11 +263,13 @@ MacroConditionMacroEdit::MacroConditionMacroEdit(
|
|||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
|
|
||||||
connect(&_countTimer, SIGNAL(timeout()), this, SLOT(UpdateCount()));
|
QWidget::connect(&_countTimer, SIGNAL(timeout()), this,
|
||||||
|
SLOT(UpdateCount()));
|
||||||
_countTimer.start(1000);
|
_countTimer.start(1000);
|
||||||
|
|
||||||
_pausedWarning->setVisible(false);
|
_pausedWarning->setVisible(false);
|
||||||
connect(&_pausedTimer, SIGNAL(timeout()), this, SLOT(UpdatePaused()));
|
QWidget::connect(&_pausedTimer, SIGNAL(timeout()), this,
|
||||||
|
SLOT(UpdatePaused()));
|
||||||
_pausedTimer.start(1000);
|
_pausedTimer.start(1000);
|
||||||
|
|
||||||
UpdateEntryData();
|
UpdateEntryData();
|
||||||
@@ -270,6 +291,7 @@ void MacroConditionMacroEdit::ClearLayouts()
|
|||||||
|
|
||||||
void MacroConditionMacroEdit::SetupStateWidgets()
|
void MacroConditionMacroEdit::SetupStateWidgets()
|
||||||
{
|
{
|
||||||
|
SetWidgetVisibility();
|
||||||
ClearLayouts();
|
ClearLayouts();
|
||||||
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
@@ -278,12 +300,11 @@ void MacroConditionMacroEdit::SetupStateWidgets()
|
|||||||
placeWidgets(
|
placeWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.condition.macro.state.entry"),
|
obs_module_text("AdvSceneSwitcher.condition.macro.state.entry"),
|
||||||
_settingsLine1, widgetPlaceholders);
|
_settingsLine1, widgetPlaceholders);
|
||||||
SetWidgetVisibility();
|
|
||||||
adjustSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMacroEdit::SetupMultiStateWidgets()
|
void MacroConditionMacroEdit::SetupMultiStateWidgets()
|
||||||
{
|
{
|
||||||
|
SetWidgetVisibility();
|
||||||
ClearLayouts();
|
ClearLayouts();
|
||||||
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
@@ -294,12 +315,11 @@ void MacroConditionMacroEdit::SetupMultiStateWidgets()
|
|||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.macro.multistate.entry"),
|
"AdvSceneSwitcher.condition.macro.multistate.entry"),
|
||||||
_settingsLine1, widgetPlaceholders);
|
_settingsLine1, widgetPlaceholders);
|
||||||
SetWidgetVisibility();
|
|
||||||
adjustSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMacroEdit::SetupCountWidgets()
|
void MacroConditionMacroEdit::SetupCountWidgets()
|
||||||
{
|
{
|
||||||
|
SetWidgetVisibility();
|
||||||
ClearLayouts();
|
ClearLayouts();
|
||||||
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
@@ -317,8 +337,6 @@ void MacroConditionMacroEdit::SetupCountWidgets()
|
|||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.macro.count.entry.line2"),
|
"AdvSceneSwitcher.condition.macro.count.entry.line2"),
|
||||||
_settingsLine2, widgetPlaceholders);
|
_settingsLine2, widgetPlaceholders);
|
||||||
SetWidgetVisibility();
|
|
||||||
adjustSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMacroEdit::SetWidgetVisibility()
|
void MacroConditionMacroEdit::SetWidgetVisibility()
|
||||||
@@ -329,7 +347,6 @@ void MacroConditionMacroEdit::SetWidgetVisibility()
|
|||||||
_counterConditions->show();
|
_counterConditions->show();
|
||||||
_count->show();
|
_count->show();
|
||||||
_currentCount->show();
|
_currentCount->show();
|
||||||
_pausedWarning->show();
|
|
||||||
_resetCount->show();
|
_resetCount->show();
|
||||||
_macroList->hide();
|
_macroList->hide();
|
||||||
_multiStateConditions->hide();
|
_multiStateConditions->hide();
|
||||||
@@ -340,7 +357,6 @@ void MacroConditionMacroEdit::SetWidgetVisibility()
|
|||||||
_counterConditions->hide();
|
_counterConditions->hide();
|
||||||
_count->hide();
|
_count->hide();
|
||||||
_currentCount->hide();
|
_currentCount->hide();
|
||||||
_pausedWarning->show();
|
|
||||||
_resetCount->hide();
|
_resetCount->hide();
|
||||||
_macroList->hide();
|
_macroList->hide();
|
||||||
_multiStateConditions->hide();
|
_multiStateConditions->hide();
|
||||||
@@ -360,6 +376,8 @@ void MacroConditionMacroEdit::SetWidgetVisibility()
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMacroEdit::UpdateEntryData()
|
void MacroConditionMacroEdit::UpdateEntryData()
|
||||||
@@ -368,8 +386,7 @@ void MacroConditionMacroEdit::UpdateEntryData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto test = _entryData->_type;
|
switch (_entryData->_type) {
|
||||||
switch (test) {
|
|
||||||
case MacroConditionMacro::Type::COUNT:
|
case MacroConditionMacro::Type::COUNT:
|
||||||
SetupCountWidgets();
|
SetupCountWidgets();
|
||||||
break;
|
break;
|
||||||
@@ -383,15 +400,15 @@ void MacroConditionMacroEdit::UpdateEntryData()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_macros->SetCurrentMacro(_entryData->_macro.get());
|
_macros->SetCurrentMacro(_entryData->_macro);
|
||||||
_types->setCurrentIndex(static_cast<int>(_entryData->_type));
|
_types->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||||
_counterConditions->setCurrentIndex(
|
_counterConditions->setCurrentIndex(
|
||||||
static_cast<int>(_entryData->_counterCondition));
|
static_cast<int>(_entryData->_counterCondition));
|
||||||
_count->setValue(_entryData->_count);
|
_count->SetValue(_entryData->_count);
|
||||||
_macroList->SetContent(_entryData->_macros);
|
_macroList->SetContent(_entryData->_macros);
|
||||||
_multiStateConditions->setCurrentIndex(
|
_multiStateConditions->setCurrentIndex(
|
||||||
static_cast<int>(_entryData->_multiSateCondition));
|
static_cast<int>(_entryData->_multiSateCondition));
|
||||||
_multiStateCount->setValue(_entryData->_multiSateCount);
|
_multiStateCount->SetValue(_entryData->_multiSateCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMacroEdit::MacroChanged(const QString &text)
|
void MacroConditionMacroEdit::MacroChanged(const QString &text)
|
||||||
@@ -401,12 +418,12 @@ void MacroConditionMacroEdit::MacroChanged(const QString &text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_macro.UpdateRef(text);
|
_entryData->_macro = text;
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMacroEdit::CountChanged(int value)
|
void MacroConditionMacroEdit::CountChanged(const NumberVariable<int> &value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
@@ -433,12 +450,9 @@ void MacroConditionMacroEdit::MacroRemove(const QString &)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_entryData->_macro.UpdateRef();
|
|
||||||
|
|
||||||
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;
|
||||||
@@ -473,18 +487,26 @@ void MacroConditionMacroEdit::TypeChanged(int type)
|
|||||||
|
|
||||||
void MacroConditionMacroEdit::ResetClicked()
|
void MacroConditionMacroEdit::ResetClicked()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData || !_entryData->_macro.get()) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_entryData->_macro->ResetRunCount();
|
auto macro = _entryData->_macro.GetMacro();
|
||||||
|
if (!macro) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
macro->ResetRunCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMacroEdit::UpdateCount()
|
void MacroConditionMacroEdit::UpdateCount()
|
||||||
{
|
{
|
||||||
if (_entryData && _entryData->_macro.get()) {
|
if (!_entryData) {
|
||||||
_currentCount->setText(
|
return;
|
||||||
QString::number(_entryData->_macro->RunCount()));
|
}
|
||||||
|
|
||||||
|
auto macro = _entryData->_macro.GetMacro();
|
||||||
|
if (macro) {
|
||||||
|
_currentCount->setText(QString::number(macro->RunCount()));
|
||||||
} else {
|
} else {
|
||||||
_currentCount->setText("-");
|
_currentCount->setText("-");
|
||||||
}
|
}
|
||||||
@@ -492,10 +514,11 @@ void MacroConditionMacroEdit::UpdateCount()
|
|||||||
|
|
||||||
void MacroConditionMacroEdit::UpdatePaused()
|
void MacroConditionMacroEdit::UpdatePaused()
|
||||||
{
|
{
|
||||||
|
auto macro = _entryData->_macro.GetMacro();
|
||||||
_pausedWarning->setVisible(
|
_pausedWarning->setVisible(
|
||||||
_entryData &&
|
_entryData &&
|
||||||
_entryData->_type != MacroConditionMacro::Type::MULTI_STATE &&
|
_entryData->_type != MacroConditionMacro::Type::MULTI_STATE &&
|
||||||
_entryData->_macro.get() && _entryData->_macro->Paused());
|
macro && macro->Paused());
|
||||||
adjustSize();
|
adjustSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,7 +533,8 @@ void MacroConditionMacroEdit::MultiStateConditionChanged(int cond)
|
|||||||
static_cast<MacroConditionMacro::MultiStateCondition>(cond);
|
static_cast<MacroConditionMacro::MultiStateCondition>(cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMacroEdit::MultiStateCountChanged(int value)
|
void MacroConditionMacroEdit::MultiStateCountChanged(
|
||||||
|
const NumberVariable<int> &value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "macro-selection.hpp"
|
#include "macro-selection.hpp"
|
||||||
#include "macro-list.hpp"
|
#include "macro-list.hpp"
|
||||||
|
#include "variable-spinbox.hpp"
|
||||||
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
@@ -22,6 +23,7 @@ public:
|
|||||||
bool CheckCondition();
|
bool CheckCondition();
|
||||||
bool Save(obs_data_t *obj) const;
|
bool Save(obs_data_t *obj) const;
|
||||||
bool Load(obs_data_t *obj);
|
bool Load(obs_data_t *obj);
|
||||||
|
bool PostLoad() override;
|
||||||
std::string GetShortDesc() const;
|
std::string GetShortDesc() const;
|
||||||
std::string GetId() const { return id; };
|
std::string GetId() const { return id; };
|
||||||
static std::shared_ptr<MacroCondition> Create(Macro *m)
|
static std::shared_ptr<MacroCondition> Create(Macro *m)
|
||||||
@@ -42,7 +44,7 @@ public:
|
|||||||
EQUAL,
|
EQUAL,
|
||||||
};
|
};
|
||||||
CounterCondition _counterCondition = CounterCondition::BELOW;
|
CounterCondition _counterCondition = CounterCondition::BELOW;
|
||||||
int _count = 0;
|
NumberVariable<int> _count = 0;
|
||||||
|
|
||||||
enum class MultiStateCondition {
|
enum class MultiStateCondition {
|
||||||
BELOW,
|
BELOW,
|
||||||
@@ -50,7 +52,7 @@ public:
|
|||||||
ABOVE,
|
ABOVE,
|
||||||
};
|
};
|
||||||
MultiStateCondition _multiSateCondition = MultiStateCondition::ABOVE;
|
MultiStateCondition _multiSateCondition = MultiStateCondition::ABOVE;
|
||||||
int _multiSateCount = 0;
|
NumberVariable<int> _multiSateCount = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CheckCountCondition();
|
bool CheckCountCondition();
|
||||||
@@ -81,13 +83,13 @@ private slots:
|
|||||||
void MacroChanged(const QString &text);
|
void MacroChanged(const QString &text);
|
||||||
void MacroRemove(const QString &name);
|
void MacroRemove(const QString &name);
|
||||||
void TypeChanged(int type);
|
void TypeChanged(int type);
|
||||||
void CountChanged(int value);
|
void CountChanged(const NumberVariable<int> &value);
|
||||||
void CountConditionChanged(int cond);
|
void CountConditionChanged(int cond);
|
||||||
void ResetClicked();
|
void ResetClicked();
|
||||||
void UpdateCount();
|
void UpdateCount();
|
||||||
void UpdatePaused();
|
void UpdatePaused();
|
||||||
void MultiStateConditionChanged(int cond);
|
void MultiStateConditionChanged(int cond);
|
||||||
void MultiStateCountChanged(int value);
|
void MultiStateCountChanged(const NumberVariable<int> &value);
|
||||||
void Add(const std::string &);
|
void Add(const std::string &);
|
||||||
void Remove(int);
|
void Remove(int);
|
||||||
void Replace(int, const std::string &);
|
void Replace(int, const std::string &);
|
||||||
@@ -98,7 +100,7 @@ protected:
|
|||||||
MacroSelection *_macros;
|
MacroSelection *_macros;
|
||||||
QComboBox *_types;
|
QComboBox *_types;
|
||||||
QComboBox *_counterConditions;
|
QComboBox *_counterConditions;
|
||||||
QSpinBox *_count;
|
VariableSpinBox *_count;
|
||||||
QLabel *_currentCount;
|
QLabel *_currentCount;
|
||||||
QLabel *_pausedWarning;
|
QLabel *_pausedWarning;
|
||||||
QPushButton *_resetCount;
|
QPushButton *_resetCount;
|
||||||
@@ -106,7 +108,7 @@ protected:
|
|||||||
QHBoxLayout *_settingsLine2;
|
QHBoxLayout *_settingsLine2;
|
||||||
MacroList *_macroList;
|
MacroList *_macroList;
|
||||||
QComboBox *_multiStateConditions;
|
QComboBox *_multiStateConditions;
|
||||||
QSpinBox *_multiStateCount;
|
VariableSpinBox *_multiStateCount;
|
||||||
QTimer _countTimer;
|
QTimer _countTimer;
|
||||||
QTimer _pausedTimer;
|
QTimer _pausedTimer;
|
||||||
std::shared_ptr<MacroConditionMacro> _entryData;
|
std::shared_ptr<MacroConditionMacro> _entryData;
|
||||||
|
|||||||
@@ -71,18 +71,18 @@ bool MacroConditionMedia::CheckTime()
|
|||||||
match = true;
|
match = true;
|
||||||
break;
|
break;
|
||||||
case Time::TIME_RESTRICTION_SHORTER:
|
case Time::TIME_RESTRICTION_SHORTER:
|
||||||
match = currentTime < _time.seconds * 1000;
|
match = currentTime < _time.Milliseconds();
|
||||||
break;
|
break;
|
||||||
case Time::TIME_RESTRICTION_LONGER:
|
case Time::TIME_RESTRICTION_LONGER:
|
||||||
match = currentTime > _time.seconds * 1000;
|
match = currentTime > _time.Milliseconds();
|
||||||
break;
|
break;
|
||||||
case Time::TIME_RESTRICTION_REMAINING_SHORTER:
|
case Time::TIME_RESTRICTION_REMAINING_SHORTER:
|
||||||
match = duration > currentTime &&
|
match = duration > currentTime &&
|
||||||
duration - currentTime < _time.seconds * 1000;
|
duration - currentTime < _time.Milliseconds();
|
||||||
break;
|
break;
|
||||||
case Time::TIME_RESTRICTION_REMAINING_LONGER:
|
case Time::TIME_RESTRICTION_REMAINING_LONGER:
|
||||||
match = duration > currentTime &&
|
match = duration > currentTime &&
|
||||||
duration - currentTime > _time.seconds * 1000;
|
duration - currentTime > _time.Milliseconds();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -401,9 +401,9 @@ static void populateSourceTypes(QComboBox *list)
|
|||||||
MacroConditionMediaEdit::MacroConditionMediaEdit(
|
MacroConditionMediaEdit::MacroConditionMediaEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroConditionMedia> entryData)
|
QWidget *parent, std::shared_ptr<MacroConditionMedia> entryData)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
|
_sourceTypes(new QComboBox()),
|
||||||
_scenes(new SceneSelectionWidget(window(), true, true, true, true,
|
_scenes(new SceneSelectionWidget(window(), true, true, true, true,
|
||||||
true)),
|
true)),
|
||||||
_sourceTypes(new QComboBox()),
|
|
||||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||||
_states(new QComboBox()),
|
_states(new QComboBox()),
|
||||||
_timeRestrictions(new QComboBox()),
|
_timeRestrictions(new QComboBox()),
|
||||||
@@ -429,10 +429,8 @@ MacroConditionMediaEdit::MacroConditionMediaEdit(
|
|||||||
SLOT(StateChanged(int)));
|
SLOT(StateChanged(int)));
|
||||||
QWidget::connect(_timeRestrictions, SIGNAL(currentIndexChanged(int)),
|
QWidget::connect(_timeRestrictions, SIGNAL(currentIndexChanged(int)),
|
||||||
this, SLOT(TimeRestrictionChanged(int)));
|
this, SLOT(TimeRestrictionChanged(int)));
|
||||||
QWidget::connect(_time, SIGNAL(DurationChanged(double)), this,
|
QWidget::connect(_time, SIGNAL(DurationChanged(const Duration &)), this,
|
||||||
SLOT(TimeChanged(double)));
|
SLOT(TimeChanged(const Duration &)));
|
||||||
QWidget::connect(_time, SIGNAL(UnitChanged(DurationUnit)), this,
|
|
||||||
SLOT(TimeUnitChanged(DurationUnit)));
|
|
||||||
QWidget::connect(_onChange, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_onChange, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(OnChangeChanged(int)));
|
SLOT(OnChangeChanged(int)));
|
||||||
|
|
||||||
@@ -560,27 +558,14 @@ void MacroConditionMediaEdit::TimeRestrictionChanged(int index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMediaEdit::TimeChanged(double seconds)
|
void MacroConditionMediaEdit::TimeChanged(const Duration &dur)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_time.seconds = seconds;
|
_entryData->_time = dur;
|
||||||
if (_entryData->_sourceType != MacroConditionMedia::Type::SOURCE) {
|
|
||||||
_entryData->UpdateMediaSourcesOfSceneList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroConditionMediaEdit::TimeUnitChanged(DurationUnit unit)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_time.displayUnit = unit;
|
|
||||||
if (_entryData->_sourceType != MacroConditionMedia::Type::SOURCE) {
|
if (_entryData->_sourceType != MacroConditionMedia::Type::SOURCE) {
|
||||||
_entryData->UpdateMediaSourcesOfSceneList();
|
_entryData->UpdateMediaSourcesOfSceneList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,8 +116,7 @@ private slots:
|
|||||||
void SceneChanged(const SceneSelection &);
|
void SceneChanged(const SceneSelection &);
|
||||||
void StateChanged(int index);
|
void StateChanged(int index);
|
||||||
void TimeRestrictionChanged(int index);
|
void TimeRestrictionChanged(int index);
|
||||||
void TimeChanged(double seconds);
|
void TimeChanged(const Duration &seconds);
|
||||||
void TimeUnitChanged(DurationUnit unit);
|
|
||||||
void OnChangeChanged(int);
|
void OnChangeChanged(int);
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|||||||
@@ -10,41 +10,43 @@ bool MacroConditionStats::_registered = MacroConditionFactory::Register(
|
|||||||
{MacroConditionStats::Create, MacroConditionStatsEdit::Create,
|
{MacroConditionStats::Create, MacroConditionStatsEdit::Create,
|
||||||
"AdvSceneSwitcher.condition.stats"});
|
"AdvSceneSwitcher.condition.stats"});
|
||||||
|
|
||||||
static std::map<StatsType, std::string> statsTypes = {
|
static std::map<MacroConditionStats::Type, std::string> statsTypes = {
|
||||||
{StatsType::FPS, "AdvSceneSwitcher.condition.stats.type.fps"},
|
{MacroConditionStats::Type::FPS,
|
||||||
{StatsType::CPU_USAGE,
|
"AdvSceneSwitcher.condition.stats.type.fps"},
|
||||||
|
{MacroConditionStats::Type::CPU_USAGE,
|
||||||
"AdvSceneSwitcher.condition.stats.type.CPUUsage"},
|
"AdvSceneSwitcher.condition.stats.type.CPUUsage"},
|
||||||
{StatsType::DISK_USAGE,
|
{MacroConditionStats::Type::DISK_USAGE,
|
||||||
"AdvSceneSwitcher.condition.stats.type.HDDSpaceAvailable"},
|
"AdvSceneSwitcher.condition.stats.type.HDDSpaceAvailable"},
|
||||||
{StatsType::MEM_USAGE,
|
{MacroConditionStats::Type::MEM_USAGE,
|
||||||
"AdvSceneSwitcher.condition.stats.type.memoryUsage"},
|
"AdvSceneSwitcher.condition.stats.type.memoryUsage"},
|
||||||
{StatsType::AVG_FRAMETIME,
|
{MacroConditionStats::Type::AVG_FRAMETIME,
|
||||||
"AdvSceneSwitcher.condition.stats.type.averageTimeToRender"},
|
"AdvSceneSwitcher.condition.stats.type.averageTimeToRender"},
|
||||||
{StatsType::RENDER_LAG,
|
{MacroConditionStats::Type::RENDER_LAG,
|
||||||
"AdvSceneSwitcher.condition.stats.type.missedFrames"},
|
"AdvSceneSwitcher.condition.stats.type.missedFrames"},
|
||||||
{StatsType::ENCODE_LAG,
|
{MacroConditionStats::Type::ENCODE_LAG,
|
||||||
"AdvSceneSwitcher.condition.stats.type.skippedFrames"},
|
"AdvSceneSwitcher.condition.stats.type.skippedFrames"},
|
||||||
{StatsType::STREAM_DROPPED_FRAMES,
|
{MacroConditionStats::Type::STREAM_DROPPED_FRAMES,
|
||||||
"AdvSceneSwitcher.condition.stats.type.droppedFrames.stream"},
|
"AdvSceneSwitcher.condition.stats.type.droppedFrames.stream"},
|
||||||
{StatsType::STREAM_BITRATE,
|
{MacroConditionStats::Type::STREAM_BITRATE,
|
||||||
"AdvSceneSwitcher.condition.stats.type.bitrate.stream"},
|
"AdvSceneSwitcher.condition.stats.type.bitrate.stream"},
|
||||||
{StatsType::STREAM_MB_SENT,
|
{MacroConditionStats::Type::STREAM_MB_SENT,
|
||||||
"AdvSceneSwitcher.condition.stats.type.megabytesSent.stream"},
|
"AdvSceneSwitcher.condition.stats.type.megabytesSent.stream"},
|
||||||
{StatsType::RECORDING_DROPPED_FRAMES,
|
{MacroConditionStats::Type::RECORDING_DROPPED_FRAMES,
|
||||||
"AdvSceneSwitcher.condition.stats.type.droppedFrames.recording"},
|
"AdvSceneSwitcher.condition.stats.type.droppedFrames.recording"},
|
||||||
{StatsType::RECORDING_BITRATE,
|
{MacroConditionStats::Type::RECORDING_BITRATE,
|
||||||
"AdvSceneSwitcher.condition.stats.type.bitrate.recording"},
|
"AdvSceneSwitcher.condition.stats.type.bitrate.recording"},
|
||||||
{StatsType::RECORDING_MB_SENT,
|
{MacroConditionStats::Type::RECORDING_MB_SENT,
|
||||||
"AdvSceneSwitcher.condition.stats.type.megabytesSent.recording"},
|
"AdvSceneSwitcher.condition.stats.type.megabytesSent.recording"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::map<StatsCondition, std::string> statsConditionTypes = {
|
static std::map<MacroConditionStats::Condition, std::string>
|
||||||
{StatsCondition::ABOVE,
|
statsConditionTypes = {
|
||||||
"AdvSceneSwitcher.condition.stats.condition.above"},
|
{MacroConditionStats::Condition::ABOVE,
|
||||||
{StatsCondition::EQUALS,
|
"AdvSceneSwitcher.condition.stats.condition.above"},
|
||||||
"AdvSceneSwitcher.condition.stats.condition.equals"},
|
{MacroConditionStats::Condition::EQUALS,
|
||||||
{StatsCondition::BELOW,
|
"AdvSceneSwitcher.condition.stats.condition.equals"},
|
||||||
"AdvSceneSwitcher.condition.stats.condition.below"},
|
{MacroConditionStats::Condition::BELOW,
|
||||||
|
"AdvSceneSwitcher.condition.stats.condition.below"},
|
||||||
};
|
};
|
||||||
|
|
||||||
MacroConditionStats::MacroConditionStats(Macro *m)
|
MacroConditionStats::MacroConditionStats(Macro *m)
|
||||||
@@ -60,11 +62,11 @@ MacroConditionStats::~MacroConditionStats()
|
|||||||
bool MacroConditionStats::CheckFPS()
|
bool MacroConditionStats::CheckFPS()
|
||||||
{
|
{
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case StatsCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
return obs_get_active_fps() > _value;
|
return obs_get_active_fps() > _value;
|
||||||
case StatsCondition::EQUALS:
|
case Condition::EQUALS:
|
||||||
return doubleEquals(obs_get_active_fps(), _value, 0.01);
|
return doubleEquals(obs_get_active_fps(), _value, 0.01);
|
||||||
case StatsCondition::BELOW:
|
case Condition::BELOW:
|
||||||
return obs_get_active_fps() < _value;
|
return obs_get_active_fps() < _value;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -77,11 +79,11 @@ bool MacroConditionStats::CheckCPU()
|
|||||||
double usage = os_cpu_usage_info_query(_cpu_info);
|
double usage = os_cpu_usage_info_query(_cpu_info);
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case StatsCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
return usage > _value;
|
return usage > _value;
|
||||||
case StatsCondition::EQUALS:
|
case Condition::EQUALS:
|
||||||
return doubleEquals(usage, _value, 0.1);
|
return doubleEquals(usage, _value, 0.1);
|
||||||
case StatsCondition::BELOW:
|
case Condition::BELOW:
|
||||||
return usage < _value;
|
return usage < _value;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -95,11 +97,11 @@ bool MacroConditionStats::CheckMemory()
|
|||||||
(long double)os_get_proc_resident_size() / (1024.0l * 1024.0l);
|
(long double)os_get_proc_resident_size() / (1024.0l * 1024.0l);
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case StatsCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
return rss > _value;
|
return rss > _value;
|
||||||
case StatsCondition::EQUALS:
|
case Condition::EQUALS:
|
||||||
return doubleEquals(rss, _value, 0.1);
|
return doubleEquals(rss, _value, 0.1);
|
||||||
case StatsCondition::BELOW:
|
case Condition::BELOW:
|
||||||
return rss < _value;
|
return rss < _value;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -112,11 +114,11 @@ bool MacroConditionStats::CheckAvgFrametime()
|
|||||||
auto num = (long double)obs_get_average_frame_time_ns() / 1000000.0l;
|
auto num = (long double)obs_get_average_frame_time_ns() / 1000000.0l;
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case StatsCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
return num > _value;
|
return num > _value;
|
||||||
case StatsCondition::EQUALS:
|
case Condition::EQUALS:
|
||||||
return doubleEquals(num, _value, 0.1);
|
return doubleEquals(num, _value, 0.1);
|
||||||
case StatsCondition::BELOW:
|
case Condition::BELOW:
|
||||||
return num < _value;
|
return num < _value;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -142,11 +144,11 @@ bool MacroConditionStats::CheckRenderLag()
|
|||||||
num *= 100.0l;
|
num *= 100.0l;
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case StatsCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
return num > _value;
|
return num > _value;
|
||||||
case StatsCondition::EQUALS:
|
case Condition::EQUALS:
|
||||||
return doubleEquals(num, _value, 0.1);
|
return doubleEquals(num, _value, 0.1);
|
||||||
case StatsCondition::BELOW:
|
case Condition::BELOW:
|
||||||
return num < _value;
|
return num < _value;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -173,11 +175,11 @@ bool MacroConditionStats::CheckEncodeLag()
|
|||||||
num *= 100.0l;
|
num *= 100.0l;
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case StatsCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
return num > _value;
|
return num > _value;
|
||||||
case StatsCondition::EQUALS:
|
case Condition::EQUALS:
|
||||||
return doubleEquals(num, _value, 0.1);
|
return doubleEquals(num, _value, 0.1);
|
||||||
case StatsCondition::BELOW:
|
case Condition::BELOW:
|
||||||
return num < _value;
|
return num < _value;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -230,11 +232,11 @@ bool MacroConditionStats::CheckStreamDroppedFrames()
|
|||||||
obs_output_release(output);
|
obs_output_release(output);
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case StatsCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
return _streamInfo.dropped_relative > _value;
|
return _streamInfo.dropped_relative > _value;
|
||||||
case StatsCondition::EQUALS:
|
case Condition::EQUALS:
|
||||||
return doubleEquals(_streamInfo.dropped_relative, _value, 0.1);
|
return doubleEquals(_streamInfo.dropped_relative, _value, 0.1);
|
||||||
case StatsCondition::BELOW:
|
case Condition::BELOW:
|
||||||
return _streamInfo.dropped_relative < _value;
|
return _streamInfo.dropped_relative < _value;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -249,11 +251,11 @@ bool MacroConditionStats::CheckStreamBitrate()
|
|||||||
obs_output_release(output);
|
obs_output_release(output);
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case StatsCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
return _streamInfo.kbps > _value;
|
return _streamInfo.kbps > _value;
|
||||||
case StatsCondition::EQUALS:
|
case Condition::EQUALS:
|
||||||
return doubleEquals(_streamInfo.kbps, _value, 1.0);
|
return doubleEquals(_streamInfo.kbps, _value, 1.0);
|
||||||
case StatsCondition::BELOW:
|
case Condition::BELOW:
|
||||||
return _streamInfo.kbps < _value;
|
return _streamInfo.kbps < _value;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -269,11 +271,11 @@ bool MacroConditionStats::CheckStreamMBSent()
|
|||||||
long double num = (long double)totalBytes / (1024.0l * 1024.0l);
|
long double num = (long double)totalBytes / (1024.0l * 1024.0l);
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case StatsCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
return num > _value;
|
return num > _value;
|
||||||
case StatsCondition::EQUALS:
|
case Condition::EQUALS:
|
||||||
return doubleEquals(num, _value, 0.1);
|
return doubleEquals(num, _value, 0.1);
|
||||||
case StatsCondition::BELOW:
|
case Condition::BELOW:
|
||||||
return num < _value;
|
return num < _value;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -288,12 +290,12 @@ bool MacroConditionStats::CheckRecordingDroppedFrames()
|
|||||||
obs_output_release(output);
|
obs_output_release(output);
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case StatsCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
return _recordingInfo.dropped_relative > _value;
|
return _recordingInfo.dropped_relative > _value;
|
||||||
case StatsCondition::EQUALS:
|
case Condition::EQUALS:
|
||||||
return doubleEquals(_recordingInfo.dropped_relative, _value,
|
return doubleEquals(_recordingInfo.dropped_relative, _value,
|
||||||
0.1);
|
0.1);
|
||||||
case StatsCondition::BELOW:
|
case Condition::BELOW:
|
||||||
return _recordingInfo.dropped_relative < _value;
|
return _recordingInfo.dropped_relative < _value;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -308,11 +310,11 @@ bool MacroConditionStats::CheckRecordingBitrate()
|
|||||||
obs_output_release(output);
|
obs_output_release(output);
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case StatsCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
return _recordingInfo.kbps > _value;
|
return _recordingInfo.kbps > _value;
|
||||||
case StatsCondition::EQUALS:
|
case Condition::EQUALS:
|
||||||
return doubleEquals(_recordingInfo.kbps, _value, 1.0);
|
return doubleEquals(_recordingInfo.kbps, _value, 1.0);
|
||||||
case StatsCondition::BELOW:
|
case Condition::BELOW:
|
||||||
return _recordingInfo.kbps < _value;
|
return _recordingInfo.kbps < _value;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -328,11 +330,11 @@ bool MacroConditionStats::CheckRecordingMBSent()
|
|||||||
long double num = (long double)totalBytes / (1024.0l * 1024.0l);
|
long double num = (long double)totalBytes / (1024.0l * 1024.0l);
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case StatsCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
return num > _value;
|
return num > _value;
|
||||||
case StatsCondition::EQUALS:
|
case Condition::EQUALS:
|
||||||
return doubleEquals(num, _value, 0.1);
|
return doubleEquals(num, _value, 0.1);
|
||||||
case StatsCondition::BELOW:
|
case Condition::BELOW:
|
||||||
return num < _value;
|
return num < _value;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -343,32 +345,32 @@ bool MacroConditionStats::CheckRecordingMBSent()
|
|||||||
bool MacroConditionStats::CheckCondition()
|
bool MacroConditionStats::CheckCondition()
|
||||||
{
|
{
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case StatsType::FPS:
|
case Type::FPS:
|
||||||
return CheckFPS();
|
return CheckFPS();
|
||||||
case StatsType::CPU_USAGE:
|
case Type::CPU_USAGE:
|
||||||
return CheckCPU();
|
return CheckCPU();
|
||||||
case StatsType::DISK_USAGE:
|
case Type::DISK_USAGE:
|
||||||
// TODO: not implemented
|
// TODO: not implemented
|
||||||
break;
|
break;
|
||||||
case StatsType::MEM_USAGE:
|
case Type::MEM_USAGE:
|
||||||
return CheckMemory();
|
return CheckMemory();
|
||||||
case StatsType::AVG_FRAMETIME:
|
case Type::AVG_FRAMETIME:
|
||||||
return CheckAvgFrametime();
|
return CheckAvgFrametime();
|
||||||
case StatsType::RENDER_LAG:
|
case Type::RENDER_LAG:
|
||||||
return CheckRenderLag();
|
return CheckRenderLag();
|
||||||
case StatsType::ENCODE_LAG:
|
case Type::ENCODE_LAG:
|
||||||
return CheckEncodeLag();
|
return CheckEncodeLag();
|
||||||
case StatsType::STREAM_DROPPED_FRAMES:
|
case Type::STREAM_DROPPED_FRAMES:
|
||||||
return CheckStreamDroppedFrames();
|
return CheckStreamDroppedFrames();
|
||||||
case StatsType::STREAM_BITRATE:
|
case Type::STREAM_BITRATE:
|
||||||
return CheckStreamBitrate();
|
return CheckStreamBitrate();
|
||||||
case StatsType::STREAM_MB_SENT:
|
case Type::STREAM_MB_SENT:
|
||||||
return CheckStreamMBSent();
|
return CheckStreamMBSent();
|
||||||
case StatsType::RECORDING_DROPPED_FRAMES:
|
case Type::RECORDING_DROPPED_FRAMES:
|
||||||
return CheckRecordingDroppedFrames();
|
return CheckRecordingDroppedFrames();
|
||||||
case StatsType::RECORDING_BITRATE:
|
case Type::RECORDING_BITRATE:
|
||||||
return CheckRecordingBitrate();
|
return CheckRecordingBitrate();
|
||||||
case StatsType::RECORDING_MB_SENT:
|
case Type::RECORDING_MB_SENT:
|
||||||
return CheckRecordingMBSent();
|
return CheckRecordingMBSent();
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -380,9 +382,10 @@ bool MacroConditionStats::CheckCondition()
|
|||||||
bool MacroConditionStats::Save(obs_data_t *obj) const
|
bool MacroConditionStats::Save(obs_data_t *obj) const
|
||||||
{
|
{
|
||||||
MacroCondition::Save(obj);
|
MacroCondition::Save(obj);
|
||||||
obs_data_set_double(obj, "value", _value);
|
_value.Save(obj, "value");
|
||||||
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
||||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||||
|
obs_data_set_int(obj, "version", 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,10 +393,14 @@ bool MacroConditionStats::Load(obs_data_t *obj)
|
|||||||
{
|
{
|
||||||
|
|
||||||
MacroCondition::Load(obj);
|
MacroCondition::Load(obj);
|
||||||
_value = obs_data_get_double(obj, "value");
|
if (!obs_data_has_user_value(obj, "version")) {
|
||||||
_type = static_cast<StatsType>(obs_data_get_int(obj, "type"));
|
_value = obs_data_get_double(obj, "value");
|
||||||
_condition =
|
} else {
|
||||||
static_cast<StatsCondition>(obs_data_get_int(obj, "condition"));
|
_value.Load(obj, "value");
|
||||||
|
}
|
||||||
|
_type = static_cast<MacroConditionStats::Type>(
|
||||||
|
obs_data_get_int(obj, "type"));
|
||||||
|
_condition = static_cast<Condition>(obs_data_get_int(obj, "condition"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,7 +419,7 @@ static inline void populateStatsTypes(QComboBox *list)
|
|||||||
for (auto entry : statsTypes) {
|
for (auto entry : statsTypes) {
|
||||||
list->addItem(obs_module_text(entry.second.c_str()));
|
list->addItem(obs_module_text(entry.second.c_str()));
|
||||||
// TODO: not implemented
|
// TODO: not implemented
|
||||||
if (entry.first == StatsType::DISK_USAGE) {
|
if (entry.first == MacroConditionStats::Type::DISK_USAGE) {
|
||||||
qobject_cast<QListView *>(list->view())
|
qobject_cast<QListView *>(list->view())
|
||||||
->setRowHidden(list->count() - 1, true);
|
->setRowHidden(list->count() - 1, true);
|
||||||
}
|
}
|
||||||
@@ -430,9 +437,9 @@ static inline void populateConditionSelection(QComboBox *list)
|
|||||||
MacroConditionStatsEdit::MacroConditionStatsEdit(
|
MacroConditionStatsEdit::MacroConditionStatsEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroConditionStats> entryData)
|
QWidget *parent, std::shared_ptr<MacroConditionStats> entryData)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
_stats(new QComboBox),
|
_stats(new QComboBox()),
|
||||||
_condition(new QComboBox),
|
_condition(new QComboBox()),
|
||||||
_value(new QDoubleSpinBox)
|
_value(new VariableDoubleSpinBox())
|
||||||
{
|
{
|
||||||
_value->setMaximum(999999999999);
|
_value->setMaximum(999999999999);
|
||||||
|
|
||||||
@@ -442,8 +449,10 @@ MacroConditionStatsEdit::MacroConditionStatsEdit(
|
|||||||
setToolTip(
|
setToolTip(
|
||||||
obs_module_text("AdvSceneSwitcher.condition.stats.dockHint"));
|
obs_module_text("AdvSceneSwitcher.condition.stats.dockHint"));
|
||||||
|
|
||||||
QWidget::connect(_value, SIGNAL(valueChanged(double)), this,
|
QWidget::connect(
|
||||||
SLOT(ValueChanged(double)));
|
_value,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
|
||||||
|
this, SLOT(ValueChanged(const NumberVariable<double> &)));
|
||||||
QWidget::connect(_stats, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_stats, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(StatsTypeChanged(int)));
|
SLOT(StatsTypeChanged(int)));
|
||||||
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
||||||
@@ -464,7 +473,7 @@ MacroConditionStatsEdit::MacroConditionStatsEdit(
|
|||||||
_loading = false;
|
_loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionStatsEdit::ValueChanged(double value)
|
void MacroConditionStatsEdit::ValueChanged(const NumberVariable<double> &value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
@@ -482,10 +491,11 @@ void MacroConditionStatsEdit::StatsTypeChanged(int type)
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_type = static_cast<StatsType>(type);
|
_entryData->_type =
|
||||||
|
static_cast<MacroConditionStats::Type>(type);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
_value->setValue(0);
|
_value->SetFixedValue(0);
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
@@ -497,7 +507,8 @@ void MacroConditionStatsEdit::ConditionChanged(int cond)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_condition = static_cast<StatsCondition>(cond);
|
_entryData->_condition =
|
||||||
|
static_cast<MacroConditionStats::Condition>(cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionStatsEdit::UpdateEntryData()
|
void MacroConditionStatsEdit::UpdateEntryData()
|
||||||
@@ -506,7 +517,7 @@ void MacroConditionStatsEdit::UpdateEntryData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_value->setValue(_entryData->_value);
|
_value->SetValue(_entryData->_value);
|
||||||
_stats->setCurrentIndex(static_cast<int>(_entryData->_type));
|
_stats->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||||
_condition->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
_condition->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
@@ -519,55 +530,55 @@ void MacroConditionStatsEdit::SetWidgetVisibility()
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (_entryData->_type) {
|
switch (_entryData->_type) {
|
||||||
case StatsType::FPS:
|
case MacroConditionStats::Type::FPS:
|
||||||
_value->setMaximum(1000);
|
_value->setMaximum(1000);
|
||||||
_value->setSuffix("");
|
_value->setSuffix("");
|
||||||
break;
|
break;
|
||||||
case StatsType::CPU_USAGE:
|
case MacroConditionStats::Type::CPU_USAGE:
|
||||||
_value->setMaximum(100);
|
_value->setMaximum(100);
|
||||||
_value->setSuffix("%");
|
_value->setSuffix("%");
|
||||||
break;
|
break;
|
||||||
case StatsType::DISK_USAGE:
|
case MacroConditionStats::Type::DISK_USAGE:
|
||||||
_value->setMaximum(999999999999);
|
_value->setMaximum(999999999999);
|
||||||
_value->setSuffix("MB");
|
_value->setSuffix("MB");
|
||||||
break;
|
break;
|
||||||
case StatsType::MEM_USAGE:
|
case MacroConditionStats::Type::MEM_USAGE:
|
||||||
_value->setMaximum(999999999999);
|
_value->setMaximum(999999999999);
|
||||||
_value->setSuffix("MB");
|
_value->setSuffix("MB");
|
||||||
break;
|
break;
|
||||||
case StatsType::AVG_FRAMETIME:
|
case MacroConditionStats::Type::AVG_FRAMETIME:
|
||||||
_value->setMaximum(999999999999);
|
_value->setMaximum(999999999999);
|
||||||
_value->setSuffix("ms");
|
_value->setSuffix("ms");
|
||||||
break;
|
break;
|
||||||
case StatsType::RENDER_LAG:
|
case MacroConditionStats::Type::RENDER_LAG:
|
||||||
_value->setMaximum(100);
|
_value->setMaximum(100);
|
||||||
_value->setSuffix("%");
|
_value->setSuffix("%");
|
||||||
break;
|
break;
|
||||||
case StatsType::ENCODE_LAG:
|
case MacroConditionStats::Type::ENCODE_LAG:
|
||||||
_value->setMaximum(100);
|
_value->setMaximum(100);
|
||||||
_value->setSuffix("%");
|
_value->setSuffix("%");
|
||||||
break;
|
break;
|
||||||
case StatsType::STREAM_DROPPED_FRAMES:
|
case MacroConditionStats::Type::STREAM_DROPPED_FRAMES:
|
||||||
_value->setMaximum(100);
|
_value->setMaximum(100);
|
||||||
_value->setSuffix("%");
|
_value->setSuffix("%");
|
||||||
break;
|
break;
|
||||||
case StatsType::STREAM_BITRATE:
|
case MacroConditionStats::Type::STREAM_BITRATE:
|
||||||
_value->setMaximum(999999999999);
|
_value->setMaximum(999999999999);
|
||||||
_value->setSuffix("kb/s");
|
_value->setSuffix("kb/s");
|
||||||
break;
|
break;
|
||||||
case StatsType::STREAM_MB_SENT:
|
case MacroConditionStats::Type::STREAM_MB_SENT:
|
||||||
_value->setMaximum(999999999999);
|
_value->setMaximum(999999999999);
|
||||||
_value->setSuffix("MB");
|
_value->setSuffix("MB");
|
||||||
break;
|
break;
|
||||||
case StatsType::RECORDING_DROPPED_FRAMES:
|
case MacroConditionStats::Type::RECORDING_DROPPED_FRAMES:
|
||||||
_value->setMaximum(100);
|
_value->setMaximum(100);
|
||||||
_value->setSuffix("%");
|
_value->setSuffix("%");
|
||||||
break;
|
break;
|
||||||
case StatsType::RECORDING_BITRATE:
|
case MacroConditionStats::Type::RECORDING_BITRATE:
|
||||||
_value->setMaximum(999999999999);
|
_value->setMaximum(999999999999);
|
||||||
_value->setSuffix("kb/s");
|
_value->setSuffix("kb/s");
|
||||||
break;
|
break;
|
||||||
case StatsType::RECORDING_MB_SENT:
|
case MacroConditionStats::Type::RECORDING_MB_SENT:
|
||||||
_value->setMaximum(999999999999);
|
_value->setMaximum(999999999999);
|
||||||
_value->setSuffix("MB");
|
_value->setSuffix("MB");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -2,31 +2,9 @@
|
|||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QDoubleSpinBox>
|
#include <variable-spinbox.hpp>
|
||||||
#include <util/platform.h>
|
#include <util/platform.h>
|
||||||
|
|
||||||
enum class StatsType {
|
|
||||||
FPS,
|
|
||||||
CPU_USAGE,
|
|
||||||
DISK_USAGE, // not implemented
|
|
||||||
MEM_USAGE,
|
|
||||||
AVG_FRAMETIME,
|
|
||||||
RENDER_LAG,
|
|
||||||
ENCODE_LAG,
|
|
||||||
STREAM_DROPPED_FRAMES,
|
|
||||||
STREAM_BITRATE,
|
|
||||||
STREAM_MB_SENT,
|
|
||||||
RECORDING_DROPPED_FRAMES, // not sure if this makes sense
|
|
||||||
RECORDING_BITRATE,
|
|
||||||
RECORDING_MB_SENT,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class StatsCondition {
|
|
||||||
ABOVE,
|
|
||||||
EQUALS,
|
|
||||||
BELOW,
|
|
||||||
};
|
|
||||||
|
|
||||||
class MacroConditionStats : public MacroCondition {
|
class MacroConditionStats : public MacroCondition {
|
||||||
public:
|
public:
|
||||||
MacroConditionStats(Macro *m);
|
MacroConditionStats(Macro *m);
|
||||||
@@ -41,9 +19,31 @@ public:
|
|||||||
return std::make_shared<MacroConditionStats>(m);
|
return std::make_shared<MacroConditionStats>(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
double _value = 0;
|
NumberVariable<double> _value = 0.0;
|
||||||
StatsType _type = StatsType::FPS;
|
|
||||||
StatsCondition _condition = StatsCondition::ABOVE;
|
enum class Type {
|
||||||
|
FPS,
|
||||||
|
CPU_USAGE,
|
||||||
|
DISK_USAGE, // not implemented
|
||||||
|
MEM_USAGE,
|
||||||
|
AVG_FRAMETIME,
|
||||||
|
RENDER_LAG,
|
||||||
|
ENCODE_LAG,
|
||||||
|
STREAM_DROPPED_FRAMES,
|
||||||
|
STREAM_BITRATE,
|
||||||
|
STREAM_MB_SENT,
|
||||||
|
RECORDING_DROPPED_FRAMES, // not sure if this makes sense
|
||||||
|
RECORDING_BITRATE,
|
||||||
|
RECORDING_MB_SENT,
|
||||||
|
};
|
||||||
|
Type _type = Type::FPS;
|
||||||
|
|
||||||
|
enum class Condition {
|
||||||
|
ABOVE,
|
||||||
|
EQUALS,
|
||||||
|
BELOW,
|
||||||
|
};
|
||||||
|
Condition _condition = Condition::ABOVE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CheckFPS();
|
bool CheckFPS();
|
||||||
@@ -98,7 +98,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ValueChanged(double value);
|
void ValueChanged(const NumberVariable<double> &value);
|
||||||
void StatsTypeChanged(int type);
|
void StatsTypeChanged(int type);
|
||||||
void ConditionChanged(int cond);
|
void ConditionChanged(int cond);
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ signals:
|
|||||||
protected:
|
protected:
|
||||||
QComboBox *_stats;
|
QComboBox *_stats;
|
||||||
QComboBox *_condition;
|
QComboBox *_condition;
|
||||||
QDoubleSpinBox *_value;
|
VariableDoubleSpinBox *_value;
|
||||||
std::shared_ptr<MacroConditionStats> _entryData;
|
std::shared_ptr<MacroConditionStats> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
222
src/macro-core/macro-condition-run.cpp
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
#include "macro-condition-edit.hpp"
|
||||||
|
#include "macro-condition-run.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
|
||||||
|
const std::string MacroConditionRun::id = "run";
|
||||||
|
|
||||||
|
bool MacroConditionRun::_registered = MacroConditionFactory::Register(
|
||||||
|
MacroConditionRun::id,
|
||||||
|
{MacroConditionRun::Create, MacroConditionRunEdit::Create,
|
||||||
|
"AdvSceneSwitcher.condition.run"});
|
||||||
|
|
||||||
|
MacroConditionRun::~MacroConditionRun()
|
||||||
|
{
|
||||||
|
if (_thread.joinable()) {
|
||||||
|
_thread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionRun::CheckCondition()
|
||||||
|
{
|
||||||
|
if (!_threadDone) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
switch (_procStatus) {
|
||||||
|
case MacroConditionRun::Status::FAILED_TO_START:
|
||||||
|
SetVariableValue("Failed to start process");
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
case MacroConditionRun::Status::TIMEOUT:
|
||||||
|
SetVariableValue("Timeout while running process");
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
case MacroConditionRun::Status::OK:
|
||||||
|
ret = _checkExitCode ? _exitCode == _procExitCode : true;
|
||||||
|
SetVariableValue(std::to_string(_procExitCode));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_thread.joinable()) {
|
||||||
|
_thread.join();
|
||||||
|
}
|
||||||
|
_threadDone = false;
|
||||||
|
_thread = std::thread(&MacroConditionRun::RunProcess, this);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionRun::RunProcess()
|
||||||
|
{
|
||||||
|
QProcess process;
|
||||||
|
process.setWorkingDirectory(
|
||||||
|
QString::fromStdString(_procConfig.WorkingDir()));
|
||||||
|
process.start(QString::fromStdString(_procConfig.Path()),
|
||||||
|
_procConfig.Args());
|
||||||
|
int timeout = _timeout.Milliseconds();
|
||||||
|
|
||||||
|
vblog(LOG_INFO, "run \"%s\" with a timeout of %d ms",
|
||||||
|
_procConfig.Path().c_str(), timeout);
|
||||||
|
|
||||||
|
bool procFinishedInTime = process.waitForFinished(timeout);
|
||||||
|
|
||||||
|
if (!procFinishedInTime) {
|
||||||
|
if (process.error() == QProcess::FailedToStart) {
|
||||||
|
vblog(LOG_INFO, "failed to start \"%s\"!",
|
||||||
|
_procConfig.Path().c_str());
|
||||||
|
_procStatus = Status::FAILED_TO_START;
|
||||||
|
} else {
|
||||||
|
vblog(LOG_INFO,
|
||||||
|
"timeout while running \"%s\"\nAttempting to kill process!",
|
||||||
|
_procConfig.Path().c_str());
|
||||||
|
process.kill();
|
||||||
|
process.waitForFinished();
|
||||||
|
_procStatus = Status::TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validExitCode = process.exitStatus() == QProcess::NormalExit;
|
||||||
|
|
||||||
|
if ((_checkExitCode && !validExitCode) || !procFinishedInTime) {
|
||||||
|
_threadDone = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_procExitCode = process.exitCode();
|
||||||
|
_procStatus = Status::OK;
|
||||||
|
_threadDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionRun::Save(obs_data_t *obj) const
|
||||||
|
{
|
||||||
|
MacroCondition::Save(obj);
|
||||||
|
_procConfig.Save(obj);
|
||||||
|
obs_data_set_bool(obj, "checkExitCode", _checkExitCode);
|
||||||
|
obs_data_set_int(obj, "exitCode", _exitCode);
|
||||||
|
_timeout.Save(obj, "timeout");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionRun::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroCondition::Load(obj);
|
||||||
|
_procConfig.Load(obj);
|
||||||
|
_checkExitCode = obs_data_get_bool(obj, "checkExitCode");
|
||||||
|
_exitCode = obs_data_get_int(obj, "exitCode");
|
||||||
|
_timeout.Load(obj, "timeout");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MacroConditionRun::GetShortDesc() const
|
||||||
|
{
|
||||||
|
return _procConfig.UnresolvedPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroConditionRunEdit::MacroConditionRunEdit(
|
||||||
|
QWidget *parent, std::shared_ptr<MacroConditionRun> entryData)
|
||||||
|
: QWidget(parent),
|
||||||
|
_procConfig(new ProcessConfigEdit(this)),
|
||||||
|
_checkExitCode(new QCheckBox()),
|
||||||
|
_exitCode(new QSpinBox()),
|
||||||
|
_timeout(new DurationSelection(this, false, 0.1))
|
||||||
|
{
|
||||||
|
_exitCode->setMinimum(-99999);
|
||||||
|
_exitCode->setMaximum(999999);
|
||||||
|
|
||||||
|
QWidget::connect(_procConfig,
|
||||||
|
SIGNAL(ConfigChanged(const ProcessConfig &)), this,
|
||||||
|
SLOT(ProcessConfigChanged(const ProcessConfig &)));
|
||||||
|
QWidget::connect(_timeout, SIGNAL(DurationChanged(const Duration &)),
|
||||||
|
this, SLOT(TimeoutChanged(const Duration &)));
|
||||||
|
QWidget::connect(_checkExitCode, SIGNAL(stateChanged(int)), this,
|
||||||
|
SLOT(CheckExitCodeChanged(int)));
|
||||||
|
QWidget::connect(_exitCode, SIGNAL(valueChanged(int)), this,
|
||||||
|
SLOT(ExitCodeChanged(int)));
|
||||||
|
|
||||||
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
|
{"{{checkExitCode}}", _checkExitCode},
|
||||||
|
{"{{exitCode}}", _exitCode},
|
||||||
|
{"{{timeout}}", _timeout},
|
||||||
|
};
|
||||||
|
|
||||||
|
auto exitLayout = new QHBoxLayout();
|
||||||
|
placeWidgets(
|
||||||
|
obs_module_text("AdvSceneSwitcher.condition.run.entry.exit"),
|
||||||
|
exitLayout, widgetPlaceholders);
|
||||||
|
auto timeoutLayout = new QHBoxLayout();
|
||||||
|
placeWidgets(obs_module_text("AdvSceneSwitcher.condition.run.entry"),
|
||||||
|
timeoutLayout, widgetPlaceholders);
|
||||||
|
|
||||||
|
auto *layout = new QVBoxLayout;
|
||||||
|
layout->addLayout(timeoutLayout);
|
||||||
|
layout->addWidget(_procConfig);
|
||||||
|
layout->addLayout(exitLayout);
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
|
UpdateEntryData();
|
||||||
|
_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionRunEdit::UpdateEntryData()
|
||||||
|
{
|
||||||
|
if (!_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_procConfig->SetProcessConfig(_entryData->_procConfig);
|
||||||
|
_timeout->SetDuration(_entryData->_timeout);
|
||||||
|
_checkExitCode->setChecked(_entryData->_checkExitCode);
|
||||||
|
_exitCode->setValue(_entryData->_exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionRunEdit::TimeoutChanged(const Duration &dur)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_timeout = dur;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionRunEdit::CheckExitCodeChanged(int state)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_checkExitCode = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionRunEdit::ExitCodeChanged(int exitCode)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_exitCode = exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionRunEdit::ProcessConfigChanged(const ProcessConfig &conf)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_procConfig = conf;
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
|
emit HeaderInfoChanged(
|
||||||
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
|
}
|
||||||
79
src/macro-core/macro-condition-run.hpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro.hpp"
|
||||||
|
#include "process-config.hpp"
|
||||||
|
#include "duration-control.hpp"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QSpinBox>
|
||||||
|
|
||||||
|
class MacroConditionRun : public MacroCondition {
|
||||||
|
public:
|
||||||
|
MacroConditionRun(Macro *m) : MacroCondition(m, true) {}
|
||||||
|
~MacroConditionRun();
|
||||||
|
bool CheckCondition();
|
||||||
|
bool Save(obs_data_t *obj) const;
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetShortDesc() const;
|
||||||
|
std::string GetId() const { return id; };
|
||||||
|
static std::shared_ptr<MacroCondition> Create(Macro *m)
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroConditionRun>(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessConfig _procConfig;
|
||||||
|
bool _checkExitCode = true;
|
||||||
|
int _exitCode = 0;
|
||||||
|
Duration _timeout = Duration(0.1);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class Status {
|
||||||
|
NONE,
|
||||||
|
FAILED_TO_START,
|
||||||
|
TIMEOUT,
|
||||||
|
OK,
|
||||||
|
};
|
||||||
|
|
||||||
|
void RunProcess();
|
||||||
|
|
||||||
|
std::thread _thread;
|
||||||
|
std::atomic_bool _threadDone{true};
|
||||||
|
Status _procStatus = Status::NONE;
|
||||||
|
int _procExitCode = 0;
|
||||||
|
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroConditionRunEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroConditionRunEdit(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroConditionRun> cond = nullptr);
|
||||||
|
void UpdateEntryData();
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroCondition> cond)
|
||||||
|
{
|
||||||
|
return new MacroConditionRunEdit(
|
||||||
|
parent,
|
||||||
|
std::dynamic_pointer_cast<MacroConditionRun>(cond));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void ProcessConfigChanged(const ProcessConfig &);
|
||||||
|
void TimeoutChanged(const Duration &);
|
||||||
|
void CheckExitCodeChanged(int);
|
||||||
|
void ExitCodeChanged(int);
|
||||||
|
signals:
|
||||||
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ProcessConfigEdit *_procConfig;
|
||||||
|
QCheckBox *_checkExitCode;
|
||||||
|
QSpinBox *_exitCode;
|
||||||
|
DurationSelection *_timeout;
|
||||||
|
std::shared_ptr<MacroConditionRun> _entryData;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _loading = true;
|
||||||
|
};
|
||||||
@@ -10,13 +10,14 @@ bool MacroConditionSceneOrder::_registered = MacroConditionFactory::Register(
|
|||||||
{MacroConditionSceneOrder::Create, MacroConditionSceneOrderEdit::Create,
|
{MacroConditionSceneOrder::Create, MacroConditionSceneOrderEdit::Create,
|
||||||
"AdvSceneSwitcher.condition.sceneOrder"});
|
"AdvSceneSwitcher.condition.sceneOrder"});
|
||||||
|
|
||||||
static std::map<SceneOrderCondition, std::string> sceneOrderConditionTypes = {
|
static std::map<MacroConditionSceneOrder::Condition, std::string>
|
||||||
{SceneOrderCondition::ABOVE,
|
sceneOrderConditionTypes = {
|
||||||
"AdvSceneSwitcher.condition.sceneOrder.type.above"},
|
{MacroConditionSceneOrder::Condition::ABOVE,
|
||||||
{SceneOrderCondition::BELOW,
|
"AdvSceneSwitcher.condition.sceneOrder.type.above"},
|
||||||
"AdvSceneSwitcher.condition.sceneOrder.type.below"},
|
{MacroConditionSceneOrder::Condition::BELOW,
|
||||||
{SceneOrderCondition::POSITION,
|
"AdvSceneSwitcher.condition.sceneOrder.type.below"},
|
||||||
"AdvSceneSwitcher.condition.sceneOrder.type.position"},
|
{MacroConditionSceneOrder::Condition::POSITION,
|
||||||
|
"AdvSceneSwitcher.condition.sceneOrder.type.position"},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PosInfo2 {
|
struct PosInfo2 {
|
||||||
@@ -115,13 +116,13 @@ bool MacroConditionSceneOrder::CheckCondition()
|
|||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case SceneOrderCondition::ABOVE:
|
case Condition::ABOVE:
|
||||||
ret = isAbove(positions1, positions2);
|
ret = isAbove(positions1, positions2);
|
||||||
break;
|
break;
|
||||||
case SceneOrderCondition::BELOW:
|
case Condition::BELOW:
|
||||||
ret = isBelow(positions1, positions2);
|
ret = isBelow(positions1, positions2);
|
||||||
break;
|
break;
|
||||||
case SceneOrderCondition::POSITION:
|
case Condition::POSITION:
|
||||||
for (int p : positions1) {
|
for (int p : positions1) {
|
||||||
if (p == _position)
|
if (p == _position)
|
||||||
ret = true;
|
ret = true;
|
||||||
@@ -143,6 +144,8 @@ bool MacroConditionSceneOrder::Save(obs_data_t *obj) const
|
|||||||
_source2.Save(obj, "sceneItemSelection2");
|
_source2.Save(obj, "sceneItemSelection2");
|
||||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||||
obs_data_set_int(obj, "position", _position);
|
obs_data_set_int(obj, "position", _position);
|
||||||
|
_position.Save(obj, "position");
|
||||||
|
obs_data_set_int(obj, "version", 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,9 +171,12 @@ bool MacroConditionSceneOrder::Load(obs_data_t *obj)
|
|||||||
} else {
|
} else {
|
||||||
_source2.Load(obj, "sceneItemSelection2");
|
_source2.Load(obj, "sceneItemSelection2");
|
||||||
}
|
}
|
||||||
_condition = static_cast<SceneOrderCondition>(
|
_condition = static_cast<Condition>(obs_data_get_int(obj, "condition"));
|
||||||
obs_data_get_int(obj, "condition"));
|
if (!obs_data_has_user_value(obj, "version")) {
|
||||||
_position = obs_data_get_int(obj, "position");
|
_position = obs_data_get_int(obj, "position");
|
||||||
|
} else {
|
||||||
|
_position.Load(obj, "position");
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +187,7 @@ std::string MacroConditionSceneOrder::GetShortDesc() const
|
|||||||
}
|
}
|
||||||
std::string header = _scene.ToString() + " - " + _source.ToString();
|
std::string header = _scene.ToString() + " - " + _source.ToString();
|
||||||
if (!_source2.ToString().empty() &&
|
if (!_source2.ToString().empty() &&
|
||||||
_condition != SceneOrderCondition::POSITION) {
|
_condition != MacroConditionSceneOrder::Condition::POSITION) {
|
||||||
header += " - " + _source2.ToString();
|
header += " - " + _source2.ToString();
|
||||||
}
|
}
|
||||||
return header;
|
return header;
|
||||||
@@ -196,19 +202,19 @@ static inline void populateConditionSelection(QComboBox *list)
|
|||||||
|
|
||||||
MacroConditionSceneOrderEdit::MacroConditionSceneOrderEdit(
|
MacroConditionSceneOrderEdit::MacroConditionSceneOrderEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroConditionSceneOrder> entryData)
|
QWidget *parent, std::shared_ptr<MacroConditionSceneOrder> entryData)
|
||||||
: QWidget(parent)
|
: QWidget(parent),
|
||||||
|
_scenes(new SceneSelectionWidget(window(), true, false, false, true)),
|
||||||
|
_conditions(new QComboBox()),
|
||||||
|
_sources(new SceneItemSelectionWidget(parent)),
|
||||||
|
_sources2(new SceneItemSelectionWidget(parent)),
|
||||||
|
_position(new VariableSpinBox()),
|
||||||
|
_posInfo(new QLabel(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.condition.sceneOrder.positionInfo")))
|
||||||
{
|
{
|
||||||
_scenes = new SceneSelectionWidget(window(), true, false, false, true);
|
|
||||||
_sources = new SceneItemSelectionWidget(parent);
|
|
||||||
_sources2 = new SceneItemSelectionWidget(parent);
|
|
||||||
_conditions = new QComboBox();
|
|
||||||
_position = new QSpinBox();
|
|
||||||
_posInfo = new QLabel(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.condition.sceneOrder.positionInfo"));
|
|
||||||
|
|
||||||
populateConditionSelection(_conditions);
|
populateConditionSelection(_conditions);
|
||||||
if (entryData.get()) {
|
if (entryData.get()) {
|
||||||
if (entryData->_condition == SceneOrderCondition::POSITION) {
|
if (entryData->_condition ==
|
||||||
|
MacroConditionSceneOrder::Condition::POSITION) {
|
||||||
_sources->SetPlaceholderType(
|
_sources->SetPlaceholderType(
|
||||||
SceneItemSelectionWidget::Placeholder::ANY);
|
SceneItemSelectionWidget::Placeholder::ANY);
|
||||||
} else {
|
} else {
|
||||||
@@ -232,8 +238,10 @@ MacroConditionSceneOrderEdit::MacroConditionSceneOrderEdit(
|
|||||||
SLOT(Source2Changed(const SceneItemSelection &)));
|
SLOT(Source2Changed(const SceneItemSelection &)));
|
||||||
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ConditionChanged(int)));
|
SLOT(ConditionChanged(int)));
|
||||||
QWidget::connect(_position, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(
|
||||||
SLOT(PositionChanged(int)));
|
_position,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
|
this, SLOT(PositionChanged(const NumberVariable<int> &)));
|
||||||
|
|
||||||
auto entryLayout = new QHBoxLayout();
|
auto entryLayout = new QHBoxLayout();
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
@@ -296,11 +304,12 @@ void MacroConditionSceneOrderEdit::ConditionChanged(int index)
|
|||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_condition =
|
_entryData->_condition =
|
||||||
static_cast<SceneOrderCondition>(index);
|
static_cast<MacroConditionSceneOrder::Condition>(index);
|
||||||
}
|
}
|
||||||
SetWidgetVisibility(_entryData->_condition ==
|
SetWidgetVisibility(_entryData->_condition ==
|
||||||
SceneOrderCondition::POSITION);
|
MacroConditionSceneOrder::Condition::POSITION);
|
||||||
if (_entryData->_condition == SceneOrderCondition::POSITION) {
|
if (_entryData->_condition ==
|
||||||
|
MacroConditionSceneOrder::Condition::POSITION) {
|
||||||
_sources->SetPlaceholderType(
|
_sources->SetPlaceholderType(
|
||||||
SceneItemSelectionWidget::Placeholder::ANY);
|
SceneItemSelectionWidget::Placeholder::ANY);
|
||||||
} else {
|
} else {
|
||||||
@@ -312,7 +321,8 @@ void MacroConditionSceneOrderEdit::ConditionChanged(int index)
|
|||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionSceneOrderEdit::PositionChanged(int value)
|
void MacroConditionSceneOrderEdit::PositionChanged(
|
||||||
|
const NumberVariable<int> &value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
@@ -339,8 +349,8 @@ void MacroConditionSceneOrderEdit::UpdateEntryData()
|
|||||||
_scenes->SetScene(_entryData->_scene);
|
_scenes->SetScene(_entryData->_scene);
|
||||||
_sources->SetSceneItem(_entryData->_source);
|
_sources->SetSceneItem(_entryData->_source);
|
||||||
_sources2->SetSceneItem(_entryData->_source2);
|
_sources2->SetSceneItem(_entryData->_source2);
|
||||||
_position->setValue(_entryData->_position);
|
_position->SetValue(_entryData->_position);
|
||||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||||
SetWidgetVisibility(_entryData->_condition ==
|
SetWidgetVisibility(_entryData->_condition ==
|
||||||
SceneOrderCondition::POSITION);
|
MacroConditionSceneOrder::Condition::POSITION);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,16 +2,11 @@
|
|||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "scene-selection.hpp"
|
#include "scene-selection.hpp"
|
||||||
#include "scene-item-selection.hpp"
|
#include "scene-item-selection.hpp"
|
||||||
|
#include "variable-spinbox.hpp"
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
|
||||||
enum class SceneOrderCondition {
|
|
||||||
ABOVE,
|
|
||||||
BELOW,
|
|
||||||
POSITION,
|
|
||||||
};
|
|
||||||
|
|
||||||
class MacroConditionSceneOrder : public MacroCondition {
|
class MacroConditionSceneOrder : public MacroCondition {
|
||||||
public:
|
public:
|
||||||
MacroConditionSceneOrder(Macro *m) : MacroCondition(m) {}
|
MacroConditionSceneOrder(Macro *m) : MacroCondition(m) {}
|
||||||
@@ -28,8 +23,14 @@ public:
|
|||||||
SceneSelection _scene;
|
SceneSelection _scene;
|
||||||
SceneItemSelection _source;
|
SceneItemSelection _source;
|
||||||
SceneItemSelection _source2;
|
SceneItemSelection _source2;
|
||||||
int _position = 0;
|
NumberVariable<int> _position = 0;
|
||||||
SceneOrderCondition _condition = SceneOrderCondition::ABOVE;
|
|
||||||
|
enum class Condition {
|
||||||
|
ABOVE,
|
||||||
|
BELOW,
|
||||||
|
POSITION,
|
||||||
|
};
|
||||||
|
Condition _condition = Condition::ABOVE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
@@ -58,7 +59,7 @@ private slots:
|
|||||||
void SourceChanged(const SceneItemSelection &);
|
void SourceChanged(const SceneItemSelection &);
|
||||||
void Source2Changed(const SceneItemSelection &);
|
void Source2Changed(const SceneItemSelection &);
|
||||||
void ConditionChanged(int cond);
|
void ConditionChanged(int cond);
|
||||||
void PositionChanged(int cond);
|
void PositionChanged(const NumberVariable<int> &);
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ protected:
|
|||||||
QComboBox *_conditions;
|
QComboBox *_conditions;
|
||||||
SceneItemSelectionWidget *_sources;
|
SceneItemSelectionWidget *_sources;
|
||||||
SceneItemSelectionWidget *_sources2;
|
SceneItemSelectionWidget *_sources2;
|
||||||
QSpinBox *_position;
|
VariableSpinBox *_position;
|
||||||
QLabel *_posInfo;
|
QLabel *_posInfo;
|
||||||
|
|
||||||
std::shared_ptr<MacroConditionSceneOrder> _entryData;
|
std::shared_ptr<MacroConditionSceneOrder> _entryData;
|
||||||
|
|||||||
@@ -17,13 +17,15 @@ bool MacroConditionSceneTransform::CheckCondition()
|
|||||||
bool ret = false;
|
bool ret = false;
|
||||||
auto items = _source.GetSceneItems(_scene);
|
auto items = _source.GetSceneItems(_scene);
|
||||||
|
|
||||||
|
std::string json;
|
||||||
for (auto &item : items) {
|
for (auto &item : items) {
|
||||||
auto json = getSceneItemTransform(item);
|
json = getSceneItemTransform(item);
|
||||||
if (matchJson(json, _settings, _regex)) {
|
if (matchJson(json, _settings, _regex)) {
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
obs_sceneitem_release(item);
|
obs_sceneitem_release(item);
|
||||||
}
|
}
|
||||||
|
SetVariableValue(json);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
class MacroConditionSceneTransform : public MacroCondition {
|
class MacroConditionSceneTransform : public MacroCondition {
|
||||||
public:
|
public:
|
||||||
MacroConditionSceneTransform(Macro *m) : MacroCondition(m) {}
|
MacroConditionSceneTransform(Macro *m) : MacroCondition(m, true) {}
|
||||||
bool CheckCondition();
|
bool CheckCondition();
|
||||||
bool Save(obs_data_t *obj) const;
|
bool Save(obs_data_t *obj) const;
|
||||||
bool Load(obs_data_t *obj);
|
bool Load(obs_data_t *obj);
|
||||||
@@ -24,7 +24,7 @@ public:
|
|||||||
SceneSelection _scene;
|
SceneSelection _scene;
|
||||||
SceneItemSelection _source;
|
SceneItemSelection _source;
|
||||||
RegexConfig _regex;
|
RegexConfig _regex;
|
||||||
VariableResolvingString _settings = "";
|
StringVariable _settings = "";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ bool MacroConditionScene::CheckCondition()
|
|||||||
auto current = obs_frontend_get_current_scene();
|
auto current = obs_frontend_get_current_scene();
|
||||||
auto weak = obs_source_get_weak_source(current);
|
auto weak = obs_source_get_weak_source(current);
|
||||||
bool match = weak == _scene.GetScene(false);
|
bool match = weak == _scene.GetScene(false);
|
||||||
SetVariableValue(obs_source_get_name(current));
|
SetVariableValue(GetWeakSourceName(weak));
|
||||||
obs_weak_source_release(weak);
|
obs_weak_source_release(weak);
|
||||||
obs_source_release(current);
|
obs_source_release(current);
|
||||||
return match;
|
return match;
|
||||||
|
|||||||