Compare commits

..

1 Commits

Author SHA1 Message Date
WarmUpTill
b74e9d2e2a Enable executing AppleScripts on MacOS 2023-03-04 18:14:16 +01:00
396 changed files with 8083 additions and 97741 deletions

View File

@@ -22,7 +22,6 @@ A clear and concise description of what you expected to happen.
**Logs** **Logs**
Please provide a log of your issue with verbose logging enabled (See General tab of the plugin). Please provide a log of your issue with verbose logging enabled (See General tab of the plugin).
In case of a crash, please also include the corresponding crash log.
See [here](https://obsproject.com/forum/threads/please-post-a-log-with-your-issue-heres-how.23074/) for a description where to find the log files and how to share them. See [here](https://obsproject.com/forum/threads/please-post-a-log-with-your-issue-heres-how.23074/) for a description where to find the log files and how to share them.
Please share the currently used plugin settings by exporting them them to a file (See General tab of the plugin). Please share the currently used plugin settings by exporting them them to a file (See General tab of the plugin).
If applicable, add screenshots to help explain your problem. If applicable, add screenshots to help explain your problem.

View File

@@ -1,79 +0,0 @@
name: 'Setup plugin build dependencies'
description: 'Builds the plugin build dependencies'
inputs:
target:
description: 'Build target for dependencies'
required: true
config:
description: 'Build configuration'
required: false
default: 'Release'
visualStudio:
description: 'Visual Studio version (Windows only)'
required: false
default: 'Visual Studio 16 2019'
workingDirectory:
description: 'Working directory for packaging'
required: false
default: ${{ github.workspace }}
runs:
using: 'composite'
steps:
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1.13
with:
cmake-version: '3.24.x'
- name: Restore cached dependencies
id: restore-cache
uses: actions/cache@v3
with:
path: ${{ env.DEP_DIR }}
key: ${{ env.DEP_DIR }}-${{ runner.os }}-${{ inputs.target }}
- name: Run macOS Build
if: ${{ runner.os == 'macOS' && steps.restore-cache.outputs.cache-hit != 'true' }}
shell: zsh {0}
run: |
build_args=(
-c ${{ inputs.config }}
-t macos-${{ inputs.target }}
)
if (( ${+CI} && ${+RUNNER_DEBUG} )) build_args+=(--debug)
${{ inputs.workingDirectory }}/.github/scripts/build-deps-macos.zsh -o ${{ env.DEP_DIR }} ${build_args}
- name: Run Linux Build
if: ${{ runner.os == 'Linux' && steps.restore-cache.outputs.cache-hit != 'true' }}
shell: bash
run: |
build_args=(
-c ${{ inputs.config }}
-t linux-${{ inputs.target }}
)
if [[ -n "${CI}" && -n "${RUNNER_DEBUG}" ]]; then
build_args+=(--debug)
fi
${{ inputs.workingDirectory }}/.github/scripts/build-deps-linux.sh -o ${{ env.DEP_DIR }} "${build_args[@]}"
- name: Run Windows Build
if: ${{ runner.os == 'Windows' && steps.restore-cache.outputs.cache-hit != 'true' }}
shell: pwsh
run: |
$BuildArgs = @{
Target = '${{ inputs.target }}'
Configuration = '${{ inputs.config }}'
CMakeGenerator = '${{ inputs.visualStudio }}'
}
if ( ( Test-Path env:CI ) -and ( Test-Path env:RUNNER_DEBUG ) ) {
$BuildArgs += @{
Debug = $true
}
}
${{ inputs.workingDirectory }}/.github/scripts/Build-Deps-Windows.ps1 -OutDirName ${{ env.DEP_DIR }} @BuildArgs

View File

@@ -49,7 +49,7 @@ runs:
if [[ '${{ inputs.codesign }}' == 'true' ]] build_args+=(-s) if [[ '${{ inputs.codesign }}' == 'true' ]] build_args+=(-s)
if (( ${+CI} && ${+RUNNER_DEBUG} )) build_args+=(--debug) if (( ${+CI} && ${+RUNNER_DEBUG} )) build_args+=(--debug)
${{ inputs.workingDirectory }}/.github/scripts/build-macos.zsh -d ${{ env.DEP_DIR }} ${build_args} ${{ inputs.workingDirectory }}/.github/scripts/build-macos.zsh ${build_args}
- name: Run Linux Build - name: Run Linux Build
if: ${{ runner.os == 'Linux' }} if: ${{ runner.os == 'Linux' }}
@@ -68,7 +68,7 @@ runs:
build_args+=(-p) build_args+=(-p)
fi fi
${{ inputs.workingDirectory }}/.github/scripts/build-linux.sh -d ${{ env.DEP_DIR }} "${build_args[@]}" ${{ inputs.workingDirectory }}/.github/scripts/build-linux.sh "${build_args[@]}"
- name: Run Windows Build - name: Run Windows Build
if: ${{ runner.os == 'Windows' }} if: ${{ runner.os == 'Windows' }}
@@ -86,4 +86,4 @@ runs:
} }
} }
${{ inputs.workingDirectory }}/.github/scripts/Build-Windows.ps1 -ADVSSDepName ${{ env.DEP_DIR }} @BuildArgs ${{ inputs.workingDirectory }}/.github/scripts/Build-Windows.ps1 @BuildArgs

View File

@@ -1,37 +0,0 @@
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

View File

@@ -7,8 +7,3 @@ package 'ninja-build', bin: 'ninja'
package 'pkg-config' package 'pkg-config'
package 'clang' package 'clang'
package 'clang-format-13' package 'clang-format-13'
package 'libxtst-dev'
package 'libxss-dev'
package 'libopencv-dev'
package 'libtesseract-dev'
package 'libprocps-dev'

View File

@@ -1,4 +1,3 @@
package '7zip.7zip', path: '7-zip', bin: '7z' package '7zip.7zip', path: '7-zip', bin: '7z'
package 'cmake', path: 'Cmake\bin', bin: 'cmake' package 'cmake', path: 'Cmake\bin', bin: 'cmake'
package 'innosetup', path: 'Inno Setup 6', bin: 'iscc' package 'innosetup', path: 'Inno Setup 6', bin: 'iscc'
package 'OpenSSL', path: 'OpenSSL', bin: 'openssl'

View File

@@ -1,324 +0,0 @@
#!/usr/bin/env zsh
builtin emulate -L zsh
setopt EXTENDED_GLOB
setopt PUSHD_SILENT
setopt ERR_EXIT
setopt ERR_RETURN
setopt NO_UNSET
setopt PIPE_FAIL
setopt NO_AUTO_PUSHD
setopt NO_PUSHD_IGNORE_DUPS
setopt FUNCTION_ARGZERO
## Enable for script debugging
# setopt WARN_CREATE_GLOBAL
# setopt WARN_NESTED_VAR
# setopt XTRACE
autoload -Uz is-at-least && if ! is-at-least 5.2; then
print -u2 -PR "%F{1}${funcstack[1]##*/}:%f Running on Zsh version %B${ZSH_VERSION}%b, but Zsh %B5.2%b is the minimum supported version. Upgrade Zsh to fix this issue."
exit 1
fi
_trap_error() {
print -u2 -PR '%F{1} ✖︎ script execution error%f'
print -PR -e "
Callstack:
${(j:\n :)funcfiletrace}
"
exit 2
}
build() {
if (( ! ${+SCRIPT_HOME} )) typeset -g SCRIPT_HOME=${ZSH_ARGZERO:A:h}
local host_os=${${(s:-:)ZSH_ARGZERO:t:r}[3]}
local target="${host_os}-${CPUTYPE}"
local project_root=${SCRIPT_HOME:A:h:h}
local buildspec_file="${project_root}/buildspec.json"
trap '_trap_error' ZERR
fpath=("${SCRIPT_HOME}/utils.zsh" ${fpath})
autoload -Uz log_info log_error log_output set_loglevel check_${host_os} setup_${host_os} setup_obs setup_ccache
if [[ ! -r ${buildspec_file} ]] {
log_error \
'No buildspec.json found. Please create a build specification for your project.' \
'A buildspec.json.template file is provided in the repository to get you started.'
return 2
}
typeset -g -a skips=()
local -i _verbosity=1
local -r _version='1.0.0'
local -r -a _valid_targets=(
macos-x86_64
macos-arm64
macos-universal
linux-x86_64
)
local -r -a _valid_configs=(Debug RelWithDebInfo Release MinSizeRel)
if [[ ${host_os} == 'macos' ]] {
local -r -a _valid_generators=(Xcode Ninja 'Unix Makefiles')
local generator="${${CI:+Ninja}:-Xcode}"
} else {
local -r -a _valid_generators=(Ninja 'Unix Makefiles')
local generator='Ninja'
}
local -r _usage="
Usage: %B${functrace[1]%:*}%b <option> [<options>]
%BOptions%b:
%F{yellow} Build configuration options%f
-----------------------------------------------------------------------------
%B-t | --target%b Specify target - default: %B%F{green}${host_os}-${CPUTYPE}%f%b
%B-c | --config%b Build configuration - default: %B%F{green}RelWithDebInfo%f%b
%B-o | --out%b Output directory - default: %B%F{green}RelWithDebInfo%f%b
%B--generator%b Specify build system to generate - default: %B%F{green}Ninja%f%b
Available generators:
- Ninja
- Unix Makefiles
- Xcode (macOS only)
%F{yellow} Output options%f
-----------------------------------------------------------------------------
%B-q | --quiet%b Quiet (error output only)
%B-v | --verbose%b Verbose (more detailed output)
%B--skip-[all|build|deps|unpack]%b Skip all|building OBS|checking for dependencies|unpacking dependencies
%B--debug%b Debug (very detailed and added output)
%F{yellow} General options%f
-----------------------------------------------------------------------------
%B-h | --help%b Print this usage help
%B-V | --version%b Print script version information"
local -a args
while (( # )) {
case ${1} {
-t|--target|-c|--config|--generator)
if (( # == 1 )) || [[ ${2:0:1} == '-' ]] {
log_error "Missing value for option %B${1}%b"
log_output ${_usage}
exit 2
}
;;
}
case ${1} {
--)
shift
args+=($@)
break
;;
-t|--target)
if (( ! ${_valid_targets[(Ie)${2}]} )) {
log_error "Invalid value %B${2}%b for option %B${1}%b"
log_output ${_usage}
exit 2
}
target=${2}
shift 2
;;
-c|--config)
if (( ! ${_valid_configs[(Ie)${2}]} )) {
log_error "Invalid value %B${2}%b for option %B${1}%b"
log_output ${_usage}
exit 2
}
BUILD_CONFIG=${2}
shift 2
;;
-o|--out)
OUT_DIR="${2}"
shift 2
;;
-q|--quiet) (( _verbosity -= 1 )) || true; shift ;;
-v|--verbose) (( _verbosity += 1 )); shift ;;
-h|--help) log_output ${_usage}; exit 0 ;;
-V|--version) print -Pr "${_version}"; exit 0 ;;
--debug) _verbosity=3; shift ;;
--generator)
if (( ! ${_valid_generators[(Ie)${2}]} )) {
log_error "Invalid value %B${2}%b for option %B${1}%b"
log_output ${_usage}
exit 2
}
generator=${2}
shift 2
;;
--skip-*)
local _skip="${${(s:-:)1}[-1]}"
local _check=(all deps unpack build)
(( ${_check[(Ie)${_skip}]} )) || log_warning "Invalid skip mode %B${_skip}%b supplied"
typeset -g -a skips=(${skips} ${_skip})
shift
;;
*) log_error "Unknown option: %B${1}%b"; log_output ${_usage}; exit 2 ;;
}
}
set -- ${(@)args}
set_loglevel ${_verbosity}
check_${host_os}
setup_ccache
typeset -g QT_VERSION
typeset -g DEPLOYMENT_TARGET
typeset -g OBS_DEPS_VERSION
setup_${host_os}
local product_name
local product_version
local git_tag="$(git describe --tags)"
read -r product_name product_version <<< \
"$(jq -r '. | {name, version} | join(" ")' ${buildspec_file})"
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 [[ -z "${OUT_DIR}" ]] {
OUT_DIR="advss-build-dependencies"
}
mkdir -p "${project_root}/../${OUT_DIR}"
local advss_dep_path="$(realpath ${project_root}/../${OUT_DIR})"
local _plugin_deps="${project_root:h}/obs-build-dependencies/plugin-deps-${OBS_DEPS_VERSION}-qt${QT_VERSION}-${target##*-}"
case ${host_os} {
macos)
local opencv_dir="${project_root}/deps/opencv"
local opencv_build_dir="${opencv_dir}/build_${target##*-}"
local -a opencv_cmake_args=(
-DCMAKE_BUILD_TYPE=Release
-DBUILD_LIST=core,imgproc,objdetect
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
-DCMAKE_PREFIX_PATH="${advss_dep_path};${_plugin_deps}"
-DCMAKE_INSTALL_PREFIX="${advss_dep_path}"
)
if [ "${target}" != "macos-x86_64" ]; then
opencv_cmake_args+=(-DWITH_IPP=OFF)
fi
pushd ${opencv_dir}
log_info "Configure OpenCV ..."
cmake -S . -B ${opencv_build_dir} -G ${generator} ${opencv_cmake_args}
log_info "Building OpenCV ..."
cmake --build ${opencv_build_dir} --config Release
log_info "Installing OpenCV..."
cmake --install ${opencv_build_dir} --prefix "${advss_dep_path}" --config Release || true
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
-DCMAKE_PREFIX_PATH="${advss_dep_path};${_plugin_deps}"
-DCMAKE_INSTALL_PREFIX="${advss_dep_path}"
)
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} --prefix "${advss_dep_path}" --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
-DCMAKE_PREFIX_PATH="${advss_dep_path};${_plugin_deps}"
-DCMAKE_INSTALL_PREFIX="${advss_dep_path}"
)
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
log_info "Installing Tesseract..."
cmake --install ${tesseract_build_dir} --prefix "${advss_dep_path}" --config Release
popd
pushd ${advss_dep_path}
log_info "Prepare openssl ..."
rm -rf openssl
git clone git://git.openssl.org/openssl.git --branch openssl-3.1.2 --depth 1
mv openssl openssl_x86
cp -r openssl_x86 openssl_arm
log_info "Building openssl x86 ..."
export MACOSX_DEPLOYMENT_TARGET=10.9
cd openssl_x86
./Configure darwin64-x86_64-cc shared
make
log_info "Building openssl arm ..."
export MACOSX_DEPLOYMENT_TARGET=10.15
cd ../openssl_arm
./Configure enable-rc5 zlib darwin64-arm64-cc no-asm
make
log_info "Combine arm and x86 openssl binaries ..."
cd ..
mkdir openssl-combined
lipo -create openssl_x86/libcrypto.a openssl_arm/libcrypto.a -output openssl-combined/libcrypto.a
lipo -create openssl_x86/libssl.a openssl_arm/libssl.a -output openssl-combined/libssl.a
log_info "Clean up openssl dir..."
mv openssl_x86 openssl
rm -rf openssl_arm
;;
linux)
# Nothing to do for now
;;
}
}
build ${@}

View File

@@ -36,7 +36,6 @@ build() {
local target="${host_os}-${CPUTYPE}" local target="${host_os}-${CPUTYPE}"
local project_root=${SCRIPT_HOME:A:h:h} local project_root=${SCRIPT_HOME:A:h:h}
local buildspec_file="${project_root}/buildspec.json" local buildspec_file="${project_root}/buildspec.json"
local dep_dir=""
trap '_trap_error' ZERR trap '_trap_error' ZERR
@@ -78,7 +77,6 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
%B-c | --config%b Build configuration - default: %B%F{green}RelWithDebInfo%f%b %B-c | --config%b Build configuration - default: %B%F{green}RelWithDebInfo%f%b
%B-s | --codesign%b Enable codesigning (macOS only) %B-s | --codesign%b Enable codesigning (macOS only)
%B-p | --portable%b Enable portable mode (Linux only) %B-p | --portable%b Enable portable mode (Linux only)
%B-d | --dep%b Dependency directory name - default: %B%F{green}advss-build-dependencies%f%b
%B--generator%b Specify build system to generate - default: %B%F{green}Ninja%f%b %B--generator%b Specify build system to generate - default: %B%F{green}Ninja%f%b
Available generators: Available generators:
- Ninja - Ninja
@@ -132,10 +130,6 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
BUILD_CONFIG=${2} BUILD_CONFIG=${2}
shift 2 shift 2
;; ;;
-d|--dep)
dep_dir="${2}"
shift 2
;;
-s|--codesign) CODESIGN=1; shift ;; -s|--codesign) CODESIGN=1; shift ;;
-p|--portable) typeset -g PORTABLE=1; shift ;; -p|--portable) typeset -g PORTABLE=1; shift ;;
-q|--quiet) (( _verbosity -= 1 )) || true; shift ;; -q|--quiet) (( _verbosity -= 1 )) || true; shift ;;
@@ -174,34 +168,109 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
typeset -g OBS_DEPS_VERSION typeset -g OBS_DEPS_VERSION
setup_${host_os} setup_${host_os}
local advss_deps_path
if [[ -z "${dep_dir}" ]] {
log_info "Building advss deps ..."
dep_dir="advss-build-dependencies"
${SCRIPT_HOME}/build-deps-${host_os}.zsh -c "${BUILD_CONFIG:-RelWithDebInfo}" -t "${target}" --generator "${generator}" -o "${dep_dir}" --skip-deps --skip-unpack
}
advss_deps_path=$(realpath ${project_root}/../${dep_dir})
log_info "Using advss deps at $advss_deps_path ..."
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})"
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}'"
}
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"
local opencv_dir="${project_root}/deps/opencv"
local opencv_build_dir="${opencv_dir}/build_${target##*-}"
local -a opencv_cmake_args=(
-DCMAKE_BUILD_TYPE=Release
-DBUILD_LIST=core,imgproc,objdetect
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
)
if [ "${target}" != "macos-x86_64" ]; then
opencv_cmake_args+=(-DWITH_IPP=OFF)
fi
pushd ${opencv_dir}
log_info "Configure OpenCV ..."
cmake -S . -B ${opencv_build_dir} -G ${generator} ${opencv_cmake_args}
log_info "Building OpenCV ..."
cmake --build ${opencv_build_dir} --config Release
log_info "Installing OpenCV..."
cmake --install ${opencv_build_dir} --config Release || true
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'' \
@@ -220,7 +289,7 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
local -a cmake_args=( local -a cmake_args=(
-DCMAKE_BUILD_TYPE=${BUILD_CONFIG:-RelWithDebInfo} -DCMAKE_BUILD_TYPE=${BUILD_CONFIG:-RelWithDebInfo}
-DQT_VERSION=${QT_VERSION} -DQT_VERSION=${QT_VERSION}
-DCMAKE_PREFIX_PATH="${_plugin_deps};${advss_deps_path}" -DCMAKE_PREFIX_PATH="${_plugin_deps}"
) )
if (( _loglevel == 0 )) cmake_args+=(-Wno_deprecated -Wno-dev --log-level=ERROR) if (( _loglevel == 0 )) cmake_args+=(-Wno_deprecated -Wno-dev --log-level=ERROR)
@@ -237,17 +306,12 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
num_procs=$(( $(sysctl -n hw.ncpu) + 1 )) num_procs=$(( $(sysctl -n hw.ncpu) + 1 ))
local openssl_lib_dir="${advss_deps_path}/openssl-combined/"
local openssl_include_dir="${advss_deps_path}/openssl/include"
cmake_args+=( cmake_args+=(
-DCMAKE_FRAMEWORK_PATH="${_plugin_deps}/Frameworks" -DCMAKE_FRAMEWORK_PATH="${_plugin_deps}/Frameworks"
-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}
-DOBS_CODESIGN_LINKER=ON -DOBS_CODESIGN_LINKER=ON
-DOBS_BUNDLE_CODESIGN_IDENTITY="${CODESIGN_IDENT:--}" -DOBS_BUNDLE_CODESIGN_IDENTITY="${CODESIGN_IDENT:--}"
-DOPENSSL_INCLUDE_DIR="${openssl_include_dir}"
-DOPENSSL_LIBRARIES="${openssl_lib_dir}/libcrypto.a;${openssl_lib_dir}/libssl.a"
) )
;; ;;

View File

@@ -128,18 +128,9 @@ 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

View File

@@ -1,172 +0,0 @@
[CmdletBinding()]
param(
[ValidateSet('Debug', 'RelWithDebInfo', 'Release', 'MinSizeRel')]
[string] $Configuration = 'RelWithDebInfo',
[ValidateSet('x86', 'x64')]
[string] $Target,
[ValidateSet('Visual Studio 17 2022', 'Visual Studio 16 2019')]
[string] $CMakeGenerator,
[string] $OutDirName,
[switch] $SkipDeps,
[switch] $SkipUnpack
)
$ErrorActionPreference = 'Stop'
if ( $DebugPreference -eq 'Continue' ) {
$VerbosePreference = 'Continue'
$InformationPreference = 'Continue'
}
if ( $PSVersionTable.PSVersion -lt '7.0.0' ) {
Write-Warning 'The obs-deps PowerShell build script requires PowerShell Core 7. Install or upgrade your PowerShell version: https://aka.ms/pscore6'
exit 2
}
function Build {
trap {
Pop-Location -Stack BuildTemp -ErrorAction 'SilentlyContinue'
Write-Error $_
exit 2
}
$ScriptHome = $PSScriptRoot
$ProjectRoot = Resolve-Path -Path "$PSScriptRoot/../.."
$BuildSpecFile = "${ProjectRoot}/buildspec.json"
$UtilityFunctions = Get-ChildItem -Path $PSScriptRoot/utils.pwsh/*.ps1 -Recurse
foreach ($Utility in $UtilityFunctions) {
Write-Debug "Loading $($Utility.FullName)"
. $Utility.FullName
}
$BuildSpec = Get-Content -Path ${BuildSpecFile} -Raw | ConvertFrom-Json
$ProductName = $BuildSpec.name
$ProductVersion = $BuildSpec.version
$script:VisualStudioVersion = ''
$script:PlatformSDK = '10.0.18363.657'
Setup-Host
if ( $CmakeGenerator -eq '' ) {
$CmakeGenerator = $script:VisualStudioVersion
}
$DepsPath = "plugin-deps-${script:DepsVersion}-*-${script:Target}"
$OBSDepPath = "$(Resolve-Path -Path ${ProjectRoot}/../obs-build-dependencies/${DepsPath})"
if ( $OutDirName -eq '' ) {
$OutDirName = "advss-build-dependencies"
}
New-Item -ItemType Directory -Force -Path ${ProjectRoot}/../${OutDirName}
$ADVSSDepPath = "$(Resolve-Path -Path ${ProjectRoot}/../${OutDirName})"
$OpenCVPath = "${ProjectRoot}/deps/opencv"
$OpenCVBuildPath = "${OpenCVPath}/build"
Push-Location -Stack BuildOpenCVTemp
Ensure-Location $ProjectRoot
$OpenCVCmakeArgs = @(
'-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=${OBSDepPath}"
"-DCMAKE_INSTALL_PREFIX:PATH=${ADVSSDepPath}"
"-DBUILD_LIST=core,imgproc,objdetect"
)
Log-Information "Configuring OpenCV..."
Invoke-External cmake -S ${OpenCVPath} -B ${OpenCVBuildPath} @OpenCVCmakeArgs
$OpenCVCmakeArgs = @(
'--config', "Release"
)
if ( $VerbosePreference -eq 'Continue' ) {
$OpenCVCmakeArgs += ('--verbose')
}
Log-Information "Building OpenCV..."
Invoke-External cmake --build "${OpenCVBuildPath}" @OpenCVCmakeArgs
Log-Information "Install OpenCV}..."
Invoke-External cmake --install "${OpenCVBuildPath}" --prefix "${ADVSSDepPath}" @OpenCVCmakeArgs
$LeptonicaPath = "${ProjectRoot}/deps/leptonica"
$LeptonicaBuildPath = "${LeptonicaPath}/build"
Push-Location -Stack BuildLeptonicaTemp
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=${Configuration}"
"-DCMAKE_PREFIX_PATH:PATH=${OBSDepPath}"
"-DCMAKE_INSTALL_PREFIX:PATH=${ADVSSDepPath}"
"-DSW_BUILD=OFF"
"-DLIBWEBP_SUPPORT=OFF"
)
Log-Information "Configuring leptonica..."
Invoke-External cmake -S ${LeptonicaPath} -B ${LeptonicaBuildPath} @LeptonicaCmakeArgs
$LeptonicaCmakeArgs = @(
'--config', "${Configuration}"
)
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 "${ADVSSDepPath}" @LeptonicaCmakeArgs
Push-Location -Stack BuildTesseractTemp
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=${Configuration}"
"-DCMAKE_PREFIX_PATH:PATH=${OBSDepPath}"
"-DCMAKE_INSTALL_PREFIX:PATH=${ADVSSDepPath}"
"-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', "${Configuration}"
)
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 "${ADVSSDepPath}" @TesseractCmakeArgs
}
Build

View File

@@ -6,7 +6,6 @@ param(
[string] $Target, [string] $Target,
[ValidateSet('Visual Studio 17 2022', 'Visual Studio 16 2019')] [ValidateSet('Visual Studio 17 2022', 'Visual Studio 16 2019')]
[string] $CMakeGenerator, [string] $CMakeGenerator,
[string] $ADVSSDepName,
[switch] $SkipAll, [switch] $SkipAll,
[switch] $SkipBuild, [switch] $SkipBuild,
[switch] $SkipDeps, [switch] $SkipDeps,
@@ -61,17 +60,116 @@ function Build {
$DepsPath = "plugin-deps-${script:DepsVersion}-qt${script:QtVersion}-${script:Target}" $DepsPath = "plugin-deps-${script:DepsVersion}-qt${script:QtVersion}-${script:Target}"
$DepInstallPath = "$(Resolve-Path -Path ${ProjectRoot}/../obs-build-dependencies/${DepsPath})" $DepInstallPath = "$(Resolve-Path -Path ${ProjectRoot}/../obs-build-dependencies/${DepsPath})"
if ( $ADVSSDepName -eq '' ) { $OpenCVPath = "${ProjectRoot}/deps/opencv"
Log-Information "Building advss deps ..." $OpenCVBuildPath = "${OpenCVPath}/build"
$ADVSSDepName = "advss-build-dependencies"
invoke-expression -Command "$PSScriptRoot/Build-Deps-Windows.ps1 -Configuration $Configuration -Target $Target -CMakeGenerator `"$CMakeGenerator`" -OutDirName $ADVSSDepName -SkipDeps -SkipUnpack" Push-Location -Stack BuildOpenCVTemp
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
Ensure-Location $ProjectRoot
$OpenCVCmakeArgs = @(
'-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}"
"-DBUILD_LIST=core,imgproc,objdetect"
)
Log-Information "Configuring OpenCV..."
Invoke-External cmake -S ${OpenCVPath} -B ${OpenCVBuildPath} @OpenCVCmakeArgs
$OpenCVCmakeArgs = @(
'--config', "Release"
)
if ( $VerbosePreference -eq 'Continue' ) {
$OpenCVCmakeArgs += ('--verbose')
}
Log-Information "Building OpenCV..."
Invoke-External cmake --build "${OpenCVBuildPath}" @OpenCVCmakeArgs
} }
$ADVSSDepPath = "$(Resolve-Path -Path ${ProjectRoot}/../${script:ADVSSDepName})" Log-Information "Install OpenCV}..."
Log-Information "Using advss deps at $ADVSSDepPath ..." 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 -NoNewline | Out-File -Path ${ProjectRoot}/CMakeLists.txt
Setup-Obs Setup-Obs
@@ -84,7 +182,7 @@ function Build {
"-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=${DepInstallPath};${ADVSSDepPath}" "-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
"-DQT_VERSION=${script:QtVersion}" "-DQT_VERSION=${script:QtVersion}"
) )

View File

@@ -1,13 +0,0 @@
#!/bin/sh
if ! type zsh > /dev/null 2>&1; then
echo ' => Installing script dependency Zsh.'
sudo apt-get -y update
sudo apt-get -y install zsh
fi
SCRIPT=$(readlink -f "${0}")
SCRIPT_DIR=$(dirname "${SCRIPT}")
zsh ${SCRIPT_DIR}/build-deps-linux.zsh "${@}"

View File

@@ -1 +0,0 @@
.build-deps.zsh

View File

@@ -1 +0,0 @@
.build-deps.zsh

View File

@@ -24,7 +24,7 @@ if (( ! ${+commands[packagesbuild]} )) {
pushd pushd
mkcd ${project_root:h}/obs-build-dependencies mkcd ${project_root:h}/obs-build-dependencies
local packages_url='https://web.archive.org/web/20230727054218/http://s.sudre.free.fr/Software/files/Packages.dmg' local packages_url='http://s.sudre.free.fr/Software/files/Packages.dmg'
local packages_hash='6afdd25386295974dad8f078b8f1e41cabebd08e72d970bf92f707c7e48b16c9' local packages_hash='6afdd25386295974dad8f078b8f1e41cabebd08e72d970bf92f707c7e48b16c9'
if [[ ! -f Packages.dmg ]] { if [[ ! -f Packages.dmg ]] {

View File

@@ -34,6 +34,13 @@ if (( ! (${skips[(Ie)all]} + ${skips[(Ie)deps]}) )) {
log_info 'Installing obs plugin dependencies...' log_info 'Installing obs plugin dependencies...'
sudo apt-get install -y \
libxtst-dev \
libxss-dev \
libopencv-dev \
libtesseract-dev \
libprocps-dev
local -a _qt_packages=() local -a _qt_packages=()
if (( QT_VERSION == 5 )) { if (( QT_VERSION == 5 )) {

View File

@@ -17,7 +17,6 @@ on:
env: env:
PLUGIN_NAME: SceneSwitcher PLUGIN_NAME: SceneSwitcher
LIB_NAME: advanced-scene-switcher LIB_NAME: advanced-scene-switcher
DEP_DIR: advss-build-dependencies-1
jobs: jobs:
clang_check: clang_check:
@@ -116,6 +115,9 @@ jobs:
with: with:
path: | path: |
${{ github.workspace }}/.ccache ${{ 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-
@@ -144,13 +146,6 @@ jobs:
print "CODESIGN_IDENT=${{ secrets.MACOS_SIGNING_APPLICATION_IDENTITY }}" >> $GITHUB_ENV print "CODESIGN_IDENT=${{ secrets.MACOS_SIGNING_APPLICATION_IDENTITY }}" >> $GITHUB_ENV
print "CODESIGN_IDENT_INSTALLER=${{ secrets.MACOS_SIGNING_INSTALLER_IDENTITY }}" >> $GITHUB_ENV print "CODESIGN_IDENT_INSTALLER=${{ secrets.MACOS_SIGNING_INSTALLER_IDENTITY }}" >> $GITHUB_ENV
- name: Build Dependencies
uses: ./plugin/.github/actions/build-dependencies
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
config: RelWithDebInfo
- name: Build Plugin - name: Build Plugin
uses: ./plugin/.github/actions/build-plugin uses: ./plugin/.github/actions/build-plugin
with: with:
@@ -160,12 +155,6 @@ 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:
@@ -253,13 +242,6 @@ jobs:
echo 'found=false' >> $GITHUB_OUTPUT echo 'found=false' >> $GITHUB_OUTPUT
fi fi
- name: Build Dependencies
uses: ./plugin/.github/actions/build-dependencies
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
config: RelWithDebInfo
- name: Build Plugin - name: Build Plugin
uses: ./plugin/.github/actions/build-plugin uses: ./plugin/.github/actions/build-plugin
with: with:
@@ -268,12 +250,6 @@ 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:
@@ -341,6 +317,9 @@ jobs:
with: with:
path: | path: |
${{ github.workspace }}/.ccache ${{ 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 }} key: windows-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
restore-keys: | restore-keys: |
windows-${{ matrix.arch }}-ccache-plugin- windows-${{ matrix.arch }}-ccache-plugin-
@@ -366,14 +345,6 @@ jobs:
"found=$(([string]${LabelFound}).ToLower())" >> $env:GITHUB_OUTPUT "found=$(([string]${LabelFound}).ToLower())" >> $env:GITHUB_OUTPUT
- name: Build Dependencies
uses: ./plugin/.github/actions/build-dependencies
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
config: RelWithDebInfo
visualStudio: 'Visual Studio 17 2022'
- name: Build Plugin - name: Build Plugin
uses: ./plugin/.github/actions/build-plugin uses: ./plugin/.github/actions/build-plugin
with: with:
@@ -382,12 +353,6 @@ 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:
@@ -442,11 +407,10 @@ 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@v1 uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5
with: with:
draft: true draft: true
prerelease: true prerelease: true

1
.gitignore vendored
View File

@@ -91,7 +91,6 @@ Thumbs.db
.settings .settings
.idea .idea
.metadata .metadata
.vscode
*.iml *.iml
*.ipr *.ipr
*.sublime* *.sublime*

9
.gitmodules vendored
View File

@@ -16,12 +16,3 @@
[submodule "deps/tesseract"] [submodule "deps/tesseract"]
path = deps/tesseract path = deps/tesseract
url = https://github.com/tesseract-ocr/tesseract.git url = https://github.com/tesseract-ocr/tesseract.git
[submodule "deps/libremidi"]
path = deps/libremidi
url = https://github.com/jcelerier/libremidi.git
[submodule "deps/cpp-httplib"]
path = deps/cpp-httplib
url = https://github.com/yhirose/cpp-httplib.git
[submodule "deps/json"]
path = deps/json
url = https://github.com/nlohmann/json.git

View File

@@ -42,20 +42,21 @@ target_sources(
src/general.cpp src/general.cpp
src/hotkey.cpp src/hotkey.cpp
src/hotkey.hpp src/hotkey.hpp
src/hotkey.hpp
src/platform-funcs.hpp src/platform-funcs.hpp
src/scene-group.cpp
src/scene-group.hpp
src/status-control.cpp src/status-control.cpp
src/status-control.hpp src/status-control.hpp
src/switcher-data.cpp src/switcher-data-structs.cpp
src/switcher-data.hpp src/switcher-data-structs.hpp
src/version.cpp src/version.cpp
src/version.h) src/version.h)
# Legacy function sources # Legacy function sources
target_sources( target_sources(
${LIB_NAME} ${LIB_NAME}
PRIVATE src/legacy/scene-group.cpp PRIVATE src/legacy/scene-trigger.cpp
src/legacy/scene-group.hpp
src/legacy/scene-trigger.cpp
src/legacy/scene-trigger.hpp src/legacy/scene-trigger.hpp
src/legacy/switch-audio.cpp src/legacy/switch-audio.cpp
src/legacy/switch-audio.hpp src/legacy/switch-audio.hpp
@@ -73,6 +74,7 @@ target_sources(
src/legacy/switch-network.hpp src/legacy/switch-network.hpp
src/legacy/switch-pause.cpp src/legacy/switch-pause.cpp
src/legacy/switch-pause.hpp src/legacy/switch-pause.hpp
src/legacy/switch-priority.cpp
src/legacy/switch-random.cpp src/legacy/switch-random.cpp
src/legacy/switch-random.hpp src/legacy/switch-random.hpp
src/legacy/switch-screen-region.cpp src/legacy/switch-screen-region.cpp
@@ -93,8 +95,6 @@ target_sources(
${LIB_NAME} ${LIB_NAME}
PRIVATE src/macro-core/macro-action-audio.cpp PRIVATE src/macro-core/macro-action-audio.cpp
src/macro-core/macro-action-audio.hpp src/macro-core/macro-action-audio.hpp
src/macro-core/macro-action-clipboard.cpp
src/macro-core/macro-action-clipboard.hpp
src/macro-core/macro-action-edit.cpp src/macro-core/macro-action-edit.cpp
src/macro-core/macro-action-edit.hpp src/macro-core/macro-action-edit.hpp
src/macro-core/macro-action-file.cpp src/macro-core/macro-action-file.cpp
@@ -109,8 +109,6 @@ target_sources(
src/macro-core/macro-action-macro.hpp src/macro-core/macro-action-macro.hpp
src/macro-core/macro-action-media.cpp src/macro-core/macro-action-media.cpp
src/macro-core/macro-action-media.hpp src/macro-core/macro-action-media.hpp
src/macro-core/macro-action-osc.cpp
src/macro-core/macro-action-osc.hpp
src/macro-core/macro-action-plugin-state.cpp src/macro-core/macro-action-plugin-state.cpp
src/macro-core/macro-action-plugin-state.hpp src/macro-core/macro-action-plugin-state.hpp
src/macro-core/macro-action-profile.cpp src/macro-core/macro-action-profile.cpp
@@ -127,8 +125,6 @@ target_sources(
src/macro-core/macro-action-run.hpp src/macro-core/macro-action-run.hpp
src/macro-core/macro-action-scene-collection.cpp src/macro-core/macro-action-scene-collection.cpp
src/macro-core/macro-action-scene-collection.hpp src/macro-core/macro-action-scene-collection.hpp
src/macro-core/macro-action-scene-lock.cpp
src/macro-core/macro-action-scene-lock.hpp
src/macro-core/macro-action-scene-order.cpp src/macro-core/macro-action-scene-order.cpp
src/macro-core/macro-action-scene-order.hpp src/macro-core/macro-action-scene-order.hpp
src/macro-core/macro-action-scene-switch.cpp src/macro-core/macro-action-scene-switch.cpp
@@ -169,8 +165,6 @@ target_sources(
src/macro-core/macro-condition-cursor.hpp src/macro-core/macro-condition-cursor.hpp
src/macro-core/macro-condition-date.cpp src/macro-core/macro-condition-date.cpp
src/macro-core/macro-condition-date.hpp src/macro-core/macro-condition-date.hpp
src/macro-core/macro-condition-display.cpp
src/macro-core/macro-condition-display.hpp
src/macro-core/macro-condition-edit.cpp src/macro-core/macro-condition-edit.cpp
src/macro-core/macro-condition-edit.hpp src/macro-core/macro-condition-edit.hpp
src/macro-core/macro-condition-file.cpp src/macro-core/macro-condition-file.cpp
@@ -197,16 +191,12 @@ 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
src/macro-core/macro-condition-scene-transform.hpp src/macro-core/macro-condition-scene-transform.hpp
src/macro-core/macro-condition-scene-visibility.cpp src/macro-core/macro-condition-scene-visibility.cpp
src/macro-core/macro-condition-scene-visibility.hpp src/macro-core/macro-condition-scene-visibility.hpp
src/macro-core/macro-condition-slideshow.cpp
src/macro-core/macro-condition-slideshow.hpp
src/macro-core/macro-condition-scene.cpp src/macro-core/macro-condition-scene.cpp
src/macro-core/macro-condition-scene.hpp src/macro-core/macro-condition-scene.hpp
src/macro-core/macro-condition-source.cpp src/macro-core/macro-condition-source.cpp
@@ -215,8 +205,6 @@ target_sources(
src/macro-core/macro-condition-streaming.hpp src/macro-core/macro-condition-streaming.hpp
src/macro-core/macro-condition-studio-mode.cpp src/macro-core/macro-condition-studio-mode.cpp
src/macro-core/macro-condition-studio-mode.hpp src/macro-core/macro-condition-studio-mode.hpp
src/macro-core/macro-condition-tempvar.cpp
src/macro-core/macro-condition-tempvar.hpp
src/macro-core/macro-condition-timer.cpp src/macro-core/macro-condition-timer.cpp
src/macro-core/macro-condition-timer.hpp src/macro-core/macro-condition-timer.hpp
src/macro-core/macro-condition-transition.cpp src/macro-core/macro-condition-transition.cpp
@@ -231,8 +219,6 @@ 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
@@ -256,47 +242,16 @@ target_sources(
src/utils/connection-manager.hpp src/utils/connection-manager.hpp
src/utils/curl-helper.cpp src/utils/curl-helper.cpp
src/utils/curl-helper.hpp src/utils/curl-helper.hpp
src/utils/duration.cpp
src/utils/duration.hpp
src/utils/duration-control.cpp src/utils/duration-control.cpp
src/utils/duration-control.hpp src/utils/duration-control.hpp
src/utils/export-symbol-helper.hpp
src/utils/item-selection-helpers.cpp src/utils/item-selection-helpers.cpp
src/utils/item-selection-helpers.hpp src/utils/item-selection-helpers.hpp
src/utils/log-helper.hpp
src/utils/file-selection.cpp src/utils/file-selection.cpp
src/utils/file-selection.hpp src/utils/file-selection.hpp
src/utils/filter-combo-box.cpp
src/utils/filter-combo-box.hpp
src/utils/filter-selection.cpp
src/utils/filter-selection.hpp
src/utils/macro-export-import-dialog.cpp
src/utils/macro-export-import-dialog.hpp
src/utils/macro-list.cpp src/utils/macro-list.cpp
src/utils/macro-list.hpp src/utils/macro-list.hpp
src/utils/macro-run-button.cpp
src/utils/macro-run-button.hpp
src/utils/macro-segment-selection.cpp
src/utils/macro-segment-selection.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/non-modal-dialog.cpp
src/utils/non-modal-dialog.hpp
src/utils/obs-dock.hpp
src/utils/obs-module-helper.cpp
src/utils/obs-module-helper.hpp
src/utils/osc-helpers.cpp
src/utils/osc-helpers.hpp
src/utils/plugin-state-helper.cpp
src/utils/plugin-state-helper.hpp
src/utils/priority-helper.cpp
src/utils/priority-helper.hpp
src/utils/process-config.cpp
src/utils/process-config.hpp
src/utils/regex-config.cpp src/utils/regex-config.cpp
src/utils/regex-config.hpp src/utils/regex-config.hpp
src/utils/resizing-text-edit.cpp src/utils/resizing-text-edit.cpp
@@ -305,8 +260,6 @@ target_sources(
src/utils/scene-item-selection.hpp src/utils/scene-item-selection.hpp
src/utils/scene-selection.cpp src/utils/scene-selection.cpp
src/utils/scene-selection.hpp src/utils/scene-selection.hpp
src/utils/scene-switch-helpers.cpp
src/utils/scene-switch-helpers.hpp
src/utils/screenshot-helper.cpp src/utils/screenshot-helper.cpp
src/utils/screenshot-helper.hpp src/utils/screenshot-helper.hpp
src/utils/section.cpp src/utils/section.cpp
@@ -315,32 +268,12 @@ 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/source-setting.cpp
src/utils/source-setting.hpp
src/utils/string-list.cpp
src/utils/string-list.hpp
src/utils/striped-frame.cpp
src/utils/striped-frame.hpp
src/utils/switch-button.cpp
src/utils/switch-button.hpp
src/utils/sync-helper.cpp
src/utils/sync-helper.hpp
src/utils/temp-variable.cpp
src/utils/temp-variable.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
@@ -387,16 +320,7 @@ 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")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/deps/json/CMakeLists.txt")
add_subdirectory(deps/json)
else()
find_package(nlohmann_json REQUIRED)
endif()
target_link_libraries(${LIB_NAME} PUBLIC nlohmann_json::nlohmann_json)
target_compile_definitions(${LIB_NAME} PRIVATE ADVSS_EXPORT_SYMBOLS=1)
# --- End of section --- # --- End of section ---
@@ -407,8 +331,7 @@ 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_)
@@ -464,24 +387,27 @@ else()
find_path(PROCPS_INCLUDE_DIR NAMES proc/procps.h) find_path(PROCPS_INCLUDE_DIR NAMES proc/procps.h)
find_path(PROCPS2_INCLUDE_DIR NAMES libproc2/pids.h) find_path(PROCPS2_INCLUDE_DIR NAMES libproc2/pids.h)
if(PROCPS_INCLUDE_DIR) find_library(PROCPS_LIBRARY NAMES procps)
find_library(PROCPS2_LIBRARY NAMES proc2)
if(PROCPS_INCLUDE_DIR AND PROCPS_LIBRARY)
message(STATUS "${PROJECT_NAME} using procps") message(STATUS "${PROJECT_NAME} using procps")
set(PROC_INCLUDE_DIR "${PROCPS_INCLUDE_DIR}") set(PROC_INCLUDE_DIR "${PROCPS_INCLUDE_DIR}")
target_compile_definitions(${LIB_NAME} PRIVATE PROCPS_AVAILABLE) set(PROC_LIBRARY "${PROCPS_LIBRARY}")
set(PROCESS_CONDITION_SUPPORTED 1) target_compile_definitions(${LIB_NAME} PRIVATE USE_PROCPS)
endif() elseif(PROCPS2_INCLUDE_DIR AND PROCPS2_LIBRARY)
if(PROCPS2_INCLUDE_DIR)
message(STATUS "${PROJECT_NAME} using libproc2") message(STATUS "${PROJECT_NAME} using libproc2")
set(PROC_INCLUDE_DIR "${PROCPS2_INCLUDE_DIR}") set(PROC_INCLUDE_DIR "${PROCPS2_INCLUDE_DIR}")
target_compile_definitions(${LIB_NAME} PRIVATE PROCPS2_AVAILABLE) set(PROC_LIBRARY "${PROCPS2_LIBRARY}")
set(PROCESS_CONDITION_SUPPORTED 1) else()
endif()
if(NOT DEFINED PROCESS_CONDITION_SUPPORTED)
message( message(
WARNING FATAL_ERROR
"found neither procps nor libproc2! Process condition will not be functional!" "found neither procps nor libproc2!
) please either set ...
PROCPS_INCLUDE_DIR and PROCPS_LIBRARY
... or ...
PROCPS2_INCLUDE_DIR and PROCPS2_LIBRARY")
endif() endif()
target_link_libraries(${LIB_NAME} PRIVATE "${PROC_LIBRARY}")
target_include_directories(${LIB_NAME} PRIVATE "${PROC_INCLUDE_DIR}") target_include_directories(${LIB_NAME} PRIVATE "${PROC_INCLUDE_DIR}")
find_package(CURL) find_package(CURL)
@@ -522,4 +448,3 @@ endif()
# --- End of section --- # --- End of section ---
add_subdirectory(src/macro-external) add_subdirectory(src/macro-external)
add_subdirectory(tests)

View File

@@ -22,5 +22,9 @@
</array> </array>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>10.13</string> <string>10.13</string>
<key>com.apple.security.automation.apple-events</key>
<true/>
<key>NSAppleEventsUsageDescription</key>
<string>Advanced scene switcher needs additional permissions to be able to run AppleScript applications</string>
</dict> </dict>
</plist> </plist>

View File

@@ -25,7 +25,7 @@ DirExistsWarning=no
Name: "english"; MessagesFile: "compiler:Default.isl" Name: "english"; MessagesFile: "compiler:Default.isl"
[Files] [Files]
Source: "..\release\*"; Excludes: "*.zip"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "..\release\*"; 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

View File

@@ -146,12 +146,18 @@ AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Während des
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}" AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}" AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
AdvSceneSwitcher.condition.window="Fenster" 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="Datei"
AdvSceneSwitcher.condition.file.type.match="entspricht" AdvSceneSwitcher.condition.file.type.match="entspricht"
AdvSceneSwitcher.condition.file.type.contentChange="Inhalt geändert" AdvSceneSwitcher.condition.file.type.contentChange="Inhalt geändert"
AdvSceneSwitcher.condition.file.type.dateChange="Änderungsdatum geändert" AdvSceneSwitcher.condition.file.type.dateChange="Änderungsdatum geändert"
AdvSceneSwitcher.condition.file.remote="Entfernte Datei" AdvSceneSwitcher.condition.file.remote="Entfernte Datei"
AdvSceneSwitcher.condition.file.local="Lokale 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="Medien"
AdvSceneSwitcher.condition.media.source="Quelle" AdvSceneSwitcher.condition.media.source="Quelle"
AdvSceneSwitcher.condition.media.anyOnScene="Beliebige Medienquelle in" AdvSceneSwitcher.condition.media.anyOnScene="Beliebige Medienquelle in"
@@ -213,13 +219,14 @@ AdvSceneSwitcher.condition.stream.state.start="Stream läuft"
AdvSceneSwitcher.condition.stream.state.stop="Stream gestoppt" AdvSceneSwitcher.condition.stream.state.stop="Stream gestoppt"
AdvSceneSwitcher.condition.stream.state.starting="Stream wird gestartet" AdvSceneSwitcher.condition.stream.state.starting="Stream wird gestartet"
AdvSceneSwitcher.condition.stream.state.stopping="Stream wird gestoppt" AdvSceneSwitcher.condition.stream.state.stopping="Stream wird gestoppt"
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}" AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
AdvSceneSwitcher.condition.record="Aufnahme" AdvSceneSwitcher.condition.record="Aufnahme"
AdvSceneSwitcher.condition.record.state.start="Aufnahme läuft" AdvSceneSwitcher.condition.record.state.start="Aufnahme läuft"
AdvSceneSwitcher.condition.record.state.pause="Aufnahme pausiert" AdvSceneSwitcher.condition.record.state.pause="Aufnahme pausiert"
AdvSceneSwitcher.condition.record.state.stop="Aufnahme gestoppt" AdvSceneSwitcher.condition.record.state.stop="Aufnahme gestoppt"
AdvSceneSwitcher.condition.record.entry="{{recordState}}"
AdvSceneSwitcher.condition.process="Prozess" AdvSceneSwitcher.condition.process="Prozess"
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}läuft{{focused}}und ist fokusiert" AdvSceneSwitcher.condition.process.entry="{{processes}} läuft {{focused}} und ist fokusiert"
AdvSceneSwitcher.condition.process.entry.focus="Aktueller Vordergrundprozess: {{focusProcess}}" AdvSceneSwitcher.condition.process.entry.focus="Aktueller Vordergrundprozess: {{focusProcess}}"
AdvSceneSwitcher.condition.idle="Leerlauf" AdvSceneSwitcher.condition.idle="Leerlauf"
AdvSceneSwitcher.condition.idle.entry="Keine Tastatur- oder Mauseingaben für {{duration}}" AdvSceneSwitcher.condition.idle.entry="Keine Tastatur- oder Mauseingaben für {{duration}}"
@@ -321,9 +328,7 @@ 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.date.entry.updateOnRepeat="{{updateOnRepeat}} Bei Wiederholung ausgewähltes Datum auf Wiederholungsdatum aktualisieren"
AdvSceneSwitcher.condition.sceneTransform="Szenenelement transformieren" AdvSceneSwitcher.condition.sceneTransform="Szenenelement transformieren"
AdvSceneSwitcher.condition.sceneTransform.getTransform="Transformation erhalten" AdvSceneSwitcher.condition.sceneTransform.getTransform="Transformation erhalten"
AdvSceneSwitcher.condition.sceneTransform.entry.line1="Auf{{scenes}}{{sources}}{{types}}" AdvSceneSwitcher.condition.sceneTransform.entry.line1="Auf{{scenes}}{{sources}}passt zur Transformation"
AdvSceneSwitcher.condition.sceneTransform.entry.type.matches="entspricht Transformation"
AdvSceneSwitcher.condition.sceneTransform.entry.type.changed="hat sich geändert"
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}" AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}" AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.transition="Übergang" AdvSceneSwitcher.condition.transition="Übergang"
@@ -387,11 +392,12 @@ AdvSceneSwitcher.condition.variable.type.valueChanged="Wert verändert"
AdvSceneSwitcher.condition.variable.type.equalsVariable="entspricht Variable" AdvSceneSwitcher.condition.variable.type.equalsVariable="entspricht Variable"
AdvSceneSwitcher.condition.variable.type.lessThanVariable="ist kleiner als die 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.type.greaterThanVariable="ist größer als die Variable"
AdvSceneSwitcher.condition.variable.entry="{{variables}}{{conditions}}{{strValue}}{{numValue}}{{variables2}}"
; Macro Actions ; Macro Actions
AdvSceneSwitcher.action.scene="Szene wechseln" AdvSceneSwitcher.action.switchScene="Szene wechseln"
AdvSceneSwitcher.action.scene.entry="Wechsle{{sceneTypes}}Szene zu{{scenes}}mittels{{transitions}}mit einer Dauer von{{duration}}Sekunden" AdvSceneSwitcher.action.scene.entry="Wechsle zu Szene{{scenes}}mittels{{transitions}}mit einer Dauer von{{duration}}Sekunden"
AdvSceneSwitcher.action.scene.entry.noDuration="Wechsle{{sceneTypes}}Szene zu{{scenes}}mittels{{transitions}}" 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.scene.blockUntilTransitionDone="Warten, bis der Übergang zur Zielszene abgeschlossen ist"
AdvSceneSwitcher.action.wait="Warten" AdvSceneSwitcher.action.wait="Warten"
AdvSceneSwitcher.action.wait.type.fixed="fixe" AdvSceneSwitcher.action.wait.type.fixed="fixe"
@@ -422,7 +428,7 @@ AdvSceneSwitcher.action.recording.type.unpause="Aufnahme nicht mehr pausieren"
AdvSceneSwitcher.action.recording.type.split="Aufnahme-Datei teilen" 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.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.split.hint="Vergewissern, dass die automatische Dateiaufteilung in den OBS-Einstellungen aktiviert ist!"
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}" AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
AdvSceneSwitcher.action.replay="Replay Buffer" 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.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.stop="Replay Buffer stoppen"
@@ -432,15 +438,20 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="Stream" AdvSceneSwitcher.action.streaming="Stream"
AdvSceneSwitcher.action.streaming.type.stop="Stream stoppen" AdvSceneSwitcher.action.streaming.type.stop="Stream stoppen"
AdvSceneSwitcher.action.streaming.type.start="Stream starten" AdvSceneSwitcher.action.streaming.type.start="Stream starten"
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}" AdvSceneSwitcher.action.streaming.entry="{{actions}}"
AdvSceneSwitcher.action.run="Ausführen" 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="Sichtbarkeit von Szenenelementen"
AdvSceneSwitcher.action.sceneVisibility.type.show="Anzeigen" AdvSceneSwitcher.action.sceneVisibility.type.show="Anzeigen"
AdvSceneSwitcher.action.sceneVisibility.type.hide="Verstecken" AdvSceneSwitcher.action.sceneVisibility.type.hide="Verstecken"
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Umschalten" AdvSceneSwitcher.action.sceneVisibility.type.toggle="Umschalten"
AdvSceneSwitcher.action.sceneVisibility.type.source="Quelle" AdvSceneSwitcher.action.sceneVisibility.type.source="Quelle"
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Beliebig" AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Beliebig"
AdvSceneSwitcher.action.sceneVisibility.entry="Auf{{scenes}}{{actions}}{{sources}}" AdvSceneSwitcher.action.sceneVisibility.entry="Auf{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
AdvSceneSwitcher.action.filter="Filter" AdvSceneSwitcher.action.filter="Filter"
AdvSceneSwitcher.action.filter.type.enable="Aktivieren" AdvSceneSwitcher.action.filter.type.enable="Aktivieren"
AdvSceneSwitcher.action.filter.type.disable="Deaktivieren" AdvSceneSwitcher.action.filter.type.disable="Deaktivieren"
@@ -455,7 +466,7 @@ AdvSceneSwitcher.action.source.type.refreshSettings="Aktualisieren der Quellenei
AdvSceneSwitcher.action.source.type.pressSettingsButton="Drücken der Einstellungstaste" 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.type.refreshSettings.tooltip="Kann verwendet werden, um Browser-, Medien- usw. Quellen zu aktualisieren"
AdvSceneSwitcher.action.source.noSettingsButtons="Keine Buttons gefunden!" AdvSceneSwitcher.action.source.noSettingsButtons="Keine Buttons gefunden!"
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}" 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.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.source.getSettings="Aktuelle Einstellungen abfragen"
AdvSceneSwitcher.action.media="Medien" AdvSceneSwitcher.action.media="Medien"
@@ -465,14 +476,15 @@ AdvSceneSwitcher.action.media.type.stop="Stoppen"
AdvSceneSwitcher.action.media.type.restart="Neu starten" AdvSceneSwitcher.action.media.type.restart="Neu starten"
AdvSceneSwitcher.action.media.type.next="Nächste" AdvSceneSwitcher.action.media.type.next="Nächste"
AdvSceneSwitcher.action.media.type.previous="Vorherige" AdvSceneSwitcher.action.media.type.previous="Vorherige"
AdvSceneSwitcher.action.media.type.seek.duration="Suche nach" AdvSceneSwitcher.action.media.type.seek="Suche nach"
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
AdvSceneSwitcher.action.macro="Makro" AdvSceneSwitcher.action.macro="Makro"
AdvSceneSwitcher.action.macro.type.pause="Pausieren" AdvSceneSwitcher.action.macro.type.pause="Pausieren"
AdvSceneSwitcher.action.macro.type.unpause="Nicht mehr pausieren" AdvSceneSwitcher.action.macro.type.unpause="Nicht mehr pausieren"
AdvSceneSwitcher.action.macro.type.resetCounter="Zähler zurücksetzen" AdvSceneSwitcher.action.macro.type.resetCounter="Zähler zurücksetzen"
AdvSceneSwitcher.action.macro.type.run="Aktionen ausführen" AdvSceneSwitcher.action.macro.type.run="Aktionen ausführen"
AdvSceneSwitcher.action.macro.type.stop="Aktionen stoppen" AdvSceneSwitcher.action.macro.type.stop="Aktionen stoppen"
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}" AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
AdvSceneSwitcher.action.pluginState="Plugin-Status" AdvSceneSwitcher.action.pluginState="Plugin-Status"
AdvSceneSwitcher.action.pluginState.type.stop="Erweiterten Automatischen Szenenwechsler stoppen" AdvSceneSwitcher.action.pluginState.type.stop="Erweiterten Automatischen Szenenwechsler stoppen"
AdvSceneSwitcher.action.pluginState.type.noMatch="Ändern des Nichtübereinstimmungsverhaltens:" AdvSceneSwitcher.action.pluginState.type.noMatch="Ändern des Nichtübereinstimmungsverhaltens:"
@@ -494,6 +506,7 @@ AdvSceneSwitcher.action.hotkey.leftMeta="Linke Meta-Taste"
AdvSceneSwitcher.action.hotkey.rightMeta="Rechte Meta-Taste" AdvSceneSwitcher.action.hotkey.rightMeta="Rechte Meta-Taste"
AdvSceneSwitcher.action.hotkey.onlyOBS="Tastendruck nur an OBS senden" 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.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}} Millisekunden"
AdvSceneSwitcher.action.sceneOrder="Reihenfolge der Szenenelemente" AdvSceneSwitcher.action.sceneOrder="Reihenfolge der Szenenelemente"
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Nach oben verschieben" AdvSceneSwitcher.action.sceneOrder.type.moveUp="Nach oben verschieben"
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Nach unten verschieben" AdvSceneSwitcher.action.sceneOrder.type.moveDown="Nach unten verschieben"
@@ -503,7 +516,7 @@ AdvSceneSwitcher.action.sceneOrder.type.movePosition="An Position verschieben"
AdvSceneSwitcher.action.sceneOrder.entry="Auf{{scenes}}{{actions}}{{sources}}{{position}}" AdvSceneSwitcher.action.sceneOrder.entry="Auf{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="Szenenelement transformieren" AdvSceneSwitcher.action.sceneTransform="Szenenelement transformieren"
AdvSceneSwitcher.action.sceneTransform.getTransform="Transformation erhalten" AdvSceneSwitcher.action.sceneTransform.getTransform="Transformation erhalten"
AdvSceneSwitcher.action.sceneTransform.entry="Auf{{scenes}}{{action}}{{rotation}}{{sources}}" AdvSceneSwitcher.action.sceneTransform.entry="Auf{{scenes}}transformieren{{sources}}"
AdvSceneSwitcher.action.file="Datei" AdvSceneSwitcher.action.file="Datei"
AdvSceneSwitcher.action.file.type.write="Schreiben" AdvSceneSwitcher.action.file.type.write="Schreiben"
AdvSceneSwitcher.action.file.type.append="Anhängen" AdvSceneSwitcher.action.file.type.append="Anhängen"
@@ -532,6 +545,7 @@ AdvSceneSwitcher.action.random="Zufall"
AdvSceneSwitcher.action.random.allowRepeat="Aufeinanderfolgende Ausführung desselben Makros zulassen" 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.random.entry="Zufällige Ausführung eines der folgenden Makros (pausierte Makros werden ignoriert)"
AdvSceneSwitcher.action.systray="Benachrichtigung im System-Tray" AdvSceneSwitcher.action.systray="Benachrichtigung im System-Tray"
AdvSceneSwitcher.action.systray.entry="Benachrichtigung anzeigen: {{message}}"
AdvSceneSwitcher.action.screenshot="Screenshot" AdvSceneSwitcher.action.screenshot="Screenshot"
AdvSceneSwitcher.action.screenshot.save.default="Standard" AdvSceneSwitcher.action.screenshot.save.default="Standard"
AdvSceneSwitcher.action.screenshot.save.custom="Benutzerdefiniert" AdvSceneSwitcher.action.screenshot.save.custom="Benutzerdefiniert"
@@ -554,6 +568,8 @@ AdvSceneSwitcher.action.sequence.continueFrom="Weiter mit ausgewähltem Element"
AdvSceneSwitcher.action.websocket="Websocket" AdvSceneSwitcher.action.websocket="Websocket"
AdvSceneSwitcher.action.websocket.type.request="Anfrage" AdvSceneSwitcher.action.websocket.type.request="Anfrage"
AdvSceneSwitcher.action.websocket.type.event="Ereignis" 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="HTTP"
AdvSceneSwitcher.action.http.type.get="GET" AdvSceneSwitcher.action.http.type.get="GET"
AdvSceneSwitcher.action.http.type.post="POST" AdvSceneSwitcher.action.http.type.post="POST"
@@ -571,7 +587,7 @@ 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.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.conditionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Bedingungen wird nicht unterstützt!"
AdvSceneSwitcher.action.variable.currentSegmentValue="Aktueller Wert:" AdvSceneSwitcher.action.variable.currentSegmentValue="Aktueller Wert:"
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}" AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}"
; Transition Tab ; Transition Tab
@@ -631,7 +647,7 @@ AdvSceneSwitcher.mediaTab.states.none="Keine Auswahl"
AdvSceneSwitcher.mediaTab.states.playing="Abspielen" AdvSceneSwitcher.mediaTab.states.playing="Abspielen"
AdvSceneSwitcher.mediaTab.states.opening="Öffnen" AdvSceneSwitcher.mediaTab.states.opening="Öffnen"
AdvSceneSwitcher.mediaTab.states.buffering="Buffern" AdvSceneSwitcher.mediaTab.states.buffering="Buffern"
AdvSceneSwitcher.mediaTab.states.paused="Pausiert" 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"

File diff suppressed because it is too large Load Diff

View File

@@ -122,7 +122,12 @@ AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Durante la tr
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}" AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}" AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
AdvSceneSwitcher.condition.window="Ventana" AdvSceneSwitcher.condition.window="Ventana"
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} existen y ..."
AdvSceneSwitcher.condition.window.entry.line2="... es {{fullscreen}} pantalla completa {{maximized}} maximizada {{focused}} enfocada {{windowFocusChanged}} ventana de primer plano cambiada"
AdvSceneSwitcher.condition.file="Archivo" AdvSceneSwitcher.condition.file="Archivo"
AdvSceneSwitcher.condition.file.entry.line1="Contenido de{{fileType}}{{filePath}}{{conditions}}"
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.condition.media="Medios" AdvSceneSwitcher.condition.media="Medios"
AdvSceneSwitcher.condition.media.anyOnScene="Cualquier fuente multimedia activada" AdvSceneSwitcher.condition.media.anyOnScene="Cualquier fuente multimedia activada"
AdvSceneSwitcher.condition.media.allOnScene="Todas las fuentes de medios activadas" AdvSceneSwitcher.condition.media.allOnScene="Todas las fuentes de medios activadas"
@@ -174,13 +179,14 @@ AdvSceneSwitcher.condition.stream.state.start="Transmisión en ejecución"
AdvSceneSwitcher.condition.stream.state.stop="Transmisión detenida" AdvSceneSwitcher.condition.stream.state.stop="Transmisión detenida"
AdvSceneSwitcher.condition.stream.state.starting="Inicio de transmisión" AdvSceneSwitcher.condition.stream.state.starting="Inicio de transmisión"
AdvSceneSwitcher.condition.stream.state.stopping="Detener transmisión" AdvSceneSwitcher.condition.stream.state.stopping="Detener transmisión"
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}" AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
AdvSceneSwitcher.condition.record="Grabación" AdvSceneSwitcher.condition.record="Grabación"
AdvSceneSwitcher.condition.record.state.start="Grabación en ejecución" AdvSceneSwitcher.condition.record.state.start="Grabación en ejecución"
AdvSceneSwitcher.condition.record.state.pause="Grabación en pausa" AdvSceneSwitcher.condition.record.state.pause="Grabación en pausa"
AdvSceneSwitcher.condition.record.state.stop="Grabación detenida" AdvSceneSwitcher.condition.record.state.stop="Grabación detenida"
AdvSceneSwitcher.condition.record.entry="{{recordState}}"
AdvSceneSwitcher.condition.process="Proceso" AdvSceneSwitcher.condition.process="Proceso"
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}se está ejecutando{{focused}}y está enfocado" AdvSceneSwitcher.condition.process.entry="{{processes}} se está ejecutando {{focused}} y está enfocado"
AdvSceneSwitcher.condition.idle="Inactivo" AdvSceneSwitcher.condition.idle="Inactivo"
AdvSceneSwitcher.condition.idle.entry="No hay entradas de teclado o ratón durante {{duration}}" AdvSceneSwitcher.condition.idle.entry="No hay entradas de teclado o ratón durante {{duration}}"
AdvSceneSwitcher.condition.pluginState="Estado del complemento" AdvSceneSwitcher.condition.pluginState="Estado del complemento"
@@ -271,8 +277,7 @@ AdvSceneSwitcher.condition.date.entry.nextMatchDate="Próxima coincidencia en: %
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} Al repetir actualizar la fecha seleccionada para repetir la fecha" AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} Al repetir actualizar la fecha seleccionada para repetir la fecha"
AdvSceneSwitcher.condition.sceneTransform="Transformar elemento de escena" AdvSceneSwitcher.condition.sceneTransform="Transformar elemento de escena"
AdvSceneSwitcher.condition.sceneTransform.getTransform="Obtener transformación" AdvSceneSwitcher.condition.sceneTransform.getTransform="Obtener transformación"
AdvSceneSwitcher.condition.sceneTransform.entry.line1="En{{scenes}}{{sources}}{{types}}" AdvSceneSwitcher.condition.sceneTransform.entry.line1="En{{scenes}}{{sources}}coincide con la transformación"
AdvSceneSwitcher.condition.sceneTransform.entry.type.matches="coincide con la transformación"
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}" AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}" AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.transition="Transición" AdvSceneSwitcher.condition.transition="Transición"
@@ -319,8 +324,8 @@ AdvSceneSwitcher.condition.stats.dockHint="Puede abrir el panel de \"Estadístic
AdvSceneSwitcher.condition.stats.entry="{{stats}} esta {{condition}} {{value}}" AdvSceneSwitcher.condition.stats.entry="{{stats}} esta {{condition}} {{value}}"
; Macro Actions ; Macro Actions
AdvSceneSwitcher.action.scene="Cambiar escena" AdvSceneSwitcher.action.switchScene="Cambiar escena"
AdvSceneSwitcher.action.scene.entry="Cambiar a la{{sceneTypes}}escena{{scenes}}usando{{transitions}}con una duración de{{duration}} segundos" AdvSceneSwitcher.action.scene.entry="Cambiar a la escena {{scenes}} usando {{transitions}} con una duración de {{duration}} segundos"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Espere hasta que se complete la transición a la escena de destino" AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Espere hasta que se complete la transición a la escena de destino"
AdvSceneSwitcher.action.wait="Esperar" AdvSceneSwitcher.action.wait="Esperar"
AdvSceneSwitcher.action.wait.type.fixed="fijo" AdvSceneSwitcher.action.wait.type.fixed="fijo"
@@ -345,7 +350,7 @@ AdvSceneSwitcher.action.recording.type.start="Iniciar grabación"
AdvSceneSwitcher.action.recording.type.pause="Pausar grabación" AdvSceneSwitcher.action.recording.type.pause="Pausar grabación"
AdvSceneSwitcher.action.recording.type.unpause="Reanudar grabación" AdvSceneSwitcher.action.recording.type.unpause="Reanudar grabación"
AdvSceneSwitcher.action.recording.pause.hint="Tenga en cuenta que, dependiendo de la configuración de grabación, es posible que no pueda pausar la grabación" AdvSceneSwitcher.action.recording.pause.hint="Tenga en cuenta que, dependiendo de la configuración de grabación, es posible que no pueda pausar la grabación"
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}" AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
AdvSceneSwitcher.action.replay="Búfer de reproducción" AdvSceneSwitcher.action.replay="Búfer de reproducción"
AdvSceneSwitcher.action.replay.saveWarn="Advertencia: ¡Guardar con demasiada frecuencia puede hacer que el búfer de reproducción no se guarde realmente!" AdvSceneSwitcher.action.replay.saveWarn="Advertencia: ¡Guardar con demasiada frecuencia puede hacer que el búfer de reproducción no se guarde realmente!"
AdvSceneSwitcher.action.replay.type.stop="Detener el búfer de reproducción" AdvSceneSwitcher.action.replay.type.stop="Detener el búfer de reproducción"
@@ -355,14 +360,18 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="Transmisión" AdvSceneSwitcher.action.streaming="Transmisión"
AdvSceneSwitcher.action.streaming.type.stop="Detener transmisión" AdvSceneSwitcher.action.streaming.type.stop="Detener transmisión"
AdvSceneSwitcher.action.streaming.type.start="Iniciar transmisión" AdvSceneSwitcher.action.streaming.type.start="Iniciar transmisión"
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}" AdvSceneSwitcher.action.streaming.entry="{{actions}}"
AdvSceneSwitcher.action.run="Ejecutar" AdvSceneSwitcher.action.run="Ejecutar"
AdvSceneSwitcher.action.run.arguments="Argumentos:"
AdvSceneSwitcher.action.run.addArgument="Agregar argumento"
AdvSceneSwitcher.action.run.addArgumentDescription="Añadir nuevo argumento:"
AdvSceneSwitcher.action.run.entry="Ejecutar {{filePath}}"
AdvSceneSwitcher.action.sceneVisibility="Visibilidad del elemento de escena" AdvSceneSwitcher.action.sceneVisibility="Visibilidad del elemento de escena"
AdvSceneSwitcher.action.sceneVisibility.type.show="Mostrar" AdvSceneSwitcher.action.sceneVisibility.type.show="Mostrar"
AdvSceneSwitcher.action.sceneVisibility.type.hide="Ocultar" AdvSceneSwitcher.action.sceneVisibility.type.hide="Ocultar"
AdvSceneSwitcher.action.sceneVisibility.type.source="Fuente" AdvSceneSwitcher.action.sceneVisibility.type.source="Fuente"
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Cualquiera" AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Cualquiera"
AdvSceneSwitcher.action.sceneVisibility.entry="En{{scenes}}{{actions}}{{sources}}" AdvSceneSwitcher.action.sceneVisibility.entry="En{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
AdvSceneSwitcher.action.filter="Filtro" AdvSceneSwitcher.action.filter="Filtro"
AdvSceneSwitcher.action.filter.type.enable="Habilitar" AdvSceneSwitcher.action.filter.type.enable="Habilitar"
AdvSceneSwitcher.action.filter.type.disable="Deshabilitar" AdvSceneSwitcher.action.filter.type.disable="Deshabilitar"
@@ -373,7 +382,7 @@ AdvSceneSwitcher.action.source="Fuente"
AdvSceneSwitcher.action.source.type.enable="Habilitar" AdvSceneSwitcher.action.source.type.enable="Habilitar"
AdvSceneSwitcher.action.source.type.disable="Deshabilitar" AdvSceneSwitcher.action.source.type.disable="Deshabilitar"
AdvSceneSwitcher.action.source.type.settings="Establecer configuración" AdvSceneSwitcher.action.source.type.settings="Establecer configuración"
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}" AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
AdvSceneSwitcher.action.source.warning="Advertencia: la IU de OBS no puede controlar la habilitación y deshabilitación global de fuentes" AdvSceneSwitcher.action.source.warning="Advertencia: la IU de OBS no puede controlar la habilitación y deshabilitación global de fuentes"
AdvSceneSwitcher.action.source.getSettings="Obtener la configuración actual" AdvSceneSwitcher.action.source.getSettings="Obtener la configuración actual"
AdvSceneSwitcher.action.media="Medios" AdvSceneSwitcher.action.media="Medios"
@@ -383,14 +392,15 @@ AdvSceneSwitcher.action.media.type.stop="Detener"
AdvSceneSwitcher.action.media.type.restart="Reiniciar" AdvSceneSwitcher.action.media.type.restart="Reiniciar"
AdvSceneSwitcher.action.media.type.next="Siguiente" AdvSceneSwitcher.action.media.type.next="Siguiente"
AdvSceneSwitcher.action.media.type.previous="Anterior" AdvSceneSwitcher.action.media.type.previous="Anterior"
AdvSceneSwitcher.action.media.type.seek.duration="Buscar" AdvSceneSwitcher.action.media.type.seek="Buscar"
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
AdvSceneSwitcher.action.macro="Macro" AdvSceneSwitcher.action.macro="Macro"
AdvSceneSwitcher.action.macro.type.pause="Pausa" AdvSceneSwitcher.action.macro.type.pause="Pausa"
AdvSceneSwitcher.action.macro.type.unpause="Reanudar" AdvSceneSwitcher.action.macro.type.unpause="Reanudar"
AdvSceneSwitcher.action.macro.type.resetCounter="Reiniciar contador" AdvSceneSwitcher.action.macro.type.resetCounter="Reiniciar contador"
AdvSceneSwitcher.action.macro.type.run="Ejecutar" AdvSceneSwitcher.action.macro.type.run="Ejecutar"
AdvSceneSwitcher.action.macro.type.stop="Detener" AdvSceneSwitcher.action.macro.type.stop="Detener"
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}" AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
AdvSceneSwitcher.action.pluginState="Estado del complemento" AdvSceneSwitcher.action.pluginState="Estado del complemento"
AdvSceneSwitcher.action.pluginState.type.stop="Detener el complemento Advanced Scene Switcher" AdvSceneSwitcher.action.pluginState.type.stop="Detener el complemento Advanced Scene Switcher"
AdvSceneSwitcher.action.pluginState.type.noMatch="Cambiar el comportamiento de no coincidencia:" AdvSceneSwitcher.action.pluginState.type.noMatch="Cambiar el comportamiento de no coincidencia:"
@@ -412,6 +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.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"
@@ -421,7 +432,7 @@ AdvSceneSwitcher.action.sceneOrder.type.movePosition="Mover a la posición"
AdvSceneSwitcher.action.sceneOrder.entry="En{{scenes}}{{actions}}{{sources}}{{position}}" AdvSceneSwitcher.action.sceneOrder.entry="En{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="Transformar elemento de escena" AdvSceneSwitcher.action.sceneTransform="Transformar elemento de escena"
AdvSceneSwitcher.action.sceneTransform.getTransform="Obtener transformación" AdvSceneSwitcher.action.sceneTransform.getTransform="Obtener transformación"
AdvSceneSwitcher.action.sceneTransform.entry="En{{scenes}}{{action}}{{rotation}}{{sources}}" AdvSceneSwitcher.action.sceneTransform.entry="En{{scenes}}transformar{{sources}}"
AdvSceneSwitcher.action.file="Archivo" AdvSceneSwitcher.action.file="Archivo"
AdvSceneSwitcher.action.file.type.write="Escribir" AdvSceneSwitcher.action.file.type.write="Escribir"
AdvSceneSwitcher.action.file.type.append="Agregar" AdvSceneSwitcher.action.file.type.append="Agregar"
@@ -449,6 +460,7 @@ AdvSceneSwitcher.action.timer.entry="{{timerAction}} temporizadores en {{macros}
AdvSceneSwitcher.action.random="Aleatorio" AdvSceneSwitcher.action.random="Aleatorio"
AdvSceneSwitcher.action.random.entry="Ejecute aleatoriamente cualquiera de las siguientes macros (las macros en pausa se ignoran)" AdvSceneSwitcher.action.random.entry="Ejecute aleatoriamente cualquiera de las siguientes macros (las macros en pausa se ignoran)"
AdvSceneSwitcher.action.systray="Notificación de la bandeja del sistema" AdvSceneSwitcher.action.systray="Notificación de la bandeja del sistema"
AdvSceneSwitcher.action.systray.entry="Mostrar notificación: {{message}}"
AdvSceneSwitcher.action.screenshot="Captura de pantalla" AdvSceneSwitcher.action.screenshot="Captura de pantalla"
AdvSceneSwitcher.action.screenshot.mainOutput="Salida principal de OBS" AdvSceneSwitcher.action.screenshot.mainOutput="Salida principal de OBS"
AdvSceneSwitcher.action.profile="Perfil" AdvSceneSwitcher.action.profile="Perfil"
@@ -520,7 +532,7 @@ AdvSceneSwitcher.mediaTab.states.none="Ninguno"
AdvSceneSwitcher.mediaTab.states.playing="Reproduciéndose" AdvSceneSwitcher.mediaTab.states.playing="Reproduciéndose"
AdvSceneSwitcher.mediaTab.states.opening="Abriendo" AdvSceneSwitcher.mediaTab.states.opening="Abriendo"
AdvSceneSwitcher.mediaTab.states.buffering="Almacenando en búfer" AdvSceneSwitcher.mediaTab.states.buffering="Almacenando en búfer"
AdvSceneSwitcher.mediaTab.states.paused="Pausado" AdvSceneSwitcher.mediaTab.states.Paused="Pausado"
AdvSceneSwitcher.mediaTab.states.stopped="Detenido" AdvSceneSwitcher.mediaTab.states.stopped="Detenido"
AdvSceneSwitcher.mediaTab.states.ended="Finalizado" AdvSceneSwitcher.mediaTab.states.ended="Finalizado"
AdvSceneSwitcher.mediaTab.states.error="Error" AdvSceneSwitcher.mediaTab.states.error="Error"

File diff suppressed because it is too large Load Diff

View File

@@ -86,7 +86,10 @@ AdvSceneSwitcher.condition.scene="Сцена"
AdvSceneSwitcher.condition.scene.type.current="Текущий" AdvSceneSwitcher.condition.scene.type.current="Текущий"
AdvSceneSwitcher.condition.scene.type.previous="Предыдущий" AdvSceneSwitcher.condition.scene.type.previous="Предыдущий"
AdvSceneSwitcher.condition.window="Окно" AdvSceneSwitcher.condition.window="Окно"
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} существует и ..."
AdvSceneSwitcher.condition.file="Файл" AdvSceneSwitcher.condition.file="Файл"
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.condition.media="Медиа" AdvSceneSwitcher.condition.media="Медиа"
AdvSceneSwitcher.condition.video="Видео" AdvSceneSwitcher.condition.video="Видео"
AdvSceneSwitcher.condition.video.condition.match="точно соответствует" AdvSceneSwitcher.condition.video.condition.match="точно соответствует"
@@ -105,7 +108,7 @@ AdvSceneSwitcher.condition.record.state.start="Запись запущена"
AdvSceneSwitcher.condition.record.state.pause="Запись приостановлена" AdvSceneSwitcher.condition.record.state.pause="Запись приостановлена"
AdvSceneSwitcher.condition.record.state.stop="Запись остановлена" AdvSceneSwitcher.condition.record.state.stop="Запись остановлена"
AdvSceneSwitcher.condition.process="Процесс" AdvSceneSwitcher.condition.process="Процесс"
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}запущен{{focused}}и сфокусирован" AdvSceneSwitcher.condition.process.entry="{{processes}} запущен {{focused}} и сфокусирован"
AdvSceneSwitcher.condition.idle="Простой" AdvSceneSwitcher.condition.idle="Простой"
AdvSceneSwitcher.condition.idle.entry="Не было ни клавиатуры, ни мыши в течении{{duration}}" AdvSceneSwitcher.condition.idle.entry="Не было ни клавиатуры, ни мыши в течении{{duration}}"
AdvSceneSwitcher.condition.pluginState="Состояние плагина" AdvSceneSwitcher.condition.pluginState="Состояние плагина"
@@ -113,8 +116,8 @@ AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Автоматиче
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}" AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
; Macro Actions ; Macro Actions
AdvSceneSwitcher.action.scene="Переключить сцену" AdvSceneSwitcher.action.switchScene="Переключить сцену"
AdvSceneSwitcher.action.scene.entry="Перейти к сцене{{sceneTypes}}{{scenes}}используя{{transitions}}с продолжительностью{{duration}}секунд" AdvSceneSwitcher.action.scene.entry="Перейти к сцене {{scenes}} используя {{transitions}} с продолжительностью {{duration}} секунд"
AdvSceneSwitcher.action.wait="Подождать" AdvSceneSwitcher.action.wait="Подождать"
AdvSceneSwitcher.action.wait.type.fixed="фиксированный" AdvSceneSwitcher.action.wait.type.fixed="фиксированный"
AdvSceneSwitcher.action.wait.type.random="случайный" AdvSceneSwitcher.action.wait.type.random="случайный"
@@ -132,7 +135,7 @@ AdvSceneSwitcher.action.recording.type.start="Начать запись"
AdvSceneSwitcher.action.recording.type.pause="Пауза записи" AdvSceneSwitcher.action.recording.type.pause="Пауза записи"
AdvSceneSwitcher.action.recording.type.unpause="Снять запись с паузы" AdvSceneSwitcher.action.recording.type.unpause="Снять запись с паузы"
AdvSceneSwitcher.action.recording.pause.hint="Обратите внимание, что в зависимости от настроек записи вы можете не иметь возможности приостановить запись" AdvSceneSwitcher.action.recording.pause.hint="Обратите внимание, что в зависимости от настроек записи вы можете не иметь возможности приостановить запись"
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}" AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
AdvSceneSwitcher.action.replay="Буфер воспроизведения" AdvSceneSwitcher.action.replay="Буфер воспроизведения"
AdvSceneSwitcher.action.replay.type.stop="Остановить буфер воспроизведения" AdvSceneSwitcher.action.replay.type.stop="Остановить буфер воспроизведения"
AdvSceneSwitcher.action.replay.type.start="Начать воспроизведение буфера" AdvSceneSwitcher.action.replay.type.start="Начать воспроизведение буфера"
@@ -141,7 +144,7 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="Потоковое вещание" AdvSceneSwitcher.action.streaming="Потоковое вещание"
AdvSceneSwitcher.action.streaming.type.stop="Остановить потоковое вещание" AdvSceneSwitcher.action.streaming.type.stop="Остановить потоковое вещание"
AdvSceneSwitcher.action.streaming.type.start="Начать потоковое вещание" AdvSceneSwitcher.action.streaming.type.start="Начать потоковое вещание"
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}" AdvSceneSwitcher.action.streaming.entry="{{actions}}"
AdvSceneSwitcher.action.run="Запустить" AdvSceneSwitcher.action.run="Запустить"
@@ -202,7 +205,7 @@ AdvSceneSwitcher.mediaTab.states.none="Нет"
AdvSceneSwitcher.mediaTab.states.playing="Играет" AdvSceneSwitcher.mediaTab.states.playing="Играет"
AdvSceneSwitcher.mediaTab.states.opening="Открытие" AdvSceneSwitcher.mediaTab.states.opening="Открытие"
AdvSceneSwitcher.mediaTab.states.buffering="Буферизация" AdvSceneSwitcher.mediaTab.states.buffering="Буферизация"
AdvSceneSwitcher.mediaTab.states.paused="Приостановлено" AdvSceneSwitcher.mediaTab.states.Paused="Приостановлено"
AdvSceneSwitcher.mediaTab.states.stopped="Остановлено" AdvSceneSwitcher.mediaTab.states.stopped="Остановлено"
AdvSceneSwitcher.mediaTab.states.ended="Закончилось" AdvSceneSwitcher.mediaTab.states.ended="Закончилось"
AdvSceneSwitcher.mediaTab.states.error="Ошибка" AdvSceneSwitcher.mediaTab.states.error="Ошибка"

View File

@@ -112,7 +112,12 @@ AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Geçiş hedefi
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}" AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}" AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
AdvSceneSwitcher.condition.window="Pencere" AdvSceneSwitcher.condition.window="Pencere"
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} Varolan ve ..."
AdvSceneSwitcher.condition.window.entry.line2="... {{fullscreen}} Tam ekran {{maximized}} büyütüldü {{focused}} odaklanıldı {{windowFocusChanged}} ön plan penceresi değişikliği"
AdvSceneSwitcher.condition.file="Dosya" AdvSceneSwitcher.condition.file="Dosya"
AdvSceneSwitcher.condition.file.entry.line1="İçerik{{fileType}}{{filePath}}{{conditions}}"
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.condition.media="Medya" AdvSceneSwitcher.condition.media="Medya"
AdvSceneSwitcher.condition.media.anyOnScene="Herhangi bir medya kaynağı" AdvSceneSwitcher.condition.media.anyOnScene="Herhangi bir medya kaynağı"
AdvSceneSwitcher.condition.media.allOnScene="Tüm medya kaynakları " AdvSceneSwitcher.condition.media.allOnScene="Tüm medya kaynakları "
@@ -151,13 +156,14 @@ AdvSceneSwitcher.condition.stream.state.start="Yayın çalışıyor"
AdvSceneSwitcher.condition.stream.state.stop="Yayın durdu" AdvSceneSwitcher.condition.stream.state.stop="Yayın durdu"
AdvSceneSwitcher.condition.stream.state.starting="Yayın başlıyor" AdvSceneSwitcher.condition.stream.state.starting="Yayın başlıyor"
AdvSceneSwitcher.condition.stream.state.stopping="Yayın duruyor" AdvSceneSwitcher.condition.stream.state.stopping="Yayın duruyor"
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}" AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
AdvSceneSwitcher.condition.record="Kayıt" AdvSceneSwitcher.condition.record="Kayıt"
AdvSceneSwitcher.condition.record.state.start="Kayıt Çalışıyor" AdvSceneSwitcher.condition.record.state.start="Kayıt Çalışıyor"
AdvSceneSwitcher.condition.record.state.pause="Kayıt durakladı" AdvSceneSwitcher.condition.record.state.pause="Kayıt durakladı"
AdvSceneSwitcher.condition.record.state.stop="Kayıt durdu" AdvSceneSwitcher.condition.record.state.stop="Kayıt durdu"
AdvSceneSwitcher.condition.record.entry="{{recordState}}"
AdvSceneSwitcher.condition.process="İşlem" AdvSceneSwitcher.condition.process="İşlem"
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}çalışıyor{{focused}}ve odaklandı" AdvSceneSwitcher.condition.process.entry="{{processes}} çalışıyor {{focused}} ve odaklandı"
AdvSceneSwitcher.condition.idle="Boşta" AdvSceneSwitcher.condition.idle="Boşta"
AdvSceneSwitcher.condition.idle.entry="...için klavye veya fare girişi yok {{duration}}" AdvSceneSwitcher.condition.idle.entry="...için klavye veya fare girişi yok {{duration}}"
AdvSceneSwitcher.condition.pluginState="Eklenti durumu" AdvSceneSwitcher.condition.pluginState="Eklenti durumu"
@@ -227,8 +233,7 @@ AdvSceneSwitcher.condition.date.state.before="Önce"
AdvSceneSwitcher.condition.date.state.between="Arasında" AdvSceneSwitcher.condition.date.state.between="Arasında"
AdvSceneSwitcher.condition.sceneTransform="Sahne öğesi dönüşümü" AdvSceneSwitcher.condition.sceneTransform="Sahne öğesi dönüşümü"
AdvSceneSwitcher.condition.sceneTransform.getTransform="Dönüşümü al" AdvSceneSwitcher.condition.sceneTransform.getTransform="Dönüşümü al"
AdvSceneSwitcher.condition.sceneTransform.entry.line1="Açık{{scenes}}{{sources}}{{types}}" AdvSceneSwitcher.condition.sceneTransform.entry.line1="Açık{{scenes}}{{sources}} dönüşümle eşleşir"
AdvSceneSwitcher.condition.sceneTransform.entry.type.matches="dönüşümle eşleşir"
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}" AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}" AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.transition="Geçiş" AdvSceneSwitcher.condition.transition="Geçiş"
@@ -256,8 +261,8 @@ AdvSceneSwitcher.condition.openvr.entry.line2="{{controls}}"
AdvSceneSwitcher.condition.openvr.entry.line3="HMD mevcut {{xPos}} x {{yPos}} x {{zPos}}" AdvSceneSwitcher.condition.openvr.entry.line3="HMD mevcut {{xPos}} x {{yPos}} x {{zPos}}"
; Macro Actions ; Macro Actions
AdvSceneSwitcher.action.scene="Sahne Degistirici" AdvSceneSwitcher.action.switchScene="Sahne Degistirici"
AdvSceneSwitcher.action.scene.entry="Sahneyi{{sceneTypes}}{{scenes}}kullanarak{{transitions}}süresi olan{{duration}}saniye" AdvSceneSwitcher.action.scene.entry="Sahneyi {{scenes}} kullanarak {{transitions}} süresi olan {{duration}} saniye"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Hedef sahneye geçiş tamamlanana kadar bekleyin" AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Hedef sahneye geçiş tamamlanana kadar bekleyin"
AdvSceneSwitcher.action.wait="Bekle" AdvSceneSwitcher.action.wait="Bekle"
AdvSceneSwitcher.action.wait.type.fixed="sabit" AdvSceneSwitcher.action.wait.type.fixed="sabit"
@@ -276,7 +281,7 @@ AdvSceneSwitcher.action.recording.type.start="Kayıt Başlat"
AdvSceneSwitcher.action.recording.type.pause="Kayıt Duraklat" AdvSceneSwitcher.action.recording.type.pause="Kayıt Duraklat"
AdvSceneSwitcher.action.recording.type.unpause="Kayıt Duraklatma" AdvSceneSwitcher.action.recording.type.unpause="Kayıt Duraklatma"
AdvSceneSwitcher.action.recording.pause.hint="Kayıt ayarlarınıza bağlı olarak kaydı duraklatamayabileceğinizi unutmayın." AdvSceneSwitcher.action.recording.pause.hint="Kayıt ayarlarınıza bağlı olarak kaydı duraklatamayabileceğinizi unutmayın."
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}" AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
AdvSceneSwitcher.action.replay="Tekrar arabelleği" AdvSceneSwitcher.action.replay="Tekrar arabelleği"
AdvSceneSwitcher.action.replay.type.stop="Tekrar arabelleğini durdur" AdvSceneSwitcher.action.replay.type.stop="Tekrar arabelleğini durdur"
AdvSceneSwitcher.action.replay.type.start="Tekrar arabelleğini başlat" AdvSceneSwitcher.action.replay.type.start="Tekrar arabelleğini başlat"
@@ -285,14 +290,18 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="Yayın" AdvSceneSwitcher.action.streaming="Yayın"
AdvSceneSwitcher.action.streaming.type.stop="Yayın durdur" AdvSceneSwitcher.action.streaming.type.stop="Yayın durdur"
AdvSceneSwitcher.action.streaming.type.start="Yayın başlat" AdvSceneSwitcher.action.streaming.type.start="Yayın başlat"
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}" AdvSceneSwitcher.action.streaming.entry="{{actions}}"
AdvSceneSwitcher.action.run="Çalıştır" AdvSceneSwitcher.action.run="Çalıştır"
AdvSceneSwitcher.action.run.arguments="Argümanlar:"
AdvSceneSwitcher.action.run.addArgument="Argüman ekle"
AdvSceneSwitcher.action.run.addArgumentDescription="Yeni Argüman ekle:"
AdvSceneSwitcher.action.run.entry="Çalıştır {{filePath}}"
AdvSceneSwitcher.action.sceneVisibility="Sahne öğesi görünürlüğü" AdvSceneSwitcher.action.sceneVisibility="Sahne öğesi görünürlüğü"
AdvSceneSwitcher.action.sceneVisibility.type.show="Göster" AdvSceneSwitcher.action.sceneVisibility.type.show="Göster"
AdvSceneSwitcher.action.sceneVisibility.type.hide="Gizle" AdvSceneSwitcher.action.sceneVisibility.type.hide="Gizle"
AdvSceneSwitcher.action.sceneVisibility.type.source="Kayıt" AdvSceneSwitcher.action.sceneVisibility.type.source="Kayıt"
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Herhangi" AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Herhangi"
AdvSceneSwitcher.action.sceneVisibility.entry="Açık{{scenes}}{{actions}}{{sources}}" AdvSceneSwitcher.action.sceneVisibility.entry="Açık{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
AdvSceneSwitcher.action.filter="Filtrele" AdvSceneSwitcher.action.filter="Filtrele"
AdvSceneSwitcher.action.filter.type.enable="Etkin" AdvSceneSwitcher.action.filter.type.enable="Etkin"
AdvSceneSwitcher.action.filter.type.disable="Etkisiz" AdvSceneSwitcher.action.filter.type.disable="Etkisiz"
@@ -303,7 +312,7 @@ AdvSceneSwitcher.action.source="Kaynak"
AdvSceneSwitcher.action.source.type.enable="Etkin" AdvSceneSwitcher.action.source.type.enable="Etkin"
AdvSceneSwitcher.action.source.type.disable="Etkisiz" AdvSceneSwitcher.action.source.type.disable="Etkisiz"
AdvSceneSwitcher.action.source.type.settings="Ayarları yap" AdvSceneSwitcher.action.source.type.settings="Ayarları yap"
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}" AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
AdvSceneSwitcher.action.source.warning="Uyarı: Kaynakların global olarak etkinleştirilmesi ve devre dışı bırakılması, OBS UI tarafından kontrol edilemez" AdvSceneSwitcher.action.source.warning="Uyarı: Kaynakların global olarak etkinleştirilmesi ve devre dışı bırakılması, OBS UI tarafından kontrol edilemez"
AdvSceneSwitcher.action.source.getSettings="Mevcut Ayarları yap" AdvSceneSwitcher.action.source.getSettings="Mevcut Ayarları yap"
AdvSceneSwitcher.action.media="Medya" AdvSceneSwitcher.action.media="Medya"
@@ -313,12 +322,13 @@ AdvSceneSwitcher.action.media.type.stop="Dur"
AdvSceneSwitcher.action.media.type.restart="Yeniden Başlat" AdvSceneSwitcher.action.media.type.restart="Yeniden Başlat"
AdvSceneSwitcher.action.media.type.next="Sonraki" AdvSceneSwitcher.action.media.type.next="Sonraki"
AdvSceneSwitcher.action.media.type.previous="Önceki" AdvSceneSwitcher.action.media.type.previous="Önceki"
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
AdvSceneSwitcher.action.macro="Makro" AdvSceneSwitcher.action.macro="Makro"
AdvSceneSwitcher.action.macro.type.pause="Duraklat" AdvSceneSwitcher.action.macro.type.pause="Duraklat"
AdvSceneSwitcher.action.macro.type.unpause="Duraklatma" AdvSceneSwitcher.action.macro.type.unpause="Duraklatma"
AdvSceneSwitcher.action.macro.type.resetCounter="Sayacı sıfırla" AdvSceneSwitcher.action.macro.type.resetCounter="Sayacı sıfırla"
AdvSceneSwitcher.action.macro.type.run="Çalıştır" AdvSceneSwitcher.action.macro.type.run="Çalıştır"
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}" AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
AdvSceneSwitcher.action.pluginState="Eklenti durumu" AdvSceneSwitcher.action.pluginState="Eklenti durumu"
AdvSceneSwitcher.action.pluginState.type.stop="Advanced Scene Switcher eklentisini durdurun" AdvSceneSwitcher.action.pluginState.type.stop="Advanced Scene Switcher eklentisini durdurun"
AdvSceneSwitcher.action.pluginState.type.noMatch="Eşleşmeme davranışını değiştirin:" AdvSceneSwitcher.action.pluginState.type.noMatch="Eşleşmeme davranışını değiştirin:"
@@ -340,6 +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.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"
@@ -349,7 +360,7 @@ AdvSceneSwitcher.action.sceneOrder.type.movePosition="Konuma taşı"
AdvSceneSwitcher.action.sceneOrder.entry="Açık{{scenes}}{{actions}}{{sources}}{{position}}" AdvSceneSwitcher.action.sceneOrder.entry="Açık{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="Sahne öğesi dönüşümü" AdvSceneSwitcher.action.sceneTransform="Sahne öğesi dönüşümü"
AdvSceneSwitcher.action.sceneTransform.getTransform="Dönüşümü al" AdvSceneSwitcher.action.sceneTransform.getTransform="Dönüşümü al"
AdvSceneSwitcher.action.sceneTransform.entry="Açık{{scenes}}{{action}}{{rotation}}{{sources}}" AdvSceneSwitcher.action.sceneTransform.entry="Açık{{scenes}}transform{{sources}}"
AdvSceneSwitcher.action.file="Dosya" AdvSceneSwitcher.action.file="Dosya"
AdvSceneSwitcher.action.file.type.write="Yaz" AdvSceneSwitcher.action.file.type.write="Yaz"
AdvSceneSwitcher.action.file.type.append="Ekle" AdvSceneSwitcher.action.file.type.append="Ekle"
@@ -366,6 +377,7 @@ AdvSceneSwitcher.action.timer.entry="{{timerAction}} zamanlayıcılar açık {{m
AdvSceneSwitcher.action.random="Rastgele" AdvSceneSwitcher.action.random="Rastgele"
AdvSceneSwitcher.action.random.entry="Aşağıdaki makrolardan herhangi birini rastgele çalıştırın (duraklatılmış makrolar yoksayılır)" AdvSceneSwitcher.action.random.entry="Aşağıdaki makrolardan herhangi birini rastgele çalıştırın (duraklatılmış makrolar yoksayılır)"
AdvSceneSwitcher.action.systray="Sistem tepsisi bildirimi" AdvSceneSwitcher.action.systray="Sistem tepsisi bildirimi"
AdvSceneSwitcher.action.systray.entry="Bildirimleri göster: {{message}}"
AdvSceneSwitcher.action.screenshot="Ekran görüntüsü" AdvSceneSwitcher.action.screenshot="Ekran görüntüsü"
AdvSceneSwitcher.action.screenshot.mainOutput="OBS'nin ana çıkışı" AdvSceneSwitcher.action.screenshot.mainOutput="OBS'nin ana çıkışı"
AdvSceneSwitcher.action.profile="Profil" AdvSceneSwitcher.action.profile="Profil"
@@ -431,7 +443,7 @@ AdvSceneSwitcher.mediaTab.states.none="Yok"
AdvSceneSwitcher.mediaTab.states.playing="Oynamak" AdvSceneSwitcher.mediaTab.states.playing="Oynamak"
AdvSceneSwitcher.mediaTab.states.opening="Açmak" AdvSceneSwitcher.mediaTab.states.opening="Açmak"
AdvSceneSwitcher.mediaTab.states.buffering="Arabelleğe alma" AdvSceneSwitcher.mediaTab.states.buffering="Arabelleğe alma"
AdvSceneSwitcher.mediaTab.states.paused="Duraklatıldı" AdvSceneSwitcher.mediaTab.states.Paused="Duraklatıldı"
AdvSceneSwitcher.mediaTab.states.stopped="Durduruldu" AdvSceneSwitcher.mediaTab.states.stopped="Durduruldu"
AdvSceneSwitcher.mediaTab.states.ended="Bitti" AdvSceneSwitcher.mediaTab.states.ended="Bitti"
AdvSceneSwitcher.mediaTab.states.error="Hata" AdvSceneSwitcher.mediaTab.states.error="Hata"

View File

@@ -4,7 +4,7 @@ AdvSceneSwitcher.windowTitle="高级场景切换器"
; General Tab ; General Tab
AdvSceneSwitcher.generalTab.title="通用" AdvSceneSwitcher.generalTab.title="通用"
AdvSceneSwitcher.generalTab.status="状态" AdvSceneSwitcher.generalTab.status="状态"
AdvSceneSwitcher.generalTab.status.hotkeytips="快捷键可在OBS设置中设置<br><br>汉化作者:[ 从不咕咕的阿坤 ] - 全平台统一名 - 如对你有所帮助,劳烦点个关注!" AdvSceneSwitcher.generalTab.status.hotkeytips="快捷键可在OBS设置中设置"
AdvSceneSwitcher.generalTab.status.currentStatus="当前状态:" AdvSceneSwitcher.generalTab.status.currentStatus="当前状态:"
AdvSceneSwitcher.generalTab.status.onStartup="在OBS启动时" AdvSceneSwitcher.generalTab.status.onStartup="在OBS启动时"
AdvSceneSwitcher.generalTab.status.onStartup.asLastRun="按照最后运行时的状态" AdvSceneSwitcher.generalTab.status.onStartup.asLastRun="按照最后运行时的状态"
@@ -24,14 +24,11 @@ AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="时间精度最
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="不切换" AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="不切换"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="切换到随机场景列表中任意随机场景" AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="切换到随机场景列表中任意随机场景"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="切换到" AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="切换到"
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="执行完操作后,跳过执行操作,为"
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="在此期间,可能的匹配项将被忽略!" AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="在此期间,可能的匹配项将被忽略!"
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="详细日志输出" AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="详细日志输出"
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="保存窗口位置和大小" AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="保存窗口位置和大小"
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="显示系统托盘通知" AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="显示系统托盘通知"
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="禁用UI提示" AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="禁用UI提示"
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailure="如果无法加载插件显示警告"
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage="<html><body>加载以下插件库失败,这可能导致某些高级场景切换器功能不可用:%1 查看 OBS 日志了解详细信息.<br>可以在“常规”选项卡上禁用此消息.</body></html>"
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="隐藏可通过宏操作的分组栏" AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="隐藏可通过宏操作的分组栏"
AdvSceneSwitcher.generalTab.matchBehavior="场景匹配设置" AdvSceneSwitcher.generalTab.matchBehavior="场景匹配设置"
AdvSceneSwitcher.generalTab.priority="优先级" AdvSceneSwitcher.generalTab.priority="优先级"
@@ -81,39 +78,17 @@ AdvSceneSwitcher.macroTab.runFail="运行 \"%1\" 失败!\n其中一个操作失
AdvSceneSwitcher.macroTab.runInParallel="与其他宏同时运行宏" AdvSceneSwitcher.macroTab.runInParallel="与其他宏同时运行宏"
AdvSceneSwitcher.macroTab.onChange="仅在条件更改时执行操作" AdvSceneSwitcher.macroTab.onChange="仅在条件更改时执行操作"
AdvSceneSwitcher.macroTab.defaultname="宏 %1" AdvSceneSwitcher.macroTab.defaultname="宏 %1"
AdvSceneSwitcher.macroTab.defaultGroupName="组 %1"
AdvSceneSwitcher.macroTab.exists="宏名称已存在" AdvSceneSwitcher.macroTab.exists="宏名称已存在"
AdvSceneSwitcher.macroTab.groupDeleteConfirm="您确定要删除 \"%1\"及其所有元素吗?"
AdvSceneSwitcher.macroTab.deleteMultipleMacrosConfirmation="您确定要删除 %1 宏吗?"
AdvSceneSwitcher.macroTab.deleteSingleMacroConfirmation="你确定你要删除 \"%1\"?"
AdvSceneSwitcher.macroTab.contextMenuAdd="增加"
AdvSceneSwitcher.macroTab.copy="创建副本" AdvSceneSwitcher.macroTab.copy="创建副本"
AdvSceneSwitcher.macroTab.group="对选定的宏进行分组"
AdvSceneSwitcher.macroTab.ungroup="解除选定的组的分组"
AdvSceneSwitcher.macroTab.rename="重命名"
AdvSceneSwitcher.macroTab.remove="删除"
AdvSceneSwitcher.macroTab.expandAll="全部展开" AdvSceneSwitcher.macroTab.expandAll="全部展开"
AdvSceneSwitcher.macroTab.collapseAll="全部收回" AdvSceneSwitcher.macroTab.collapseAll="全部收回"
AdvSceneSwitcher.macroTab.maximize="最大化" AdvSceneSwitcher.macroTab.maximize="最大化"
AdvSceneSwitcher.macroTab.minimize="最小化" AdvSceneSwitcher.macroTab.minimize="最小化"
AdvSceneSwitcher.macroTab.highlightSettings="显示 设置"
AdvSceneSwitcher.macroTab.hotkeySettings="热键 设置"
AdvSceneSwitcher.macroTab.dockSettings="停靠 设置"
AdvSceneSwitcher.macroTab.highlightExecutedMacros="突出显示最近执行的宏" AdvSceneSwitcher.macroTab.highlightExecutedMacros="突出显示最近执行的宏"
AdvSceneSwitcher.macroTab.highlightTrueConditions="突出显示最近运算为 真 的当前选定宏的条件" AdvSceneSwitcher.macroTab.highlightTrueConditions="突出显示最近运算为 真 的当前选定宏的条件"
AdvSceneSwitcher.macroTab.highlightPerformedActions="突出显示当前选定宏的最近执行的操作" AdvSceneSwitcher.macroTab.highlightPerformedActions="突出显示当前选定宏的最近执行的操作"
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="使用快捷键控制新增宏的暂停状态" AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="使用快捷键控制新增宏的暂停状态"
AdvSceneSwitcher.macroTab.currentDisableHotkeys="使用快捷键控制所选宏的暂停状态" AdvSceneSwitcher.macroTab.currentDisableHotkeys="使用快捷键控制所选宏的暂停状态"
AdvSceneSwitcher.macroTab.currentRegisterDock="注册停靠小部件以控制所选宏的暂停状态或手动运行它"
AdvSceneSwitcher.macroTab.currentDockAddRunButton="添加按钮以运行宏"
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="添加按钮以暂停或取消暂停宏"
AdvSceneSwitcher.macroTab.currentDockButtonText.run="运行按钮文本:"
AdvSceneSwitcher.macroTab.currentDockButtonText.pause="暂停按钮文本:"
AdvSceneSwitcher.macroTab.currentDockButtonText.unpause="取消暂停按钮文本:"
AdvSceneSwitcher.macroDock.pause="暂停"
AdvSceneSwitcher.macroDock.unpause="取消暂停"
AdvSceneSwitcher.macroDock.run="运行"
; Macro List ; Macro List
AdvSceneSwitcher.macroList.deleted="删除" AdvSceneSwitcher.macroList.deleted="删除"
@@ -137,17 +112,10 @@ AdvSceneSwitcher.condition.audio.state.mute="静音"
AdvSceneSwitcher.condition.audio.state.unmute="取消静音" AdvSceneSwitcher.condition.audio.state.unmute="取消静音"
AdvSceneSwitcher.condition.audio.type.output="输出音频" AdvSceneSwitcher.condition.audio.type.output="输出音频"
AdvSceneSwitcher.condition.audio.type.volume="配置音量级别" AdvSceneSwitcher.condition.audio.type.volume="配置音量级别"
AdvSceneSwitcher.condition.audio.type.syncOffset="同步偏移"
AdvSceneSwitcher.condition.audio.type.monitor="音频监控"
AdvSceneSwitcher.condition.audio.type.balance="音频平衡"
AdvSceneSwitcher.condition.audio.entry="{{checkType}} 的 {{audioSources}} 是 {{condition}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.condition.audio.entry="{{checkType}} 的 {{audioSources}} 是 {{condition}}{{volume}}{{syncOffset}}{{monitorTypes}}"
AdvSceneSwitcher.condition.cursor="屏幕区域" AdvSceneSwitcher.condition.cursor="屏幕区域"
AdvSceneSwitcher.condition.cursor.type.region="当前位置" AdvSceneSwitcher.condition.cursor.type.region="当前位置"
AdvSceneSwitcher.condition.cursor.type.moving="正在移动" AdvSceneSwitcher.condition.cursor.type.moving="正在移动"
AdvSceneSwitcher.condition.cursor.type.click="点击"
AdvSceneSwitcher.condition.cursor.button.left="鼠标左键"
AdvSceneSwitcher.condition.cursor.button.middle="鼠标中键"
AdvSceneSwitcher.condition.cursor.button.right="鼠标右键"
AdvSceneSwitcher.condition.cursor.showFrame="显示帧率" AdvSceneSwitcher.condition.cursor.showFrame="显示帧率"
AdvSceneSwitcher.condition.cursor.hideFrame="隐藏帧率" AdvSceneSwitcher.condition.cursor.hideFrame="隐藏帧率"
AdvSceneSwitcher.condition.cursor.entry.line1="鼠标 处于{{conditions}}{{buttons}}{{minX}}{{minY}}{{maxX}}{{maxY}}{{toggleFrameButton}}" AdvSceneSwitcher.condition.cursor.entry.line1="鼠标 处于{{conditions}}{{buttons}}{{minX}}{{minY}}{{maxX}}{{maxY}}{{toggleFrameButton}}"
@@ -157,44 +125,36 @@ AdvSceneSwitcher.condition.scene.type.current="当前场景是"
AdvSceneSwitcher.condition.scene.type.previous="上一个场景是" AdvSceneSwitcher.condition.scene.type.previous="上一个场景是"
AdvSceneSwitcher.condition.scene.type.changed="场景改变了" AdvSceneSwitcher.condition.scene.type.changed="场景改变了"
AdvSceneSwitcher.condition.scene.type.notChanged="场景没有改变" AdvSceneSwitcher.condition.scene.type.notChanged="场景没有改变"
AdvSceneSwitcher.condition.scene.type.currentPattern="当前场景匹配"
AdvSceneSwitcher.condition.scene.type.previousPattern="上一个场景匹配"
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="在转场过程中检查转场源场景" AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="在转场过程中检查转场源场景"
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="在转场过程中检查转场源场景" AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="在转场过程中检查转场源场景"
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}" AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}" AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
AdvSceneSwitcher.condition.window="窗口" AdvSceneSwitcher.condition.window="窗口"
AdvSceneSwitcher.condition.window.entry.window="{{checkTitle}}窗口标题匹配{{windowRegex}}{{windows}}" AdvSceneSwitcher.condition.window.entry.line1="{{windows}} 存在..."
AdvSceneSwitcher.condition.window.entry.fullscreen="{{fullscreen}}窗口为全屏" AdvSceneSwitcher.condition.window.entry.line2="... 并且是 {{fullscreen}} 全屏 {{maximized}} 最大化 {{focused}} 获得焦点 {{windowFocusChanged}} 焦点窗口已更改"
AdvSceneSwitcher.condition.window.entry.maximized="{{maximized}}窗口为最大化" AdvSceneSwitcher.condition.window.entry.line3="当前焦点窗口: {{focusWindow}}"
AdvSceneSwitcher.condition.window.entry.focused="{{focused}}窗口为焦点"
AdvSceneSwitcher.condition.window.entry.focusedChange="{{windowFocusChanged}}焦点窗口被改变"
AdvSceneSwitcher.condition.window.entry.text="{{checkText}}窗口包含文本{{textRegex}}{{windowText}}"
AdvSceneSwitcher.condition.window.entry.text.note="此选项可能不会对窗口中显示的每个文本起作用。\n如果是这种情况您可以考虑使用视频条件OCR检查来代替。"
AdvSceneSwitcher.condition.window.entry.currentFocus="当前焦点窗口:{{focusWindow}}"
AdvSceneSwitcher.condition.file="文件" AdvSceneSwitcher.condition.file="文件"
AdvSceneSwitcher.condition.file.type.match="内容完全匹配" AdvSceneSwitcher.condition.file.type.match="内容完全匹配"
AdvSceneSwitcher.condition.file.type.contentChange="内容已更改" AdvSceneSwitcher.condition.file.type.contentChange="内容已更改"
AdvSceneSwitcher.condition.file.type.dateChange="修改日期已更改" AdvSceneSwitcher.condition.file.type.dateChange="修改日期已更改"
AdvSceneSwitcher.condition.file.remote="远程文件" AdvSceneSwitcher.condition.file.entry.line1="文件内容来自{{fileType}}{{filePath}}{{conditions}}"
AdvSceneSwitcher.condition.file.local="本地文件" AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.condition.media="媒体" AdvSceneSwitcher.condition.media="媒体"
AdvSceneSwitcher.condition.media.source="源" AdvSceneSwitcher.condition.media.anyOnScene="任何媒体来源"
AdvSceneSwitcher.condition.media.anyOnScene="任何媒体源" AdvSceneSwitcher.condition.media.allOnScene="所有媒体源"
AdvSceneSwitcher.condition.media.allOnScene="所有媒体源"
AdvSceneSwitcher.condition.media.matchOnChange="仅在更改时匹配(注意:此选项将在未来版本中删除-请改用时间限制)" AdvSceneSwitcher.condition.media.matchOnChange="仅在更改时匹配(注意:此选项将在未来版本中删除-请改用时间限制)"
AdvSceneSwitcher.condition.media.inconsistencyInfo="不幸的是并非所有媒体源类型的行为都相同例如媒体源与VLC视频源“停止”状态。\n所以请尝试适合您的设置" AdvSceneSwitcher.condition.media.inconsistencyInfo="不幸的是并非所有媒体源类型的行为都相同例如媒体源与VLC视频源“停止”状态。\n所以请尝试适合您的设置"
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}} 的状态是 {{states}}{{timeRestrictions}}{{time}}" AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}的状态是{{states}}{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.video="视频" AdvSceneSwitcher.condition.video="视频"
AdvSceneSwitcher.condition.video.condition.match="完全匹配" AdvSceneSwitcher.condition.video.condition.match="完全匹配"
AdvSceneSwitcher.condition.video.condition.differ="不匹配" AdvSceneSwitcher.condition.video.condition.differ="不匹配"
AdvSceneSwitcher.condition.video.condition.hasChanged="改变" AdvSceneSwitcher.condition.video.condition.hasChanged="改变"
AdvSceneSwitcher.condition.video.condition.hasNotChanged="改变" AdvSceneSwitcher.condition.video.condition.hasNotChanged="没有改变"
AdvSceneSwitcher.condition.video.condition.noImage="没有输出" AdvSceneSwitcher.condition.video.condition.noImage="没有输出"
AdvSceneSwitcher.condition.video.condition.pattern="匹配模式" AdvSceneSwitcher.condition.video.condition.pattern="匹配模式"
AdvSceneSwitcher.condition.video.condition.object="包含对象" AdvSceneSwitcher.condition.video.condition.object="包含对象"
AdvSceneSwitcher.condition.video.condition.brightness="亮度" AdvSceneSwitcher.condition.video.condition.brightness="亮度"
AdvSceneSwitcher.condition.video.condition.ocr="包含文本"
AdvSceneSwitcher.condition.video.askFileAction="是否要使用现有文件或创建当前选定源的屏幕截图?" AdvSceneSwitcher.condition.video.askFileAction="是否要使用现有文件或创建当前选定源的屏幕截图?"
AdvSceneSwitcher.condition.video.askFileAction.file="使用现有文件" AdvSceneSwitcher.condition.video.askFileAction.file="使用现有文件"
AdvSceneSwitcher.condition.video.askFileAction.screenshot="创建屏幕截图" AdvSceneSwitcher.condition.video.askFileAction.screenshot="创建屏幕截图"
@@ -204,49 +164,28 @@ AdvSceneSwitcher.condition.video.usePatternForChangedCheck="使用模式匹配"
AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip="这将允许您控制图像必须更改多少才能使条件为真." AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip="这将允许您控制图像必须更改多少才能使条件为真."
AdvSceneSwitcher.condition.video.patternThreshold="阈值: " AdvSceneSwitcher.condition.video.patternThreshold="阈值: "
AdvSceneSwitcher.condition.video.patternThresholdDescription="较高的阈值意味着模式需要更紧密地匹配视频源." AdvSceneSwitcher.condition.video.patternThresholdDescription="较高的阈值意味着模式需要更紧密地匹配视频源."
AdvSceneSwitcher.condition.video.patternThresholdUseAlphaAsMask="使用alpha通道作为模式的遮罩." AdvSceneSwitcher.condition.video.patternThresholdUseAlphaAsMask="使用alpha通道作为图案的遮罩."
AdvSceneSwitcher.condition.video.patternMatchMode="使用模式匹配方式 {{patternMatchingModes}}"
AdvSceneSwitcher.condition.video.patternMatchMode.crossCorrelation="交叉相关"
AdvSceneSwitcher.condition.video.patternMatchMode.correlationCoefficient="相关系数"
AdvSceneSwitcher.condition.video.patternMatchMode.squaredDifference="平方差"
AdvSceneSwitcher.condition.video.patternMatchMode.tip="使用的最佳方法取决于具体问题和所涉及图像的特性。\n在实践中通常需要使用不同的方法和参数进行实验以找到对特定用例的最佳匹配。"
AdvSceneSwitcher.condition.video.brightnessThreshold="平均亮度:" AdvSceneSwitcher.condition.video.brightnessThreshold="平均亮度:"
AdvSceneSwitcher.condition.video.brightnessThresholdDescription="高的值表示明亮的图像,低的值表示较暗的图像。" AdvSceneSwitcher.condition.video.brightnessThresholdDescription="高的值表示图像较亮,较低的值表示图像较暗。"
AdvSceneSwitcher.condition.video.currentBrightness="当前平均亮度: %1" AdvSceneSwitcher.condition.video.currentBrightness="当前平均亮度: %1"
AdvSceneSwitcher.condition.video.objectScaleThreshold="模型比例: " AdvSceneSwitcher.condition.video.objectScaleThreshold="模型比例: "
AdvSceneSwitcher.condition.video.objectScaleThresholdDescription="较低的模比例会产生更多的匹配,但导致CPU负载更高." AdvSceneSwitcher.condition.video.objectScaleThresholdDescription="较低的模比例将导致更多的匹配,但导致更高的CPU负载."
AdvSceneSwitcher.condition.video.minNeighborDescription="较高的“最小区域”值将导致较少但质量较高的匹配." AdvSceneSwitcher.condition.video.minNeighborDescription="较高的“最小区域”值将导致较少但质量较高的匹配."
AdvSceneSwitcher.condition.video.showMatch="显示模式" AdvSceneSwitcher.condition.video.showMatch="显示模式"
AdvSceneSwitcher.condition.video.showMatch.loading="检查是否匹配" AdvSceneSwitcher.condition.video.showMatch.loading="Checking for match"
AdvSceneSwitcher.condition.video.screenshotFail="无法获取源的屏幕截图!" AdvSceneSwitcher.condition.video.screenshotFail="无法获取源的屏幕截图!"
AdvSceneSwitcher.condition.video.screenshotEmpty="屏幕截图为空 - 源是否可见?" AdvSceneSwitcher.condition.video.screenshotEmpty="Screenshot is empty - Is the source visible?"
AdvSceneSwitcher.condition.video.patternMatchFail="没有找到模式!" AdvSceneSwitcher.condition.video.patternMatchFail="没有找到模式!"
AdvSceneSwitcher.condition.video.patternMatchSuccess="模式以红色突出显示" AdvSceneSwitcher.condition.video.patternMatchSuccess="Pattern is highlighted in red"
AdvSceneSwitcher.condition.video.objectMatchFail="找不到对象!" AdvSceneSwitcher.condition.video.objectMatchFail="找不到对象!"
AdvSceneSwitcher.condition.video.objectMatchSuccess="对象以红色突出显示" AdvSceneSwitcher.condition.video.objectMatchSuccess="Object is highlighted in red"
AdvSceneSwitcher.condition.video.ocrMatchSuccess="检测到的文本:\n\n%1"
AdvSceneSwitcher.condition.video.modelLoadFail="无法加载模型数据!" AdvSceneSwitcher.condition.video.modelLoadFail="无法加载模型数据!"
AdvSceneSwitcher.condition.video.selectColor="选择颜色"
AdvSceneSwitcher.condition.video.ocrMode.singleColumn="单列可变大小的文本"
AdvSceneSwitcher.condition.video.ocrMode.singleBlockVertText="垂直对齐的单个统一文本块"
AdvSceneSwitcher.condition.video.ocrMode.singleBlock="单个统一的文本块"
AdvSceneSwitcher.condition.video.ocrMode.singleLine="单个文本行"
AdvSceneSwitcher.condition.video.ocrMode.singleWord="单词"
AdvSceneSwitcher.condition.video.ocrMode.circleWord="圆圈中的单个单词"
AdvSceneSwitcher.condition.video.ocrMode.singleChar="单个字符"
AdvSceneSwitcher.condition.video.ocrMode.sparseText="不按特定顺序查找文本"
AdvSceneSwitcher.condition.video.ocrMode.sparseTextOSD="不按特定顺序查找文本OSD"
AdvSceneSwitcher.condition.video.type.main="OBS的主输出"
AdvSceneSwitcher.condition.video.type.source="源"
AdvSceneSwitcher.condition.video.type.scene="场景"
AdvSceneSwitcher.condition.video.entry="{{videoInputTypes}}{{sources}}{{scenes}}{{condition}}{{imagePath}}" AdvSceneSwitcher.condition.video.entry="{{videoInputTypes}}{{sources}}{{scenes}}{{condition}}{{imagePath}}"
AdvSceneSwitcher.condition.video.entry.modelPath="模型数据 (haar级联分类器): {{modelDataPath}}" AdvSceneSwitcher.condition.video.entry.modelPath="模型数据 (haar级联分类器): {{modelDataPath}}"
AdvSceneSwitcher.condition.video.entry.minNeighbor="最小区域: {{minNeighbors}}" AdvSceneSwitcher.condition.video.entry.minNeighbor="最小区域: {{minNeighbors}}"
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}每隔一段时间检查一次,来减少CPU负载 {{throttleCount}} 毫秒" AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}通过只执行每一次检查来减少CPU负载 {{throttleCount}} 毫秒"
AdvSceneSwitcher.condition.video.entry.checkAreaEnable="仅在区域内执行检查" AdvSceneSwitcher.condition.video.entry.checkAreaEnable="仅在区域内执行检查"
AdvSceneSwitcher.condition.video.entry.checkArea="{{checkAreaEnable}}{{checkArea}}{{selectArea}}" AdvSceneSwitcher.condition.video.entry.checkArea="{{checkAreaEnable}}{{checkArea}}{{selectArea}}"
AdvSceneSwitcher.condition.video.entry.orcColorPick="检查文本颜色:{{textColor}}{{selectColor}}"
AdvSceneSwitcher.condition.video.entry.orcTextType="检查文本类型:{{textType}}"
AdvSceneSwitcher.condition.video.minSize="最小尺寸:" AdvSceneSwitcher.condition.video.minSize="最小尺寸:"
AdvSceneSwitcher.condition.video.maxSize="最大尺寸:" AdvSceneSwitcher.condition.video.maxSize="最大尺寸:"
AdvSceneSwitcher.condition.video.selectArea="选择区域" AdvSceneSwitcher.condition.video.selectArea="选择区域"
@@ -258,24 +197,21 @@ AdvSceneSwitcher.condition.stream.state.start="推流启动"
AdvSceneSwitcher.condition.stream.state.stop="推流停止" AdvSceneSwitcher.condition.stream.state.stop="推流停止"
AdvSceneSwitcher.condition.stream.state.starting="推流启动中" AdvSceneSwitcher.condition.stream.state.starting="推流启动中"
AdvSceneSwitcher.condition.stream.state.stopping="推流停止中" AdvSceneSwitcher.condition.stream.state.stopping="推流停止中"
AdvSceneSwitcher.condition.stream.state.keyFrameInterval="关键帧间隔等于" AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
AdvSceneSwitcher.condition.record="录制" AdvSceneSwitcher.condition.record="录制"
AdvSceneSwitcher.condition.record.state.start="录制运行中" AdvSceneSwitcher.condition.record.state.start="录制运行中"
AdvSceneSwitcher.condition.record.state.pause="录制暂停" AdvSceneSwitcher.condition.record.state.pause="录制暂停"
AdvSceneSwitcher.condition.record.state.stop="录制停止" AdvSceneSwitcher.condition.record.state.stop="录制停止"
AdvSceneSwitcher.condition.record.entry="{{recordState}}"
AdvSceneSwitcher.condition.process="进程" AdvSceneSwitcher.condition.process="进程"
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}是正在运行{{focused}}且是获得焦点" AdvSceneSwitcher.condition.process.entry="{{processes}} 是正在运行 {{focused}}且是获得焦点"
AdvSceneSwitcher.condition.process.entry.focus="当前焦点进程: {{focusProcess}}" AdvSceneSwitcher.condition.process.entry.focus="当前焦点进程: {{focusProcess}}"
AdvSceneSwitcher.condition.idle="闲置检测" AdvSceneSwitcher.condition.idle="闲置检测"
AdvSceneSwitcher.condition.idle.entry="没有键盘或鼠标输入{{duration}}" AdvSceneSwitcher.condition.idle.entry="没有键盘或鼠标输入{{duration}}"
AdvSceneSwitcher.condition.pluginState="插件状态" AdvSceneSwitcher.condition.pluginState="插件状态"
AdvSceneSwitcher.condition.pluginState.state.start="插件已启动" AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="在此时间间隔内触发了自动场景更改"
AdvSceneSwitcher.condition.pluginState.state.restart="插件已重新启动" AdvSceneSwitcher.condition.pluginState.state.running="高级场景切换程序正在运行"
AdvSceneSwitcher.condition.pluginState.state.running="插件正在运行"
AdvSceneSwitcher.condition.pluginState.state.shutdown="OBS正在关闭" AdvSceneSwitcher.condition.pluginState.state.shutdown="OBS正在关闭"
AdvSceneSwitcher.condition.pluginState.state.sceneCollection="场景集合已加载"
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="场景被上一个宏改变"
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}" AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
AdvSceneSwitcher.condition.timer="计时器" AdvSceneSwitcher.condition.timer="计时器"
AdvSceneSwitcher.condition.timer.type.fixed="固定" AdvSceneSwitcher.condition.timer.type.fixed="固定"
@@ -300,11 +236,11 @@ AdvSceneSwitcher.condition.macro.state.type.above="大于"
AdvSceneSwitcher.condition.macro.state.type.equal="等于" AdvSceneSwitcher.condition.macro.state.type.equal="等于"
AdvSceneSwitcher.condition.macro.count.reset="重置" AdvSceneSwitcher.condition.macro.count.reset="重置"
AdvSceneSwitcher.condition.macro.pausedWarning="所选宏当前已暂停!" AdvSceneSwitcher.condition.macro.pausedWarning="所选宏当前已暂停!"
AdvSceneSwitcher.condition.macro.state.entry="{{macros}} 的条件为真" AdvSceneSwitcher.condition.macro.state.entry="条件 {{macros}} 运行结果为真"
AdvSceneSwitcher.condition.macro.multistate.entry=" 以下宏的 {{multiStateConditions}}{{multiStateCount}} 的条件为真:" AdvSceneSwitcher.condition.macro.multistate.entry="条件 {{multiStateConditions}}{{multiStateCount}} 以下宏运行结果为真:"
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} 行 {{conditions}} {{count}} 次(相对于下面计数匹配)" AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} 行 {{conditions}} {{count}} 次(相对于下面计数匹配)"
AdvSceneSwitcher.condition.macro.count.entry.line2="当前计数: {{currentCount}} {{resetCount}}" AdvSceneSwitcher.condition.macro.count.entry.line2="当前计数: {{currentCount}} {{resetCount}}"
AdvSceneSwitcher.condition.source="源" AdvSceneSwitcher.condition.source="源"
AdvSceneSwitcher.condition.source.type.active="是激活状态" AdvSceneSwitcher.condition.source.type.active="是激活状态"
AdvSceneSwitcher.condition.source.type.showing="是显示状态" AdvSceneSwitcher.condition.source.type.showing="是显示状态"
AdvSceneSwitcher.condition.source.type.settings="设置完全匹配" AdvSceneSwitcher.condition.source.type.settings="设置完全匹配"
@@ -321,7 +257,7 @@ AdvSceneSwitcher.condition.filter.type.active="已启用"
AdvSceneSwitcher.condition.filter.type.showing="已关闭" AdvSceneSwitcher.condition.filter.type.showing="已关闭"
AdvSceneSwitcher.condition.filter.type.settings="设置完全匹配" AdvSceneSwitcher.condition.filter.type.settings="设置完全匹配"
AdvSceneSwitcher.condition.filter.getSettings="获取当前设置" AdvSceneSwitcher.condition.filter.getSettings="获取当前设置"
AdvSceneSwitcher.condition.filter.entry.line1="在 {{sources}} {{filters}} {{conditions}}" AdvSceneSwitcher.condition.filter.entry.line1="在 {{sources}} {{filters}} {{conditions}}"
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}" AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}" AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.sceneOrder="场景项目顺序" AdvSceneSwitcher.condition.sceneOrder="场景项目顺序"
@@ -353,8 +289,7 @@ AdvSceneSwitcher.condition.date.state.at="现在"
AdvSceneSwitcher.condition.date.state.after="之后" AdvSceneSwitcher.condition.date.state.after="之后"
AdvSceneSwitcher.condition.date.state.before="之前" AdvSceneSwitcher.condition.date.state.before="之前"
AdvSceneSwitcher.condition.date.state.between="之间" AdvSceneSwitcher.condition.date.state.between="之间"
AdvSceneSwitcher.condition.date.state.pattern="模式" AdvSceneSwitcher.condition.date.separator=""
AdvSceneSwitcher.condition.date.separator="到"
AdvSceneSwitcher.condition.date.ignoreDate="如果未选中,日期组件将被忽略" AdvSceneSwitcher.condition.date.ignoreDate="如果未选中,日期组件将被忽略"
AdvSceneSwitcher.condition.date.ignoreTime="如果未选中,时间组件将被忽略" AdvSceneSwitcher.condition.date.ignoreTime="如果未选中,时间组件将被忽略"
AdvSceneSwitcher.condition.date.showAdvancedSettings="显示高级设置" AdvSceneSwitcher.condition.date.showAdvancedSettings="显示高级设置"
@@ -362,13 +297,11 @@ AdvSceneSwitcher.condition.date.showSimpleSettings="显示简单设置"
AdvSceneSwitcher.condition.date.entry.simple="在 {{dayOfWeek}} {{weekCondition}} {{ignoreWeekTime}}{{weekTime}}" AdvSceneSwitcher.condition.date.entry.simple="在 {{dayOfWeek}} {{weekCondition}} {{ignoreWeekTime}}{{weekTime}}"
AdvSceneSwitcher.condition.date.entry.advanced="{{condition}} {{ignoreDate}}{{date}} {{ignoreTime}}{{time}} {{separator}} {{date2}} {{time2}}" AdvSceneSwitcher.condition.date.entry.advanced="{{condition}} {{ignoreDate}}{{date}} {{ignoreTime}}{{time}} {{separator}} {{date2}} {{time2}}"
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}} 在匹配到日期时间后,每隔 {{duration}} 重复一次" AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}} 在匹配到日期时间后,每隔 {{duration}} 重复一次"
AdvSceneSwitcher.condition.date.entry.pattern="当前日期 \"{{currentDate}}\" 匹配模式 {{pattern}}" AdvSceneSwitcher.condition.date.entry.nextMatchDate="Next match at: %1"
AdvSceneSwitcher.condition.date.entry.nextMatchDate="下一次匹配 在: %1" AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} On repeat update selected date to repeat date"
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} 重复时,将选定的日期更新为重复日期"
AdvSceneSwitcher.condition.sceneTransform="场景项目被改变" AdvSceneSwitcher.condition.sceneTransform="场景项目被改变"
AdvSceneSwitcher.condition.sceneTransform.getTransform="内容或者设置被改变了" AdvSceneSwitcher.condition.sceneTransform.getTransform="内容或者设置被改变了"
AdvSceneSwitcher.condition.sceneTransform.entry.line1="在 {{scenes}} {{sources}} {{types}}" AdvSceneSwitcher.condition.sceneTransform.entry.line1="在 {{scenes}} {{sources}} 匹配变换"
AdvSceneSwitcher.condition.sceneTransform.entry.type.matches="匹配变换"
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}" AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}" AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.transition="转场" AdvSceneSwitcher.condition.transition="转场"
@@ -383,7 +316,6 @@ AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{scen
AdvSceneSwitcher.condition.sceneVisibility="场景项目可见" AdvSceneSwitcher.condition.sceneVisibility="场景项目可见"
AdvSceneSwitcher.condition.sceneVisibility.type.shown="显示的" AdvSceneSwitcher.condition.sceneVisibility.type.shown="显示的"
AdvSceneSwitcher.condition.sceneVisibility.type.hidden="隐藏的" AdvSceneSwitcher.condition.sceneVisibility.type.hidden="隐藏的"
AdvSceneSwitcher.condition.sceneVisibility.type.changed="可见性已更改"
AdvSceneSwitcher.condition.sceneVisibility.entry="在 {{scenes}} {{sources}} 是 {{conditions}} " AdvSceneSwitcher.condition.sceneVisibility.entry="在 {{scenes}} {{sources}} 是 {{conditions}} "
AdvSceneSwitcher.condition.studioMode="工作室模式" AdvSceneSwitcher.condition.studioMode="工作室模式"
AdvSceneSwitcher.condition.studioMode.state.active="工作室模式处于活动状态" AdvSceneSwitcher.condition.studioMode.state.active="工作室模式处于活动状态"
@@ -413,7 +345,7 @@ AdvSceneSwitcher.condition.stats.condition.above="大于"
AdvSceneSwitcher.condition.stats.condition.equals="等于" AdvSceneSwitcher.condition.stats.condition.equals="等于"
AdvSceneSwitcher.condition.stats.condition.below="少于" AdvSceneSwitcher.condition.stats.condition.below="少于"
AdvSceneSwitcher.condition.stats.dockHint="你可以打开“统计”窗口查看当前状态" AdvSceneSwitcher.condition.stats.dockHint="你可以打开“统计”窗口查看当前状态"
AdvSceneSwitcher.condition.stats.entry="{{stats}} {{condition}} {{value}}" AdvSceneSwitcher.condition.stats.entry="{{stats}} is {{condition}} {{value}}"
AdvSceneSwitcher.condition.profile="配置文件" AdvSceneSwitcher.condition.profile="配置文件"
AdvSceneSwitcher.condition.profile.entry="当前活动的配置文件为 {{profiles}}" AdvSceneSwitcher.condition.profile.entry="当前活动的配置文件为 {{profiles}}"
AdvSceneSwitcher.condition.websocket="websocket" AdvSceneSwitcher.condition.websocket="websocket"
@@ -429,24 +361,12 @@ AdvSceneSwitcher.condition.variable.type.number="是一个数字"
AdvSceneSwitcher.condition.variable.type.lessThan="小于" AdvSceneSwitcher.condition.variable.type.lessThan="小于"
AdvSceneSwitcher.condition.variable.type.greaterThan="大于" AdvSceneSwitcher.condition.variable.type.greaterThan="大于"
AdvSceneSwitcher.condition.variable.type.valueChanged="值已更改" AdvSceneSwitcher.condition.variable.type.valueChanged="值已更改"
AdvSceneSwitcher.condition.variable.type.equalsVariable="等于变量" AdvSceneSwitcher.condition.variable.entry="{{variables}}{{conditions}}{{strValue}}{{numValue}}{{variables2}}"
AdvSceneSwitcher.condition.variable.type.lessThanVariable="小于变量"
AdvSceneSwitcher.condition.variable.type.greaterThanVariable="大于变量"
AdvSceneSwitcher.condition.run="运行"
AdvSceneSwitcher.condition.run.entry="进程在超时 {{timeout}} 秒之前退出"
AdvSceneSwitcher.condition.run.entry.exit="{{checkExitCode}}检查退出代码{{exitCode}}"
AdvSceneSwitcher.condition.midi="MIDI"
AdvSceneSwitcher.condition.midi.entry="从{{device}} 收到的信息,符合:(从不咕咕的阿坤:这个好像是声卡工作是录音相关的功能,英文太抽象了,我就硬译过来了,如有相关设备,音乐好的,可以根据英文翻译好发给我!)"
AdvSceneSwitcher.condition.midi.entry.listen="将MIDI信息选择设置为从选定设备上接收的信息: {{listenButton}}"
AdvSceneSwitcher.condition.display="显示器"
AdvSceneSwitcher.condition.display.type.displayName="连接的显示器的名称匹配"
AdvSceneSwitcher.condition.display.type.displayCount="连接的显示器的数量为"
AdvSceneSwitcher.condition.display.entry="{{conditions}}{{displays}}{{regex}}{{displayCount}}"
; Macro Actions ; Macro Actions
AdvSceneSwitcher.action.scene="切换场景" AdvSceneSwitcher.action.switchScene="切换场景"
AdvSceneSwitcher.action.scene.entry="切换场景{{sceneTypes}}{{scenes}}使用{{transitions}}时长{{duration}}秒" AdvSceneSwitcher.action.scene.entry="切换场景 {{scenes}} 使用 {{transitions}} 时长 {{duration}} 秒"
AdvSceneSwitcher.action.scene.entry.noDuration="切换到场景{{sceneTypes}}{{scenes}}使用{{transitions}}" AdvSceneSwitcher.action.scene.entry.noDuration="切换到场景{{scenes}}使用{{transitions}}"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="等待目标场景的过渡完成" AdvSceneSwitcher.action.scene.blockUntilTransitionDone="等待目标场景的过渡完成"
AdvSceneSwitcher.action.wait="等待" AdvSceneSwitcher.action.wait="等待"
AdvSceneSwitcher.action.wait.type.fixed="固定数值" AdvSceneSwitcher.action.wait.type.fixed="固定数值"
@@ -458,10 +378,6 @@ AdvSceneSwitcher.action.audio.type.mute="静音"
AdvSceneSwitcher.action.audio.type.unmute="取消静音" AdvSceneSwitcher.action.audio.type.unmute="取消静音"
AdvSceneSwitcher.action.audio.type.sourceVolume="来源音量" AdvSceneSwitcher.action.audio.type.sourceVolume="来源音量"
AdvSceneSwitcher.action.audio.type.masterVolume="主音量" AdvSceneSwitcher.action.audio.type.masterVolume="主音量"
AdvSceneSwitcher.action.audio.type.syncOffset="设置同步偏移"
AdvSceneSwitcher.action.audio.type.monitor="设置音频监听"
AdvSceneSwitcher.action.audio.type.balance="设置平衡"
AdvSceneSwitcher.action.audio.balance.description="选择的音频源将滑块方向移动(从不咕咕的阿坤的理解:左/右声道偏侧向)"
AdvSceneSwitcher.action.audio.fade.type.duration="持续时间" AdvSceneSwitcher.action.audio.fade.type.duration="持续时间"
AdvSceneSwitcher.action.audio.fade.type.rate="百分比" AdvSceneSwitcher.action.audio.fade.type.rate="百分比"
AdvSceneSwitcher.action.audio.fade.duration="{{fade}}淡出 {{fadeTypes}} {{duration}} 秒." AdvSceneSwitcher.action.audio.fade.duration="{{fade}}淡出 {{fadeTypes}} {{duration}} 秒."
@@ -475,45 +391,43 @@ AdvSceneSwitcher.action.recording.type.start="开始录制"
AdvSceneSwitcher.action.recording.type.pause="暂停录制" AdvSceneSwitcher.action.recording.type.pause="暂停录制"
AdvSceneSwitcher.action.recording.type.unpause="取消录制暂停" AdvSceneSwitcher.action.recording.type.unpause="取消录制暂停"
AdvSceneSwitcher.action.recording.type.split="分割录制文件" AdvSceneSwitcher.action.recording.type.split="分割录制文件"
AdvSceneSwitcher.action.recording.type.changeOutputFolder="更改输出文件夹"
AdvSceneSwitcher.action.recording.type.changeOutputFileFormat="改变文件名的格式"
AdvSceneSwitcher.action.recording.pause.hint="请注意,根据您的录制设置,您可能无法暂停录制" AdvSceneSwitcher.action.recording.pause.hint="请注意,根据您的录制设置,您可能无法暂停录制"
AdvSceneSwitcher.action.recording.split.hint="确保先在OBS设置中启用自动分割文件!" AdvSceneSwitcher.action.recording.split.hint="确保先在OBS设置中启用自动分割文件!"
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}" AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
AdvSceneSwitcher.action.replay="回放缓" AdvSceneSwitcher.action.replay="回放缓冲区"
AdvSceneSwitcher.action.replay.saveWarn="警告:保存过于频繁可能会导致回放缓存实际上未保存!" AdvSceneSwitcher.action.replay.saveWarn="警告:保存过于频繁可能会导致重播缓冲区实际上未保存!"
AdvSceneSwitcher.action.replay.type.stop="停止回放缓" AdvSceneSwitcher.action.replay.type.stop="停止回放缓冲区"
AdvSceneSwitcher.action.replay.type.start="启动回放缓" AdvSceneSwitcher.action.replay.type.start="启动回放缓冲区"
AdvSceneSwitcher.action.replay.type.save="保存回放缓" AdvSceneSwitcher.action.replay.type.save="保存回放缓冲区"
AdvSceneSwitcher.action.replay.entry="{{actions}}" AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="推流" AdvSceneSwitcher.action.streaming="推流"
AdvSceneSwitcher.action.streaming.type.stop="停止推流" AdvSceneSwitcher.action.streaming.type.stop="停止推流"
AdvSceneSwitcher.action.streaming.type.start="开始推流" AdvSceneSwitcher.action.streaming.type.start="开始推流"
AdvSceneSwitcher.action.streaming.type.keyFrameInterval="设置关键帧间隔" AdvSceneSwitcher.action.streaming.entry="{{actions}}"
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
AdvSceneSwitcher.action.run="运行" AdvSceneSwitcher.action.run="运行"
AdvSceneSwitcher.action.run.arguments="参数:"
AdvSceneSwitcher.action.run.addArgument="添加参数"
AdvSceneSwitcher.action.run.addArgumentDescription="添加新参数:"
AdvSceneSwitcher.action.run.entry="运行 {{filePath}}"
AdvSceneSwitcher.action.sceneVisibility="场景项目可见性" AdvSceneSwitcher.action.sceneVisibility="场景项目可见性"
AdvSceneSwitcher.action.sceneVisibility.type.show="显示" AdvSceneSwitcher.action.sceneVisibility.type.show="显示"
AdvSceneSwitcher.action.sceneVisibility.type.hide="隐藏" AdvSceneSwitcher.action.sceneVisibility.type.hide="隐藏"
AdvSceneSwitcher.action.sceneVisibility.type.toggle="切换"
AdvSceneSwitcher.action.sceneVisibility.type.source="来源" AdvSceneSwitcher.action.sceneVisibility.type.source="来源"
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="全部" AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="全部"
AdvSceneSwitcher.action.sceneVisibility.entry="置{{scenes}}{{actions}}{{sources}}" AdvSceneSwitcher.action.sceneVisibility.entry="置{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
AdvSceneSwitcher.action.filter="滤镜" AdvSceneSwitcher.action.filter="滤镜"
AdvSceneSwitcher.action.filter.type.enable="开启" AdvSceneSwitcher.action.filter.type.enable="开启"
AdvSceneSwitcher.action.filter.type.disable="关闭" AdvSceneSwitcher.action.filter.type.disable="关闭"
AdvSceneSwitcher.action.filter.type.settings="参数设置" AdvSceneSwitcher.action.filter.type.settings="参数设置"
AdvSceneSwitcher.action.filter.entry=" {{sources}} {{actions}} {{filters}}" AdvSceneSwitcher.action.filter.entry=" {{sources}} {{actions}} {{filters}}"
AdvSceneSwitcher.action.filter.getSettings="获取当前设置" AdvSceneSwitcher.action.filter.getSettings="获取当前设置"
AdvSceneSwitcher.action.source="源" AdvSceneSwitcher.action.source="源"
AdvSceneSwitcher.action.source.type.enable="启用" AdvSceneSwitcher.action.source.type.enable="启用"
AdvSceneSwitcher.action.source.type.disable="停用" AdvSceneSwitcher.action.source.type.disable="停用"
AdvSceneSwitcher.action.source.type.settings="配置设置" AdvSceneSwitcher.action.source.type.settings="配置设置"
AdvSceneSwitcher.action.source.type.refreshSettings="刷新源设置" AdvSceneSwitcher.action.source.type.refreshSettings="刷新源设置"
AdvSceneSwitcher.action.source.type.pressSettingsButton="按下设置按钮" AdvSceneSwitcher.action.source.type.refreshSettings.tooltip="可用于刷新浏览器、媒体等源"
AdvSceneSwitcher.action.source.type.refreshSettings.tooltip="可用于刷新浏览器、媒体、源、etc" AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
AdvSceneSwitcher.action.source.noSettingsButtons="未找到按钮!"
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}"
AdvSceneSwitcher.action.source.warning="警告OBS UI无法控制全局启用和禁用源注意通过这个设置禁用我测试你必须通过这个在启用才行不然点击小眼睛你无法显示" AdvSceneSwitcher.action.source.warning="警告OBS UI无法控制全局启用和禁用源注意通过这个设置禁用我测试你必须通过这个在启用才行不然点击小眼睛你无法显示"
AdvSceneSwitcher.action.source.getSettings="获取当前设置" AdvSceneSwitcher.action.source.getSettings="获取当前设置"
AdvSceneSwitcher.action.media="媒体" AdvSceneSwitcher.action.media="媒体"
@@ -523,21 +437,20 @@ AdvSceneSwitcher.action.media.type.stop="停止"
AdvSceneSwitcher.action.media.type.restart="重新启动" AdvSceneSwitcher.action.media.type.restart="重新启动"
AdvSceneSwitcher.action.media.type.next="下一个" AdvSceneSwitcher.action.media.type.next="下一个"
AdvSceneSwitcher.action.media.type.previous="上一个" AdvSceneSwitcher.action.media.type.previous="上一个"
AdvSceneSwitcher.action.media.type.seek.duration="时间轴定位" AdvSceneSwitcher.action.media.type.seek="时间轴定位"
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
AdvSceneSwitcher.action.macro="宏" AdvSceneSwitcher.action.macro="宏"
AdvSceneSwitcher.action.macro.type.pause="暂停" AdvSceneSwitcher.action.macro.type.pause="暂停"
AdvSceneSwitcher.action.macro.type.unpause="取消暂停" AdvSceneSwitcher.action.macro.type.unpause="取消暂停"
AdvSceneSwitcher.action.macro.type.resetCounter="复位计数器" AdvSceneSwitcher.action.macro.type.resetCounter="复位计数器"
AdvSceneSwitcher.action.macro.type.run="运行操作" AdvSceneSwitcher.action.macro.type.run="运行"
AdvSceneSwitcher.action.macro.type.stop="停止操作" AdvSceneSwitcher.action.macro.type.stop="停止"
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}" AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
AdvSceneSwitcher.action.pluginState="插件状态" AdvSceneSwitcher.action.pluginState="插件状态"
AdvSceneSwitcher.action.pluginState.type.stop="停止高级场景切换插件" AdvSceneSwitcher.action.pluginState.type.stop="停止高级场景切换插件"
AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项:" AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项:"
AdvSceneSwitcher.action.pluginState.type.import="从设置导入" AdvSceneSwitcher.action.pluginState.type.import="从设置导入"
AdvSceneSwitcher.action.pluginState.importWarning="注意:当“设置”窗口打开时,操作将被忽略。" AdvSceneSwitcher.action.pluginState.importWarning="注意:当“设置”窗口打开时,操作将被忽略。"
AdvSceneSwitcher.action.pluginState.type.terminate="关闭 OBS"
AdvSceneSwitcher.action.pluginState.terminateConfirm="OBS将在10秒后自动关闭/n你想继续关闭OBS吗"
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}" AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
AdvSceneSwitcher.action.virtualCamera="虚拟摄像机" AdvSceneSwitcher.action.virtualCamera="虚拟摄像机"
AdvSceneSwitcher.action.virtualCamera.type.stop="停止虚拟摄像机" AdvSceneSwitcher.action.virtualCamera.type.stop="停止虚拟摄像机"
@@ -554,6 +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.sceneOrder="场景项目顺序" AdvSceneSwitcher.action.sceneOrder="场景项目顺序"
AdvSceneSwitcher.action.sceneOrder.type.moveUp="上移" AdvSceneSwitcher.action.sceneOrder.type.moveUp="上移"
AdvSceneSwitcher.action.sceneOrder.type.moveDown="下移" AdvSceneSwitcher.action.sceneOrder.type.moveDown="下移"
@@ -561,9 +475,9 @@ AdvSceneSwitcher.action.sceneOrder.type.moveTop="顶部"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="底部" AdvSceneSwitcher.action.sceneOrder.type.moveBottom="底部"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="移动到数值位置" AdvSceneSwitcher.action.sceneOrder.type.movePosition="移动到数值位置"
AdvSceneSwitcher.action.sceneOrder.entry="在 {{scenes}} {{actions}} {{sources}} {{position}}" AdvSceneSwitcher.action.sceneOrder.entry="在 {{scenes}} {{actions}} {{sources}} {{position}}"
AdvSceneSwitcher.action.sceneTransform="场景项目换" AdvSceneSwitcher.action.sceneTransform="场景项目换"
AdvSceneSwitcher.action.sceneTransform.getTransform="获得转换" AdvSceneSwitcher.action.sceneTransform.getTransform="得到变换"
AdvSceneSwitcher.action.sceneTransform.entry="在 {{scenes}}{{action}}{{rotation}}{{sources}}" AdvSceneSwitcher.action.sceneTransform.entry="在 {{scenes}} 变换 {{sources}}"
AdvSceneSwitcher.action.file="文件" AdvSceneSwitcher.action.file="文件"
AdvSceneSwitcher.action.file.type.write="写入" AdvSceneSwitcher.action.file.type.write="写入"
AdvSceneSwitcher.action.file.type.append="追加写入" AdvSceneSwitcher.action.file.type.append="追加写入"
@@ -589,13 +503,9 @@ AdvSceneSwitcher.action.timer.type.reset="重置"
AdvSceneSwitcher.action.timer.type.setTimeRemaining="设置剩余时间" AdvSceneSwitcher.action.timer.type.setTimeRemaining="设置剩余时间"
AdvSceneSwitcher.action.timer.entry="{{timerAction}} 定时在 {{macros}} {{duration}}" AdvSceneSwitcher.action.timer.entry="{{timerAction}} 定时在 {{macros}} {{duration}}"
AdvSceneSwitcher.action.random="随机" AdvSceneSwitcher.action.random="随机"
AdvSceneSwitcher.action.random.allowRepeat="允许连续执行同一宏"
AdvSceneSwitcher.action.random.entry="随机运行以下任何宏(忽略暂停的宏)" AdvSceneSwitcher.action.random.entry="随机运行以下任何宏(忽略暂停的宏)"
AdvSceneSwitcher.action.systray="系统托盘通知" AdvSceneSwitcher.action.systray="系统托盘通知"
AdvSceneSwitcher.action.systray.title="标题:" AdvSceneSwitcher.action.systray.entry="显示通知: {{message}}"
AdvSceneSwitcher.action.systray.message="信息:"
AdvSceneSwitcher.action.systray.icon="图标:"
AdvSceneSwitcher.action.systray.iconHint="留空以使用默认图标"
AdvSceneSwitcher.action.screenshot="截图" AdvSceneSwitcher.action.screenshot="截图"
AdvSceneSwitcher.action.screenshot.save.default="默认" AdvSceneSwitcher.action.screenshot.save.default="默认"
AdvSceneSwitcher.action.screenshot.save.custom="其他" AdvSceneSwitcher.action.screenshot.save.custom="其他"
@@ -618,54 +528,21 @@ AdvSceneSwitcher.action.sequence.continueFrom="继续所选项目"
AdvSceneSwitcher.action.websocket="websocket" AdvSceneSwitcher.action.websocket="websocket"
AdvSceneSwitcher.action.websocket.type.request="request" AdvSceneSwitcher.action.websocket.type.request="request"
AdvSceneSwitcher.action.websocket.type.event="event" AdvSceneSwitcher.action.websocket.type.event="event"
AdvSceneSwitcher.action.websocket.entry.request="发送场景切换器 {{type}}{{connection}}"
AdvSceneSwitcher.action.websocket.entry.event="发送场景切换器 {{type}} 到连接的客户端"
AdvSceneSwitcher.action.http="Http" AdvSceneSwitcher.action.http="Http"
AdvSceneSwitcher.action.http.setHeaders="设置头信息(SET headers)" AdvSceneSwitcher.action.http.type.get="GET"
AdvSceneSwitcher.action.http.headers="头信息(headers):" AdvSceneSwitcher.action.http.type.post="POST"
AdvSceneSwitcher.action.http.addHeader="增加头信息(ADD headers)"
AdvSceneSwitcher.action.http.type.get="获取(GET)"
AdvSceneSwitcher.action.http.type.post="发送(POST)"
AdvSceneSwitcher.action.http.entry.line1="发送 {{method}} 到 {{url}}" AdvSceneSwitcher.action.http.entry.line1="发送 {{method}} 到 {{url}}"
AdvSceneSwitcher.action.http.entry.line2="超时: {{timeout}} 秒" AdvSceneSwitcher.action.http.entry.line2="超时: {{timeout}} 秒"
AdvSceneSwitcher.action.variable="变量" AdvSceneSwitcher.action.variable="变量"
AdvSceneSwitcher.action.variable.type.set="设置为固定值" AdvSceneSwitcher.action.variable.type.set="设置"
AdvSceneSwitcher.action.variable.type.append="追加" 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.type.setActionValue="设置为操作值" AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}"
AdvSceneSwitcher.action.variable.type.setConditionValue="设置为条件值"
AdvSceneSwitcher.action.variable.type.roundToInt="取整到最近的整数"
AdvSceneSwitcher.action.variable.type.subString="设置为当前值的子字符串"
AdvSceneSwitcher.action.variable.type.findAndReplace="在当前值中查找并替换"
AdvSceneSwitcher.action.variable.type.mathExpression="数学表达式"
AdvSceneSwitcher.action.variable.mathExpression.example="( 1 + 2 * 3 ) / 4"
AdvSceneSwitcher.action.variable.findAndReplace.find="要查找的文本"
AdvSceneSwitcher.action.variable.findAndReplace.replace="要替换为的文本"
AdvSceneSwitcher.action.variable.subString.begin="开始"
AdvSceneSwitcher.action.variable.subString.all="全部"
AdvSceneSwitcher.action.variable.invalidSelection="无效选择!"
AdvSceneSwitcher.action.variable.actionNoVariableSupport="不支持从 %1 个操作获取变量值!"
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="不支持从 %1 条件中获取变量值!"
AdvSceneSwitcher.action.variable.currentSegmentValue="当前值:"
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}"
AdvSceneSwitcher.action.variable.entry.substringIndex="子字符串开始:{{subStringStart}} 子字符串大小:{{subStringSize}}"
AdvSceneSwitcher.action.variable.entry.substringRegex="使用正则表达式为 {{regexMatchIdx}} 匹配的值:"
AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{replaceStr}}"
AdvSceneSwitcher.action.projector="投影仪"
AdvSceneSwitcher.action.projector.type.source="源"
AdvSceneSwitcher.action.projector.type.scene="场景"
AdvSceneSwitcher.action.projector.type.preview="预览"
AdvSceneSwitcher.action.projector.type.program="程序"
AdvSceneSwitcher.action.projector.type.multiview="多视图"
AdvSceneSwitcher.action.projector.display="显示"
AdvSceneSwitcher.action.projector.windowed="窗口"
AdvSceneSwitcher.action.projector.fullscreen="全屏"
AdvSceneSwitcher.action.projector.entry="打开为{{windowTypes}} 的 {{types}}{{scenes}}{{sources}}投影"
AdvSceneSwitcher.action.projector.entry.monitor="在 {{monitors}} 上 (从不咕咕的阿坤说:谨慎开启!)"
AdvSceneSwitcher.action.midi="MIDI"
AdvSceneSwitcher.action.midi.entry="发送消息到 {{device}}:"
AdvSceneSwitcher.action.midi.entry.listen="将MIDI消息选择设置为 {{listenDevices}} 上传入的消息: {{listenButton}}"
AdvSceneSwitcher.action.osc="打开声音控制"
; Transition Tab ; Transition Tab
AdvSceneSwitcher.transitionTab.title="转场特效" AdvSceneSwitcher.transitionTab.title="转场特效"
@@ -724,7 +601,7 @@ AdvSceneSwitcher.mediaTab.states.none="无"
AdvSceneSwitcher.mediaTab.states.playing="播放中" AdvSceneSwitcher.mediaTab.states.playing="播放中"
AdvSceneSwitcher.mediaTab.states.opening="打开中" AdvSceneSwitcher.mediaTab.states.opening="打开中"
AdvSceneSwitcher.mediaTab.states.buffering="缓冲中" AdvSceneSwitcher.mediaTab.states.buffering="缓冲中"
AdvSceneSwitcher.mediaTab.states.paused="暂停" AdvSceneSwitcher.mediaTab.states.Paused="暂停"
AdvSceneSwitcher.mediaTab.states.stopped="停止" AdvSceneSwitcher.mediaTab.states.stopped="停止"
AdvSceneSwitcher.mediaTab.states.ended="结束" AdvSceneSwitcher.mediaTab.states.ended="结束"
AdvSceneSwitcher.mediaTab.states.error="错误" AdvSceneSwitcher.mediaTab.states.error="错误"
@@ -945,7 +822,6 @@ AdvSceneSwitcher.connection.password="密码:"
AdvSceneSwitcher.connection.reconnect="自动重新连接:" AdvSceneSwitcher.connection.reconnect="自动重新连接:"
AdvSceneSwitcher.connection.reconnectDelay="自动重新连接延迟:" AdvSceneSwitcher.connection.reconnectDelay="自动重新连接延迟:"
AdvSceneSwitcher.connection.connectOnStart="启动时自动连接:" AdvSceneSwitcher.connection.connectOnStart="启动时自动连接:"
AdvSceneSwitcher.connection.useOBSWebsocketProtocol="<html><head/><body><p>如何使用 obs-websocket <a href=\"https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md\"><span style=\" text-decoration: underline; color:#268bd2;\">protocol</span></a></p></body></html>"
AdvSceneSwitcher.connection.test="测试连接" AdvSceneSwitcher.connection.test="测试连接"
AdvSceneSwitcher.connection.status.disconnected="断开" AdvSceneSwitcher.connection.status.disconnected="断开"
AdvSceneSwitcher.connection.status.connecting="连接" AdvSceneSwitcher.connection.status.connecting="连接"
@@ -959,68 +835,6 @@ AdvSceneSwitcher.regex.dotMatchNewline=". 匹配换行符"
AdvSceneSwitcher.regex.multiLine="^ 和 $ 是匹配行的开始/结束" AdvSceneSwitcher.regex.multiLine="^ 和 $ 是匹配行的开始/结束"
AdvSceneSwitcher.regex.extendedPattern="启用Qt的扩展模式语法" AdvSceneSwitcher.regex.extendedPattern="启用Qt的扩展模式语法"
AdvSceneSwitcher.process.showAdvanced="显示高级设置"
AdvSceneSwitcher.process.arguments="参数:"
AdvSceneSwitcher.process.addArgument="增加参数"
AdvSceneSwitcher.process.addArgumentDescription="添加新参数:"
AdvSceneSwitcher.process.entry="运行{{filePath}}{{advancedSettings}}"
AdvSceneSwitcher.process.entry.workingDirectory="工作目录:{{workingDirectory}}"
AdvSceneSwitcher.math.expressionFail="计算表达式失败"
AdvSceneSwitcher.midi.deviceNamePattern="[端口 #%1] %2"
AdvSceneSwitcher.midi.message.type="类型:"
AdvSceneSwitcher.midi.message.type.optional="任意"
AdvSceneSwitcher.midi.message.type.invalid="无效"
AdvSceneSwitcher.midi.message.type.noteOff="关闭音符"
AdvSceneSwitcher.midi.message.type.noteOn="打开音符"
AdvSceneSwitcher.midi.message.type.polyphonicPressure="合成音压力"
AdvSceneSwitcher.midi.message.type.controlChange="控制更改"
AdvSceneSwitcher.midi.message.type.programChange="程序更改"
AdvSceneSwitcher.midi.message.type.channelAftertouch="频道余音"
AdvSceneSwitcher.midi.message.type.pitchBend="音高弯曲"
AdvSceneSwitcher.midi.message.type.systemExclusive="系统独占"
AdvSceneSwitcher.midi.message.type.timeCode="时间码"
AdvSceneSwitcher.midi.message.type.songPositionPointer="歌曲位置指针"
AdvSceneSwitcher.midi.message.type.songSelect="歌曲选择"
AdvSceneSwitcher.midi.message.type.reserved1="保留 (1)"
AdvSceneSwitcher.midi.message.type.reserved2="保留 (2)"
AdvSceneSwitcher.midi.message.type.tuneRequest="调音请求"
AdvSceneSwitcher.midi.message.type.endOfSystemExclusive="系统独占结束"
AdvSceneSwitcher.midi.message.type.timeClock="时间时钟"
AdvSceneSwitcher.midi.message.type.reserved3="保留 (3)"
AdvSceneSwitcher.midi.message.type.startFile="开始文件"
AdvSceneSwitcher.midi.message.type.continueFile="继续文件"
AdvSceneSwitcher.midi.message.type.stopFile="停止文件"
AdvSceneSwitcher.midi.message.type.reserved4="保留 (4)"
AdvSceneSwitcher.midi.message.type.activeSensing="主动感应"
AdvSceneSwitcher.midi.message.type.systemReset="系统充值"
AdvSceneSwitcher.midi.message.type.unknown="未知"
AdvSceneSwitcher.midi.message.channel="频道 :"
AdvSceneSwitcher.midi.message.note="音符 / 值(1):"
AdvSceneSwitcher.midi.message.value="值(2):"
AdvSceneSwitcher.midi.message.placeholder="任意"
AdvSceneSwitcher.midi.resetDevices="重新连接所有 MIDI 设备"
AdvSceneSwitcher.midi.startListen="开始监听"
AdvSceneSwitcher.midi.stopListen="停止监听"
AdvSceneSwitcher.midi.startListenFail="设备正忙!\n其他设备已经在监听!"
AdvSceneSwitcher.midi.deviceOpenFail="初始化 MIDI 设备失败!"
AdvSceneSwitcher.osc.network="网络"
AdvSceneSwitcher.osc.network.protocol="协议:"
AdvSceneSwitcher.osc.network.address="地址:"
AdvSceneSwitcher.osc.network.port="端口:"
AdvSceneSwitcher.osc.message="信息"
AdvSceneSwitcher.osc.message.type.none="无"
AdvSceneSwitcher.osc.message.type.float="浮点数哦"
AdvSceneSwitcher.osc.message.type.int="整数"
AdvSceneSwitcher.osc.message.type.string="字符串"
AdvSceneSwitcher.osc.message.type.binaryBlob="二进制"
AdvSceneSwitcher.osc.message.type.true="真"
AdvSceneSwitcher.osc.message.type.false="假"
AdvSceneSwitcher.osc.message.type.infinity="无限"
AdvSceneSwitcher.osc.message.type.null="无"
AdvSceneSwitcher.selectScene="--选择场景--" AdvSceneSwitcher.selectScene="--选择场景--"
AdvSceneSwitcher.selectPreviousScene="上个场景" AdvSceneSwitcher.selectPreviousScene="上个场景"
AdvSceneSwitcher.selectCurrentScene="当前场景" AdvSceneSwitcher.selectCurrentScene="当前场景"
@@ -1030,7 +844,7 @@ AdvSceneSwitcher.currentTransition="当前转场特效"
AdvSceneSwitcher.anyTransition="任何转场特效" AdvSceneSwitcher.anyTransition="任何转场特效"
AdvSceneSwitcher.selectTransition="--选择转场特效--" AdvSceneSwitcher.selectTransition="--选择转场特效--"
AdvSceneSwitcher.selectWindow="--选择窗口--" AdvSceneSwitcher.selectWindow="--选择窗口--"
AdvSceneSwitcher.selectSource="--选择源--" AdvSceneSwitcher.selectSource="--选择源--"
AdvSceneSwitcher.selectAudioSource="--选择音频源--" AdvSceneSwitcher.selectAudioSource="--选择音频源--"
AdvSceneSwitcher.selectVideoSource="--选择视频源--" AdvSceneSwitcher.selectVideoSource="--选择视频源--"
AdvSceneSwitcher.OBSVideoOutput="OBS的主要输出" AdvSceneSwitcher.OBSVideoOutput="OBS的主要输出"
@@ -1051,8 +865,8 @@ AdvSceneSwitcher.sceneItemSelection.any="任何"
AdvSceneSwitcher.status.active="运行中" AdvSceneSwitcher.status.active="运行中"
AdvSceneSwitcher.status.inactive="已停止" AdvSceneSwitcher.status.inactive="已停止"
AdvSceneSwitcher.running="插件正在运行" AdvSceneSwitcher.running="插件运行"
AdvSceneSwitcher.stopped="插件停止" AdvSceneSwitcher.stopped="插件停止"
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>这似乎是第一次启动高级场景切换程序.<br>请看一下 <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> 查看指南和示例列表.<br>如果有问题在在OBS论坛插件帖子内提问 <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">thread</span></a></p></body></html>" AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>这似乎是第一次启动高级场景切换程序.<br>请看一下 <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> 查看指南和示例列表.<br>如果有问题在在OBS论坛插件帖子内提问 <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">thread</span></a></p></body></html>"
@@ -1066,8 +880,4 @@ AdvSceneSwitcher.duration.condition.none="没有时间限制"
AdvSceneSwitcher.duration.condition.more="时间少于" AdvSceneSwitcher.duration.condition.more="时间少于"
AdvSceneSwitcher.duration.condition.equal="时间等于" AdvSceneSwitcher.duration.condition.equal="时间等于"
AdvSceneSwitcher.duration.condition.less="时间大于" AdvSceneSwitcher.duration.condition.less="时间大于"
AdvSceneSwitcher.duration.condition.within="在最后" AdvSceneSwitcher.duration.condition.within="保留结果后余存"
AdvSceneSwitcher.audio.monitor.none="关闭监听"
AdvSceneSwitcher.audio.monitor.monitorOnly="仅监听(输出静音)"
AdvSceneSwitcher.audio.monitor.both="监听并输出"

View File

@@ -1,4 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,9 +0,0 @@
<?xml version="1.0"?>
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g class="layer">
<title>Layer 1</title>
<path d="m1,2c0,-0.27 0.11,-0.52 0.29,-0.71c0.39,-0.39 1.03,-0.39 1.42,0l5.29,5.3l5.29,-5.3c0.39,-0.39 1.03,-0.39 1.42,0c0.18,0.19 0.29,0.44 0.29,0.71s-0.11,0.52 -0.29,0.71l-6,6c-0.39,0.39 -1.03,0.39 -1.42,0l-6,-6c-0.18,-0.19 -0.29,-0.44 -0.29,-0.71zm0,0" fill="#fefefe" id="svg_1" transform="matrix(1, 0, 0, 1, 0, 0)"/>
<path d="m1,8c0,-0.27 0.09,-0.52 0.28,-0.71c0.38,-0.39 1.03,-0.39 1.41,0l5.31,5.3l5.28,-5.3c0.38,-0.39 1.03,-0.39 1.41,0c0.19,0.19 0.31,0.44 0.31,0.71s-0.13,0.52 -0.31,0.71l-6,6c-0.38,0.39 -1.03,0.39 -1.41,0l-6,-6c-0.19,-0.19 -0.28,-0.44 -0.28,-0.71zm0,0" fill="#fefefe" id="svg_2"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 791 B

View File

@@ -1,9 +0,0 @@
<?xml version="1.0"?>
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g class="layer">
<title>Layer 1</title>
<path d="m1,8c0,-0.27 0.11,-0.52 0.29,-0.71l6,-6c0.39,-0.39 1.03,-0.39 1.42,0l6,6c0.18,0.19 0.29,0.44 0.29,0.71s-0.11,0.52 -0.29,0.71c-0.39,0.39 -1.03,0.39 -1.42,0l-5.29,-5.3l-5.29,5.3c-0.39,0.39 -1.03,0.39 -1.42,0c-0.18,-0.19 -0.29,-0.44 -0.29,-0.71zm0,0" fill="#fefefe" id="svg_1"/>
<path d="m1,14c0,-0.27 0.11,-0.52 0.28,-0.71l6,-6c0.39,-0.39 1.03,-0.39 1.42,0l6,6c0.19,0.19 0.3,0.44 0.3,0.71s-0.11,0.52 -0.3,0.71c-0.39,0.39 -1.03,0.39 -1.42,0l-5.28,-5.3l-5.3,5.3c-0.39,0.39 -1.03,0.39 -1.42,0c-0.17,-0.19 -0.28,-0.44 -0.28,-0.71zm0,0" fill="#fefefe" id="svg_2"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 753 B

View File

@@ -1,7 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0"?>
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" version="1.1">
<!-- Created with SVG-edit - https://github.com/SVG-Edit/svgedit-->
<g class="layer">
<title>Layer 1</title>
<rect fill="#fefefe" height="2.25" id="svg_1" stroke="#fefefe" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="matrix(1, 0, 0, 1, 0, 0)" width="13" x="1.5" y="4"/>
<rect fill="#fefefe" height="2.25" id="svg_2" stroke="#fefefe" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="matrix(1, 0, 0, 1, 0, 0)" width="13" x="1.5" y="10"/>
<rect fill="#fefefe" height="1" id="svg_4" stroke="#fefefe" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="matrix(0.341951, -0.926734, 0.939718, 0.337226, -1.948, 13.2448)" width="14" x="1" y="7"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 931 B

View File

@@ -1,24 +0,0 @@
<?xml version="1.0"?>
<svg width="640" height="640" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" version="1.1">
<defs>
<path d="m599.62,325.49c0,151.77 -123.21,274.98 -274.98,274.98c-151.76,0 -274.97,-123.21 -274.97,-274.98c0,-151.76 123.21,-274.97 274.97,-274.97c151.77,0 274.98,123.21 274.98,274.97z" id="c3Wyq0kfYS"/>
<mask height="689.95" id="maskanTyyngos" maskUnits="userSpaceOnUse" width="689.95" x="-20.33" y="-19.48">
<rect fill="white" height="689.95" id="svg_1" width="689.95" x="-20.33" y="-19.48"/>
<use fill="black" id="svg_2" xlink:href="#c3Wyq0kfYS"/>
</mask>
<path d="m334.97,96.07c4.54,0 8.23,3.68 8.23,8.23c0,46.94 0,179.54 0,226.48c0,4.54 -3.69,8.22 -8.23,8.22c-5.77,0 -14.88,0 -20.66,0c-4.54,0 -8.22,-3.68 -8.22,-8.22c0,-46.94 0,-179.54 0,-226.48c0,-4.55 3.68,-8.23 8.22,-8.23c5.78,0 14.89,0 20.66,0z" id="fxMeu932c"/>
<path d="m471.96,338.21c0.01,3.1 -2.5,5.62 -5.59,5.63c-32.02,0.09 -122.45,0.37 -154.46,0.47c-3.1,0.01 -5.61,-2.49 -5.62,-5.59c-0.02,-6.3 -0.06,-19.59 -0.08,-25.89c-0.01,-3.1 2.49,-5.62 5.59,-5.63c32.01,-0.09 122.44,-0.37 154.45,-0.47c3.1,-0.01 5.62,2.5 5.63,5.59c0.02,6.3 0.06,19.59 0.08,25.89z" id="h65nGmP2BL"/>
</defs>
<g class="layer">
<title>Layer 1</title>
<path fill="none" fill-opacity="null" id="svg_11" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02"/>
<ellipse cx="103.84" cy="562.04" fill="#fefefe" id="svg_3" rx="80" ry="45" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-18.699, 103.843, 562.038)"/>
<ellipse cx="506" cy="554" fill="#fefefe" id="svg_4" rx="77" ry="45" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-18.699, 506, 554)"/>
<rect fill="#fefefe" height="359" id="svg_7" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" stroke-width="0" width="58" x="122" y="185"/>
<rect fill="#fefefe" height="453" id="svg_8" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="58" x="522" y="84.5"/>
<rect fill="#fefefe" height="37" id="svg_9" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-14.1985, 351.556, 146.245)" width="463.07" x="120.02" y="127.74"/>
<rect fill="none" fill-opacity="null" height="0" id="svg_10" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="0" x="538.25" y="107.12"/>
<path d="m537.42,112.06l0,-67.88l17.58,67.88z" fill="#fefefe" id="svg_16" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-90, 546.203, 78.1248)"/>
<rect fill="#fefefe" height="0" id="svg_18" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="0" x="82.12" y="287.56"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,10 +0,0 @@
<?xml version="1.0"?>
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" version="1.1">
<!-- Created with SVG-edit - https://github.com/SVG-Edit/svgedit-->
<g class="layer">
<title>Layer 1</title>
<text fill="#fefefe" font-family="Serif" font-size="24" id="svg_1" stroke="#fefefe" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" text-anchor="middle" transform="matrix(1.0974, 0, 0, 1.0974, -4.98544, 4.97639)" x="14" xml:space="preserve" y="13">*</text>
<rect fill="#fefefe" height="3.3" id="svg_2" stroke="#fefefe" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="matrix(1, 0, 0, 1, 0, 0)" width="5" x="1" y="12"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 815 B

View File

@@ -1,8 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
<defs>
</defs>
<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)" >
<path d="M 87.803 77.194 L 68.212 57.602 c 9.5 -14.422 7.912 -34.054 -4.766 -46.732 c 0 0 -0.001 0 -0.001 0 c -14.495 -14.493 -38.08 -14.494 -52.574 0 c -14.494 14.495 -14.494 38.079 0 52.575 c 7.248 7.247 16.767 10.87 26.287 10.87 c 7.134 0 14.267 -2.035 20.445 -6.104 l 19.591 19.591 C 78.659 89.267 80.579 90 82.498 90 s 3.84 -0.733 5.305 -2.197 C 90.732 84.873 90.732 80.124 87.803 77.194 z M 21.48 52.837 c -8.645 -8.646 -8.645 -22.713 0 -31.358 c 4.323 -4.322 10 -6.483 15.679 -6.483 c 5.678 0 11.356 2.161 15.678 6.483 c 8.644 8.644 8.645 22.707 0.005 31.352 c -0.002 0.002 -0.004 0.003 -0.005 0.005 c -0.002 0.002 -0.003 0.003 -0.004 0.005 C 44.184 61.481 30.123 61.48 21.48 52.837 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: #fefefe; fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,4 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,9 +0,0 @@
<?xml version="1.0"?>
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g class="layer">
<title>Layer 1</title>
<path d="m1,2c0,-0.27 0.11,-0.52 0.29,-0.71c0.39,-0.39 1.03,-0.39 1.42,0l5.29,5.3l5.29,-5.3c0.39,-0.39 1.03,-0.39 1.42,0c0.18,0.19 0.29,0.44 0.29,0.71s-0.11,0.52 -0.29,0.71l-6,6c-0.39,0.39 -1.03,0.39 -1.42,0l-6,-6c-0.18,-0.19 -0.29,-0.44 -0.29,-0.71zm0,0" fill="#202020" id="svg_1"/>
<path d="m1,8c0,-0.27 0.11,-0.52 0.29,-0.71c0.39,-0.39 1.03,-0.39 1.42,0l5.29,5.3l5.29,-5.3c0.39,-0.39 1.03,-0.39 1.42,0c0.18,0.19 0.29,0.44 0.29,0.71s-0.11,0.52 -0.29,0.71l-6,6c-0.39,0.39 -1.03,0.39 -1.42,0l-6,-6c-0.18,-0.19 -0.29,-0.44 -0.29,-0.71zm0,0" fill="#202020" id="svg_4" transform="matrix(1, 0, 0, 1, 0, 0)"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 791 B

View File

@@ -1,9 +0,0 @@
<?xml version="1.0"?>
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g class="layer">
<title>Layer 1</title>
<path d="m1,8c0,-0.27 0.11,-0.52 0.29,-0.71l6,-6c0.39,-0.39 1.03,-0.39 1.42,0l6,6c0.18,0.19 0.29,0.44 0.29,0.71s-0.11,0.52 -0.29,0.71c-0.39,0.39 -1.03,0.39 -1.42,0l-5.29,-5.3l-5.29,5.3c-0.39,0.39 -1.03,0.39 -1.42,0c-0.18,-0.19 -0.29,-0.44 -0.29,-0.71zm0,0" fill="#202020" id="svg_1"/>
<path d="m1,14c0,-0.27 0.11,-0.52 0.29,-0.71l6,-6c0.39,-0.39 1.03,-0.39 1.42,0l6,6c0.18,0.19 0.29,0.44 0.29,0.71s-0.11,0.52 -0.29,0.71c-0.39,0.39 -1.03,0.39 -1.42,0l-5.29,-5.3l-5.29,5.3c-0.39,0.39 -1.03,0.39 -1.42,0c-0.18,-0.19 -0.29,-0.44 -0.29,-0.71zm0,0" fill="#202020" id="svg_2"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 757 B

View File

@@ -1,7 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0"?>
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" version="1.1">
<!-- Created with SVG-edit - https://github.com/SVG-Edit/svgedit-->
<g class="layer">
<title>Layer 1</title>
<rect fill="#202020" height="2.25" id="svg_1" stroke="#202020" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="matrix(1, 0, 0, 1, 0, 0)" width="13" x="1.5" y="4"/>
<rect fill="#202020" height="2.25" id="svg_2" stroke="#202020" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="matrix(1, 0, 0, 1, 0, 0)" width="13" x="1.5" y="10"/>
<rect fill="#202020" height="1" id="svg_4" stroke="#202020" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="matrix(0.341951, -0.926734, 0.939718, 0.337226, -1.948, 13.2448)" width="14" x="1" y="7"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 931 B

View File

@@ -1,24 +0,0 @@
<?xml version="1.0"?>
<svg width="640" height="640" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" version="1.1">
<defs>
<path d="m599.62,325.49c0,151.77 -123.21,274.98 -274.98,274.98c-151.76,0 -274.97,-123.21 -274.97,-274.98c0,-151.76 123.21,-274.97 274.97,-274.97c151.77,0 274.98,123.21 274.98,274.97z" id="c3Wyq0kfYS"/>
<mask height="689.95" id="maskanTyyngos" maskUnits="userSpaceOnUse" width="689.95" x="-20.33" y="-19.48">
<rect fill="white" height="689.95" id="svg_1" width="689.95" x="-20.33" y="-19.48"/>
<use fill="black" id="svg_2" xlink:href="#c3Wyq0kfYS"/>
</mask>
<path d="m334.97,96.07c4.54,0 8.23,3.68 8.23,8.23c0,46.94 0,179.54 0,226.48c0,4.54 -3.69,8.22 -8.23,8.22c-5.77,0 -14.88,0 -20.66,0c-4.54,0 -8.22,-3.68 -8.22,-8.22c0,-46.94 0,-179.54 0,-226.48c0,-4.55 3.68,-8.23 8.22,-8.23c5.78,0 14.89,0 20.66,0z" id="fxMeu932c"/>
<path d="m471.96,338.21c0.01,3.1 -2.5,5.62 -5.59,5.63c-32.02,0.09 -122.45,0.37 -154.46,0.47c-3.1,0.01 -5.61,-2.49 -5.62,-5.59c-0.02,-6.3 -0.06,-19.59 -0.08,-25.89c-0.01,-3.1 2.49,-5.62 5.59,-5.63c32.01,-0.09 122.44,-0.37 154.45,-0.47c3.1,-0.01 5.62,2.5 5.63,5.59c0.02,6.3 0.06,19.59 0.08,25.89z" id="h65nGmP2BL"/>
</defs>
<g class="layer">
<title>Layer 1</title>
<path fill="none" fill-opacity="null" id="svg_11" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02"/>
<ellipse cx="103.84" cy="562.04" fill="#202020" id="svg_3" rx="80" ry="45" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-18.699, 103.843, 562.038)"/>
<ellipse cx="506" cy="554" fill="#202020" id="svg_4" rx="77" ry="45" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-18.699, 506, 554)"/>
<rect fill="#202020" height="359" id="svg_7" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" stroke-width="0" width="58" x="122" y="185"/>
<rect fill="#202020" height="453" id="svg_8" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="58" x="522" y="84.5"/>
<rect fill="#202020" height="37" id="svg_9" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-14.1985, 351.556, 146.245)" width="463.07" x="120.02" y="127.74"/>
<rect fill="none" fill-opacity="null" height="0" id="svg_10" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="0" x="538.25" y="107.12"/>
<path d="m537.42,112.06l0,-67.88l17.58,67.88z" fill="#202020" id="svg_16" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-90, 546.203, 78.1248)"/>
<rect fill="#202020" height="0" id="svg_18" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="0" x="82.12" y="287.56"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,10 +0,0 @@
<?xml version="1.0"?>
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" version="1.1">
<!-- Created with SVG-edit - https://github.com/SVG-Edit/svgedit-->
<g class="layer">
<title>Layer 1</title>
<text fill="#202020" font-family="Serif" font-size="24" id="svg_1" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" text-anchor="middle" transform="matrix(1.0974, 0, 0, 1.0974, -4.98544, 4.97639)" x="14" xml:space="preserve" y="13">*</text>
<rect fill="#202020" height="3.3" id="svg_2" stroke="#202020" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="matrix(1, 0, 0, 1, 0, 0)" width="5" x="1" y="12"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 815 B

View File

@@ -1,8 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
<defs>
</defs>
<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)" >
<path d="M 87.803 77.194 L 68.212 57.602 c 9.5 -14.422 7.912 -34.054 -4.766 -46.732 c 0 0 -0.001 0 -0.001 0 c -14.495 -14.493 -38.08 -14.494 -52.574 0 c -14.494 14.495 -14.494 38.079 0 52.575 c 7.248 7.247 16.767 10.87 26.287 10.87 c 7.134 0 14.267 -2.035 20.445 -6.104 l 19.591 19.591 C 78.659 89.267 80.579 90 82.498 90 s 3.84 -0.733 5.305 -2.197 C 90.732 84.873 90.732 80.124 87.803 77.194 z M 21.48 52.837 c -8.645 -8.646 -8.645 -22.713 0 -31.358 c 4.323 -4.322 10 -6.483 15.679 -6.483 c 5.678 0 11.356 2.161 15.678 6.483 c 8.644 8.644 8.645 22.707 0.005 31.352 c -0.002 0.002 -0.004 0.003 -0.005 0.005 c -0.002 0.002 -0.003 0.003 -0.004 0.005 C 44.184 61.481 30.123 61.48 21.48 52.837 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: #202020; fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,2 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,2 +1,3 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?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="#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> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 640 640" width="640" height="640"><defs><path d="M599.62 325.49C599.62 477.26 476.41 600.47 324.64 600.47C172.88 600.47 49.67 477.26 49.67 325.49C49.67 173.73 172.88 50.52 324.64 50.52C476.41 50.52 599.62 173.73 599.62 325.49Z" id="c3Wyq0kfYS"></path><mask id="maskanTyyngos" x="-20.33" y="-19.48" width="689.95" height="689.95" maskUnits="userSpaceOnUse"><rect x="-20.33" y="-19.48" width="689.95" height="689.95" fill="white"></rect><use xlink:href="#c3Wyq0kfYS" opacity="1" fill="black"></use></mask><path d="M334.97 96.07C339.51 96.07 343.2 99.75 343.2 104.3C343.2 151.24 343.2 283.84 343.2 330.78C343.2 335.32 339.51 339 334.97 339C329.2 339 320.09 339 314.31 339C309.77 339 306.09 335.32 306.09 330.78C306.09 283.84 306.09 151.24 306.09 104.3C306.09 99.75 309.77 96.07 314.31 96.07C320.09 96.07 329.2 96.07 334.97 96.07Z" id="fxMeu932c"></path><path d="M471.96 338.21C471.97 341.31 469.46 343.83 466.37 343.84C434.35 343.93 343.92 344.21 311.91 344.31C308.81 344.32 306.3 341.82 306.29 338.72C306.27 332.42 306.23 319.13 306.21 312.83C306.2 309.73 308.7 307.21 311.8 307.2C343.81 307.11 434.24 306.83 466.25 306.73C469.35 306.72 471.87 309.23 471.88 312.32C471.9 318.62 471.94 331.91 471.96 338.21Z" id="h65nGmP2BL"></path></defs><g><g><g><g mask="url(#maskanTyyngos)"><use xlink:href="#c3Wyq0kfYS" opacity="1" fill-opacity="0" stroke="#d2d2d2" stroke-width="70" stroke-opacity="1"></use></g></g><g><use xlink:href="#fxMeu932c" opacity="1" fill="#d2d2d2" fill-opacity="1"></use></g><g><use xlink:href="#h65nGmP2BL" opacity="1" fill="#d2d2d2" fill-opacity="1"></use></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

2
deps/asio vendored

Submodule deps/asio updated: c465349fa5...b73dc1d2c0

1
deps/cpp-httplib vendored

Submodule deps/cpp-httplib deleted from c7ed1796a7

41032
deps/exprtk/exprtk.hpp vendored

File diff suppressed because it is too large Load Diff

1
deps/json vendored

Submodule deps/json deleted from bc889afb4c

1
deps/libremidi vendored

Submodule deps/libremidi deleted from 56147984ee

View File

@@ -67,8 +67,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>962</width> <width>957</width>
<height>1033</height> <height>905</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_19"> <layout class="QVBoxLayout" name="verticalLayout_19">
@@ -256,54 +256,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QCheckBox" name="disableComboBoxFilter">
<property name="text">
<string>AdvSceneSwitcher.generalTab.generalBehavior.comboBoxFilterDisable</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_13">
<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>
<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>
@@ -682,7 +634,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="advss::MacroTree" name="macros"> <widget class="MacroTree" name="macros">
<property name="showDropIndicator" stdset="0"> <property name="showDropIndicator" stdset="0">
<bool>true</bool> <bool>true</bool>
</property> </property>
@@ -829,7 +781,7 @@
<property name="title"> <property name="title">
<string>AdvSceneSwitcher.macroTab.edit</string> <string>AdvSceneSwitcher.macroTab.edit</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_38"> <layout class="QVBoxLayout" name="verticalLayout_33">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_18" stretch="0,0,0,0,0,0,0,0,0"> <layout class="QHBoxLayout" name="horizontalLayout_18" stretch="0,0,0,0,0,0,0,0,0">
<item> <item>
@@ -843,7 +795,7 @@
<widget class="QLineEdit" name="macroName"/> <widget class="QLineEdit" name="macroName"/>
</item> </item>
<item> <item>
<widget class="advss::MacroRunButton" name="runMacro"> <widget class="QPushButton" name="runMacro">
<property name="text"> <property name="text">
<string>AdvSceneSwitcher.macroTab.run</string> <string>AdvSceneSwitcher.macroTab.run</string>
</property> </property>
@@ -936,16 +888,6 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item>
<widget class="advss::MacroSegmentList" name="conditionsList">
<property name="minimumSize">
<size>
<width>0</width>
<height>1</height>
</size>
</property>
</widget>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_12"> <layout class="QHBoxLayout" name="horizontalLayout_12">
<property name="leftMargin"> <property name="leftMargin">
@@ -1022,19 +964,6 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item>
<widget class="QPushButton" name="conditionTop">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="conditionUp"> <widget class="QPushButton" name="conditionUp">
<property name="maximumSize"> <property name="maximumSize">
@@ -1070,19 +999,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="conditionBottom">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_15"> <spacer name="horizontalSpacer_15">
<property name="orientation"> <property name="orientation">
@@ -1100,376 +1016,144 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QSplitter" name="macroElseActionSplitter"> <widget class="QWidget" name="macroActions" native="true">
<property name="orientation"> <layout class="QVBoxLayout" name="macroActionsLayout">
<enum>Qt::Vertical</enum> <property name="leftMargin">
</property> <number>0</number>
<widget class="QWidget" name="macroActions" native="true"> </property>
<layout class="QVBoxLayout" name="macroActionsLayout"> <property name="topMargin">
<property name="leftMargin"> <number>0</number>
<number>0</number> </property>
</property> <property name="rightMargin">
<property name="topMargin"> <number>0</number>
<number>0</number> </property>
</property> <property name="bottomMargin">
<property name="rightMargin"> <number>0</number>
<number>0</number> </property>
</property> <item>
<property name="bottomMargin"> <layout class="QHBoxLayout" name="horizontalLayout_21">
<number>0</number> <property name="leftMargin">
</property> <number>9</number>
<item> </property>
<widget class="advss::MacroSegmentList" name="actionsList"> <item>
<property name="minimumSize"> <widget class="QPushButton" name="actionAdd">
<size> <property name="maximumSize">
<width>0</width> <size>
<height>1</height> <width>22</width>
</size> <height>16777215</height>
</property> </size>
</widget> </property>
</item> <property name="flat">
<item> <bool>true</bool>
<layout class="QHBoxLayout" name="horizontalLayout_21"> </property>
<property name="leftMargin"> <property name="themeID" stdset="0">
<number>9</number> <string notr="true">addIconSmall</string>
</property> </property>
<item> </widget>
<widget class="QPushButton" name="actionAdd"> </item>
<property name="maximumSize"> <item>
<size> <widget class="QPushButton" name="actionRemove">
<width>22</width> <property name="maximumSize">
<height>16777215</height> <size>
</size> <width>22</width>
</property> <height>16777215</height>
<property name="flat"> </size>
<bool>true</bool> </property>
</property> <property name="flat">
<property name="themeID" stdset="0"> <bool>true</bool>
<string notr="true">addIconSmall</string> </property>
</property> <property name="themeID" stdset="0">
</widget> <string notr="true">removeIconSmall</string>
</item> </property>
<item> </widget>
<widget class="QPushButton" name="actionRemove"> </item>
<property name="maximumSize"> <item>
<size> <spacer name="horizontalSpacer_133">
<width>22</width> <property name="orientation">
<height>16777215</height> <enum>Qt::Horizontal</enum>
</size> </property>
</property> <property name="sizeType">
<property name="flat"> <enum>QSizePolicy::Fixed</enum>
<bool>true</bool> </property>
</property> <property name="sizeHint" stdset="0">
<property name="themeID" stdset="0"> <size>
<string notr="true">removeIconSmall</string> <width>5</width>
</property> <height>20</height>
</widget> </size>
</item> </property>
<item> </spacer>
<spacer name="horizontalSpacer_133"> </item>
<property name="orientation"> <item>
<enum>Qt::Horizontal</enum> <widget class="Line" name="line_47">
</property> <property name="orientation">
<property name="sizeType"> <enum>Qt::Vertical</enum>
<enum>QSizePolicy::Fixed</enum> </property>
</property> </widget>
<property name="sizeHint" stdset="0"> </item>
<size> <item>
<width>5</width> <spacer name="horizontalSpacer_132">
<height>20</height> <property name="orientation">
</size> <enum>Qt::Horizontal</enum>
</property> </property>
</spacer> <property name="sizeType">
</item> <enum>QSizePolicy::Fixed</enum>
<item> </property>
<widget class="Line" name="line_47"> <property name="sizeHint" stdset="0">
<property name="orientation"> <size>
<enum>Qt::Vertical</enum> <width>5</width>
</property> <height>20</height>
</widget> </size>
</item> </property>
<item> </spacer>
<spacer name="horizontalSpacer_132"> </item>
<property name="orientation"> <item>
<enum>Qt::Horizontal</enum> <widget class="QPushButton" name="actionUp">
</property> <property name="maximumSize">
<property name="sizeType"> <size>
<enum>QSizePolicy::Fixed</enum> <width>22</width>
</property> <height>16777215</height>
<property name="sizeHint" stdset="0"> </size>
<size> </property>
<width>5</width> <property name="flat">
<height>20</height> <bool>true</bool>
</size> </property>
</property> <property name="themeID" stdset="0">
</spacer> <string notr="true">upArrowIconSmall</string>
</item> </property>
<item> </widget>
<widget class="QPushButton" name="actionTop"> </item>
<property name="maximumSize"> <item>
<size> <widget class="QPushButton" name="actionDown">
<width>22</width> <property name="maximumSize">
<height>16777215</height> <size>
</size> <width>22</width>
</property> <height>16777215</height>
<property name="flat"> </size>
<bool>true</bool> </property>
</property> <property name="flat">
</widget> <bool>true</bool>
</item> </property>
<item> <property name="themeID" stdset="0">
<widget class="QPushButton" name="actionUp"> <string notr="true">downArrowIconSmall</string>
<property name="maximumSize"> </property>
<size> </widget>
<width>22</width> </item>
<height>16777215</height> <item>
</size> <spacer name="horizontalSpacer_14">
</property> <property name="orientation">
<property name="flat"> <enum>Qt::Horizontal</enum>
<bool>true</bool> </property>
</property> <property name="sizeHint" stdset="0">
<property name="themeID" stdset="0"> <size>
<string notr="true">upArrowIconSmall</string> <width>40</width>
</property> <height>20</height>
</widget> </size>
</item> </property>
<item> </spacer>
<widget class="QPushButton" name="actionDown"> </item>
<property name="maximumSize"> </layout>
<size> </item>
<width>22</width> </layout>
<height>16777215</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">downArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="actionBottom">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_14">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="toggleElseActions">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="macroElseActions" native="true">
<layout class="QVBoxLayout" name="macroElseActionsLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="advss::MacroSegmentList" name="elseActionsList">
<property name="minimumSize">
<size>
<width>0</width>
<height>1</height>
</size>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_33">
<property name="leftMargin">
<number>9</number>
</property>
<item>
<widget class="QPushButton" name="elseActionAdd">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">addIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="elseActionRemove">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">removeIconSmall</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_138">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="Line" name="line_50">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_139">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="elseActionTop">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="elseActionUp">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">upArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="elseActionDown">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">downArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="elseActionBottom">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_22">
<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>
</layout>
</widget>
</widget> </widget>
</widget> </widget>
</item> </item>
@@ -4855,21 +4539,10 @@
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>
<class>advss::MacroTree</class> <class>MacroTree</class>
<extends>QListView</extends> <extends>QListView</extends>
<header>macro-tree.hpp</header> <header>macro-tree.hpp</header>
</customwidget> </customwidget>
<customwidget>
<class>advss::MacroSegmentList</class>
<extends>QScrollArea</extends>
<header>macro-segment-list.hpp</header>
<container>1</container>
</customwidget>
<customwidget>
<class>advss::MacroRunButton</class>
<extends>QPushButton</extends>
<header>macro-run-button.hpp</header>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections/> <connections/>

View File

@@ -1,22 +1,34 @@
#include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "status-control.hpp"
#include "scene-switch-helpers.hpp"
#include "curl-helper.hpp"
#include "platform-funcs.hpp"
#include "utility.hpp"
#include "version.h"
#include <QMainWindow> #include <QMainWindow>
#include <QAction> #include <QAction>
#include <QFileDialog> #include <QFileDialog>
#include <QDirIterator> #include <QDirIterator>
#include <regex> #include <regex>
#include <filesystem> #include <filesystem>
#include <obs-module.h> #include <obs-module.h>
#include <obs-frontend-api.h> #include <obs-frontend-api.h>
namespace advss { #include "advanced-scene-switcher.hpp"
#include "status-control.hpp"
#include "curl-helper.hpp"
#include "utility.hpp"
#include "version.h"
const char *obs_module_text(const char *text)
{
return switcher->translate(text);
}
obs_module_t *obs_current_module()
{
return switcher->modulePtr;
}
SwitcherData *switcher = nullptr;
SwitcherData *GetSwitcher()
{
return switcher;
}
AdvSceneSwitcher *AdvSceneSwitcher::window = nullptr; AdvSceneSwitcher *AdvSceneSwitcher::window = nullptr;
@@ -28,9 +40,11 @@ AdvSceneSwitcher::AdvSceneSwitcher(QWidget *parent)
{ {
switcher->settingsWindowOpened = true; switcher->settingsWindowOpened = true;
ui->setupUi(this); ui->setupUi(this);
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switcher->Prune(); switcher->Prune();
LoadUI(); loadUI();
} }
AdvSceneSwitcher::~AdvSceneSwitcher() AdvSceneSwitcher::~AdvSceneSwitcher()
@@ -41,113 +55,65 @@ AdvSceneSwitcher::~AdvSceneSwitcher()
} }
} }
static bool translationAvailable() bool translationAvailable()
{ {
return !!strcmp(obs_module_text("AdvSceneSwitcher.pluginName"), return !!strcmp(obs_module_text("AdvSceneSwitcher.pluginName"),
"AdvSceneSwitcher.pluginName"); "AdvSceneSwitcher.pluginName");
} }
static void DisplayMissingDependencyWarning() void AdvSceneSwitcher::loadUI()
{ {
if (!switcher->warnPluginLoadFailure || if (!translationAvailable()) {
switcher->loadFailureLibs.isEmpty()) { QString msg = "Failed to find plug-in's 'data' directory.\n"
return; "Please check installation instructions!\n\n"
} "Data most likely expected at:\n\n";
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 #ifdef _WIN32
msg += QString::fromStdString( msg += QString::fromStdString(
(std::filesystem::current_path().string())); (std::filesystem::current_path().string()));
msg += "/"; msg += "/";
#endif #endif
msg += obs_get_module_data_path(obs_current_module()); msg += obs_get_module_data_path(obs_current_module());
DisplayMessage(msg); (void)DisplayMessage(msg);
} }
void AdvSceneSwitcher::LoadUI() setupGeneralTab();
{ setupTitleTab();
DisplayMissingDataDirWarning(); setupExecutableTab();
DisplayMissingDependencyWarning(); setupRegionTab();
setupPauseTab();
setupSequenceTab();
setupTransitionsTab();
setupIdleTab();
setupRandomTab();
setupMediaTab();
setupFileTab();
setupTimeTab();
setupAudioTab();
setupVideoTab();
setupNetworkTab();
setupSceneGroupTab();
setupTriggerTab();
setupMacroTab();
SetupGeneralTab(); setDeprecationWarnings();
SetupTitleTab(); setTabOrder();
SetupExecutableTab(); setCurrentTab();
SetupRegionTab(); restoreWindowGeo();
SetupPauseTab(); checkFirstTimeSetup();
SetupSequenceTab();
SetupTransitionsTab();
SetupIdleTab();
SetupRandomTab();
SetupMediaTab();
SetupFileTab();
SetupTimeTab();
SetupAudioTab();
SetupVideoTab();
SetupNetworkTab();
SetupSceneGroupTab();
SetupTriggerTab();
SetupMacroTab();
SetDeprecationWarnings();
SetTabOrder();
SetCurrentTab();
RestoreWindowGeo();
CheckFirstTimeSetup();
loading = false; loading = false;
} }
bool AdvSceneSwitcher::eventFilter(QObject *obj, QEvent *event)
{
auto eventType = event->type();
if (obj == ui->macroElseActions && eventType == QEvent::Resize) {
QResizeEvent *resizeEvent = static_cast<QResizeEvent *>(event);
if (resizeEvent->size().height() == 0) {
SetElseActionsStateToHidden();
return QDialog::eventFilter(obj, event);
}
SetElseActionsStateToVisible();
}
return QDialog::eventFilter(obj, event);
}
/****************************************************************************** /******************************************************************************
* Saving and loading * Saving and loading
******************************************************************************/ ******************************************************************************/
static void AskForBackup(obs_data_t *obj);
static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *) static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
{ {
if (!switcher) {
return;
}
if (saving) { if (saving) {
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switcher->Prune(); switcher->Prune();
obs_data_t *obj = obs_data_create(); obs_data_t *obj = obs_data_create();
switcher->SaveSettings(obj); switcher->saveSettings(obj);
obs_data_set_obj(save_data, "advanced-scene-switcher", obj); obs_data_set_obj(save_data, "advanced-scene-switcher", obj);
obs_data_release(obj); obs_data_release(obj);
} else { } else {
@@ -161,10 +127,10 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
if (!obj) { if (!obj) {
obj = obs_data_create(); obj = obs_data_create();
} }
if (switcher->VersionChanged(obj, g_GIT_SHA1)) { if (switcher->versionChanged(obj, g_GIT_SHA1)) {
AskForBackup(obj); AskForBackup(obj);
} }
switcher->LoadSettings(obj); switcher->loadSettings(obj);
obs_data_release(obj); obs_data_release(obj);
switcher->m.unlock(); switcher->m.unlock();
@@ -174,34 +140,6 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
} }
} }
static void AskForBackup(obs_data_t *obj)
{
bool backupSettings = DisplayMessage(
obs_module_text("AdvSceneSwitcher.askBackup"), true);
if (!backupSettings) {
return;
}
QString path = QFileDialog::getSaveFileName(
nullptr,
obs_module_text(
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle"),
GetDefaultSettingsSaveLocation(),
obs_module_text(
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType"));
if (path.isEmpty()) {
return;
}
QFile file(path);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return;
}
obs_data_save_json(obj, file.fileName().toUtf8().constData());
}
/****************************************************************************** /******************************************************************************
* Main switcher thread * Main switcher thread
******************************************************************************/ ******************************************************************************/
@@ -245,7 +183,7 @@ void SwitcherData::Thread()
} }
vblog(LOG_INFO, "try to sleep for %ld", duration.count()); vblog(LOG_INFO, "try to sleep for %ld", duration.count());
SetWaitScene(); setWaitScene();
cv.wait_for(lock, duration); cv.wait_for(lock, duration);
startTime = std::chrono::high_resolution_clock::now(); startTime = std::chrono::high_resolution_clock::now();
@@ -259,13 +197,13 @@ void SwitcherData::Thread()
if (checkPause()) { if (checkPause()) {
continue; continue;
} }
SetPreconditions(); setPreconditions();
match = CheckForMatch(scene, transition, linger, match = checkForMatch(scene, transition, linger,
setPrevSceneAfterLinger, macroMatch); setPrevSceneAfterLinger, macroMatch);
if (stop) { if (stop) {
break; break;
} }
CheckNoMatchSwitch(match, scene, transition, sleep); checkNoMatchSwitch(match, scene, transition, sleep);
checkSwitchCooldown(match); checkSwitchCooldown(match);
if (linger) { if (linger) {
@@ -273,14 +211,14 @@ void SwitcherData::Thread()
vblog(LOG_INFO, "sleep for %ld before switching scene", vblog(LOG_INFO, "sleep for %ld before switching scene",
duration.count()); duration.count());
SetWaitScene(); setWaitScene();
cv.wait_for(lock, duration); cv.wait_for(lock, duration);
if (stop) { if (stop) {
break; break;
} }
if (SceneChangedDuringWait()) { if (sceneChangedDuringWait()) {
vblog(LOG_INFO, vblog(LOG_INFO,
"scene was changed manually - ignoring match"); "scene was changed manually - ignoring match");
@@ -291,13 +229,13 @@ void SwitcherData::Thread()
} }
} }
ResetForNextInterval(); ClearWebsocketMessages();
if (match) { if (match) {
if (macroMatch) { if (macroMatch) {
RunMacros(); runMacros();
} else { } else {
SwitchScene({scene, transition, 0}); switchScene({scene, transition, 0});
} }
} }
@@ -310,7 +248,7 @@ void SwitcherData::Thread()
blog(LOG_INFO, "stopped"); blog(LOG_INFO, "stopped");
} }
void SwitcherData::SetPreconditions() void SwitcherData::setPreconditions()
{ {
// Window title // Window title
lastTitle = currentTitle; lastTitle = currentTitle;
@@ -338,24 +276,13 @@ void SwitcherData::SetPreconditions()
GetForegroundProcessName(currentForegroundProcess); GetForegroundProcessName(currentForegroundProcess);
// Cursor // Cursor
std::pair<int, int> cursorPos = GetCursorPos(); std::pair<int, int> cursorPos = getCursorPos();
cursorPosChanged = cursorPos.first != switcher->lastCursorPos.first || cursorPosChanged = cursorPos.first != switcher->lastCursorPos.first ||
cursorPos.second != switcher->lastCursorPos.second; cursorPos.second != switcher->lastCursorPos.second;
lastCursorPos = GetCursorPos(); lastCursorPos = getCursorPos();
// Macro
InvalidateMacroTempVarValues();
} }
void SwitcherData::ResetForNextInterval() bool SwitcherData::checkForMatch(OBSWeakSource &scene,
{
// Plugin reset functions
for (const auto &func : resetIntervalSteps) {
func();
}
}
bool SwitcherData::CheckForMatch(OBSWeakSource &scene,
OBSWeakSource &transition, int &linger, OBSWeakSource &transition, int &linger,
bool &setPrevSceneAfterLinger, bool &setPrevSceneAfterLinger,
bool &macroMatch) bool &macroMatch)
@@ -405,7 +332,7 @@ bool SwitcherData::CheckForMatch(OBSWeakSource &scene,
match = checkVideoSwitch(scene, transition); match = checkVideoSwitch(scene, transition);
break; break;
case macro_func: case macro_func:
if (CheckMacros()) { if (checkMacros()) {
match = true; match = true;
macroMatch = true; macroMatch = true;
} }
@@ -422,20 +349,48 @@ bool SwitcherData::CheckForMatch(OBSWeakSource &scene,
return match; return match;
} }
static void ResetMacros() void switchScene(const sceneSwitchInfo &sceneSwitch, bool force)
{ {
for (auto &m : switcher->macros) { if (!sceneSwitch.scene && switcher->verbose) {
m->ResetRunCount(); blog(LOG_INFO, "nothing to switch to");
m->ResetTimers(); return;
} }
obs_source_t *source = obs_weak_source_get_source(sceneSwitch.scene);
obs_source_t *currentSource = obs_frontend_get_current_scene();
if (source && (source != currentSource || force)) {
transitionData currentTransitionData;
setNextTransition(sceneSwitch, currentSource,
currentTransitionData);
obs_frontend_set_current_scene(source);
if (switcher->transitionOverrideOverride) {
restoreTransitionOverride(source,
currentTransitionData);
}
if (switcher->verbose) {
blog(LOG_INFO, "switched scene");
}
if (switcher->networkConfig.ShouldSendSceneChange()) {
switcher->server.sendMessage(sceneSwitch);
}
}
obs_source_release(currentSource);
obs_source_release(source);
}
void switchPreviewScene(const OBSWeakSource &ws)
{
auto source = obs_weak_source_get_source(ws);
obs_frontend_set_current_preview_scene(source);
obs_source_release(source);
} }
void SwitcherData::Start() void SwitcherData::Start()
{ {
if (!(th && th->isRunning())) { if (!(th && th->isRunning())) {
ResetForNextInterval();
ResetMacros();
stop = false; stop = false;
th = new SwitcherThread(); th = new SwitcherThread();
th->start((QThread::Priority)threadPriority); th->start((QThread::Priority)threadPriority);
@@ -460,7 +415,13 @@ void SwitcherData::Start()
} }
} }
bool CloseAllInputDialogs(); void ResetMacros()
{
for (auto &m : switcher->macros) {
m->ResetRunCount();
m->ResetTimers();
}
}
void SwitcherData::Stop() void SwitcherData::Stop()
{ {
@@ -470,24 +431,12 @@ void SwitcherData::Stop()
abortMacroWait = true; abortMacroWait = true;
macroWaitCv.notify_all(); macroWaitCv.notify_all();
macroTransitionCv.notify_all(); macroTransitionCv.notify_all();
th->wait();
delete th;
th = nullptr;
// Not waiting if a dialog was closed is a workaround to avoid
// deadlocks when a variable input dialog is opened while Stop()
// is called.
//
// The QEventLoop handling the dialog would not exit until Stop()
// would return, which itself would wait for the switcher thread
// to complete, which itself is blocked by the variable input
// dialog.
//
// Must be reworked in the future, as this will not go well when
// OBS is shutting down and a dialog is still opened.
if (!CloseAllInputDialogs()) {
th->wait();
delete th;
th = nullptr;
}
writeToStatusFile("Advanced Scene Switcher stopped"); writeToStatusFile("Advanced Scene Switcher stopped");
ResetMacros();
} }
server.stop(); server.stop();
@@ -500,13 +449,13 @@ void SwitcherData::Stop()
} }
} }
void SwitcherData::SetWaitScene() void SwitcherData::setWaitScene()
{ {
waitScene = obs_frontend_get_current_scene(); waitScene = obs_frontend_get_current_scene();
obs_source_release(waitScene); obs_source_release(waitScene);
} }
bool SwitcherData::SceneChangedDuringWait() bool SwitcherData::sceneChangedDuringWait()
{ {
obs_source_t *currentSource = obs_frontend_get_current_scene(); obs_source_t *currentSource = obs_frontend_get_current_scene();
if (!currentSource) { if (!currentSource) {
@@ -519,7 +468,7 @@ bool SwitcherData::SceneChangedDuringWait()
// Relies on the fact that switcher->currentScene will only be updated on event // Relies on the fact that switcher->currentScene will only be updated on event
// OBS_FRONTEND_EVENT_SCENE_CHANGED but obs_frontend_get_current_scene() will // OBS_FRONTEND_EVENT_SCENE_CHANGED but obs_frontend_get_current_scene() will
// already return the scene to be transitioned to. // already return the scene to be transitioned to.
bool SwitcherData::AnySceneTransitionStarted() bool SwitcherData::anySceneTransitionStarted()
{ {
auto currentSceneSrouce = obs_frontend_get_current_scene(); auto currentSceneSrouce = obs_frontend_get_current_scene();
auto currentScene = obs_source_get_weak_source(currentSceneSrouce); auto currentScene = obs_source_get_weak_source(currentSceneSrouce);
@@ -540,13 +489,13 @@ extern "C" void FreeSceneSwitcher()
switcher = nullptr; switcher = nullptr;
} }
static void handleSceneChange() void handleSceneChange()
{ {
switcher->lastSceneChangeTime = switcher->lastSceneChangeTime =
std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::now();
// Stop waiting if scene was changed // Stop waiting if scene was changed
if (switcher->SceneChangedDuringWait()) { if (switcher->sceneChangedDuringWait()) {
switcher->cv.notify_one(); switcher->cv.notify_one();
} }
@@ -574,33 +523,31 @@ static void handleSceneChange()
} }
} }
static void setLiveTime() void setLiveTime()
{ {
switcher->liveTime = QDateTime::currentDateTime(); switcher->liveTime = QDateTime::currentDateTime();
} }
static void resetLiveTime() void resetLiveTime()
{ {
switcher->liveTime = QDateTime(); switcher->liveTime = QDateTime();
} }
static void checkAutoStartRecording() void checkAutoStartRecording()
{ {
if (switcher->autoStartEvent == SwitcherData::AutoStart::RECORDING || if (switcher->autoStartEvent == AutoStartEvent::RECORDING ||
switcher->autoStartEvent == switcher->autoStartEvent == AutoStartEvent::RECORINDG_OR_STREAMING)
SwitcherData::AutoStart::RECORINDG_OR_STREAMING)
switcher->Start(); switcher->Start();
} }
static void checkAutoStartStreaming() void checkAutoStartStreaming()
{ {
if (switcher->autoStartEvent == SwitcherData::AutoStart::STREAMING || if (switcher->autoStartEvent == AutoStartEvent::STREAMING ||
switcher->autoStartEvent == switcher->autoStartEvent == AutoStartEvent::RECORINDG_OR_STREAMING)
SwitcherData::AutoStart::RECORINDG_OR_STREAMING)
switcher->Start(); switcher->Start();
} }
static void handlePeviewSceneChange() void handlePeviewSceneChange()
{ {
if (switcher->networkConfig.ShouldSendPrviewSceneChange()) { if (switcher->networkConfig.ShouldSendPrviewSceneChange()) {
auto source = obs_frontend_get_current_preview_scene(); auto source = obs_frontend_get_current_preview_scene();
@@ -611,51 +558,43 @@ static void handlePeviewSceneChange()
} }
} }
static void setReplayBufferSaved() void setReplayBufferSaved()
{ {
switcher->replayBufferSaved = true; switcher->replayBufferSaved = true;
} }
static void setTranstionEnd() void setTranstionEnd()
{ {
switcher->lastTransitionEndTime = switcher->lastTransitionEndTime =
std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::now();
switcher->macroTransitionCv.notify_all(); switcher->macroTransitionCv.notify_all();
} }
static void setStreamStarting() void setStreamStarting()
{ {
switcher->lastStreamStartingTime = switcher->lastStreamStartingTime =
std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::now();
} }
static void setStreamStopping() void setStreamStopping()
{ {
switcher->lastStreamStoppingTime = switcher->lastStreamStoppingTime =
std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::now();
} }
static void handleShutdown() void handleExit()
{ {
if (!switcher) {
return;
}
switcher->obsIsShuttingDown = true; switcher->obsIsShuttingDown = true;
if (switcher->shutdownConditionCount) { if (switcher && switcher->obsIsShuttingDown &&
switcher->shutdownConditionCount) {
switcher->Stop(); switcher->Stop();
switcher->CheckMacros(); switcher->checkMacros();
switcher->RunMacros(); switcher->runMacros();
// Unfortunately this will not work as OBS will now allow saving
// the scene collection data at this point, So any OBS specific
// changes done during shutdown will be lost
//
// TODO: Look for a way to possibly resolve this
obs_frontend_save();
} }
FreeSceneSwitcher();
} }
static void handleSceneCollectionChanging() void handleSceneCollectionChanging()
{ {
if (switcher->settingsWindowOpened) { if (switcher->settingsWindowOpened) {
AdvSceneSwitcher::window->close(); AdvSceneSwitcher::window->close();
@@ -676,12 +615,8 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
} }
switch (event) { switch (event) {
case OBS_FRONTEND_EVENT_SCRIPTING_SHUTDOWN: case OBS_FRONTEND_EVENT_EXIT:
// Note: We are intentionally not listening for handleExit();
// OBS_FRONTEND_EVENT_EXIT here as at that point all scene
// collection data will already have been cleared and thus all
// macros will have already been cleared
handleShutdown();
break; break;
case OBS_FRONTEND_EVENT_SCENE_CHANGED: case OBS_FRONTEND_EVENT_SCENE_CHANGED:
handleSceneChange(); handleSceneChange();
@@ -719,16 +654,13 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING: case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING:
handleSceneCollectionChanging(); handleSceneCollectionChanging();
break; break;
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP:
SaveSceneSwitcher(nullptr, false, nullptr);
break;
#endif #endif
default: default:
break; break;
} }
} }
static void LoadPlugins() void LoadPlugins()
{ {
QFileInfo libPath( QFileInfo libPath(
QString(obs_get_module_binary_path(obs_current_module()))); QString(obs_get_module_binary_path(obs_current_module())));
@@ -752,7 +684,6 @@ static 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;
} }
} }
} }
@@ -772,21 +703,18 @@ void OpenSettingsWindow()
} }
} }
void SetupConnectionManager(); extern "C" void InitSceneSwitcher(obs_module_t *m, translateFunc t)
void SetupWebsocketHelpers();
extern "C" void InitSceneSwitcher(obs_module_t *module, translateFunc translate)
{ {
blog(LOG_INFO, "version: %s", g_GIT_TAG); blog(LOG_INFO, "version: %s", g_GIT_TAG);
blog(LOG_INFO, "version: %s", g_GIT_SHA1); blog(LOG_INFO, "version: %s", g_GIT_SHA1);
switcher = new SwitcherData(module, translate); switcher = new SwitcherData;
switcher->modulePtr = m;
switcher->translate = t;
PlatformInit(); PlatformInit();
LoadPlugins(); LoadPlugins();
SetupDock(); SetupDock();
SetupConnectionManager();
SetupWebsocketHelpers();
obs_frontend_add_save_callback(SaveSceneSwitcher, nullptr); obs_frontend_add_save_callback(SaveSceneSwitcher, nullptr);
obs_frontend_add_event_callback(OBSEvent, switcher); obs_frontend_add_event_callback(OBSEvent, switcher);
@@ -795,5 +723,3 @@ extern "C" void InitSceneSwitcher(obs_module_t *module, translateFunc translate)
obs_module_text("AdvSceneSwitcher.pluginName")); obs_module_text("AdvSceneSwitcher.pluginName"));
action->connect(action, &QAction::triggered, OpenSettingsWindow); action->connect(action, &QAction::triggered, OpenSettingsWindow);
} }
} // namespace advss

View File

@@ -1,18 +1,19 @@
#pragma once #pragma once
#include "macro-segment-list.hpp" #include "switcher-data-structs.hpp"
#include "log-helper.hpp" #include "platform-funcs.hpp"
#include <macro-segment-list.hpp>
#include <ui_advanced-scene-switcher.h> #include <ui_advanced-scene-switcher.h>
#define blog(level, msg, ...) blog(level, "[adv-ss] " msg, ##__VA_ARGS__)
#define vblog(level, msg, ...) \
if (switcher->verbose) { \
blog(level, msg, ##__VA_ARGS__); \
}
class QCloseEvent; class QCloseEvent;
namespace advss {
class MacroActionEdit; class MacroActionEdit;
class MacroConditionEdit; class MacroConditionEdit;
class Duration;
class SequenceWidget;
struct SceneGroup;
/******************************************************************************* /*******************************************************************************
* Advanced Scene Switcher window * Advanced Scene Switcher window
@@ -32,139 +33,134 @@ public:
void reject() override; void reject() override;
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
void LoadUI(); void SetShowFrames();
void SetHideFrames();
void clearFrames(QListWidget *list);
void SetTabOrder(); int IgnoreWindowsFindByData(const QString &window);
void SetCurrentTab(); int IgnoreIdleWindowsFindByData(const QString &window);
void RestoreWindowGeo();
void CheckFirstTimeSetup();
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
/* --- Begin of general tab section --- */
public:
void SetupGeneralTab();
void UpdateNonMatchingScene(const QString &name); void UpdateNonMatchingScene(const QString &name);
void SetDeprecationWarnings(); void OpenSequenceExtendEdit(SequenceWidget *sw);
void SetEditSceneGroup(SceneGroup &sg);
bool addNewMacro(std::shared_ptr<Macro> &res, std::string &name,
std::string format = "");
void RemoveMacro(std::shared_ptr<Macro> &);
void RenameMacro(std::shared_ptr<Macro> &, const QString &name);
std::shared_ptr<Macro> getSelectedMacro();
std::vector<std::shared_ptr<Macro>> getSelectedMacros();
void SetEditMacro(Macro &m);
void SetMacroEditAreaDisabled(bool);
void HighlightAction(int idx, QColor color = QColor(Qt::green));
void HighlightCondition(int idx, QColor color = QColor(Qt::green));
void PopulateMacroActions(Macro &m, uint32_t afterIdx = 0);
void PopulateMacroConditions(Macro &m, uint32_t afterIdx = 0);
void SetActionData(Macro &m);
void SetConditionData(Macro &m);
void SwapActions(Macro *m, int pos1, int pos2);
void SwapConditions(Macro *m, int pos1, int pos2);
void loadUI();
void setupGeneralTab();
void setupTitleTab();
void setupExecutableTab();
void setupRegionTab();
void setupPauseTab();
void setupSequenceTab();
void setupTransitionsTab();
void setupIdleTab();
void setupRandomTab();
void setupMediaTab();
void setupFileTab();
void setupTimeTab();
void setupAudioTab();
void setupSceneGroupTab();
void setupTriggerTab();
void setupVideoTab();
void setupNetworkTab();
void setupMacroTab();
void setDeprecationWarnings();
void setTabOrder();
void setCurrentTab();
void restoreWindowGeo();
void checkFirstTimeSetup();
signals:
void MacroAdded(const QString &name);
void MacroRemoved(const QString &name);
void MacroRenamed(const QString &oldName, const QString &newName);
void MacroSegmentOrderChanged();
void HighlightMacrosChanged(bool value);
void HighlightActionsChanged(bool value);
void HighlightConditionsChanged(bool value);
void SceneGroupAdded(const QString &name);
void SceneGroupRemoved(const QString &name);
void SceneGroupRenamed(const QString &oldName, const QString newName);
void ConnectionAdded(const QString &);
void ConnectionRenamed(const QString &oldName, const QString &newName);
void ConnectionRemoved(const QString &);
void VariableAdded(const QString &);
void VariableRenamed(const QString &oldName, const QString &newName);
void VariableRemoved(const QString &);
public slots: public slots:
void on_windowUp_clicked();
void on_windowDown_clicked();
void on_windowAdd_clicked();
void on_windowRemove_clicked();
void on_noMatchDontSwitch_clicked(); void on_noMatchDontSwitch_clicked();
void on_noMatchSwitch_clicked(); void on_noMatchSwitch_clicked();
void on_noMatchRandomSwitch_clicked(); void on_noMatchRandomSwitch_clicked();
void NoMatchDelayDurationChanged(const Duration &); void NoMatchDelayDurationChanged(double);
void CooldownDurationChanged(const Duration &); void NoMatchDelayUnitChanged(DurationUnit);
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);
void on_checkInterval_valueChanged(int value); void on_checkInterval_valueChanged(int value);
void on_tabMoved(int from, int to); void on_tabMoved(int from, int to);
void on_tabWidget_currentChanged(int index); void on_tabWidget_currentChanged(int index);
void on_exportSettings_clicked();
void on_importSettings_clicked();
void on_verboseLogging_stateChanged(int state);
void on_saveWindowGeo_stateChanged(int state);
void on_showTrayNotifications_stateChanged(int state);
void on_uiHintsDisable_stateChanged(int state);
void on_disableComboBoxFilter_stateChanged(int state);
void on_warnPluginLoadFailure_stateChanged(int state);
void on_hideLegacyTabs_stateChanged(int state);
void on_priorityUp_clicked();
void on_priorityDown_clicked();
void on_threadPriority_currentTextChanged(const QString &text);
/* --- End of legacy tab section --- */
/* --- Begin of macro tab section --- */
public:
void SetupMacroTab();
bool AddNewMacro(std::shared_ptr<Macro> &res, std::string &name,
std::string format = "");
void RemoveMacro(std::shared_ptr<Macro> &);
void RenameMacro(std::shared_ptr<Macro> &, const QString &name);
std::shared_ptr<Macro> GetSelectedMacro();
std::vector<std::shared_ptr<Macro>> GetSelectedMacros();
void SetEditMacro(Macro &m);
void SetMacroEditAreaDisabled(bool);
void HighlightAction(int idx, QColor color = QColor(Qt::green));
void HighlightElseAction(int idx, QColor color = QColor(Qt::green));
void HighlightCondition(int idx, QColor color = QColor(Qt::green));
void PopulateMacroActions(Macro &m, uint32_t afterIdx = 0);
void PopulateMacroElseActions(Macro &m, uint32_t afterIdx = 0);
void PopulateMacroConditions(Macro &m, uint32_t afterIdx = 0);
void SetActionData(Macro &m);
void SetElseActionData(Macro &m);
void SetConditionData(Macro &m);
void SwapActions(Macro *m, int pos1, int pos2);
void SwapConditions(Macro *m, int pos1, int pos2);
public slots:
void on_macroAdd_clicked(); void on_macroAdd_clicked();
void on_macroRemove_clicked(); void on_macroRemove_clicked();
void on_macroUp_clicked(); void on_macroUp_clicked();
void on_macroDown_clicked(); void on_macroDown_clicked();
void on_macroName_editingFinished(); void on_macroName_editingFinished();
void on_runMacro_clicked();
void on_runMacroInParallel_stateChanged(int value); void on_runMacroInParallel_stateChanged(int value);
void on_runMacroOnChange_stateChanged(int value); void on_runMacroOnChange_stateChanged(int value);
void on_conditionAdd_clicked(); void on_conditionAdd_clicked();
void on_conditionRemove_clicked(); void on_conditionRemove_clicked();
void on_conditionTop_clicked();
void on_conditionUp_clicked(); void on_conditionUp_clicked();
void on_conditionDown_clicked(); void on_conditionDown_clicked();
void on_conditionBottom_clicked();
void on_actionAdd_clicked(); void on_actionAdd_clicked();
void on_actionRemove_clicked(); void on_actionRemove_clicked();
void on_actionTop_clicked();
void on_actionUp_clicked(); void on_actionUp_clicked();
void on_actionDown_clicked(); void on_actionDown_clicked();
void on_actionBottom_clicked(); void MacroSelectionChanged(const QItemSelection &,
void on_toggleElseActions_clicked(); const QItemSelection &);
void on_elseActionAdd_clicked();
void on_elseActionRemove_clicked();
void on_elseActionTop_clicked();
void on_elseActionUp_clicked();
void on_elseActionDown_clicked();
void on_elseActionBottom_clicked();
void MacroSelectionAboutToChange();
void MacroSelectionChanged();
void UpMacroSegementHotkey(); void UpMacroSegementHotkey();
void DownMacroSegementHotkey(); void DownMacroSegementHotkey();
void DeleteMacroSegementHotkey(); void DeleteMacroSegementHotkey();
void ShowMacroContextMenu(const QPoint &); void ShowMacroContextMenu(const QPoint &);
void ShowMacroActionsContextMenu(const QPoint &); void ShowMacroActionsContextMenu(const QPoint &);
void ShowMacroElseActionsContextMenu(const QPoint &);
void ShowMacroConditionsContextMenu(const QPoint &); void ShowMacroConditionsContextMenu(const QPoint &);
void CopyMacro(); void CopyMacro();
void RenameCurrentMacro(); void RenameCurrentMacro();
void ExportMacros();
void ImportMacros();
void ExpandAllActions(); void ExpandAllActions();
void ExpandAllElseActions();
void ExpandAllConditions(); void ExpandAllConditions();
void CollapseAllActions(); void CollapseAllActions();
void CollapseAllElseActions();
void CollapseAllConditions(); void CollapseAllConditions();
void MinimizeActions(); void MinimizeActions();
void MaximizeActions();
void MinimizeElseActions();
void MaximizeElseActions();
void MinimizeConditions(); void MinimizeConditions();
void MaximizeConditions();
void SetElseActionsStateToHidden();
void SetElseActionsStateToVisible();
void MacroActionSelectionChanged(int idx); void MacroActionSelectionChanged(int idx);
void MacroActionReorder(int to, int target); void MacroActionReorder(int to, int target);
void AddMacroAction(int idx); void AddMacroAction(int idx);
void RemoveMacroAction(int idx); void RemoveMacroAction(int idx);
void MoveMacroActionUp(int idx); void MoveMacroActionUp(int idx);
void MoveMacroActionDown(int idx); void MoveMacroActionDown(int idx);
void MacroElseActionSelectionChanged(int idx);
void MacroElseActionReorder(int to, int target);
void AddMacroElseAction(int idx);
void RemoveMacroElseAction(int idx);
void SwapElseActions(Macro *m, int pos1, int pos2);
void MoveMacroElseActionUp(int idx);
void MoveMacroElseActionDown(int idx);
void MacroConditionSelectionChanged(int idx); void MacroConditionSelectionChanged(int idx);
void MacroConditionReorder(int to, int target); void MacroConditionReorder(int to, int target);
void AddMacroCondition(int idx); void AddMacroCondition(int idx);
@@ -179,84 +175,22 @@ public slots:
void HighlightOnChange(); void HighlightOnChange();
void on_macroProperties_clicked(); void on_macroProperties_clicked();
signals:
void MacroAdded(const QString &name);
void MacroRemoved(const QString &name);
void MacroRenamed(const QString &oldName, const QString &newName);
void MacroSegmentOrderChanged();
void SegmentTempVarsChanged();
void HighlightMacrosChanged(bool value);
void HighlightActionsChanged(bool value);
void HighlightElseActionsChanged(bool value);
void HighlightConditionsChanged(bool value);
void ConnectionAdded(const QString &);
void ConnectionRenamed(const QString &oldName, const QString &newName);
void ConnectionRemoved(const QString &);
void VariableAdded(const QString &);
void VariableRenamed(const QString &oldName, const QString &newName);
void VariableRemoved(const QString &);
private:
enum class MacroSection { CONDITIONS, ACTIONS, ELSE_ACTIONS };
void SetupMacroSegmentSelection(MacroSection type, int idx);
bool ResolveMacroImportNameConflict(std::shared_ptr<Macro> &);
bool MacroTabIsInFocus();
MacroSection lastInteracted = MacroSection::CONDITIONS;
int currentConditionIdx = -1;
int currentActionIdx = -1;
int currentElseActionIdx = -1;
/* --- End of macro tab section --- */
/* --- Begin of legacy tab section --- */
public:
void ClearFrames(QListWidget *list);
int IgnoreWindowsFindByData(const QString &window);
int IgnoreIdleWindowsFindByData(const QString &window);
void OpenSequenceExtendEdit(SequenceWidget *sw);
// Window tab
public:
void SetupTitleTab();
public slots:
void on_windowUp_clicked();
void on_windowDown_clicked();
void on_windowAdd_clicked();
void on_windowRemove_clicked();
void on_ignoreWindows_currentRowChanged(int idx);
void on_ignoreWindowsAdd_clicked();
void on_ignoreWindowsRemove_clicked();
// Screen region tab
public:
void SetupRegionTab();
public slots:
void SetShowFrames();
void SetHideFrames();
void on_screenRegionSwitches_currentRowChanged(int idx); void on_screenRegionSwitches_currentRowChanged(int idx);
void on_showFrame_clicked(); void on_showFrame_clicked();
void on_screenRegionAdd_clicked(); void on_screenRegionAdd_clicked();
void on_screenRegionRemove_clicked(); void on_screenRegionRemove_clicked();
void on_screenRegionUp_clicked(); void on_screenRegionUp_clicked();
void on_screenRegionDown_clicked(); void on_screenRegionDown_clicked();
void updateScreenRegionCursorPos();
// Pause tab
public:
void SetupPauseTab();
public slots:
void on_pauseUp_clicked(); void on_pauseUp_clicked();
void on_pauseDown_clicked(); void on_pauseDown_clicked();
void on_pauseAdd_clicked(); void on_pauseAdd_clicked();
void on_pauseRemove_clicked(); void on_pauseRemove_clicked();
// Sequence tab void on_ignoreWindows_currentRowChanged(int idx);
public: void on_ignoreWindowsAdd_clicked();
void SetupSequenceTab(); void on_ignoreWindowsRemove_clicked();
public slots:
void on_sceneSequenceAdd_clicked(); void on_sceneSequenceAdd_clicked();
void on_sceneSequenceRemove_clicked(); void on_sceneSequenceRemove_clicked();
void on_sceneSequenceUp_clicked(); void on_sceneSequenceUp_clicked();
@@ -266,10 +200,15 @@ public slots:
void on_sequenceEdit_clicked(); void on_sequenceEdit_clicked();
void on_sceneSequenceSwitches_itemDoubleClicked(QListWidgetItem *item); void on_sceneSequenceSwitches_itemDoubleClicked(QListWidgetItem *item);
// Transition tab void on_verboseLogging_stateChanged(int state);
public: void on_saveWindowGeo_stateChanged(int state);
void SetupTransitionsTab(); void on_showTrayNotifications_stateChanged(int state);
public slots: void on_uiHintsDisable_stateChanged(int state);
void on_hideLegacyTabs_stateChanged(int state);
void on_exportSettings_clicked();
void on_importSettings_clicked();
void on_transitionsAdd_clicked(); void on_transitionsAdd_clicked();
void on_transitionsRemove_clicked(); void on_transitionsRemove_clicked();
void on_transitionsUp_clicked(); void on_transitionsUp_clicked();
@@ -280,95 +219,60 @@ public slots:
void on_defaultTransitionsDown_clicked(); void on_defaultTransitionsDown_clicked();
void on_transitionOverridecheckBox_stateChanged(int state); void on_transitionOverridecheckBox_stateChanged(int state);
void on_adjustActiveTransitionType_stateChanged(int state); void on_adjustActiveTransitionType_stateChanged(int state);
void DefTransitionDelayValueChanged(int value); void defTransitionDelayValueChanged(int value);
// Executable tab
public:
void SetupExecutableTab();
public slots:
void on_executableUp_clicked();
void on_executableDown_clicked();
void on_executableAdd_clicked();
void on_executableRemove_clicked();
// Idle tab
public:
void SetupIdleTab();
public slots:
void on_idleCheckBox_stateChanged(int state);
void on_ignoreIdleWindows_currentRowChanged(int idx);
void on_ignoreIdleAdd_clicked();
void on_ignoreIdleRemove_clicked();
// Random tab
public:
void SetupRandomTab();
public slots:
void on_randomAdd_clicked();
void on_randomRemove_clicked();
// File tab
public:
void SetupFileTab();
public slots:
void on_fileAdd_clicked();
void on_fileRemove_clicked();
void on_fileSwitches_currentRowChanged(int idx);
void on_fileUp_clicked();
void on_fileDown_clicked();
void on_browseButton_clicked(); void on_browseButton_clicked();
void on_readFileCheckBox_stateChanged(int state); void on_readFileCheckBox_stateChanged(int state);
void on_readPathLineEdit_textChanged(const QString &text); void on_readPathLineEdit_textChanged(const QString &text);
void on_writePathLineEdit_textChanged(const QString &text); void on_writePathLineEdit_textChanged(const QString &text);
void on_browseButton_2_clicked(); void on_browseButton_2_clicked();
// Media tab void on_executableUp_clicked();
public: void on_executableDown_clicked();
void SetupMediaTab(); void on_executableAdd_clicked();
public slots: void on_executableRemove_clicked();
void on_idleCheckBox_stateChanged(int state);
void on_ignoreIdleWindows_currentRowChanged(int idx);
void on_ignoreIdleAdd_clicked();
void on_ignoreIdleRemove_clicked();
void on_randomAdd_clicked();
void on_randomRemove_clicked();
void on_fileAdd_clicked();
void on_fileRemove_clicked();
void on_fileSwitches_currentRowChanged(int idx);
void on_fileUp_clicked();
void on_fileDown_clicked();
void on_mediaAdd_clicked(); void on_mediaAdd_clicked();
void on_mediaRemove_clicked(); void on_mediaRemove_clicked();
void on_mediaUp_clicked(); void on_mediaUp_clicked();
void on_mediaDown_clicked(); void on_mediaDown_clicked();
// Time tab
public:
void SetupTimeTab();
public slots:
void on_timeAdd_clicked(); void on_timeAdd_clicked();
void on_timeRemove_clicked(); void on_timeRemove_clicked();
void on_timeUp_clicked(); void on_timeUp_clicked();
void on_timeDown_clicked(); void on_timeDown_clicked();
// Audio tab
public:
void SetupAudioTab();
public slots:
void on_audioAdd_clicked(); void on_audioAdd_clicked();
void on_audioRemove_clicked(); void on_audioRemove_clicked();
void on_audioUp_clicked(); void on_audioUp_clicked();
void on_audioDown_clicked(); void on_audioDown_clicked();
void on_audioFallback_toggled(bool on); void on_audioFallback_toggled(bool on);
// Video tab
public:
void SetupVideoTab();
public slots:
void on_videoAdd_clicked(); void on_videoAdd_clicked();
void on_videoRemove_clicked(); void on_videoRemove_clicked();
void on_videoUp_clicked(); void on_videoUp_clicked();
void on_videoDown_clicked(); void on_videoDown_clicked();
void on_getScreenshot_clicked(); void on_getScreenshot_clicked();
// Scene group tab
public:
void SetupNetworkTab();
public slots:
void on_serverSettings_toggled(bool on); void on_serverSettings_toggled(bool on);
void on_serverPort_valueChanged(int value); void on_serverPort_valueChanged(int value);
void on_lockToIPv4_stateChanged(int state); void on_lockToIPv4_stateChanged(int state);
void on_serverRestart_clicked(); void on_serverRestart_clicked();
void UpdateServerStatus(); void updateServerStatus();
void on_clientSettings_toggled(bool on); void on_clientSettings_toggled(bool on);
void on_clientHostname_textChanged(const QString &text); void on_clientHostname_textChanged(const QString &text);
void on_clientPort_valueChanged(int value); void on_clientPort_valueChanged(int value);
@@ -376,41 +280,67 @@ public slots:
void on_restrictSend_stateChanged(int state); void on_restrictSend_stateChanged(int state);
void on_sendPreview_stateChanged(int state); void on_sendPreview_stateChanged(int state);
void on_clientReconnect_clicked(); void on_clientReconnect_clicked();
void UpdateClientStatus(); void updateClientStatus();
// Scene group tab
public:
void SetupSceneGroupTab();
void SetEditSceneGroup(SceneGroup &sg);
public slots:
void on_sceneGroupAdd_clicked(); void on_sceneGroupAdd_clicked();
void on_sceneGroupRemove_clicked(); void on_sceneGroupRemove_clicked();
void on_sceneGroupUp_clicked(); void on_sceneGroupUp_clicked();
void on_sceneGroupDown_clicked(); void on_sceneGroupDown_clicked();
void on_sceneGroupName_editingFinished(); void on_sceneGroupName_editingFinished();
void on_sceneGroups_currentRowChanged(int idx); void on_sceneGroups_currentRowChanged(int idx);
void on_sceneGroupSceneAdd_clicked(); void on_sceneGroupSceneAdd_clicked();
void on_sceneGroupSceneRemove_clicked(); void on_sceneGroupSceneRemove_clicked();
void on_sceneGroupSceneUp_clicked(); void on_sceneGroupSceneUp_clicked();
void on_sceneGroupSceneDown_clicked(); void on_sceneGroupSceneDown_clicked();
signals:
void SceneGroupAdded(const QString &name);
void SceneGroupRemoved(const QString &name);
void SceneGroupRenamed(const QString &oldName, const QString newName);
// Trigger tab
public:
void SetupTriggerTab();
public slots:
void on_triggerAdd_clicked(); void on_triggerAdd_clicked();
void on_triggerRemove_clicked(); void on_triggerRemove_clicked();
void on_triggerUp_clicked(); void on_triggerUp_clicked();
void on_triggerDown_clicked(); void on_triggerDown_clicked();
/* --- End of legacy tab section --- */ void on_priorityUp_clicked();
void on_priorityDown_clicked();
void on_threadPriority_currentTextChanged(const QString &text);
void updateScreenRegionCursorPos();
private:
bool MacroTabIsInFocus();
MacroSegmentList *conditionsList = nullptr;
MacroSegmentList *actionsList = nullptr;
enum class MacroSection {
CONDITIONS,
ACTIONS,
};
MacroSection lastInteracted = MacroSection::CONDITIONS;
int currentConditionIdx = -1;
int currentActionIdx = -1;
}; };
void OpenSettingsWindow(); void OpenSettingsWindow();
} // namespace advss /******************************************************************************
* Sceneswitch helper
******************************************************************************/
void setNextTransition(const sceneSwitchInfo &ssi, obs_source_t *currentSource,
transitionData &td);
void overwriteTransitionOverride(const sceneSwitchInfo &ssi,
transitionData &td);
void restoreTransitionOverride(obs_source_t *scene, const transitionData &td);
void switchScene(const sceneSwitchInfo &ssi, bool force = false);
void switchPreviewScene(const OBSWeakSource &ws);
/******************************************************************************
* Settings helper
******************************************************************************/
void AskForBackup(obs_data_t *obj);
/******************************************************************************
* Main SwitcherData
******************************************************************************/
struct SwitcherData;
extern SwitcherData *switcher;
SwitcherData *GetSwitcher();

View File

@@ -1,14 +1,11 @@
#include "advanced-scene-switcher.hpp" #include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "status-control.hpp" #include "status-control.hpp"
#include "file-selection.hpp" #include "file-selection.hpp"
#include "filter-combo-box.hpp"
#include "utility.hpp" #include "utility.hpp"
#include "version.h" #include "version.h"
#include <QFileDialog> #include <QFileDialog>
#include <QStandardPaths>
namespace advss {
void AdvSceneSwitcher::reject() void AdvSceneSwitcher::reject()
{ {
@@ -33,7 +30,7 @@ void AdvSceneSwitcher::on_noMatchDontSwitch_clicked()
} }
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switcher->switchIfNotMatching = NoMatchBehavior::NO_SWITCH; switcher->switchIfNotMatching = NO_SWITCH;
ui->noMatchSwitchScene->setEnabled(false); ui->noMatchSwitchScene->setEnabled(false);
ui->randomDisabledWarning->setVisible(true); ui->randomDisabledWarning->setVisible(true);
} }
@@ -45,7 +42,7 @@ void AdvSceneSwitcher::on_noMatchSwitch_clicked()
} }
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switcher->switchIfNotMatching = NoMatchBehavior::SWITCH; switcher->switchIfNotMatching = SWITCH;
ui->noMatchSwitchScene->setEnabled(true); ui->noMatchSwitchScene->setEnabled(true);
UpdateNonMatchingScene(ui->noMatchSwitchScene->currentText()); UpdateNonMatchingScene(ui->noMatchSwitchScene->currentText());
ui->randomDisabledWarning->setVisible(true); ui->randomDisabledWarning->setVisible(true);
@@ -58,29 +55,49 @@ void AdvSceneSwitcher::on_noMatchRandomSwitch_clicked()
} }
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switcher->switchIfNotMatching = NoMatchBehavior::RANDOM_SWITCH; switcher->switchIfNotMatching = RANDOM_SWITCH;
ui->noMatchSwitchScene->setEnabled(false); ui->noMatchSwitchScene->setEnabled(false);
ui->randomDisabledWarning->setVisible(false); ui->randomDisabledWarning->setVisible(false);
} }
void AdvSceneSwitcher::NoMatchDelayDurationChanged(const Duration &dur) void AdvSceneSwitcher::NoMatchDelayDurationChanged(double sec)
{ {
if (loading) { if (loading) {
return; return;
} }
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switcher->noMatchDelay = dur; switcher->noMatchDelay.seconds = sec;
} }
void AdvSceneSwitcher::CooldownDurationChanged(const Duration &dur) void AdvSceneSwitcher::NoMatchDelayUnitChanged(DurationUnit unit)
{ {
if (loading) { if (loading) {
return; return;
} }
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switcher->cooldown = dur; switcher->noMatchDelay.displayUnit = unit;
}
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)
@@ -90,8 +107,7 @@ void AdvSceneSwitcher::on_startupBehavior_currentIndexChanged(int index)
} }
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switcher->startupBehavior = switcher->startupBehavior = (StartupBehavior)index;
static_cast<SwitcherData::StartupBehavior>(index);
} }
void AdvSceneSwitcher::on_autoStartEvent_currentIndexChanged(int index) void AdvSceneSwitcher::on_autoStartEvent_currentIndexChanged(int index)
@@ -101,7 +117,7 @@ void AdvSceneSwitcher::on_autoStartEvent_currentIndexChanged(int index)
} }
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switcher->autoStartEvent = static_cast<SwitcherData::AutoStart>(index); switcher->autoStartEvent = static_cast<AutoStartEvent>(index);
} }
void AdvSceneSwitcher::on_noMatchSwitchScene_currentTextChanged( void AdvSceneSwitcher::on_noMatchSwitchScene_currentTextChanged(
@@ -132,9 +148,10 @@ void AdvSceneSwitcher::closeEvent(QCloseEvent *)
} }
switcher->windowPos = this->pos(); switcher->windowPos = this->pos();
switcher->windowSize = this->size(); switcher->windowSize = this->size();
switcher->macroActionConditionSplitterPosition =
ui->macroActionConditionSplitter->sizes();
switcher->macroListMacroEditSplitterPosition = switcher->macroListMacroEditSplitterPosition =
ui->macroListMacroEditSplitter->sizes(); ui->macroListMacroEditSplitter->sizes();
MacroSelectionAboutToChange(); // Trigger saving of splitter states
obs_frontend_save(); obs_frontend_save();
} }
@@ -175,26 +192,7 @@ void AdvSceneSwitcher::on_uiHintsDisable_stateChanged(int state)
switcher->disableHints = state; switcher->disableHints = state;
} }
void AdvSceneSwitcher::on_disableComboBoxFilter_stateChanged(int state) bool isLegacyTab(const QString &name)
{
if (loading) {
return;
}
switcher->disableFilterComboboxFilter = state;
FilterComboBox::SetFilterBehaviourEnabled(!state);
}
void AdvSceneSwitcher::on_warnPluginLoadFailure_stateChanged(int state)
{
if (loading) {
return;
}
switcher->warnPluginLoadFailure = state;
}
static bool isLegacyTab(const QString &name)
{ {
return name == obs_module_text( return name == obs_module_text(
"AdvSceneSwitcher.sceneGroupTab.title") || "AdvSceneSwitcher.sceneGroupTab.title") ||
@@ -239,7 +237,7 @@ void AdvSceneSwitcher::on_hideLegacyTabs_stateChanged(int state)
} }
} }
void AdvSceneSwitcher::SetDeprecationWarnings() void AdvSceneSwitcher::setDeprecationWarnings()
{ {
QString toolTip = QString toolTip =
switcher->disableHints switcher->disableHints
@@ -253,13 +251,70 @@ void AdvSceneSwitcher::SetDeprecationWarnings()
} }
} }
QString getDefaultSaveLocation()
{
QString desktopPath = QStandardPaths::writableLocation(
QStandardPaths::DesktopLocation);
auto scName = obs_frontend_get_current_scene_collection();
QString sceneCollectionName(scName);
bfree(scName);
auto timestamp = QDateTime::currentDateTime();
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");
}
void AskForBackup(obs_data_t *obj)
{
bool backupSettings = DisplayMessage(
obs_module_text("AdvSceneSwitcher.askBackup"), true);
if (!backupSettings) {
return;
}
QString path = QFileDialog::getSaveFileName(
nullptr,
obs_module_text(
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle"),
getDefaultSaveLocation(),
obs_module_text(
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType"));
if (path.isEmpty()) {
return;
}
QFile file(path);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return;
}
obs_data_save_json(obj, file.fileName().toUtf8().constData());
}
void AdvSceneSwitcher::on_exportSettings_clicked() void AdvSceneSwitcher::on_exportSettings_clicked()
{ {
QString directory = QFileDialog::getSaveFileName( QString directory = QFileDialog::getSaveFileName(
this, this,
tr(obs_module_text( tr(obs_module_text(
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle")), "AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle")),
GetDefaultSettingsSaveLocation(), getDefaultSaveLocation(),
tr(obs_module_text( tr(obs_module_text(
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType"))); "AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType")));
if (directory.isEmpty()) { if (directory.isEmpty()) {
@@ -272,7 +327,7 @@ void AdvSceneSwitcher::on_exportSettings_clicked()
} }
obs_data_t *obj = obs_data_create(); obs_data_t *obj = obs_data_create();
switcher->SaveSettings(obj); switcher->saveSettings(obj);
obs_data_save_json(obj, file.fileName().toUtf8().constData()); obs_data_save_json(obj, file.fileName().toUtf8().constData());
obs_data_release(obj); obs_data_release(obj);
} }
@@ -312,7 +367,7 @@ void AdvSceneSwitcher::on_importSettings_clicked()
} }
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switcher->LoadSettings(obj); switcher->loadSettings(obj);
obs_data_release(obj); obs_data_release(obj);
switcher->lastImportPath = path.toStdString(); switcher->lastImportPath = path.toStdString();
@@ -328,7 +383,7 @@ void AdvSceneSwitcher::on_importSettings_clicked()
} }
} }
static int findTabIndex(QTabWidget *tabWidget, int pos) int findTabIndex(QTabWidget *tabWidget, int pos)
{ {
int at = -1; int at = -1;
@@ -402,10 +457,10 @@ static int findTabIndex(QTabWidget *tabWidget, int pos)
return at; return at;
} }
void AdvSceneSwitcher::SetTabOrder() void AdvSceneSwitcher::setTabOrder()
{ {
if (!switcher->TabOrderValid()) { if (!switcher->tabOrderValid()) {
switcher->ResetTabOrder(); switcher->resetTabOrder();
} }
QTabBar *bar = ui->tabWidget->tabBar(); QTabBar *bar = ui->tabWidget->tabBar();
@@ -420,22 +475,22 @@ void AdvSceneSwitcher::SetTabOrder()
connect(bar, &QTabBar::tabMoved, this, &AdvSceneSwitcher::on_tabMoved); connect(bar, &QTabBar::tabMoved, this, &AdvSceneSwitcher::on_tabMoved);
} }
void AdvSceneSwitcher::SetCurrentTab() void AdvSceneSwitcher::setCurrentTab()
{ {
if (switcher->lastOpenedTab >= 0) { if (switcher->lastOpenedTab >= 0) {
ui->tabWidget->setCurrentIndex(switcher->lastOpenedTab); ui->tabWidget->setCurrentIndex(switcher->lastOpenedTab);
} }
} }
void AdvSceneSwitcher::RestoreWindowGeo() void AdvSceneSwitcher::restoreWindowGeo()
{ {
if (switcher->saveWindowGeo && WindowPosValid(switcher->windowPos)) { if (switcher->saveWindowGeo && windowPosValid(switcher->windowPos)) {
this->resize(switcher->windowSize); this->resize(switcher->windowSize);
this->move(switcher->windowPos); this->move(switcher->windowPos);
} }
} }
void AdvSceneSwitcher::CheckFirstTimeSetup() void AdvSceneSwitcher::checkFirstTimeSetup()
{ {
if (switcher->firstBoot && !switcher->disableHints) { if (switcher->firstBoot && !switcher->disableHints) {
switcher->firstBoot = false; switcher->firstBoot = false;
@@ -456,7 +511,7 @@ void AdvSceneSwitcher::on_tabMoved(int from, int to)
void AdvSceneSwitcher::on_tabWidget_currentChanged(int) void AdvSceneSwitcher::on_tabWidget_currentChanged(int)
{ {
switcher->showFrame = false; switcher->showFrame = false;
ClearFrames(ui->screenRegionSwitches); clearFrames(ui->screenRegionSwitches);
SetShowFrames(); SetShowFrames();
} }
@@ -493,25 +548,18 @@ void AdvSceneSwitcher::on_adjustActiveTransitionType_stateChanged(int state)
switcher->adjustActiveTransitionType = state; switcher->adjustActiveTransitionType = state;
} }
void SwitcherData::LoadSettings(obs_data_t *obj) void SwitcherData::loadSettings(obs_data_t *obj)
{ {
if (!obj) { if (!obj) {
return; return;
} }
// New post load steps to be declared during load
postLoadSteps.clear();
// Needs to be loaded before any entries which might rely on scene group // Needs to be loaded before any entries which might rely on scene group
// selections to be available. // selections to be available.
loadSceneGroups(obj); loadSceneGroups(obj);
LoadVariables(obj); loadVariables(obj);
loadMacros(obj);
for (const auto &func : loadSteps) { loadConnections(obj);
func(obj);
}
LoadMacros(obj);
loadWindowTitleSwitches(obj); loadWindowTitleSwitches(obj);
loadScreenRegionSwitches(obj); loadScreenRegionSwitches(obj);
loadPauseSwitches(obj); loadPauseSwitches(obj);
@@ -527,28 +575,24 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
loadVideoSwitches(obj); loadVideoSwitches(obj);
loadNetworkSettings(obj); loadNetworkSettings(obj);
loadSceneTriggers(obj); loadSceneTriggers(obj);
LoadGeneralSettings(obj); loadGeneralSettings(obj);
LoadHotkeys(obj); loadHotkeys(obj);
LoadUISettings(obj); loadUISettings(obj);
for (const auto &func : postLoadSteps) {
func();
}
// Reset on startup and scene collection change // Reset on startup and scene collection change
switcher->lastOpenedTab = -1; switcher->lastOpenedTab = -1;
startupLoadDone = true;
} }
void SwitcherData::SaveSettings(obs_data_t *obj) void SwitcherData::saveSettings(obs_data_t *obj)
{ {
if (!obj) { if (!obj) {
return; return;
} }
saveSceneGroups(obj); saveSceneGroups(obj);
SaveMacros(obj); saveMacros(obj);
SaveVariables(obj); saveConnections(obj);
saveVariables(obj);
saveWindowTitleSwitches(obj); saveWindowTitleSwitches(obj);
saveScreenRegionSwitches(obj); saveScreenRegionSwitches(obj);
savePauseSwitches(obj); savePauseSwitches(obj);
@@ -564,33 +608,27 @@ void SwitcherData::SaveSettings(obs_data_t *obj)
saveVideoSwitches(obj); saveVideoSwitches(obj);
saveNetworkSwitches(obj); saveNetworkSwitches(obj);
saveSceneTriggers(obj); saveSceneTriggers(obj);
SaveGeneralSettings(obj); saveGeneralSettings(obj);
SaveHotkeys(obj); saveHotkeys(obj);
SaveUISettings(obj); saveUISettings(obj);
SaveVersion(obj, g_GIT_SHA1); saveVersion(obj, g_GIT_SHA1);
for (const auto &func : saveSteps) {
func(obj);
}
} }
void SwitcherData::SaveGeneralSettings(obs_data_t *obj) void SwitcherData::saveGeneralSettings(obs_data_t *obj)
{ {
obs_data_set_int(obj, "interval", interval); obs_data_set_int(obj, "interval", interval);
std::string nonMatchingSceneName = GetWeakSourceName(nonMatchingScene); std::string nonMatchingSceneName = GetWeakSourceName(nonMatchingScene);
obs_data_set_string(obj, "non_matching_scene", obs_data_set_string(obj, "non_matching_scene",
nonMatchingSceneName.c_str()); nonMatchingSceneName.c_str());
obs_data_set_int(obj, "switch_if_not_matching", obs_data_set_int(obj, "switch_if_not_matching", switchIfNotMatching);
static_cast<int>(switchIfNotMatching)); noMatchDelay.Save(obj, "noMatchDelay", "noMatchDelayUnit");
noMatchDelay.Save(obj, "noMatchDelay");
cooldown.Save(obj, "cooldown"); cooldown.Save(obj, "cooldown", "cooldownUnit");
obs_data_set_bool(obj, "active", sceneColletionStop ? true : !stop); obs_data_set_bool(obj, "active", sceneColletionStop ? true : !stop);
sceneColletionStop = false; sceneColletionStop = false;
obs_data_set_int(obj, "startup_behavior", obs_data_set_int(obj, "startup_behavior", startupBehavior);
static_cast<int>(startupBehavior));
obs_data_set_int(obj, "autoStartEvent", obs_data_set_int(obj, "autoStartEvent",
static_cast<int>(autoStartEvent)); static_cast<int>(autoStartEvent));
@@ -599,12 +637,19 @@ 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, "disableFilterComboboxFilter",
disableFilterComboboxFilter);
obs_data_set_bool(obj, "warnPluginLoadFailure", warnPluginLoadFailure);
obs_data_set_bool(obj, "hideLegacyTabs", hideLegacyTabs); obs_data_set_bool(obj, "hideLegacyTabs", hideLegacyTabs);
SaveFunctionPriorities(obj, functionNamesByPriority); obs_data_set_int(obj, "priority0", functionNamesByPriority[0]);
obs_data_set_int(obj, "priority1", functionNamesByPriority[1]);
obs_data_set_int(obj, "priority2", functionNamesByPriority[2]);
obs_data_set_int(obj, "priority3", functionNamesByPriority[3]);
obs_data_set_int(obj, "priority4", functionNamesByPriority[4]);
obs_data_set_int(obj, "priority5", functionNamesByPriority[5]);
obs_data_set_int(obj, "priority6", functionNamesByPriority[6]);
obs_data_set_int(obj, "priority7", functionNamesByPriority[7]);
obs_data_set_int(obj, "priority8", functionNamesByPriority[8]);
obs_data_set_int(obj, "priority9", functionNamesByPriority[9]);
obs_data_set_int(obj, "priority10", functionNamesByPriority[10]);
obs_data_set_int(obj, "threadPriority", threadPriority); obs_data_set_int(obj, "threadPriority", threadPriority);
@@ -616,58 +661,88 @@ void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
obs_data_set_string(obj, "lastImportPath", lastImportPath.c_str()); obs_data_set_string(obj, "lastImportPath", lastImportPath.c_str());
} }
void SwitcherData::LoadGeneralSettings(obs_data_t *obj) void SwitcherData::loadGeneralSettings(obs_data_t *obj)
{ {
obs_data_set_default_int(obj, "interval", default_interval); obs_data_set_default_int(obj, "interval", default_interval);
interval = obs_data_get_int(obj, "interval"); interval = obs_data_get_int(obj, "interval");
obs_data_set_default_int(obj, "switch_if_not_matching", obs_data_set_default_int(obj, "switch_if_not_matching", NO_SWITCH);
static_cast<int>(NoMatchBehavior::NO_SWITCH)); switchIfNotMatching =
switchIfNotMatching = static_cast<NoMatchBehavior>( (NoMatch)obs_data_get_int(obj, "switch_if_not_matching");
obs_data_get_int(obj, "switch_if_not_matching"));
std::string nonMatchingSceneName = std::string nonMatchingSceneName =
obs_data_get_string(obj, "non_matching_scene"); obs_data_get_string(obj, "non_matching_scene");
nonMatchingScene = GetWeakSourceByName(nonMatchingSceneName.c_str()); nonMatchingScene = GetWeakSourceByName(nonMatchingSceneName.c_str());
noMatchDelay.Load(obj, "noMatchDelay"); noMatchDelay.Load(obj, "noMatchDelay", "noMatchDelayUnit");
cooldown.Load(obj, "cooldown"); cooldown.Load(obj, "cooldown", "cooldownUnit");
stop = !obs_data_get_bool(obj, "active"); stop = !obs_data_get_bool(obj, "active");
startupBehavior = startupBehavior =
(StartupBehavior)obs_data_get_int(obj, "startup_behavior"); (StartupBehavior)obs_data_get_int(obj, "startup_behavior");
if (startupBehavior == StartupBehavior::START) { if (startupBehavior == START) {
stop = false; stop = false;
} }
if (startupBehavior == StartupBehavior::STOP) { if (startupBehavior == STOP) {
stop = true; stop = true;
} }
autoStartEvent = autoStartEvent = static_cast<AutoStartEvent>(
static_cast<AutoStart>(obs_data_get_int(obj, "autoStartEvent")); obs_data_get_int(obj, "autoStartEvent"));
verbose = obs_data_get_bool(obj, "verbose"); verbose = obs_data_get_bool(obj, "verbose");
showSystemTrayNotifications = showSystemTrayNotifications =
obs_data_get_bool(obj, "showSystemTrayNotifications"); obs_data_get_bool(obj, "showSystemTrayNotifications");
disableHints = obs_data_get_bool(obj, "disableHints"); disableHints = obs_data_get_bool(obj, "disableHints");
disableFilterComboboxFilter =
obs_data_get_bool(obj, "disableFilterComboboxFilter");
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");
SetDefaultFunctionPriorities(obj); obs_data_set_default_int(obj, "priority0", default_priority_0);
LoadFunctionPriorities(obj, functionNamesByPriority); obs_data_set_default_int(obj, "priority1", default_priority_1);
if (!PrioFuncsValid()) { obs_data_set_default_int(obj, "priority2", default_priority_2);
functionNamesByPriority = GetDefaultFunctionPriorityList(); obs_data_set_default_int(obj, "priority3", default_priority_3);
obs_data_set_default_int(obj, "priority4", default_priority_4);
obs_data_set_default_int(obj, "priority5", default_priority_5);
obs_data_set_default_int(obj, "priority6", default_priority_6);
obs_data_set_default_int(obj, "priority7", default_priority_7);
obs_data_set_default_int(obj, "priority8", default_priority_8);
functionNamesByPriority[0] = (obs_data_get_int(obj, "priority0"));
functionNamesByPriority[1] = (obs_data_get_int(obj, "priority1"));
functionNamesByPriority[2] = (obs_data_get_int(obj, "priority2"));
functionNamesByPriority[3] = (obs_data_get_int(obj, "priority3"));
functionNamesByPriority[4] = (obs_data_get_int(obj, "priority4"));
functionNamesByPriority[5] = (obs_data_get_int(obj, "priority5"));
functionNamesByPriority[6] = (obs_data_get_int(obj, "priority6"));
functionNamesByPriority[7] = (obs_data_get_int(obj, "priority7"));
functionNamesByPriority[8] = (obs_data_get_int(obj, "priority8"));
functionNamesByPriority[9] = (obs_data_get_int(obj, "priority9"));
functionNamesByPriority[10] = (obs_data_get_int(obj, "priority10"));
if (!prioFuncsValid()) {
functionNamesByPriority[0] = (default_priority_0);
functionNamesByPriority[1] = (default_priority_1);
functionNamesByPriority[2] = (default_priority_2);
functionNamesByPriority[3] = (default_priority_3);
functionNamesByPriority[4] = (default_priority_4);
functionNamesByPriority[5] = (default_priority_5);
functionNamesByPriority[6] = (default_priority_6);
functionNamesByPriority[7] = (default_priority_7);
functionNamesByPriority[8] = (default_priority_8);
functionNamesByPriority[9] = (default_priority_9);
functionNamesByPriority[10] = (default_priority_10);
} }
obs_data_set_default_int(obj, "threadPriority", obs_data_set_default_int(obj, "threadPriority",
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, "transitionOverrideOverride"); 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");
@@ -680,7 +755,33 @@ void SwitcherData::LoadGeneralSettings(obs_data_t *obj)
lastImportPath = obs_data_get_string(obj, "lastImportPath"); lastImportPath = obs_data_get_string(obj, "lastImportPath");
} }
void SwitcherData::SaveUISettings(obs_data_t *obj) void saveSplitterPos(QList<int> &sizes, obs_data_t *obj, const std::string name)
{
auto array = obs_data_array_create();
for (int i = 0; i < sizes.count(); ++i) {
obs_data_t *array_obj = obs_data_create();
obs_data_set_int(array_obj, "pos", sizes[i]);
obs_data_array_push_back(array, array_obj);
obs_data_release(array_obj);
}
obs_data_set_array(obj, name.c_str(), array);
obs_data_array_release(array);
}
void loadSplitterPos(QList<int> &sizes, obs_data_t *obj, const std::string name)
{
sizes.clear();
obs_data_array_t *array = obs_data_get_array(obj, name.c_str());
size_t count = obs_data_array_count(array);
for (size_t i = 0; i < count; i++) {
obs_data_t *item = obs_data_array_item(array, i);
sizes << obs_data_get_int(item, "pos");
obs_data_release(item);
}
obs_data_array_release(array);
}
void SwitcherData::saveUISettings(obs_data_t *obj)
{ {
obs_data_set_int(obj, "generalTabPos", tabOrder[0]); obs_data_set_int(obj, "generalTabPos", tabOrder[0]);
obs_data_set_int(obj, "macroTabPos", tabOrder[1]); obs_data_set_int(obj, "macroTabPos", tabOrder[1]);
@@ -707,11 +808,13 @@ void SwitcherData::SaveUISettings(obs_data_t *obj)
obs_data_set_int(obj, "windowWidth", windowSize.width()); obs_data_set_int(obj, "windowWidth", windowSize.width());
obs_data_set_int(obj, "windowHeight", windowSize.height()); obs_data_set_int(obj, "windowHeight", windowSize.height());
SaveSplitterPos(macroListMacroEditSplitterPosition, obj, saveSplitterPos(macroActionConditionSplitterPosition, obj,
"macroActionConditionSplitterPosition");
saveSplitterPos(macroListMacroEditSplitterPosition, obj,
"macroListMacroEditSplitterPosition"); "macroListMacroEditSplitterPosition");
} }
void SwitcherData::LoadUISettings(obs_data_t *obj) void SwitcherData::loadUISettings(obs_data_t *obj)
{ {
obs_data_set_default_int(obj, "generalTabPos", 0); obs_data_set_default_int(obj, "generalTabPos", 0);
obs_data_set_default_int(obj, "macroTabPos", 1); obs_data_set_default_int(obj, "macroTabPos", 1);
@@ -752,8 +855,8 @@ void SwitcherData::LoadUISettings(obs_data_t *obj)
tabOrder.emplace_back((int)(obs_data_get_int(obj, "sceneGroupTabPos"))); tabOrder.emplace_back((int)(obs_data_get_int(obj, "sceneGroupTabPos")));
tabOrder.emplace_back((int)(obs_data_get_int(obj, "triggerTabPos"))); tabOrder.emplace_back((int)(obs_data_get_int(obj, "triggerTabPos")));
if (!TabOrderValid()) { if (!tabOrderValid()) {
ResetTabOrder(); resetTabOrder();
} }
saveWindowGeo = obs_data_get_bool(obj, "saveWindowGeo"); saveWindowGeo = obs_data_get_bool(obj, "saveWindowGeo");
@@ -761,12 +864,13 @@ void SwitcherData::LoadUISettings(obs_data_t *obj)
(int)obs_data_get_int(obj, "windowPosY")}; (int)obs_data_get_int(obj, "windowPosY")};
windowSize = {(int)obs_data_get_int(obj, "windowWidth"), windowSize = {(int)obs_data_get_int(obj, "windowWidth"),
(int)obs_data_get_int(obj, "windowHeight")}; (int)obs_data_get_int(obj, "windowHeight")};
loadSplitterPos(macroActionConditionSplitterPosition, obj,
LoadSplitterPos(macroListMacroEditSplitterPosition, obj, "macroActionConditionSplitterPosition");
loadSplitterPos(macroListMacroEditSplitterPosition, obj,
"macroListMacroEditSplitterPosition"); "macroListMacroEditSplitterPosition");
} }
bool SwitcherData::TabOrderValid() bool SwitcherData::tabOrderValid()
{ {
auto tmp = std::vector<int>(tab_count); auto tmp = std::vector<int>(tab_count);
std::iota(tmp.begin(), tmp.end(), 0); std::iota(tmp.begin(), tmp.end(), 0);
@@ -780,13 +884,13 @@ bool SwitcherData::TabOrderValid()
return true; return true;
} }
void SwitcherData::ResetTabOrder() void SwitcherData::resetTabOrder()
{ {
tabOrder = std::vector<int>(tab_count); tabOrder = std::vector<int>(tab_count);
std::iota(tabOrder.begin(), tabOrder.end(), 0); std::iota(tabOrder.begin(), tabOrder.end(), 0);
} }
void SwitcherData::CheckNoMatchSwitch(bool &match, OBSWeakSource &scene, void SwitcherData::checkNoMatchSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition, int &sleep) OBSWeakSource &transition, int &sleep)
{ {
if (match) { if (match) {
@@ -798,13 +902,12 @@ void SwitcherData::CheckNoMatchSwitch(bool &match, OBSWeakSource &scene,
return; return;
} }
if (switchIfNotMatching == NoMatchBehavior::SWITCH && if (switchIfNotMatching == SWITCH && nonMatchingScene) {
nonMatchingScene) {
match = true; match = true;
scene = nonMatchingScene; scene = nonMatchingScene;
transition = nullptr; transition = nullptr;
} }
if (switchIfNotMatching == NoMatchBehavior::RANDOM_SWITCH) { if (switchIfNotMatching == RANDOM_SWITCH) {
match = checkRandom(scene, transition, sleep); match = checkRandom(scene, transition, sleep);
} }
} }
@@ -823,7 +926,7 @@ void SwitcherData::checkSwitchCooldown(bool &match)
} }
} }
static void populateStartupBehavior(QComboBox *cb) void populateStartupBehavior(QComboBox *cb)
{ {
cb->addItem(obs_module_text( cb->addItem(obs_module_text(
"AdvSceneSwitcher.generalTab.status.onStartup.asLastRun")); "AdvSceneSwitcher.generalTab.status.onStartup.asLastRun"));
@@ -833,7 +936,7 @@ static void populateStartupBehavior(QComboBox *cb)
"AdvSceneSwitcher.generalTab.status.onStartup.doNotStart")); "AdvSceneSwitcher.generalTab.status.onStartup.doNotStart"));
} }
static void populateAutoStartEventSelection(QComboBox *cb) void populateAutoStartEventSelection(QComboBox *cb)
{ {
cb->addItem(obs_module_text( cb->addItem(obs_module_text(
"AdvSceneSwitcher.generalTab.status.autoStart.never")); "AdvSceneSwitcher.generalTab.status.autoStart.never"));
@@ -845,8 +948,53 @@ static void populateAutoStartEventSelection(QComboBox *cb)
"AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming")); "AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming"));
} }
static void populatePriorityFunctionList(QListWidget *list) void AdvSceneSwitcher::setupGeneralTab()
{ {
populateSceneSelection(ui->noMatchSwitchScene, false);
if (switcher->switchIfNotMatching == SWITCH) {
ui->noMatchSwitch->setChecked(true);
ui->noMatchSwitchScene->setEnabled(true);
} else if (switcher->switchIfNotMatching == NO_SWITCH) {
ui->noMatchDontSwitch->setChecked(true);
ui->noMatchSwitchScene->setEnabled(false);
} else {
ui->noMatchRandomSwitch->setChecked(true);
ui->noMatchSwitchScene->setEnabled(false);
}
ui->noMatchSwitchScene->setCurrentText(
GetWeakSourceName(switcher->nonMatchingScene).c_str());
DurationSelection *noMatchDelay = new DurationSelection();
noMatchDelay->SetDuration(switcher->noMatchDelay);
noMatchDelay->setToolTip(obs_module_text(
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip"));
ui->noMatchLayout->addWidget(noMatchDelay);
QWidget::connect(noMatchDelay, SIGNAL(DurationChanged(double)), this,
SLOT(NoMatchDelayDurationChanged(double)));
QWidget::connect(noMatchDelay, SIGNAL(UnitChanged(DurationUnit)), this,
SLOT(NoMatchDelayUnitChanged(DurationUnit)));
ui->checkInterval->setValue(switcher->interval);
DurationSelection *cooldownTime = new DurationSelection();
cooldownTime->SetDuration(switcher->cooldown);
cooldownTime->setToolTip(obs_module_text(
"AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint"));
ui->cooldownLayout->addWidget(cooldownTime);
ui->cooldownLayout->addStretch();
QWidget::connect(cooldownTime, SIGNAL(DurationChanged(double)), this,
SLOT(CooldownDurationChanged(double)));
QWidget::connect(cooldownTime, SIGNAL(UnitChanged(DurationUnit)), this,
SLOT(CooldownUnitChanged(DurationUnit)));
ui->verboseLogging->setChecked(switcher->verbose);
ui->saveWindowGeo->setChecked(switcher->saveWindowGeo);
ui->showTrayNotifications->setChecked(
switcher->showSystemTrayNotifications);
ui->uiHintsDisable->setChecked(switcher->disableHints);
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
for (int p : switcher->functionNamesByPriority) { for (int p : switcher->functionNamesByPriority) {
std::string s = ""; std::string s = "";
switch (p) { switch (p) {
@@ -896,118 +1044,26 @@ static void populatePriorityFunctionList(QListWidget *list)
break; break;
} }
QString text(s.c_str()); QString text(s.c_str());
QListWidgetItem *item = new QListWidgetItem(text, list); QListWidgetItem *item =
new QListWidgetItem(text, ui->priorityList);
item->setData(Qt::UserRole, text); item->setData(Qt::UserRole, text);
} }
}
static void populateThreadPriorityList(QComboBox *list)
{
for (int i = 0; i < (int)switcher->threadPriorities.size(); ++i) { for (int i = 0; i < (int)switcher->threadPriorities.size(); ++i) {
list->addItem(switcher->threadPriorities[i].name.c_str()); ui->threadPriority->addItem(
list->setItemData( switcher->threadPriorities[i].name.c_str());
ui->threadPriority->setItemData(
i, switcher->threadPriorities[i].description.c_str(), i, switcher->threadPriorities[i].description.c_str(),
Qt::ToolTipRole); Qt::ToolTipRole);
if (switcher->threadPriority == if (switcher->threadPriority ==
switcher->threadPriorities[i].value) { switcher->threadPriorities[i].value) {
list->setCurrentText( ui->threadPriority->setCurrentText(
switcher->threadPriorities[i].name.c_str()); switcher->threadPriorities[i].name.c_str());
} }
} }
}
static bool isGeneralTab(const QString &name)
{
return name == obs_module_text("AdvSceneSwitcher.generalTab.title");
}
static int getGeneralTabIdx(QTabWidget *tabWidget)
{
for (int idx = 0; idx < tabWidget->count(); idx++) {
if (isGeneralTab(tabWidget->tabText(idx))) {
return idx;
}
}
return -1;
}
static void setupGeneralTabInactiveWarning(QTabWidget *tabs)
{
auto callback = [tabs]() {
const bool isRunning = switcher && switcher->th &&
switcher->th->isRunning();
auto idx = getGeneralTabIdx(tabs);
tabs->setTabIcon(
idx,
isRunning ? QIcon()
: QIcon::fromTheme(
"obs",
QIcon(":/res/images/warning.svg")));
};
auto inactiveTimer = new QTimer(tabs);
inactiveTimer->setInterval(1000);
QObject::connect(inactiveTimer, &QTimer::timeout, callback);
inactiveTimer->start();
}
void AdvSceneSwitcher::SetupGeneralTab()
{
PopulateSceneSelection(ui->noMatchSwitchScene, false);
if (switcher->switchIfNotMatching == NoMatchBehavior::SWITCH) {
ui->noMatchSwitch->setChecked(true);
ui->noMatchSwitchScene->setEnabled(true);
} else if (switcher->switchIfNotMatching ==
NoMatchBehavior::NO_SWITCH) {
ui->noMatchDontSwitch->setChecked(true);
ui->noMatchSwitchScene->setEnabled(false);
} else {
ui->noMatchRandomSwitch->setChecked(true);
ui->noMatchSwitchScene->setEnabled(false);
}
ui->noMatchSwitchScene->setCurrentText(
GetWeakSourceName(switcher->nonMatchingScene).c_str());
DurationSelection *noMatchDelay = new DurationSelection();
noMatchDelay->SetDuration(switcher->noMatchDelay);
noMatchDelay->setToolTip(obs_module_text(
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip"));
ui->noMatchLayout->addWidget(noMatchDelay);
QWidget::connect(noMatchDelay,
SIGNAL(DurationChanged(const Duration &)), this,
SLOT(NoMatchDelayDurationChanged(const Duration &)));
ui->checkInterval->setValue(switcher->interval);
DurationSelection *cooldownTime = new DurationSelection();
cooldownTime->SetDuration(switcher->cooldown);
cooldownTime->setToolTip(obs_module_text(
"AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint"));
ui->cooldownLayout->addWidget(cooldownTime);
ui->cooldownLayout->addStretch();
QWidget::connect(cooldownTime,
SIGNAL(DurationChanged(const Duration &)), this,
SLOT(CooldownDurationChanged(const Duration &)));
ui->verboseLogging->setChecked(switcher->verbose);
ui->saveWindowGeo->setChecked(switcher->saveWindowGeo);
ui->showTrayNotifications->setChecked(
switcher->showSystemTrayNotifications);
ui->uiHintsDisable->setChecked(switcher->disableHints);
ui->disableComboBoxFilter->setChecked(
switcher->disableFilterComboboxFilter);
FilterComboBox::SetFilterBehaviourEnabled(
!switcher->disableFilterComboboxFilter);
ui->warnPluginLoadFailure->setChecked(switcher->warnPluginLoadFailure);
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
populatePriorityFunctionList(ui->priorityList);
populateThreadPriorityList(ui->threadPriority);
populateStartupBehavior(ui->startupBehavior); populateStartupBehavior(ui->startupBehavior);
ui->startupBehavior->setCurrentIndex( ui->startupBehavior->setCurrentIndex(switcher->startupBehavior);
static_cast<int>(switcher->startupBehavior));
populateAutoStartEventSelection(ui->autoStartEvent); populateAutoStartEventSelection(ui->autoStartEvent);
ui->autoStartEvent->setCurrentIndex( ui->autoStartEvent->setCurrentIndex(
@@ -1024,10 +1080,6 @@ void AdvSceneSwitcher::SetupGeneralTab()
// Hide the now empty invisible shell of the statusControl widget // Hide the now empty invisible shell of the statusControl widget
// as otherwise it could block user input // as otherwise it could block user input
statusControl->hide(); statusControl->hide();
setupGeneralTabInactiveWarning(ui->tabWidget);
MinimizeSizeOfColumn(ui->statusLayout, 0);
setWindowTitle(windowTitle() + " - " + g_GIT_TAG); setWindowTitle(windowTitle() + " - " + g_GIT_TAG);
} }
} // namespace advss

View File

@@ -1,12 +1,9 @@
#include "hotkey.hpp" #include "hotkey.hpp"
#include "advanced-scene-switcher.hpp" #include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include <obs-module.h> #include <obs-module.h>
#include <fstream> #include <fstream>
#include <regex> #include <regex>
namespace advss {
std::vector<std::weak_ptr<Hotkey>> Hotkey::_registeredHotkeys = {}; std::vector<std::weak_ptr<Hotkey>> Hotkey::_registeredHotkeys = {};
uint32_t Hotkey::_hotkeyCounter = 1; uint32_t Hotkey::_hotkeyCounter = 1;
@@ -120,7 +117,7 @@ void Hotkey::ClearAllHotkeys()
_registeredHotkeys.clear(); _registeredHotkeys.clear();
} }
static void startHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed) void startHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
{ {
if (pressed) { if (pressed) {
if (!(switcher->th && switcher->th->isRunning())) { if (!(switcher->th && switcher->th->isRunning())) {
@@ -129,7 +126,7 @@ static void startHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
} }
} }
static void stopHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed) void stopHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
{ {
if (pressed) { if (pressed) {
if (switcher->th && switcher->th->isRunning()) { if (switcher->th && switcher->th->isRunning()) {
@@ -138,8 +135,8 @@ static void stopHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
} }
} }
static void startStopToggleHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, void startStopToggleHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
bool pressed) bool pressed)
{ {
if (pressed) { if (pressed) {
if (switcher->th && switcher->th->isRunning()) { if (switcher->th && switcher->th->isRunning()) {
@@ -150,8 +147,8 @@ static void startStopToggleHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
} }
} }
static void upMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, void upMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
bool pressed) bool pressed)
{ {
if (pressed && switcher->settingsWindowOpened && if (pressed && switcher->settingsWindowOpened &&
AdvSceneSwitcher::window) { AdvSceneSwitcher::window) {
@@ -161,8 +158,8 @@ static void upMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
} }
} }
static void downMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, void downMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
bool pressed) bool pressed)
{ {
if (pressed && switcher->settingsWindowOpened && if (pressed && switcher->settingsWindowOpened &&
AdvSceneSwitcher::window) { AdvSceneSwitcher::window) {
@@ -172,8 +169,8 @@ static void downMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
} }
} }
static void removeMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, void removeMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
bool pressed) bool pressed)
{ {
if (pressed && switcher->settingsWindowOpened && if (pressed && switcher->settingsWindowOpened &&
AdvSceneSwitcher::window) { AdvSceneSwitcher::window) {
@@ -183,7 +180,7 @@ static void removeMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
} }
} }
static void registerHotkeys() void registerHotkeys()
{ {
switcher->startHotkey = obs_hotkey_register_frontend( switcher->startHotkey = obs_hotkey_register_frontend(
"startSwitcherHotkey", "startSwitcherHotkey",
@@ -216,14 +213,14 @@ static void registerHotkeys()
switcher->hotkeysRegistered = true; switcher->hotkeysRegistered = true;
} }
static void saveHotkey(obs_data_t *obj, obs_hotkey_id id, const char *name) void saveHotkey(obs_data_t *obj, obs_hotkey_id id, const char *name)
{ {
obs_data_array_t *a = obs_hotkey_save(id); obs_data_array_t *a = obs_hotkey_save(id);
obs_data_set_array(obj, name, a); obs_data_set_array(obj, name, a);
obs_data_array_release(a); obs_data_array_release(a);
} }
void SwitcherData::SaveHotkeys(obs_data_t *obj) void SwitcherData::saveHotkeys(obs_data_t *obj)
{ {
saveHotkey(obj, startHotkey, "startHotkey"); saveHotkey(obj, startHotkey, "startHotkey");
saveHotkey(obj, stopHotkey, "stopHotkey"); saveHotkey(obj, stopHotkey, "stopHotkey");
@@ -233,14 +230,14 @@ void SwitcherData::SaveHotkeys(obs_data_t *obj)
saveHotkey(obj, removeMacroSegment, "removeMacroSegmentHotkey"); saveHotkey(obj, removeMacroSegment, "removeMacroSegmentHotkey");
} }
static void loadHotkey(obs_data_t *obj, obs_hotkey_id id, const char *name) void loadHotkey(obs_data_t *obj, obs_hotkey_id id, const char *name)
{ {
obs_data_array_t *a = obs_data_get_array(obj, name); obs_data_array_t *a = obs_data_get_array(obj, name);
obs_hotkey_load(id, a); obs_hotkey_load(id, a);
obs_data_array_release(a); obs_data_array_release(a);
} }
void SwitcherData::LoadHotkeys(obs_data_t *obj) void SwitcherData::loadHotkeys(obs_data_t *obj)
{ {
if (!hotkeysRegistered) { if (!hotkeysRegistered) {
registerHotkeys(); registerHotkeys();
@@ -252,5 +249,3 @@ void SwitcherData::LoadHotkeys(obs_data_t *obj)
loadHotkey(obj, downMacroSegment, "downMacroSegmentHotkey"); loadHotkey(obj, downMacroSegment, "downMacroSegmentHotkey");
loadHotkey(obj, removeMacroSegment, "removeMacroSegmentHotkey"); loadHotkey(obj, removeMacroSegment, "removeMacroSegmentHotkey");
} }
} // namespace advss

View File

@@ -5,8 +5,6 @@
#include <vector> #include <vector>
#include <chrono> #include <chrono>
namespace advss {
extern bool canSimulateKeyPresses; extern bool canSimulateKeyPresses;
class Hotkey { class Hotkey {
@@ -163,4 +161,4 @@ enum class HotkeyType {
Key_NumpadEnter Key_NumpadEnter
}; };
} // namespace advss void registerHotkeys();

View File

@@ -1,10 +1,7 @@
#include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "utility.hpp"
#include <thread> #include <thread>
namespace advss { #include "advanced-scene-switcher.hpp"
#include "utility.hpp"
bool SceneTrigger::pause = false; bool SceneTrigger::pause = false;
static QMetaObject::Connection addPulse; static QMetaObject::Connection addPulse;
@@ -159,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)
@@ -269,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));
@@ -352,7 +349,7 @@ void SwitcherData::loadSceneTriggers(obs_data_t *obj)
obs_data_array_release(triggerArray); obs_data_array_release(triggerArray);
} }
void AdvSceneSwitcher::SetupTriggerTab() void AdvSceneSwitcher::setupTriggerTab()
{ {
for (auto &s : switcher->sceneTriggers) { for (auto &s : switcher->sceneTriggers) {
QListWidgetItem *item; QListWidgetItem *item;
@@ -401,7 +398,7 @@ void SceneTrigger::load(obs_data_t *obj)
static inline void populateTriggers(QComboBox *list) static inline void populateTriggers(QComboBox *list)
{ {
AddSelectionEntry( addSelectionEntry(
list, list,
obs_module_text( obs_module_text(
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none")); "AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none"));
@@ -416,7 +413,7 @@ static inline void populateTriggers(QComboBox *list)
inline void populateActions(QComboBox *list) inline void populateActions(QComboBox *list)
{ {
AddSelectionEntry( addSelectionEntry(
list, list,
obs_module_text( obs_module_text(
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none")); "AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none"));
@@ -463,15 +460,17 @@ 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(const Duration &)), QWidget::connect(duration, SIGNAL(DurationChanged(double)), this,
this, SLOT(DurationChanged(const Duration &))); SLOT(DurationChanged(double)));
QWidget::connect(duration, SIGNAL(UnitChanged(DurationUnit)), this,
SLOT(DurationUnitChanged(DurationUnit)));
QWidget::connect(audioSources, QWidget::connect(audioSources,
SIGNAL(currentTextChanged(const QString &)), this, SIGNAL(currentTextChanged(const QString &)), this,
SLOT(AudioSourceChanged(const QString &))); SLOT(AudioSourceChanged(const QString &)));
populateTriggers(triggers); populateTriggers(triggers);
populateActions(actions); populateActions(actions);
PopulateAudioSelection(audioSources); populateAudioSelection(audioSources);
if (s) { if (s) {
triggers->setCurrentIndex(static_cast<int>(s->triggerType)); triggers->setCurrentIndex(static_cast<int>(s->triggerType));
@@ -495,7 +494,7 @@ SceneTriggerWidget::SceneTriggerWidget(QWidget *parent, SceneTrigger *s)
{"{{audioSources}}", audioSources}, {"{{audioSources}}", audioSources},
{"{{duration}}", duration}, {"{{duration}}", duration},
{"{{scenes}}", scenes}}; {"{{scenes}}", scenes}};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.sceneTriggerTab.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.sceneTriggerTab.entry"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
setLayout(mainLayout); setLayout(mainLayout);
@@ -553,14 +552,24 @@ void SceneTriggerWidget::TriggerActionChanged(int index)
} }
} }
void SceneTriggerWidget::DurationChanged(const Duration &duration) void SceneTriggerWidget::DurationChanged(double seconds)
{ {
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 = duration; switchData->duration.seconds = seconds;
}
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)
@@ -572,5 +581,3 @@ void SceneTriggerWidget::AudioSourceChanged(const QString &text)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switchData->audioSource = GetWeakSourceByQString(text); switchData->audioSource = GetWeakSourceByQString(text);
} }
} // namespace advss

View File

@@ -10,8 +10,6 @@
#include "switch-generic.hpp" #include "switch-generic.hpp"
#include "duration-control.hpp" #include "duration-control.hpp"
namespace advss {
enum class sceneTriggerType { enum class sceneTriggerType {
NONE = 0, NONE = 0,
SCENE_ACTIVE = 1, SCENE_ACTIVE = 1,
@@ -73,7 +71,8 @@ public:
private slots: private slots:
void TriggerTypeChanged(int index); void TriggerTypeChanged(int index);
void TriggerActionChanged(int index); void TriggerActionChanged(int index);
void DurationChanged(const Duration &); void DurationChanged(double seconds);
void DurationUnitChanged(DurationUnit unit);
void AudioSourceChanged(const QString &text); void AudioSourceChanged(const QString &text);
private: private:
@@ -84,5 +83,3 @@ private:
SceneTrigger *switchData; SceneTrigger *switchData;
}; };
} // namespace advss

View File

@@ -1,11 +1,8 @@
#include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "volume-control.hpp"
#include "utility.hpp"
#include <float.h> #include <float.h>
namespace advss { #include "advanced-scene-switcher.hpp"
#include "volume-control.hpp"
#include "utility.hpp"
bool AudioSwitch::pause = false; bool AudioSwitch::pause = false;
static QMetaObject::Connection addPulse; static QMetaObject::Connection addPulse;
@@ -215,7 +212,7 @@ void SwitcherData::loadAudioSwitches(obs_data_t *obj)
audioFallback.load(obj); audioFallback.load(obj);
} }
void AdvSceneSwitcher::SetupAudioTab() void AdvSceneSwitcher::setupAudioTab()
{ {
for (auto &s : switcher->audioSwitches) { for (auto &s : switcher->audioSwitches) {
QListWidgetItem *item; QListWidgetItem *item;
@@ -441,15 +438,15 @@ AudioSwitchWidget::AudioSwitchWidget(QWidget *parent, AudioSwitch *s)
SLOT(VolumeThresholdChanged(int))); SLOT(VolumeThresholdChanged(int)));
QWidget::connect(condition, SIGNAL(currentIndexChanged(int)), this, QWidget::connect(condition, SIGNAL(currentIndexChanged(int)), this,
SLOT(ConditionChanged(int))); SLOT(ConditionChanged(int)));
QWidget::connect(duration, SIGNAL(DurationChanged(const Duration &)), QWidget::connect(duration, SIGNAL(DurationChanged(double)), this,
this, SLOT(DurationChanged(const Duration &))); SLOT(DurationChanged(double)));
QWidget::connect(audioSources, QWidget::connect(audioSources,
SIGNAL(currentTextChanged(const QString &)), this, SIGNAL(currentTextChanged(const QString &)), this,
SLOT(SourceChanged(const QString &))); SLOT(SourceChanged(const QString &)));
QWidget::connect(ignoreInactiveSource, SIGNAL(stateChanged(int)), this, QWidget::connect(ignoreInactiveSource, SIGNAL(stateChanged(int)), this,
SLOT(IgnoreInactiveChanged(int))); SLOT(IgnoreInactiveChanged(int)));
PopulateAudioSelection(audioSources); populateAudioSelection(audioSources);
populateConditionSelection(condition); populateConditionSelection(condition);
if (s) { if (s) {
@@ -470,7 +467,7 @@ AudioSwitchWidget::AudioSwitchWidget(QWidget *parent, AudioSwitch *s)
{"{{ignoreInactiveSource}}", ignoreInactiveSource}, {"{{ignoreInactiveSource}}", ignoreInactiveSource},
{"{{scenes}}", scenes}, {"{{scenes}}", scenes},
{"{{transitions}}", transitions}}; {"{{transitions}}", transitions}};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.audioTab.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.audioTab.entry"),
switchLayout, widgetPlaceholders); switchLayout, widgetPlaceholders);
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout;
@@ -557,14 +554,14 @@ void AudioSwitchWidget::ConditionChanged(int cond)
switchData->condition = (audioCondition)cond; switchData->condition = (audioCondition)cond;
} }
void AudioSwitchWidget::DurationChanged(const Duration &dur) void AudioSwitchWidget::DurationChanged(double sec)
{ {
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 = dur; switchData->duration.seconds = sec;
} }
void AudioSwitchWidget::IgnoreInactiveChanged(int state) void AudioSwitchWidget::IgnoreInactiveChanged(int state)
@@ -583,8 +580,8 @@ AudioSwitchFallbackWidget::AudioSwitchFallbackWidget(QWidget *parent,
{ {
duration = new DurationSelection(this, false); duration = new DurationSelection(this, false);
QWidget::connect(duration, SIGNAL(DurationChanged(const Duration &)), QWidget::connect(duration, SIGNAL(DurationChanged(double)), this,
this, SLOT(DurationChanged(const Duration &))); SLOT(DurationChanged(double)));
if (s) { if (s) {
duration->SetDuration(s->duration); duration->SetDuration(s->duration);
@@ -595,7 +592,7 @@ AudioSwitchFallbackWidget::AudioSwitchFallbackWidget(QWidget *parent,
{"{{scenes}}", scenes}, {"{{scenes}}", scenes},
{"{{duration}}", duration}, {"{{duration}}", duration},
{"{{transitions}}", transitions}}; {"{{transitions}}", transitions}};
PlaceWidgets( placeWidgets(
obs_module_text("AdvSceneSwitcher.audioTab.multiMatchfallback"), obs_module_text("AdvSceneSwitcher.audioTab.multiMatchfallback"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
setLayout(mainLayout); setLayout(mainLayout);
@@ -605,14 +602,12 @@ AudioSwitchFallbackWidget::AudioSwitchFallbackWidget(QWidget *parent,
loading = false; loading = false;
} }
void AudioSwitchFallbackWidget::DurationChanged(const Duration &dur) void AudioSwitchFallbackWidget::DurationChanged(double sec)
{ {
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 = dur; switchData->duration.seconds = sec;
} }
} // namespace advss

View File

@@ -13,8 +13,6 @@
#include "duration-control.hpp" #include "duration-control.hpp"
#include "volume-control.hpp" #include "volume-control.hpp"
namespace advss {
constexpr auto audio_func = 8; constexpr auto audio_func = 8;
typedef enum { typedef enum {
@@ -77,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(const Duration &); void DurationChanged(double dur);
void IgnoreInactiveChanged(int state); void IgnoreInactiveChanged(int state);
private: private:
@@ -98,12 +96,10 @@ public:
AudioSwitchFallbackWidget(QWidget *parent, AudioSwitchFallback *s); AudioSwitchFallbackWidget(QWidget *parent, AudioSwitchFallback *s);
private slots: private slots:
void DurationChanged(const Duration &dur); void DurationChanged(double dur);
private: private:
DurationSelection *duration; DurationSelection *duration;
AudioSwitchFallback *switchData; AudioSwitchFallback *switchData;
}; };
} // namespace advss

View File

@@ -1,10 +1,6 @@
#include "advanced-scene-switcher.hpp" #include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "platform-funcs.hpp"
#include "utility.hpp" #include "utility.hpp"
namespace advss {
bool ExecutableSwitch::pause = false; bool ExecutableSwitch::pause = false;
static QMetaObject::Connection addPulse; static QMetaObject::Connection addPulse;
@@ -103,7 +99,7 @@ bool SwitcherData::checkExeSwitch(OBSWeakSource &scene,
bool equals = runningProcesses.contains(s.exe); bool equals = runningProcesses.contains(s.exe);
bool matches = (runningProcesses.indexOf( bool matches = (runningProcesses.indexOf(
QRegularExpression(s.exe)) != -1); QRegularExpression(s.exe)) != -1);
bool focus = (!s.inFocus || IsInFocus(s.exe)); bool focus = (!s.inFocus || isInFocus(s.exe));
// True if current window is ignored AND switch equals OR matches last window // True if current window is ignored AND switch equals OR matches last window
bool ignore = bool ignore =
@@ -160,7 +156,7 @@ void SwitcherData::loadExecutableSwitches(obs_data_t *obj)
obs_data_array_release(executableArray); obs_data_array_release(executableArray);
} }
void AdvSceneSwitcher::SetupExecutableTab() void AdvSceneSwitcher::setupExecutableTab()
{ {
for (auto &s : switcher->executableSwitches) { for (auto &s : switcher->executableSwitches) {
QListWidgetItem *item; QListWidgetItem *item;
@@ -212,7 +208,7 @@ ExecutableSwitchWidget::ExecutableSwitchWidget(QWidget *parent,
QWidget::connect(requiresFocus, SIGNAL(stateChanged(int)), this, QWidget::connect(requiresFocus, SIGNAL(stateChanged(int)), this,
SLOT(FocusChanged(int))); SLOT(FocusChanged(int)));
PopulateProcessSelection(processes); populateProcessSelection(processes);
processes->setEditable(true); processes->setEditable(true);
processes->setMaxVisibleItems(20); processes->setMaxVisibleItems(20);
@@ -228,7 +224,7 @@ ExecutableSwitchWidget::ExecutableSwitchWidget(QWidget *parent,
{"{{requiresFocus}}", requiresFocus}, {"{{requiresFocus}}", requiresFocus},
{"{{scenes}}", scenes}, {"{{scenes}}", scenes},
{"{{transitions}}", transitions}}; {"{{transitions}}", transitions}};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.executableTab.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.executableTab.entry"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
setLayout(mainLayout); setLayout(mainLayout);
@@ -276,5 +272,3 @@ void ExecutableSwitchWidget::FocusChanged(int state)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switchData->inFocus = state; switchData->inFocus = state;
} }
} // namespace advss

View File

@@ -9,8 +9,6 @@
#include <QCheckBox> #include <QCheckBox>
#include "switch-generic.hpp" #include "switch-generic.hpp"
namespace advss {
constexpr auto exe_func = 3; constexpr auto exe_func = 3;
struct ExecutableSwitch : SceneSwitcherEntry { struct ExecutableSwitch : SceneSwitcherEntry {
@@ -44,5 +42,3 @@ private:
ExecutableSwitch *switchData; ExecutableSwitch *switchData;
}; };
} // namespace advss

View File

@@ -1,8 +1,3 @@
#include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "curl-helper.hpp"
#include "utility.hpp"
#include <QtGlobal> #include <QtGlobal>
#include <QFileDialog> #include <QFileDialog>
#include <QTextStream> #include <QTextStream>
@@ -11,7 +6,9 @@
#include <regex> #include <regex>
#include <curl/curl.h> #include <curl/curl.h>
namespace advss { #include "advanced-scene-switcher.hpp"
#include "curl-helper.hpp"
#include "utility.hpp"
bool FileSwitch::pause = false; bool FileSwitch::pause = false;
static QMetaObject::Connection addPulse; static QMetaObject::Connection addPulse;
@@ -119,7 +116,7 @@ void SwitcherData::writeToStatusFile(const QString &msg)
if (file.open(QIODevice::ReadWrite)) { if (file.open(QIODevice::ReadWrite)) {
QTextStream stream(&file); QTextStream stream(&file);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
stream << msg << "\n"; stream << msg << endl;
#else #else
stream << msg << Qt::endl; stream << msg << Qt::endl;
#endif #endif
@@ -212,7 +209,7 @@ bool matchFileContent(QString &filedata, FileSwitch &s)
} }
QString text = QString::fromStdString(s.text); QString text = QString::fromStdString(s.text);
return CompareIgnoringLineEnding(text, filedata); return compareIgnoringLineEnding(text, filedata);
} }
bool checkRemoteFileContent(FileSwitch &s) bool checkRemoteFileContent(FileSwitch &s)
@@ -414,7 +411,7 @@ void SwitcherData::loadFileSwitches(obs_data_t *obj)
fileIO.writePath = obs_data_get_string(obj, "writePath"); fileIO.writePath = obs_data_get_string(obj, "writePath");
} }
void AdvSceneSwitcher::SetupFileTab() void AdvSceneSwitcher::setupFileTab()
{ {
ui->remoteFileWarningLabel->setText( ui->remoteFileWarningLabel->setText(
obs_module_text("AdvSceneSwitcher.fileTab.remoteFileWarning1") + obs_module_text("AdvSceneSwitcher.fileTab.remoteFileWarning1") +
@@ -545,11 +542,11 @@ FileSwitchWidget::FileSwitchWidget(QWidget *parent, FileSwitch *s)
QHBoxLayout *line1Layout = new QHBoxLayout; QHBoxLayout *line1Layout = new QHBoxLayout;
QHBoxLayout *line2Layout = new QHBoxLayout; QHBoxLayout *line2Layout = new QHBoxLayout;
QHBoxLayout *line3Layout = new QHBoxLayout; QHBoxLayout *line3Layout = new QHBoxLayout;
PlaceWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry"),
line1Layout, widgetPlaceholders); line1Layout, widgetPlaceholders);
PlaceWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry2"), placeWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry2"),
line2Layout, widgetPlaceholders, false); line2Layout, widgetPlaceholders, false);
PlaceWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry3"), placeWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry3"),
line3Layout, widgetPlaceholders); line3Layout, widgetPlaceholders);
mainLayout->addLayout(line1Layout); mainLayout->addLayout(line1Layout);
mainLayout->addLayout(line2Layout); mainLayout->addLayout(line2Layout);
@@ -668,5 +665,3 @@ void FileSwitchWidget::CheckFileContentChanged(int state)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switchData->onlyMatchIfChanged = state; switchData->onlyMatchIfChanged = state;
} }
} // namespace advss

View File

@@ -8,11 +8,8 @@
#pragma once #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QDateTime>
#include <obs-module.h> #include <obs-module.h>
namespace advss {
constexpr auto read_file_func = 0; constexpr auto read_file_func = 0;
typedef enum { typedef enum {
@@ -80,5 +77,3 @@ static inline QString MakeFileSwitchName(const QString &scene,
const QString &fileName, const QString &fileName,
const QString &text, bool useRegex, const QString &text, bool useRegex,
bool useTime, bool onlyMatchIfChanged); bool useTime, bool onlyMatchIfChanged);
} // namespace advss

View File

@@ -1,12 +1,6 @@
#include "advanced-scene-switcher.hpp" #include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "utility.hpp" #include "utility.hpp"
constexpr auto previous_scene_name = "Previous Scene";
constexpr auto current_transition_name = "Current Transition";
namespace advss {
static inline bool SceneGroupValid(SceneGroup *group) static inline bool SceneGroupValid(SceneGroup *group)
{ {
if (group) { if (group) {
@@ -214,9 +208,9 @@ SwitchWidget::SwitchWidget(QWidget *parent, SceneSwitcherEntry *s,
SIGNAL(SceneGroupRenamed(const QString &, const QString &)), SIGNAL(SceneGroupRenamed(const QString &, const QString &)),
this, SLOT(SceneGroupRename(const QString &, const QString &))); this, SLOT(SceneGroupRename(const QString &, const QString &)));
PopulateSceneSelection(scenes, usePreviousScene, false, false, populateSceneSelection(scenes, usePreviousScene, false, false,
addSceneGroup, &switcher->sceneGroups); addSceneGroup, &switcher->sceneGroups);
PopulateTransitionSelection(transitions, addCurrentTransition); populateTransitionSelection(transitions, addCurrentTransition);
switchData = s; switchData = s;
showSwitchData(); showSwitchData();
@@ -306,5 +300,3 @@ void SwitchWidget::TransitionChanged(const QString &text)
switchData->transition = GetWeakTransitionByQString(text); switchData->transition = GetWeakTransitionByQString(text);
switchData->useCurrentTransition = switchData->transition == nullptr; switchData->useCurrentTransition = switchData->transition == nullptr;
} }
} // namespace advss

View File

@@ -4,8 +4,6 @@
#include "scene-group.hpp" #include "scene-group.hpp"
namespace advss {
enum class SwitchTargetType { enum class SwitchTargetType {
Scene, Scene,
SceneGroup, SceneGroup,
@@ -97,5 +95,3 @@ protected:
SceneSwitcherEntry *switchData; SceneSwitcherEntry *switchData;
}; };
} // namespace advss

View File

@@ -1,11 +1,7 @@
#include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "platform-funcs.hpp"
#include "utility.hpp"
#include <regex> #include <regex>
namespace advss { #include "advanced-scene-switcher.hpp"
#include "utility.hpp"
bool IdleData::pause = false; bool IdleData::pause = false;
IdleWidget *idleWidget = nullptr; IdleWidget *idleWidget = nullptr;
@@ -42,7 +38,7 @@ bool SwitcherData::checkIdleSwitch(OBSWeakSource &scene,
} }
} }
if (!ignoreIdle && SecondsSinceLastInput() > idleData.time) { if (!ignoreIdle && secondsSinceLastInput() > idleData.time) {
if (idleData.alreadySwitched) { if (idleData.alreadySwitched) {
return false; return false;
} }
@@ -209,9 +205,9 @@ void SwitcherData::loadIdleSwitches(obs_data_t *obj)
idleData.load(obj); idleData.load(obj);
} }
void AdvSceneSwitcher::SetupIdleTab() void AdvSceneSwitcher::setupIdleTab()
{ {
PopulateWindowSelection(ui->ignoreIdleWindowsWindows); populateWindowSelection(ui->ignoreIdleWindowsWindows);
for (auto &window : switcher->ignoreIdleWindows) { for (auto &window : switcher->ignoreIdleWindows) {
QString text = QString::fromStdString(window); QString text = QString::fromStdString(window);
@@ -271,7 +267,7 @@ IdleWidget::IdleWidget(QWidget *parent, IdleData *s)
{"{{duration}}", duration}, {"{{duration}}", duration},
{"{{scenes}}", scenes}, {"{{scenes}}", scenes},
{"{{transitions}}", transitions}}; {"{{transitions}}", transitions}};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.idleTab.idleswitch"), placeWidgets(obs_module_text("AdvSceneSwitcher.idleTab.idleswitch"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
setLayout(mainLayout); setLayout(mainLayout);
@@ -289,5 +285,3 @@ void IdleWidget::DurationChanged(int dur)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switcher->idleData.time = dur; switcher->idleData.time = dur;
} }
} // namespace advss

View File

@@ -8,8 +8,6 @@
#pragma once #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"
namespace advss {
constexpr auto default_idle_time = 60; constexpr auto default_idle_time = 60;
constexpr auto idle_func = 2; constexpr auto idle_func = 2;
@@ -38,5 +36,3 @@ private:
IdleData *switchData; IdleData *switchData;
}; };
} // namespace advss

View File

@@ -1,9 +1,6 @@
#include "advanced-scene-switcher.hpp" #include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "utility.hpp" #include "utility.hpp"
namespace advss {
bool MediaSwitch::pause = false; bool MediaSwitch::pause = false;
static QMetaObject::Connection addPulse; static QMetaObject::Connection addPulse;
@@ -235,7 +232,7 @@ void SwitcherData::loadMediaSwitches(obs_data_t *obj)
obs_data_array_release(mediaArray); obs_data_array_release(mediaArray);
} }
void AdvSceneSwitcher::SetupMediaTab() void AdvSceneSwitcher::setupMediaTab()
{ {
for (auto &s : switcher->mediaSwitches) { for (auto &s : switcher->mediaSwitches) {
QListWidgetItem *item; QListWidgetItem *item;
@@ -463,7 +460,7 @@ MediaSwitchWidget::MediaSwitchWidget(QWidget *parent, MediaSwitch *s)
QWidget::connect(time, SIGNAL(valueChanged(int)), this, QWidget::connect(time, SIGNAL(valueChanged(int)), this,
SLOT(TimeChanged(int))); SLOT(TimeChanged(int)));
PopulateMediaSelection(mediaSources); populateMediaSelection(mediaSources);
populateMediaStates(states); populateMediaStates(states);
populateTimeRestrictions(timeRestrictions); populateTimeRestrictions(timeRestrictions);
@@ -486,7 +483,7 @@ MediaSwitchWidget::MediaSwitchWidget(QWidget *parent, MediaSwitch *s)
{"{{time}}", time}, {"{{time}}", time},
{"{{scenes}}", scenes}, {"{{scenes}}", scenes},
{"{{transitions}}", transitions}}; {"{{transitions}}", transitions}};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.mediaTab.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.mediaTab.entry"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
setLayout(mainLayout); setLayout(mainLayout);
@@ -563,5 +560,3 @@ void MediaSwitchWidget::TimeChanged(int time)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switchData->time = time; switchData->time = time;
} }
} // namespace advss

View File

@@ -8,8 +8,6 @@
#pragma once #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"
namespace advss {
constexpr auto media_func = 6; constexpr auto media_func = 6;
typedef enum { typedef enum {
@@ -85,5 +83,3 @@ private:
MediaSwitch *switchData; MediaSwitch *switchData;
}; };
} // namespace advss

View File

@@ -7,12 +7,8 @@ Most of this code is based on https://github.com/Palakis/obs-websocket
#include <QMessageBox> #include <QMessageBox>
#include "advanced-scene-switcher.hpp" #include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "scene-switch-helpers.hpp"
#include "utility.hpp" #include "utility.hpp"
namespace advss {
#define PARAM_SERVER_ENABLE "ServerEnabled" #define PARAM_SERVER_ENABLE "ServerEnabled"
#define PARAM_SERVER_PORT "ServerPort" #define PARAM_SERVER_PORT "ServerPort"
#define PARAM_LOCKTOIPV4 "LockToIPv4" #define PARAM_LOCKTOIPV4 "LockToIPv4"
@@ -128,9 +124,10 @@ WSServer::WSServer() : QObject(nullptr), _connections(), _clMutex()
_server.set_reuse_addr(true); _server.set_reuse_addr(true);
#endif #endif
_server.set_open_handler(bind(&WSServer::onOpen, this, _1)); _server.set_open_handler(bind(&WSServer::onOpen, this, ::_1));
_server.set_close_handler(bind(&WSServer::onClose, this, _1)); _server.set_close_handler(bind(&WSServer::onClose, this, ::_1));
_server.set_message_handler(bind(&WSServer::onMessage, this, _1, _2)); _server.set_message_handler(
bind(&WSServer::onMessage, this, ::_1, ::_2));
} }
WSServer::~WSServer() WSServer::~WSServer()
@@ -224,7 +221,7 @@ void WSServer::stop()
blog(LOG_INFO, "server stopped successfully"); blog(LOG_INFO, "server stopped successfully");
} }
void WSServer::sendMessage(SceneSwitchInfo sceneSwitch, bool preview) void WSServer::sendMessage(sceneSwitchInfo sceneSwitch, bool preview)
{ {
if (!sceneSwitch.scene) { if (!sceneSwitch.scene) {
return; return;
@@ -308,9 +305,9 @@ std::string processMessage(std::string payload)
"'"; "'";
} }
if (preview) { if (preview) {
SwitchPreviewScene(scene); switchPreviewScene(scene);
} else { } else {
SwitchScene({scene, transition, duration}); switchScene({scene, transition, duration});
} }
return ret; return ret;
} }
@@ -364,10 +361,11 @@ WSClient::WSClient() : QObject(nullptr)
_client.set_reuse_addr(true); _client.set_reuse_addr(true);
#endif #endif
_client.set_open_handler(bind(&WSClient::onOpen, this, _1)); _client.set_open_handler(bind(&WSClient::onOpen, this, ::_1));
_client.set_fail_handler(bind(&WSClient::onFail, this, _1)); _client.set_fail_handler(bind(&WSClient::onFail, this, ::_1));
_client.set_message_handler(bind(&WSClient::onMessage, this, _1, _2)); _client.set_message_handler(
_client.set_close_handler(bind(&WSClient::onClose, this, _1)); bind(&WSClient::onMessage, this, ::_1, ::_2));
_client.set_close_handler(bind(&WSClient::onClose, this, ::_1));
} }
WSClient::~WSClient() WSClient::~WSClient()
@@ -503,7 +501,7 @@ void SwitcherData::saveNetworkSwitches(obs_data_t *obj)
} }
} }
void AdvSceneSwitcher::SetupNetworkTab() void AdvSceneSwitcher::setupNetworkTab()
{ {
ui->serverSettings->setChecked(switcher->networkConfig.ServerEnabled); ui->serverSettings->setChecked(switcher->networkConfig.ServerEnabled);
ui->serverPort->setValue(switcher->networkConfig.ServerPort); ui->serverPort->setValue(switcher->networkConfig.ServerPort);
@@ -521,9 +519,9 @@ void AdvSceneSwitcher::SetupNetworkTab()
QTimer *statusTimer = new QTimer(this); QTimer *statusTimer = new QTimer(this);
connect(statusTimer, SIGNAL(timeout()), this, connect(statusTimer, SIGNAL(timeout()), this,
SLOT(UpdateClientStatus())); SLOT(updateClientStatus()));
connect(statusTimer, SIGNAL(timeout()), this, connect(statusTimer, SIGNAL(timeout()), this,
SLOT(UpdateServerStatus())); SLOT(updateServerStatus()));
statusTimer->start(500); statusTimer->start(500);
} }
@@ -574,7 +572,7 @@ void AdvSceneSwitcher::on_serverRestart_clicked()
switcher->networkConfig.LockToIPv4); switcher->networkConfig.LockToIPv4);
} }
void AdvSceneSwitcher::UpdateServerStatus() void AdvSceneSwitcher::updateServerStatus()
{ {
switch (switcher->serverStatus) { switch (switcher->serverStatus) {
case ServerStatus::NOT_RUNNING: case ServerStatus::NOT_RUNNING:
@@ -672,7 +670,7 @@ void AdvSceneSwitcher::on_clientReconnect_clicked()
switcher->client.connect(switcher->networkConfig.GetClientUri()); switcher->client.connect(switcher->networkConfig.GetClientUri());
} }
void AdvSceneSwitcher::UpdateClientStatus() void AdvSceneSwitcher::updateClientStatus()
{ {
switch (switcher->clientStatus) { switch (switcher->clientStatus) {
case ClientStatus::DISCONNECTED: case ClientStatus::DISCONNECTED:
@@ -711,5 +709,3 @@ Compatability::StdFunctionRunnable::StdFunctionRunnable(
: cb(std::move(func)) : cb(std::move(func))
{ {
} }
} // namespace advss

View File

@@ -19,13 +19,11 @@ Most of this code is based on https://github.com/Palakis/obs-websocket
#include <websocketpp/server.hpp> #include <websocketpp/server.hpp>
#include <websocketpp/client.hpp> #include <websocketpp/client.hpp>
namespace advss {
using websocketpp::connection_hdl; using websocketpp::connection_hdl;
typedef websocketpp::server<websocketpp::config::asio> server; typedef websocketpp::server<websocketpp::config::asio> server;
typedef websocketpp::client<websocketpp::config::asio_client> client; typedef websocketpp::client<websocketpp::config::asio_client> client;
struct SceneSwitchInfo; struct sceneSwitchInfo;
class NetworkConfig { class NetworkConfig {
public: public:
@@ -62,7 +60,7 @@ public:
virtual ~WSServer(); virtual ~WSServer();
void start(quint16 port, bool lockToIPv4); void start(quint16 port, bool lockToIPv4);
void stop(); void stop();
void sendMessage(SceneSwitchInfo sceneSwitch, bool preview = false); void sendMessage(sceneSwitchInfo sceneSwitch, bool preview = false);
QThreadPool *threadPool() { return &_threadPool; } QThreadPool *threadPool() { return &_threadPool; }
private: private:
@@ -133,5 +131,3 @@ public:
QRunnable *CreateFunctionRunnable(std::function<void()> func); QRunnable *CreateFunctionRunnable(std::function<void()> func);
} }
} // namespace advss

View File

@@ -1,10 +1,7 @@
#include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "utility.hpp"
#include <regex> #include <regex>
namespace advss { #include "advanced-scene-switcher.hpp"
#include "utility.hpp"
static QMetaObject::Connection addPulse; static QMetaObject::Connection addPulse;
@@ -247,7 +244,7 @@ void SwitcherData::loadPauseSwitches(obs_data_t *obj)
obs_data_array_release(pauseArray); obs_data_array_release(pauseArray);
} }
void AdvSceneSwitcher::SetupPauseTab() void AdvSceneSwitcher::setupPauseTab()
{ {
for (auto &s : switcher->pauseEntries) { for (auto &s : switcher->pauseEntries) {
QListWidgetItem *item; QListWidgetItem *item;
@@ -312,7 +309,7 @@ PauseEntryWidget::PauseEntryWidget(QWidget *parent, PauseEntry *s)
populatePauseTypes(pauseTypes); populatePauseTypes(pauseTypes);
populatePauseTargets(pauseTargets); populatePauseTargets(pauseTargets);
PopulateWindowSelection(windows); populateWindowSelection(windows);
windows->setEditable(true); windows->setEditable(true);
windows->setMaxVisibleItems(20); windows->setMaxVisibleItems(20);
@@ -338,7 +335,7 @@ PauseEntryWidget::PauseEntryWidget(QWidget *parent, PauseEntry *s)
{"{{pauseTargets}}", pauseTargets}, {"{{pauseTargets}}", pauseTargets},
{"{{windows}}", windows}}; {"{{windows}}", windows}};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.pauseTab.pauseEntry"), placeWidgets(obs_module_text("AdvSceneSwitcher.pauseTab.pauseEntry"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
setLayout(mainLayout); setLayout(mainLayout);
@@ -413,5 +410,3 @@ bool PauseEntry::valid()
{ {
return true; return true;
} }
} // namespace advss

View File

@@ -8,8 +8,6 @@
#pragma once #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"
namespace advss {
enum class PauseType { enum class PauseType {
Scene, Scene,
Window, Window,
@@ -72,5 +70,3 @@ private:
PauseEntry *switchData; PauseEntry *switchData;
}; };
} // namespace advss

View File

@@ -0,0 +1,78 @@
#include <algorithm>
#include "advanced-scene-switcher.hpp"
void AdvSceneSwitcher::on_threadPriority_currentTextChanged(const QString &text)
{
if (loading || ui->threadPriority->count() !=
(int)switcher->threadPriorities.size())
return;
std::lock_guard<std::mutex> lock(switcher->m);
for (auto p : switcher->threadPriorities) {
if (p.name == text.toUtf8().constData()) {
switcher->threadPriority = p.value;
break;
}
}
}
void AdvSceneSwitcher::on_priorityUp_clicked()
{
int currentIndex = ui->priorityList->currentRow();
if (currentIndex != -1 && currentIndex != 0) {
ui->priorityList->insertItem(
currentIndex - 1,
ui->priorityList->takeItem(currentIndex));
ui->priorityList->setCurrentRow(currentIndex - 1);
std::lock_guard<std::mutex> lock(switcher->m);
iter_swap(switcher->functionNamesByPriority.begin() +
currentIndex,
switcher->functionNamesByPriority.begin() +
currentIndex - 1);
}
ui->macroPriorityWarning->setVisible(
switcher->functionNamesByPriority[0] != macro_func);
}
void AdvSceneSwitcher::on_priorityDown_clicked()
{
int currentIndex = ui->priorityList->currentRow();
if (currentIndex != -1 &&
currentIndex != ui->priorityList->count() - 1) {
ui->priorityList->insertItem(
currentIndex + 1,
ui->priorityList->takeItem(currentIndex));
ui->priorityList->setCurrentRow(currentIndex + 1);
std::lock_guard<std::mutex> lock(switcher->m);
iter_swap(switcher->functionNamesByPriority.begin() +
currentIndex,
switcher->functionNamesByPriority.begin() +
currentIndex + 1);
}
ui->macroPriorityWarning->setVisible(
switcher->functionNamesByPriority[0] != macro_func);
}
bool SwitcherData::prioFuncsValid()
{
auto fNBPCopy = functionNamesByPriority;
std::sort(fNBPCopy.begin(), fNBPCopy.end());
auto it = std::unique(fNBPCopy.begin(), fNBPCopy.end());
bool wasUnique = (it == fNBPCopy.end());
if (!wasUnique) {
return false;
}
for (int p : functionNamesByPriority) {
if (p < 0 || p > 10) {
return false;
}
}
return true;
}

View File

@@ -1,10 +1,7 @@
#include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "utility.hpp"
#include <random> #include <random>
namespace advss { #include "advanced-scene-switcher.hpp"
#include "utility.hpp"
bool RandomSwitch::pause = false; bool RandomSwitch::pause = false;
static QMetaObject::Connection addPulse; static QMetaObject::Connection addPulse;
@@ -116,7 +113,7 @@ void SwitcherData::loadRandomSwitches(obs_data_t *obj)
obs_data_array_release(randomArray); obs_data_array_release(randomArray);
} }
void AdvSceneSwitcher::SetupRandomTab() void AdvSceneSwitcher::setupRandomTab()
{ {
for (auto &s : switcher->randomSwitches) { for (auto &s : switcher->randomSwitches) {
QListWidgetItem *item; QListWidgetItem *item;
@@ -143,7 +140,7 @@ void AdvSceneSwitcher::SetupRandomTab()
border-radius: 7px; \ border-radius: 7px; \
border-color: rgb(0,0,0,0) \ border-color: rgb(0,0,0,0) \
}"); }");
if (switcher->switchIfNotMatching != NoMatchBehavior::RANDOM_SWITCH) { if (switcher->switchIfNotMatching != RANDOM_SWITCH) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
PulseWidget(ui->randomDisabledWarning, QColor(Qt::red), PulseWidget(ui->randomDisabledWarning, QColor(Qt::red),
QColor(0, 0, 0, 0)); QColor(0, 0, 0, 0));
@@ -185,7 +182,7 @@ RandomSwitchWidget::RandomSwitchWidget(QWidget *parent, RandomSwitch *s)
{"{{scenes}}", scenes}, {"{{scenes}}", scenes},
{"{{transitions}}", transitions}, {"{{transitions}}", transitions},
{"{{delay}}", delay}}; {"{{delay}}", delay}};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.randomTab.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.randomTab.entry"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
setLayout(mainLayout); setLayout(mainLayout);
@@ -223,5 +220,3 @@ void RandomSwitchWidget::DelayChanged(double d)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switchData->delay = d; switchData->delay = d;
} }
} // namespace advss

View File

@@ -8,8 +8,6 @@
#pragma once #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"
namespace advss {
struct RandomSwitch : SceneSwitcherEntry { struct RandomSwitch : SceneSwitcherEntry {
static bool pause; static bool pause;
double delay = 0.0; double delay = 0.0;
@@ -38,5 +36,3 @@ private:
RandomSwitch *switchData; RandomSwitch *switchData;
}; };
} // namespace advss

View File

@@ -1,15 +1,12 @@
#include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "utility.hpp"
#include <QTimer> #include <QTimer>
namespace advss { #include "advanced-scene-switcher.hpp"
#include "utility.hpp"
bool ScreenRegionSwitch::pause = false; bool ScreenRegionSwitch::pause = false;
static QMetaObject::Connection addPulse; static QMetaObject::Connection addPulse;
void AdvSceneSwitcher::ClearFrames(QListWidget *list) void AdvSceneSwitcher::clearFrames(QListWidget *list)
{ {
for (int i = 0; i < list->count(); ++i) { for (int i = 0; i < list->count(); ++i) {
ScreenRegionWidget *sw = ScreenRegionWidget *sw =
@@ -51,7 +48,7 @@ void AdvSceneSwitcher::on_showFrame_clicked()
showCurrentFrame(ui->screenRegionSwitches); showCurrentFrame(ui->screenRegionSwitches);
} else { } else {
SetShowFrames(); SetShowFrames();
ClearFrames(ui->screenRegionSwitches); clearFrames(ui->screenRegionSwitches);
} }
} }
@@ -62,7 +59,7 @@ void AdvSceneSwitcher::on_screenRegionSwitches_currentRowChanged(int idx)
} }
if (switcher->showFrame) { if (switcher->showFrame) {
ClearFrames(ui->screenRegionSwitches); clearFrames(ui->screenRegionSwitches);
showCurrentFrame(ui->screenRegionSwitches); showCurrentFrame(ui->screenRegionSwitches);
} }
} }
@@ -156,7 +153,7 @@ bool SwitcherData::checkScreenRegionSwitch(OBSWeakSource &scene,
return false; return false;
} }
std::pair<int, int> cursorPos = GetCursorPos(); std::pair<int, int> cursorPos = getCursorPos();
int minRegionSize = 99999; int minRegionSize = 99999;
bool match = false; bool match = false;
@@ -191,7 +188,7 @@ bool SwitcherData::checkScreenRegionSwitch(OBSWeakSource &scene,
void AdvSceneSwitcher::updateScreenRegionCursorPos() void AdvSceneSwitcher::updateScreenRegionCursorPos()
{ {
std::pair<int, int> position = GetCursorPos(); std::pair<int, int> position = getCursorPos();
ui->cursorXPosition->setText(QString::number(position.first)); ui->cursorXPosition->setText(QString::number(position.first));
ui->cursorYPosition->setText(QString::number(position.second)); ui->cursorYPosition->setText(QString::number(position.second));
} }
@@ -231,7 +228,7 @@ void SwitcherData::loadScreenRegionSwitches(obs_data_t *obj)
obs_data_array_release(screenRegionArray); obs_data_array_release(screenRegionArray);
} }
void AdvSceneSwitcher::SetupRegionTab() void AdvSceneSwitcher::setupRegionTab()
{ {
for (auto &s : switcher->screenRegionSwitches) { for (auto &s : switcher->screenRegionSwitches) {
QListWidgetItem *item; QListWidgetItem *item;
@@ -321,7 +318,7 @@ ScreenRegionWidget::ScreenRegionWidget(QWidget *parent, ScreenRegionSwitch *s)
QWidget::connect(maxY, SIGNAL(valueChanged(int)), this, QWidget::connect(maxY, SIGNAL(valueChanged(int)), this,
SLOT(MaxYChanged(int))); SLOT(MaxYChanged(int)));
PopulateSceneSelection( populateSceneSelection(
excludeScenes, false, false, false, false, nullptr, true, excludeScenes, false, false, false, false, nullptr, true,
obs_module_text( obs_module_text(
"AdvSceneSwitcher.screenRegionTab.excludeScenes.None"), "AdvSceneSwitcher.screenRegionTab.excludeScenes.None"),
@@ -345,7 +342,7 @@ ScreenRegionWidget::ScreenRegionWidget(QWidget *parent, ScreenRegionSwitch *s)
{"{{scenes}}", scenes}, {"{{scenes}}", scenes},
{"{{transitions}}", transitions}, {"{{transitions}}", transitions},
{"{{excludeScenes}}", excludeScenes}}; {"{{excludeScenes}}", excludeScenes}};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.screenRegionTab.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.screenRegionTab.entry"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
setLayout(mainLayout); setLayout(mainLayout);
@@ -458,5 +455,3 @@ void ScreenRegionWidget::drawFrame()
switchData->maxY - switchData->minY); switchData->maxY - switchData->minY);
} }
} }
} // namespace advss

View File

@@ -9,8 +9,6 @@
#include <QSpinBox> #include <QSpinBox>
#include "switch-generic.hpp" #include "switch-generic.hpp"
namespace advss {
constexpr auto screen_region_func = 4; constexpr auto screen_region_func = 4;
struct ScreenRegionSwitch : SceneSwitcherEntry { struct ScreenRegionSwitch : SceneSwitcherEntry {
@@ -57,5 +55,3 @@ private:
void drawFrame(); void drawFrame();
}; };
} // namespace advss

View File

@@ -1,12 +1,9 @@
#include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "utility.hpp"
#include <QFileDialog> #include <QFileDialog>
#include <QTextStream> #include <QTextStream>
#include <QScrollArea> #include <QScrollArea>
namespace advss { #include "advanced-scene-switcher.hpp"
#include "utility.hpp"
constexpr auto max_extend_text_size = 150; constexpr auto max_extend_text_size = 150;
@@ -281,7 +278,7 @@ void SwitcherData::loadSceneSequenceSwitches(obs_data_t *obj)
obs_data_array_release(sceneSequenceArray); obs_data_array_release(sceneSequenceArray);
} }
void AdvSceneSwitcher::SetupSequenceTab() void AdvSceneSwitcher::setupSequenceTab()
{ {
for (auto &s : switcher->sceneSequenceSwitches) { for (auto &s : switcher->sceneSequenceSwitches) {
QListWidgetItem *item; QListWidgetItem *item;
@@ -458,7 +455,7 @@ bool SceneSequenceSwitch::checkDurationMatchInterruptible()
void SceneSequenceSwitch::prepareUninterruptibleMatch(int &linger) void SceneSequenceSwitch::prepareUninterruptibleMatch(int &linger)
{ {
int dur = delay.Milliseconds(); int dur = delay.seconds * 1000;
if (dur > 0) { if (dur > 0) {
linger = dur; linger = dur;
} }
@@ -591,8 +588,10 @@ 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(const Duration &)), this, QWidget::connect(delay, SIGNAL(DurationChanged(double)), this,
SLOT(DelayChanged(const Duration &))); SLOT(DelayChanged(double)));
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 &)));
@@ -604,7 +603,7 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s,
QWidget::connect(reduce, SIGNAL(clicked()), this, QWidget::connect(reduce, SIGNAL(clicked()), this,
SLOT(ReduceClicked())); SLOT(ReduceClicked()));
PopulateSceneSelection(startScenes); populateSceneSelection(startScenes);
interruptible->setToolTip(obs_module_text( interruptible->setToolTip(obs_module_text(
"AdvSceneSwitcher.sceneSequenceTab.interruptibleHint")); "AdvSceneSwitcher.sceneSequenceTab.interruptibleHint"));
@@ -616,7 +615,7 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s,
{"{{scenes}}", scenes}, {"{{scenes}}", scenes},
{"{{delay}}", delay}, {"{{delay}}", delay},
{"{{transitions}}", transitions}}; {"{{transitions}}", transitions}};
PlaceWidgets( placeWidgets(
obs_module_text( obs_module_text(
"AdvSceneSwitcher.sceneSequenceTab.extendEntry"), "AdvSceneSwitcher.sceneSequenceTab.extendEntry"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
@@ -629,7 +628,7 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s,
{"{{delay}}", delay}, {"{{delay}}", delay},
{"{{transitions}}", transitions}, {"{{transitions}}", transitions},
{"{{interruptible}}", interruptible}}; {"{{interruptible}}", interruptible}};
PlaceWidgets(obs_module_text( placeWidgets(obs_module_text(
"AdvSceneSwitcher.sceneSequenceTab.entry"), "AdvSceneSwitcher.sceneSequenceTab.entry"),
startSequence, widgetPlaceholders); startSequence, widgetPlaceholders);
@@ -690,14 +689,24 @@ void SequenceWidget::swapSwitchData(SequenceWidget *s1, SequenceWidget *s2)
s2->setSwitchData(t); s2->setSwitchData(t);
} }
void SequenceWidget::DelayChanged(const Duration &delay) void SequenceWidget::DelayChanged(double sec)
{ {
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 = delay; switchData->delay.seconds = sec;
}
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()
@@ -796,5 +805,3 @@ void SequenceWidget::ReduceClicked()
delete item; delete item;
} }
} }
} // namespace advss

View File

@@ -11,8 +11,6 @@
#include "switch-generic.hpp" #include "switch-generic.hpp"
#include "duration-control.hpp" #include "duration-control.hpp"
namespace advss {
constexpr auto round_trip_func = 1; constexpr auto round_trip_func = 1;
struct SceneSequenceSwitch : SceneSwitcherEntry { struct SceneSequenceSwitch : SceneSwitcherEntry {
@@ -61,7 +59,8 @@ public:
private slots: private slots:
void SceneChanged(const QString &text); void SceneChanged(const QString &text);
void DelayChanged(const Duration &delay); void DelayChanged(double 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();
@@ -84,5 +83,3 @@ protected:
SceneSequenceSwitch *switchData; SceneSequenceSwitch *switchData;
}; };
} // namespace advss

View File

@@ -1,9 +1,6 @@
#include "advanced-scene-switcher.hpp" #include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "utility.hpp" #include "utility.hpp"
namespace advss {
bool TimeSwitch::pause = false; bool TimeSwitch::pause = false;
static QMetaObject::Connection addPulse; static QMetaObject::Connection addPulse;
@@ -182,7 +179,7 @@ void SwitcherData::loadTimeSwitches(obs_data_t *obj)
obs_data_array_release(timeArray); obs_data_array_release(timeArray);
} }
void AdvSceneSwitcher::SetupTimeTab() void AdvSceneSwitcher::setupTimeTab()
{ {
for (auto &s : switcher->timeSwitches) { for (auto &s : switcher->timeSwitches) {
QListWidgetItem *item; QListWidgetItem *item;
@@ -261,7 +258,7 @@ TimeSwitchWidget::TimeSwitchWidget(QWidget *parent, TimeSwitch *s)
{"{{time}}", time}, {"{{time}}", time},
{"{{scenes}}", scenes}, {"{{scenes}}", scenes},
{"{{transitions}}", transitions}}; {"{{transitions}}", transitions}};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.timeTab.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.timeTab.entry"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
setLayout(mainLayout); setLayout(mainLayout);
@@ -309,5 +306,3 @@ void TimeSwitchWidget::TimeChanged(const QTime &time)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switchData->time = time; switchData->time = time;
} }
} // namespace advss

View File

@@ -10,8 +10,6 @@
#include "switch-generic.hpp" #include "switch-generic.hpp"
namespace advss {
constexpr auto time_func = 7; constexpr auto time_func = 7;
typedef enum { typedef enum {
@@ -56,5 +54,3 @@ private:
TimeSwitch *switchData; TimeSwitch *switchData;
}; };
} // namespace advss

View File

@@ -1,10 +1,7 @@
#include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "utility.hpp"
#include <thread> #include <thread>
namespace advss { #include "advanced-scene-switcher.hpp"
#include "utility.hpp"
constexpr auto default_def_transition_dealy = 300; constexpr auto default_def_transition_dealy = 300;
bool DefaultSceneTransition::pause = false; bool DefaultSceneTransition::pause = false;
@@ -172,7 +169,7 @@ void SwitcherData::checkDefaultSceneTransitions()
} }
} }
void AdvSceneSwitcher::DefTransitionDelayValueChanged(int value) void AdvSceneSwitcher::defTransitionDelayValueChanged(int value)
{ {
if (loading) { if (loading) {
return; return;
@@ -182,6 +179,104 @@ void AdvSceneSwitcher::DefTransitionDelayValueChanged(int value)
DefaultSceneTransition::delay = value; DefaultSceneTransition::delay = value;
} }
std::pair<obs_weak_source_t *, int> getNextTransition(obs_weak_source_t *scene1,
obs_weak_source_t *scene2)
{
obs_weak_source_t *ws = nullptr;
int duration = 0;
if (scene1 && scene2) {
for (SceneTransition &t : switcher->sceneTransitions) {
if (!t.initialized()) {
continue;
}
if (t.scene == scene1 && t.scene2 == scene2) {
ws = t.transition;
duration = t.duration * 1000;
break;
}
}
}
return std::make_pair(ws, duration);
}
void overwriteTransitionOverride(const sceneSwitchInfo &ssi, transitionData &td)
{
obs_source_t *scene = obs_weak_source_get_source(ssi.scene);
obs_data_t *data = obs_source_get_private_settings(scene);
td.name = obs_data_get_string(data, "transition");
td.duration = obs_data_get_int(data, "transition_duration");
std::string name = GetWeakSourceName(ssi.transition);
obs_data_set_string(data, "transition", name.c_str());
obs_data_set_int(data, "transition_duration", ssi.duration);
obs_data_release(data);
obs_source_release(scene);
}
void restoreTransitionOverride(obs_source_t *scene, const transitionData &td)
{
obs_data_t *data = obs_source_get_private_settings(scene);
obs_data_set_string(data, "transition", td.name.c_str());
obs_data_set_int(data, "transition_duration", td.duration);
obs_data_release(data);
}
void setNextTransition(const sceneSwitchInfo &sceneSwitch,
obs_source_t *currentSource, transitionData &td)
{
// Priority:
// 1. Transition tab
// 2. Individual switcher entry
// 3. Current transition settings
// Transition Tab
obs_weak_source_t *currentScene =
obs_source_get_weak_source(currentSource);
auto tinfo = getNextTransition(currentScene, sceneSwitch.scene);
obs_weak_source_release(currentScene);
OBSWeakSource nextTransition = tinfo.first;
int nextTransitionDuration = tinfo.second;
// Individual switcher entry
if (!nextTransition) {
nextTransition = sceneSwitch.transition;
}
if (!nextTransitionDuration) {
nextTransitionDuration = sceneSwitch.duration;
}
// Current transition settings
if (!nextTransition) {
auto ct = obs_frontend_get_current_transition();
nextTransition = obs_source_get_weak_source(ct);
obs_weak_source_release(nextTransition);
obs_source_release(ct);
}
if (!nextTransitionDuration) {
nextTransitionDuration = obs_frontend_get_transition_duration();
}
if (switcher->adjustActiveTransitionType) {
obs_frontend_set_transition_duration(nextTransitionDuration);
auto t = obs_weak_source_get_source(nextTransition);
obs_frontend_set_current_transition(t);
obs_source_release(t);
}
if (switcher->transitionOverrideOverride) {
overwriteTransitionOverride({sceneSwitch.scene, nextTransition,
nextTransitionDuration},
td);
}
}
void SwitcherData::saveSceneTransitions(obs_data_t *obj) void SwitcherData::saveSceneTransitions(obs_data_t *obj)
{ {
obs_data_array_t *sceneTransitionsArray = obs_data_array_create(); obs_data_array_t *sceneTransitionsArray = obs_data_array_create();
@@ -254,7 +349,7 @@ void SwitcherData::loadSceneTransitions(obs_data_t *obj)
obs_data_get_int(obj, "defTransitionDelay"); obs_data_get_int(obj, "defTransitionDelay");
} }
void AdvSceneSwitcher::SetupTransitionsTab() void AdvSceneSwitcher::setupTransitionsTab()
{ {
for (auto &s : switcher->sceneTransitions) { for (auto &s : switcher->sceneTransitions) {
QListWidgetItem *item; QListWidgetItem *item;
@@ -302,11 +397,11 @@ void AdvSceneSwitcher::SetupTransitionsTab()
"AdvSceneSwitcher.transitionTab.defaultTransition.delay.help")); "AdvSceneSwitcher.transitionTab.defaultTransition.delay.help"));
QWidget::connect(defTransitionDelay, SIGNAL(valueChanged(int)), this, QWidget::connect(defTransitionDelay, SIGNAL(valueChanged(int)), this,
SLOT(DefTransitionDelayValueChanged(int))); SLOT(defTransitionDelayValueChanged(int)));
std::unordered_map<std::string, QWidget *> widgetPlaceholders = { std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{defTransitionDelay}}", defTransitionDelay}}; {"{{defTransitionDelay}}", defTransitionDelay}};
PlaceWidgets( placeWidgets(
obs_module_text( obs_module_text(
"AdvSceneSwitcher.transitionTab.defaultTransition.delay"), "AdvSceneSwitcher.transitionTab.defaultTransition.delay"),
ui->defTransitionDelayLayout, widgetPlaceholders); ui->defTransitionDelayLayout, widgetPlaceholders);
@@ -354,7 +449,7 @@ TransitionSwitchWidget::TransitionSwitchWidget(QWidget *parent,
QWidget::connect(duration, SIGNAL(valueChanged(double)), this, QWidget::connect(duration, SIGNAL(valueChanged(double)), this,
SLOT(DurationChanged(double))); SLOT(DurationChanged(double)));
PopulateSceneSelection(scenes2); populateSceneSelection(scenes2);
if (s) { if (s) {
scenes2->setCurrentText(GetWeakSourceName(s->scene2).c_str()); scenes2->setCurrentText(GetWeakSourceName(s->scene2).c_str());
@@ -367,7 +462,7 @@ TransitionSwitchWidget::TransitionSwitchWidget(QWidget *parent,
{"{{scenes2}}", scenes2}, {"{{scenes2}}", scenes2},
{"{{duration}}", duration}, {"{{duration}}", duration},
{"{{transitions}}", transitions}}; {"{{transitions}}", transitions}};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.transitionTab.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.transitionTab.entry"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
setLayout(mainLayout); setLayout(mainLayout);
@@ -423,7 +518,7 @@ DefTransitionSwitchWidget::DefTransitionSwitchWidget(QWidget *parent,
QHBoxLayout *mainLayout = new QHBoxLayout; QHBoxLayout *mainLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = { std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{scenes}}", scenes}, {"{{transitions}}", transitions}}; {"{{scenes}}", scenes}, {"{{transitions}}", transitions}};
PlaceWidgets( placeWidgets(
obs_module_text( obs_module_text(
"AdvSceneSwitcher.transitionTab.defaultTransitionEntry"), "AdvSceneSwitcher.transitionTab.defaultTransitionEntry"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
@@ -497,5 +592,3 @@ void DefaultSceneTransition::setTransition()
t = std::thread(setTransitionDelayed, transition, delay); t = std::thread(setTransitionDelayed, transition, delay);
t.detach(); t.detach();
} }
} // namespace advss

View File

@@ -3,8 +3,6 @@
#include "switch-generic.hpp" #include "switch-generic.hpp"
namespace advss {
struct SceneTransition : SceneSwitcherEntry { struct SceneTransition : SceneSwitcherEntry {
OBSWeakSource scene2 = nullptr; OBSWeakSource scene2 = nullptr;
double duration = 0.3; double duration = 0.3;
@@ -79,5 +77,3 @@ public:
private: private:
DefaultSceneTransition *switchData; DefaultSceneTransition *switchData;
}; };
} // namespace advss

View File

@@ -1,13 +1,10 @@
#include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "utility.hpp"
#include <QFileDialog> #include <QFileDialog>
#include <QBuffer> #include <QBuffer>
#include <QToolTip> #include <QToolTip>
#include <thread> #include <thread>
namespace advss { #include "advanced-scene-switcher.hpp"
#include "utility.hpp"
bool VideoSwitch::pause = false; bool VideoSwitch::pause = false;
static QMetaObject::Connection addPulse; static QMetaObject::Connection addPulse;
@@ -185,7 +182,7 @@ void SwitcherData::loadVideoSwitches(obs_data_t *obj)
obs_data_array_release(videoArray); obs_data_array_release(videoArray);
} }
void AdvSceneSwitcher::SetupVideoTab() void AdvSceneSwitcher::setupVideoTab()
{ {
for (auto &s : switcher->videoSwitches) { for (auto &s : switcher->videoSwitches) {
QListWidgetItem *item; QListWidgetItem *item;
@@ -431,7 +428,7 @@ VideoSwitchWidget::VideoSwitchWidget(QWidget *parent, VideoSwitch *s)
{"{{ignoreInactiveSource}}", ignoreInactiveSource}, {"{{ignoreInactiveSource}}", ignoreInactiveSource},
{"{{scenes}}", scenes}, {"{{scenes}}", scenes},
{"{{transitions}}", transitions}}; {"{{transitions}}", transitions}};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.videoTab.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.videoTab.entry"),
switchLayout, widgetPlaceholders); switchLayout, widgetPlaceholders);
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout;
@@ -580,5 +577,3 @@ void VideoSwitchWidget::IgnoreInactiveChanged(int state)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switchData->ignoreInactiveSource = state; switchData->ignoreInactiveSource = state;
} }
} // namespace advss

View File

@@ -11,8 +11,6 @@
#include "switch-generic.hpp" #include "switch-generic.hpp"
#include "screenshot-helper.hpp" #include "screenshot-helper.hpp"
namespace advss {
constexpr auto video_func = 9; constexpr auto video_func = 9;
enum class videoSwitchType { enum class videoSwitchType {
@@ -82,5 +80,3 @@ private:
VideoSwitch *switchData; VideoSwitch *switchData;
}; };
} // namespace advss

View File

@@ -1,11 +1,7 @@
#include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "platform-funcs.hpp"
#include "utility.hpp"
#include <regex> #include <regex>
namespace advss { #include "advanced-scene-switcher.hpp"
#include "utility.hpp"
bool WindowSwitch::pause = false; bool WindowSwitch::pause = false;
static QMetaObject::Connection addPulse; static QMetaObject::Connection addPulse;
@@ -181,8 +177,8 @@ void checkWindowTitleSwitchDirect(WindowSwitch &s,
OBSWeakSource &transition) OBSWeakSource &transition)
{ {
bool focus = (!s.focus || s.window == currentWindowTitle); bool focus = (!s.focus || s.window == currentWindowTitle);
bool fullscreen = (!s.fullscreen || IsFullscreen(s.window)); bool fullscreen = (!s.fullscreen || isFullscreen(s.window));
bool max = (!s.maximized || IsMaximized(s.window)); bool max = (!s.maximized || isMaximized(s.window));
if (focus && fullscreen && max) { if (focus && fullscreen && max) {
match = true; match = true;
@@ -207,8 +203,8 @@ void checkWindowTitleSwitchRegex(WindowSwitch &s,
} }
bool focus = (!s.focus || window == currentWindowTitle); bool focus = (!s.focus || window == currentWindowTitle);
bool fullscreen = (!s.fullscreen || IsFullscreen(window)); bool fullscreen = (!s.fullscreen || isFullscreen(window));
bool max = (!s.maximized || IsMaximized(window)); bool max = (!s.maximized || isMaximized(window));
if (focus && fullscreen && max) { if (focus && fullscreen && max) {
match = true; match = true;
@@ -319,7 +315,7 @@ void SwitcherData::loadWindowTitleSwitches(obs_data_t *obj)
obs_data_array_release(ignoreWindowsArray); obs_data_array_release(ignoreWindowsArray);
} }
void AdvSceneSwitcher::SetupTitleTab() void AdvSceneSwitcher::setupTitleTab()
{ {
for (auto &s : switcher->windowSwitches) { for (auto &s : switcher->windowSwitches) {
QListWidgetItem *item; QListWidgetItem *item;
@@ -340,7 +336,7 @@ void AdvSceneSwitcher::SetupTitleTab()
ui->windowHelp->setVisible(false); ui->windowHelp->setVisible(false);
} }
PopulateWindowSelection(ui->ignoreWindowsWindows); populateWindowSelection(ui->ignoreWindowsWindows);
for (auto &window : switcher->ignoreWindowsSwitches) { for (auto &window : switcher->ignoreWindowsSwitches) {
QString text = QString::fromStdString(window); QString text = QString::fromStdString(window);
@@ -398,7 +394,7 @@ WindowSwitchWidget::WindowSwitchWidget(QWidget *parent, WindowSwitch *s)
QWidget::connect(focused, SIGNAL(stateChanged(int)), this, QWidget::connect(focused, SIGNAL(stateChanged(int)), this,
SLOT(FocusChanged(int))); SLOT(FocusChanged(int)));
PopulateWindowSelection(windows); populateWindowSelection(windows);
windows->setEditable(true); windows->setEditable(true);
windows->setMaxVisibleItems(20); windows->setMaxVisibleItems(20);
@@ -418,7 +414,7 @@ WindowSwitchWidget::WindowSwitchWidget(QWidget *parent, WindowSwitch *s)
{"{{fullscreen}}", fullscreen}, {"{{fullscreen}}", fullscreen},
{"{{maximized}}", maximized}, {"{{maximized}}", maximized},
{"{{focused}}", focused}}; {"{{focused}}", focused}};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.windowTitleTab.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.windowTitleTab.entry"),
mainLayout, widgetPlaceholders); mainLayout, widgetPlaceholders);
setLayout(mainLayout); setLayout(mainLayout);
@@ -486,5 +482,3 @@ void WindowSwitchWidget::FocusChanged(int state)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
switchData->focus = state; switchData->focus = state;
} }
} // namespace advss

View File

@@ -8,8 +8,6 @@
#pragma once #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"
namespace advss {
constexpr auto window_title_func = 5; constexpr auto window_title_func = 5;
struct WindowSwitch : SceneSwitcherEntry { struct WindowSwitch : SceneSwitcherEntry {
@@ -49,5 +47,3 @@ private:
WindowSwitch *switchData; WindowSwitch *switchData;
}; };
} // namespace advss

View File

@@ -1,6 +1,5 @@
#include "platform-funcs.hpp" #include "platform-funcs.hpp"
#include "hotkey.hpp" #include "hotkey.hpp"
#include "log-helper.hpp"
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
@@ -26,17 +25,14 @@
#include <QStringList> #include <QStringList>
#include <QRegularExpression> #include <QRegularExpression>
#include <QLibrary> #include <QLibrary>
#ifdef PROCPS_AVAILABLE #ifdef USE_PROCPS
#include <proc/readproc.h> #include <proc/readproc.h>
#endif #else
#ifdef PROCPS2_AVAILABLE
#include <libproc2/pids.h> #include <libproc2/pids.h>
#endif #endif
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
namespace advss {
static Display *xdisplay = 0; static Display *xdisplay = 0;
static QLibrary *libXtstHandle = nullptr; static QLibrary *libXtstHandle = nullptr;
@@ -55,31 +51,6 @@ std::chrono::high_resolution_clock::time_point lastMouseLeftClickTime{};
std::chrono::high_resolution_clock::time_point lastMouseMiddleClickTime{}; std::chrono::high_resolution_clock::time_point lastMouseMiddleClickTime{};
std::chrono::high_resolution_clock::time_point lastMouseRightClickTime{}; std::chrono::high_resolution_clock::time_point lastMouseRightClickTime{};
static QLibrary *libprocps = nullptr;
#ifdef PROCPS_AVAILABLE
typedef PROCTAB *(*openproc_func)(int flags);
typedef void (*closeproc_func)(PROCTAB *PT);
typedef proc_t *(*readproc_func)(PROCTAB *__restrict const PT,
proc_t *__restrict p);
static openproc_func openproc_ = nullptr;
static closeproc_func closeproc_ = nullptr;
static readproc_func readproc_ = nullptr;
#endif
static bool libprocpsSupported = false;
static QLibrary *libproc2 = nullptr;
#ifdef PROCPS2_AVAILABLE
typedef int (*procps_pids_new_func)(struct pids_info **info,
enum pids_item *items, int numitems);
typedef struct pids_stack *(*procps_pids_get_func)(struct pids_info *info,
enum pids_fetch_type which);
typedef int (*procps_pids_unref_func)(struct pids_info **info);
static procps_pids_new_func procps_pids_new_ = nullptr;
static procps_pids_get_func procps_pids_get_ = nullptr;
static procps_pids_unref_func procps_pids_unref_ = nullptr;
#endif
static bool libprocps2Supported = false;
Display *disp() Display *disp()
{ {
if (!xdisplay) { if (!xdisplay) {
@@ -344,7 +315,7 @@ bool windowStatesAreSet(const std::string &windowTitle,
return false; return false;
} }
bool IsMaximized(const std::string &title) bool isMaximized(const std::string &title)
{ {
std::vector<QString> states; std::vector<QString> states;
states.emplace_back("_NET_WM_STATE_MAXIMIZED_VERT"); states.emplace_back("_NET_WM_STATE_MAXIMIZED_VERT");
@@ -352,70 +323,53 @@ bool IsMaximized(const std::string &title)
return windowStatesAreSet(title, states); return windowStatesAreSet(title, states);
} }
bool IsFullscreen(const std::string &title) bool isFullscreen(const std::string &title)
{ {
std::vector<QString> states; std::vector<QString> states;
states.emplace_back("_NET_WM_STATE_FULLSCREEN"); states.emplace_back("_NET_WM_STATE_FULLSCREEN");
return windowStatesAreSet(title, states); return windowStatesAreSet(title, states);
} }
std::optional<std::string> GetTextInWindow(const std::string &) #ifdef USE_PROCPS
void GetProcessList(QStringList &processes)
{ {
// Not implemented processes.clear();
return {}; PROCTAB *proc = openproc(PROC_FILLSTAT);
}
static void getProcessListProcps(QStringList &processes)
{
#ifdef PROCPS_AVAILABLE
PROCTAB *proc = openproc_(PROC_FILLSTAT);
proc_t proc_info; proc_t proc_info;
memset(&proc_info, 0, sizeof(proc_info)); memset(&proc_info, 0, sizeof(proc_info));
while (readproc_(proc, &proc_info) != NULL) { while (readproc(proc, &proc_info) != NULL) {
QString procName(proc_info.cmd); QString procName(proc_info.cmd);
if (!procName.isEmpty() && !processes.contains(procName)) { if (!procName.isEmpty() && !processes.contains(procName)) {
processes << procName; processes << procName;
} }
} }
closeproc_(proc); closeproc(proc);
#endif
} }
#else
static void getProcessListProcps2(QStringList &processes) void GetProcessList(QStringList &processes)
{ {
#ifdef PROCPS2_AVAILABLE processes.clear();
struct pids_info *info = NULL; struct pids_info *info = NULL;
struct pids_stack *stack; struct pids_stack *stack;
enum pids_item Items[] = { enum pids_item Items[] = {
PIDS_CMD, PIDS_CMD,
}; };
if (procps_pids_new_(&info, Items, sizeof(Items) / sizeof(Items[0])) < if (procps_pids_new(&info, Items, sizeof(Items) / sizeof(Items[0])) <
0) { 0) {
return; return;
} }
while ((stack = procps_pids_get_(info, PIDS_FETCH_TASKS_ONLY))) {
while ((stack = procps_pids_get(info, PIDS_FETCH_TASKS_ONLY))) {
auto cmd = PIDS_VAL(0, str, stack, info); auto cmd = PIDS_VAL(0, str, stack, info);
QString procName(cmd); QString procName(cmd);
if (!procName.isEmpty() && !processes.contains(procName)) { if (!procName.isEmpty() && !processes.contains(procName)) {
processes << procName; processes << procName;
} }
} }
procps_pids_unref_(&info); procps_pids_unref(&info);
}
#endif #endif
}
void GetProcessList(QStringList &processes)
{
processes.clear();
if (libprocpsSupported) {
getProcessListProcps(processes);
return;
}
if (libprocps2Supported) {
getProcessListProcps2(processes);
}
}
long getForegroundProcessPid() long getForegroundProcessPid()
{ {
@@ -474,7 +428,7 @@ void GetForegroundProcessName(std::string &proc)
proc = getProcNameFromPid(pid); proc = getProcNameFromPid(pid);
} }
bool IsInFocus(const QString &executable) bool isInFocus(const QString &executable)
{ {
std::string current; std::string current;
GetForegroundProcessName(current); GetForegroundProcessName(current);
@@ -488,7 +442,7 @@ bool IsInFocus(const QString &executable)
return (equals || matches); return (equals || matches);
} }
int SecondsSinceLastInput() int secondsSinceLastInput()
{ {
if (!canGetIdleTime) { if (!canGetIdleTime) {
return 0; return 0;
@@ -671,58 +625,6 @@ void PressKeys(const std::vector<HotkeyType> keys, int duration)
XFlush(display); XFlush(display);
} }
static void initXtst()
{
libXtstHandle = new QLibrary("libXtst", nullptr);
pressFunc = (keyPressFunc)libXtstHandle->resolve("XTestFakeKeyEvent");
int _;
canSimulateKeyPresses = pressFunc &&
XQueryExtension(disp(), "XTEST", &_, &_, &_);
}
static void initXss()
{
libXssHandle = new QLibrary("libXss", nullptr);
allocSSFunc = (XScreenSaverAllocInfoFunc)libXssHandle->resolve(
"XScreenSaverAllocInfo");
querySSFunc = (XScreenSaverQueryInfoFunc)libXssHandle->resolve(
"XScreenSaverQueryInfo");
int _;
canGetIdleTime = allocSSFunc && querySSFunc &&
XQueryExtension(disp(), ScreenSaverName, &_, &_, &_);
}
static void initProcps()
{
#ifdef PROCPS_AVAILABLE
libprocps = new QLibrary("libprocps", nullptr);
openproc_ = (openproc_func)libprocps->resolve("openproc");
closeproc_ = (closeproc_func)libprocps->resolve("closeproc");
readproc_ = (readproc_func)libprocps->resolve("readproc");
if (openproc_ && closeproc_ && readproc_) {
libprocpsSupported = true;
blog(LOG_INFO, "libprocps symbols resolved successfully!");
}
#endif
}
static void initProc2()
{
#ifdef PROCPS2_AVAILABLE
libproc2 = new QLibrary("libproc2", nullptr);
procps_pids_new_ =
(procps_pids_new_func)libproc2->resolve("procps_pids_new");
procps_pids_get_ =
(procps_pids_get_func)libproc2->resolve("procps_pids_get");
procps_pids_unref_ =
(procps_pids_unref_func)libproc2->resolve("procps_pids_unref");
if (procps_pids_new_ && procps_pids_get_ && procps_pids_unref_) {
libprocps2Supported = true;
blog(LOG_INFO, "libproc2 symbols resolved successfully!");
}
#endif
}
void PlatformInit() void PlatformInit()
{ {
auto display = disp(); auto display = disp();
@@ -730,27 +632,30 @@ void PlatformInit()
return; return;
} }
initXtst(); libXtstHandle = new QLibrary("libXtst", nullptr);
initXss(); pressFunc = (keyPressFunc)libXtstHandle->resolve("XTestFakeKeyEvent");
initProcps(); int _;
initProc2(); canSimulateKeyPresses = pressFunc &&
} XQueryExtension(disp(), "XTEST", &_, &_, &_);
static void cleanupHelper(QLibrary *lib) libXssHandle = new QLibrary("libXss", nullptr);
{ allocSSFunc = (XScreenSaverAllocInfoFunc)libXssHandle->resolve(
if (lib) { "XScreenSaverAllocInfo");
delete lib; querySSFunc = (XScreenSaverQueryInfoFunc)libXssHandle->resolve(
lib = nullptr; "XScreenSaverQueryInfo");
} canGetIdleTime = allocSSFunc && querySSFunc &&
XQueryExtension(disp(), ScreenSaverName, &_, &_, &_);
} }
void PlatformCleanup() void PlatformCleanup()
{ {
cleanupHelper(libXtstHandle); if (libXtstHandle) {
cleanupHelper(libXssHandle); delete libXtstHandle;
cleanupHelper(libprocps); libXtstHandle = nullptr;
cleanupHelper(libproc2); }
if (libXssHandle) {
delete libXssHandle;
libXssHandle = nullptr;
}
cleanupDisplay(); cleanupDisplay();
} }
} // namespace advss

View File

@@ -1,9 +1,7 @@
#include "macro-action-audio.hpp" #include "macro-action-audio.hpp"
#include "switcher-data.hpp" #include "advanced-scene-switcher.hpp"
#include "utility.hpp" #include "utility.hpp"
namespace advss {
constexpr int64_t nsPerMs = 1000000; constexpr int64_t nsPerMs = 1000000;
const std::string MacroActionAudio::id = "audio"; const std::string MacroActionAudio::id = "audio";
@@ -39,22 +37,6 @@ const static std::map<MacroActionAudio::FadeType, std::string> fadeTypes = {
constexpr auto fadeInterval = std::chrono::milliseconds(100); constexpr auto fadeInterval = std::chrono::milliseconds(100);
constexpr float minFade = 0.000001f; constexpr float minFade = 0.000001f;
// For backwards compatibility
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(29, 0, 0)
static float get_master_volume()
{
return 1.f;
}
static void set_master_volume(float)
{
return;
}
#else
auto get_master_volume = obs_get_master_volume;
auto set_master_volume = obs_set_master_volume;
#endif
void MacroActionAudio::SetFadeActive(bool value) void MacroActionAudio::SetFadeActive(bool value)
{ {
if (_action == Action::SOURCE_VOLUME) { if (_action == Action::SOURCE_VOLUME) {
@@ -103,7 +85,7 @@ void MacroActionAudio::SetVolume(float vol)
obs_source_set_volume(s, vol); obs_source_set_volume(s, vol);
obs_source_release(s); obs_source_release(s);
} else { } else {
set_master_volume(vol); obs_set_master_volume(vol);
} }
} }
@@ -118,7 +100,7 @@ float MacroActionAudio::GetVolume()
curVol = obs_source_get_volume(s); curVol = obs_source_get_volume(s);
obs_source_release(s); obs_source_release(s);
} else { } else {
curVol = get_master_volume(); curVol = obs_get_master_volume();
} }
return curVol; return curVol;
} }
@@ -132,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.Milliseconds() / fadeInterval.count(); nrSteps = _duration.seconds * 1000 / fadeInterval.count();
volStep = volDiff / nrSteps; volStep = volDiff / nrSteps;
} else { } else {
volStep = _rate / 1000.0f; volStep = _rate / 1000.0f;
@@ -230,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.GetValue(), _fade, _duration.Seconds()); _volume, _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));
@@ -243,16 +225,15 @@ 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);
_syncOffset.Save(obj, "syncOffset"); obs_data_set_double(obj, "balance", _balance);
_balance.Save(obj, "balance"); obs_data_set_int(obj, "volume", _volume);
_volume.Save(obj, "volume"); obs_data_set_double(obj, "rate", _rate);
_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;
} }
@@ -262,19 +243,12 @@ 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"));
if (!obs_data_has_user_value(obj, "version")) { _balance = obs_data_get_double(obj, "balance");
_syncOffset = obs_data_get_int(obj, "syncOffset"); _volume = obs_data_get_int(obj, "volume");
_balance = obs_data_get_double(obj, "balance"); _rate = obs_data_get_double(obj, "rate");
_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");
@@ -303,13 +277,15 @@ std::string MacroActionAudio::GetShortDesc() const
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (const auto &[action, name] : actionTypes) { for (const auto &[action, name] : actionTypes) {
if (action == MacroActionAudio::Action::MONITOR && if (action == MacroActionAudio::Action::MONITOR) {
!obs_audio_monitoring_available()) { if (obs_audio_monitoring_available()) {
continue; list->addItem(obs_module_text(name.c_str()),
static_cast<int>(action));
}
} else {
list->addItem(obs_module_text(name.c_str()),
static_cast<int>(action));
} }
list->addItem(obs_module_text(name.c_str()),
static_cast<int>(action));
} }
} }
@@ -326,16 +302,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 VariableSpinBox), _syncOffset(new QSpinBox),
_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 VariableSpinBox), _volumePercent(new QSpinBox),
_fade(new QCheckBox), _fade(new QCheckBox),
_duration(new DurationSelection(parent, false)), _duration(new DurationSelection(parent, false)),
_rate(new VariableDoubleSpinBox), _rate(new QDoubleSpinBox),
_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(
@@ -360,35 +336,27 @@ MacroActionAudioEdit::MacroActionAudioEdit(
sources.sort(); sources.sort();
_sources->SetSourceNameList(sources); _sources->SetSourceNameList(sources);
populateFadeTypeSelection(_fadeTypes); populateFadeTypeSelection(_fadeTypes);
PopulateMonitorTypeSelection(_monitorTypes); populateMonitorTypeSelection(_monitorTypes);
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ActionChanged(int))); SLOT(ActionChanged(int)));
QWidget::connect(_sources, QWidget::connect(_sources,
SIGNAL(SourceChanged(const SourceSelection &)), this, SIGNAL(SourceChanged(const SourceSelection &)), this,
SLOT(SourceChanged(const SourceSelection &))); SLOT(SourceChanged(const SourceSelection &)));
QWidget::connect( QWidget::connect(_syncOffset, SIGNAL(valueChanged(int)), this,
_syncOffset, SLOT(SyncOffsetChanged(int)));
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)), QWidget::connect(_balance, SIGNAL(DoubleValueChanged(double)), this,
this, SLOT(SyncOffsetChanged(const NumberVariable<int> &))); SLOT(BalanceChanged(double)));
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( QWidget::connect(_volumePercent, SIGNAL(valueChanged(int)), this,
_volumePercent, SLOT(VolumeChanged(int)));
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(const Duration &)), QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
this, SLOT(DurationChanged(const Duration &))); SLOT(DurationChanged(double)));
QWidget::connect( QWidget::connect(_rate, SIGNAL(valueChanged(double)), this,
_rate, SLOT(RateChanged(double)));
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,
@@ -411,10 +379,10 @@ MacroActionAudioEdit::MacroActionAudioEdit(
{"{{fadeTypes}}", _fadeTypes}, {"{{fadeTypes}}", _fadeTypes},
}; };
QHBoxLayout *entryLayout = new QHBoxLayout; QHBoxLayout *entryLayout = new QHBoxLayout;
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.audio.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.action.audio.entry"),
entryLayout, widgetPlaceholders); entryLayout, widgetPlaceholders);
_fadeTypeLayout = new QHBoxLayout; _fadeTypeLayout = new QHBoxLayout;
PlaceWidgets( placeWidgets(
obs_module_text("AdvSceneSwitcher.action.audio.fade.duration"), obs_module_text("AdvSceneSwitcher.action.audio.fade.duration"),
_fadeTypeLayout, widgetPlaceholders); _fadeTypeLayout, widgetPlaceholders);
@@ -433,7 +401,7 @@ MacroActionAudioEdit::MacroActionAudioEdit(
_loading = false; _loading = false;
} }
static bool hasVolumeControl(MacroActionAudio::Action action) bool hasVolumeControl(MacroActionAudio::Action action)
{ {
return action == MacroActionAudio::Action::SOURCE_VOLUME || return action == MacroActionAudio::Action::SOURCE_VOLUME ||
action == MacroActionAudio::Action::MASTER_VOLUME; action == MacroActionAudio::Action::MASTER_VOLUME;
@@ -451,11 +419,17 @@ void MacroActionAudioEdit::SetWidgetVisibility()
_balance->setVisible(_entryData->_action == _balance->setVisible(_entryData->_action ==
MacroActionAudio::Action::BALANCE); MacroActionAudio::Action::BALANCE);
_fadeTypes->setDisabled(!_entryData->_fade);
_wait->setDisabled(!_entryData->_fade);
_abortActiveFade->setDisabled(!_entryData->_fade);
_duration->setDisabled(!_entryData->_fade);
_rate->setDisabled(!_entryData->_fade);
_fadeTypeLayout->removeWidget(_fade); _fadeTypeLayout->removeWidget(_fade);
_fadeTypeLayout->removeWidget(_fadeTypes); _fadeTypeLayout->removeWidget(_fadeTypes);
_fadeTypeLayout->removeWidget(_duration); _fadeTypeLayout->removeWidget(_duration);
_fadeTypeLayout->removeWidget(_rate); _fadeTypeLayout->removeWidget(_rate);
ClearLayout(_fadeTypeLayout); clearLayout(_fadeTypeLayout);
std::unordered_map<std::string, QWidget *> widgetPlaceholders = { std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{fade}}", _fade}, {"{{fade}}", _fade},
{"{{duration}}", _duration}, {"{{duration}}", _duration},
@@ -463,12 +437,12 @@ void MacroActionAudioEdit::SetWidgetVisibility()
{"{{fadeTypes}}", _fadeTypes}, {"{{fadeTypes}}", _fadeTypes},
}; };
if (_entryData->_fadeType == MacroActionAudio::FadeType::DURATION) { if (_entryData->_fadeType == MacroActionAudio::FadeType::DURATION) {
PlaceWidgets( placeWidgets(
obs_module_text( obs_module_text(
"AdvSceneSwitcher.action.audio.fade.duration"), "AdvSceneSwitcher.action.audio.fade.duration"),
_fadeTypeLayout, widgetPlaceholders); _fadeTypeLayout, widgetPlaceholders);
} else { } else {
PlaceWidgets(obs_module_text( placeWidgets(obs_module_text(
"AdvSceneSwitcher.action.audio.fade.rate"), "AdvSceneSwitcher.action.audio.fade.rate"),
_fadeTypeLayout, widgetPlaceholders); _fadeTypeLayout, widgetPlaceholders);
} }
@@ -478,24 +452,10 @@ void MacroActionAudioEdit::SetWidgetVisibility()
_rate->setVisible(_entryData->_fadeType == _rate->setVisible(_entryData->_fadeType ==
MacroActionAudio::FadeType::RATE); MacroActionAudio::FadeType::RATE);
SetLayoutVisible(_fadeTypeLayout, setLayoutVisible(_fadeTypeLayout,
hasVolumeControl(_entryData->_action)); hasVolumeControl(_entryData->_action));
SetLayoutVisible(_fadeOptionsLayout, setLayoutVisible(_fadeOptionsLayout,
hasVolumeControl(_entryData->_action)); hasVolumeControl(_entryData->_action));
_abortActiveFade->setVisible(hasVolumeControl(_entryData->_action) &&
_entryData->_fade);
_wait->setVisible(hasVolumeControl(_entryData->_action) &&
_entryData->_fade);
// TODO: Remove this in a future version:
if (_entryData->_action != MacroActionAudio::Action::MASTER_VOLUME &&
obs_get_version() >= MAKE_SEMANTIC_VERSION(29, 0, 0)) {
_actions->removeItem(_actions->findText(obs_module_text(
actionTypes.at(MacroActionAudio::Action::MASTER_VOLUME)
.c_str())));
}
updateGeometry();
adjustSize(); adjustSize();
} }
@@ -508,13 +468,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));
@@ -527,7 +487,7 @@ void MacroActionAudioEdit::SourceChanged(const SourceSelection &source)
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_audioSource = source; _entryData->_audioSource = source;
emit HeaderInfoChanged( emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc())); QString::fromStdString(_entryData->GetShortDesc()));
@@ -539,19 +499,19 @@ void MacroActionAudioEdit::ActionChanged(int idx)
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_action = static_cast<MacroActionAudio::Action>( _entryData->_action = static_cast<MacroActionAudio::Action>(
_actions->itemData(idx).toInt()); _actions->itemData(idx).toInt());
SetWidgetVisibility(); SetWidgetVisibility();
} }
void MacroActionAudioEdit::SyncOffsetChanged(const NumberVariable<int> &value) void MacroActionAudioEdit::SyncOffsetChanged(int value)
{ {
if (_loading || !_entryData) { if (_loading || !_entryData) {
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_syncOffset = value; _entryData->_syncOffset = value;
} }
@@ -561,27 +521,27 @@ void MacroActionAudioEdit::MonitorTypeChanged(int value)
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_monitorType = static_cast<obs_monitoring_type>(value); _entryData->_monitorType = static_cast<obs_monitoring_type>(value);
} }
void MacroActionAudioEdit::BalanceChanged(const NumberVariable<double> &value) void MacroActionAudioEdit::BalanceChanged(double value)
{ {
if (_loading || !_entryData) { if (_loading || !_entryData) {
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_balance = value; _entryData->_balance = value;
} }
void MacroActionAudioEdit::VolumeChanged(const NumberVariable<int> &value) void MacroActionAudioEdit::VolumeChanged(int value)
{ {
if (_loading || !_entryData) { if (_loading || !_entryData) {
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_volume = value; _entryData->_volume = value;
} }
@@ -591,28 +551,28 @@ void MacroActionAudioEdit::FadeChanged(int value)
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_fade = value; _entryData->_fade = value;
SetWidgetVisibility(); SetWidgetVisibility();
} }
void MacroActionAudioEdit::DurationChanged(const Duration &dur) void MacroActionAudioEdit::DurationChanged(double seconds)
{ {
if (_loading || !_entryData) { if (_loading || !_entryData) {
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_duration = dur; _entryData->_duration.seconds = seconds;
} }
void MacroActionAudioEdit::RateChanged(const NumberVariable<double> &value) void MacroActionAudioEdit::RateChanged(double value)
{ {
if (_loading || !_entryData) { if (_loading || !_entryData) {
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_rate = value; _entryData->_rate = value;
} }
@@ -622,7 +582,7 @@ void MacroActionAudioEdit::WaitChanged(int value)
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_wait = value; _entryData->_wait = value;
} }
@@ -632,7 +592,7 @@ void MacroActionAudioEdit::AbortActiveFadeChanged(int value)
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_abortActiveFade = value; _entryData->_abortActiveFade = value;
} }
@@ -642,9 +602,7 @@ void MacroActionAudioEdit::FadeTypeChanged(int value)
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_fadeType = static_cast<MacroActionAudio::FadeType>(value); _entryData->_fadeType = static_cast<MacroActionAudio::FadeType>(value);
SetWidgetVisibility(); SetWidgetVisibility();
} }
} // namespace advss

View File

@@ -9,8 +9,6 @@
#include <QCheckBox> #include <QCheckBox>
#include <QHBoxLayout> #include <QHBoxLayout>
namespace advss {
class MacroActionAudio : public MacroAction { class MacroActionAudio : public MacroAction {
public: public:
MacroActionAudio(Macro *m) : MacroAction(m) {} MacroActionAudio(Macro *m) : MacroAction(m) {}
@@ -44,13 +42,13 @@ public:
Action _action = Action::MUTE; Action _action = Action::MUTE;
FadeType _fadeType = FadeType::DURATION; FadeType _fadeType = FadeType::DURATION;
NumberVariable<int> _syncOffset = 0; int64_t _syncOffset = 0;
obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE; obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE;
NumberVariable<double> _balance = 0.5; double _balance = 0.5;
NumberVariable<int> _volume = 0; int _volume = 0;
bool _fade = false; bool _fade = false;
Duration _duration; Duration _duration;
NumberVariable<double> _rate = 100.; double _rate = 100.;
bool _wait = false; bool _wait = false;
bool _abortActiveFade = false; bool _abortActiveFade = false;
@@ -86,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(const NumberVariable<int> &value); void SyncOffsetChanged(int value);
void MonitorTypeChanged(int value); void MonitorTypeChanged(int value);
void BalanceChanged(const NumberVariable<double> &value); void BalanceChanged(double value);
void VolumeChanged(const NumberVariable<int> &value); void VolumeChanged(int value);
void FadeChanged(int value); void FadeChanged(int value);
void DurationChanged(const Duration &seconds); void DurationChanged(double seconds);
void RateChanged(const NumberVariable<double> &value); void RateChanged(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);
@@ -103,13 +101,13 @@ protected:
SourceSelectionWidget *_sources; SourceSelectionWidget *_sources;
QComboBox *_actions; QComboBox *_actions;
QComboBox *_fadeTypes; QComboBox *_fadeTypes;
VariableSpinBox *_syncOffset; QSpinBox *_syncOffset;
QComboBox *_monitorTypes; QComboBox *_monitorTypes;
SliderSpinBox *_balance; SliderSpinBox *_balance;
VariableSpinBox *_volumePercent; QSpinBox *_volumePercent;
QCheckBox *_fade; QCheckBox *_fade;
DurationSelection *_duration; DurationSelection *_duration;
VariableDoubleSpinBox *_rate; QDoubleSpinBox *_rate;
QCheckBox *_wait; QCheckBox *_wait;
QCheckBox *_abortActiveFade; QCheckBox *_abortActiveFade;
QHBoxLayout *_fadeTypeLayout; QHBoxLayout *_fadeTypeLayout;
@@ -121,5 +119,3 @@ private:
bool _loading = true; bool _loading = true;
}; };
} // namespace advss

View File

@@ -1,257 +0,0 @@
#include "macro-action-clipboard.hpp"
#include "curl-helper.hpp"
#include "switcher-data.hpp"
#include <QApplication>
#include <QClipboard>
#include <QImage>
#include <QMimeData>
namespace advss {
const std::string MacroActionClipboard::id = "clipboard";
bool MacroActionClipboard::_registered = MacroActionFactory::Register(
MacroActionClipboard::id,
{MacroActionClipboard::Create, MacroActionClipboardEdit::Create,
"AdvSceneSwitcher.action.clipboard"});
const static std::map<MacroActionClipboard::Action, std::string> actionTypes = {
{MacroActionClipboard::Action::COPY_TEXT,
"AdvSceneSwitcher.action.clipboard.type.copy.text"},
{MacroActionClipboard::Action::COPY_IMAGE,
"AdvSceneSwitcher.action.clipboard.type.copy.image"},
};
static size_t writeCallback(void *ptr, size_t size, size_t nmemb,
QByteArray *buffer)
{
buffer->append((char *)ptr, nmemb);
return size * nmemb;
}
static std::optional<QImage> getImageFromUrl(const char *url)
{
QByteArray response;
switcher->curl.SetOpt(CURLOPT_URL, url);
switcher->curl.SetOpt(CURLOPT_HTTPGET, 1L);
switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, 30000);
switcher->curl.SetOpt(CURLOPT_WRITEFUNCTION, writeCallback);
switcher->curl.SetOpt(CURLOPT_WRITEDATA, &response);
auto code = switcher->curl.Perform();
if (code != CURLE_OK) {
blog(LOG_WARNING,
"Retrieving image failed in %s with error: %s", __func__,
switcher->curl.GetError(code));
return {};
}
return QImage::fromData(response);
}
static void setMimeTypeParams(ClipboardQueueParams *params,
QClipboard *clipboard)
{
auto mimeData = clipboard->mimeData();
if (!mimeData) {
return;
}
auto mimeTypeList = mimeData->formats();
if (mimeTypeList.empty()) {
return;
}
params->mimeTypePrimary = mimeTypeList.first().toStdString();
params->mimeTypeAll = mimeTypeList.join(" ").toStdString();
}
static void copyText(void *param)
{
auto params = static_cast<ClipboardTextQueueParams *>(param);
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(params->text.c_str());
setMimeTypeParams(params, clipboard);
}
static void copyImageFromUrl(void *param)
{
auto params = static_cast<ClipboardImageQueueParams *>(param);
auto url = params->url.c_str();
auto image = getImageFromUrl(url);
if (!image || (*image).isNull()) {
blog(LOG_WARNING, "Failed to convert %s URL to image!", url);
return;
}
QClipboard *clipboard = QApplication::clipboard();
clipboard->setImage(*image);
setMimeTypeParams(params, clipboard);
}
bool MacroActionClipboard::PerformAction()
{
switch (_action) {
case Action::COPY_TEXT: {
ClipboardTextQueueParams params{"", "", _text};
obs_queue_task(OBS_TASK_UI, copyText, &params, true);
SetTempVarValues(params);
break;
}
case Action::COPY_IMAGE: {
ClipboardImageQueueParams params{"", "", _url};
obs_queue_task(OBS_TASK_UI, copyImageFromUrl, &params, true);
SetTempVarValues(params);
break;
}
default:
break;
}
return true;
}
void MacroActionClipboard::SetupTempVars()
{
MacroAction::SetupTempVars();
AddTempvar(
"mimeType.primary",
obs_module_text(
"AdvSceneSwitcher.tempVar.clipboard.mimeType.primary"),
obs_module_text(
"AdvSceneSwitcher.tempVar.clipboard.mimeType.primary.description"));
AddTempvar(
"mimeType.all",
obs_module_text(
"AdvSceneSwitcher.tempVar.clipboard.mimeType.all"),
obs_module_text(
"AdvSceneSwitcher.tempVar.clipboard.mimeType.all.description"));
}
void MacroActionClipboard::SetTempVarValues(const ClipboardQueueParams &params)
{
SetTempVarValue("mimeType.primary", params.mimeTypePrimary);
SetTempVarValue("mimeType.all", params.mimeTypeAll);
}
bool MacroActionClipboard::Save(obs_data_t *obj) const
{
MacroAction::Save(obj);
obs_data_set_int(obj, "action", static_cast<int>(_action));
_text.Save(obj, "text");
_url.Save(obj, "url");
return true;
}
bool MacroActionClipboard::Load(obs_data_t *obj)
{
MacroAction::Load(obj);
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
_text.Load(obj, "text");
_url.Load(obj, "url");
return true;
}
static inline void populateActionSelection(QComboBox *list)
{
for (const auto &[action, name] : actionTypes) {
list->addItem(obs_module_text(name.c_str()),
static_cast<int>(action));
}
}
MacroActionClipboardEdit::MacroActionClipboardEdit(
QWidget *parent, std::shared_ptr<MacroActionClipboard> entryData)
: QWidget(parent),
_actions(new FilterComboBox(this)),
_text(new VariableLineEdit(this)),
_url(new VariableLineEdit(this))
{
populateActionSelection(_actions);
_url->setToolTip(obs_module_text(
"AdvSceneSwitcher.action.clipboard.copy.image.url.tooltip"));
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ActionChanged(int)));
QWidget::connect(_text, SIGNAL(editingFinished()), this,
SLOT(TextChanged()));
QWidget::connect(_url, SIGNAL(editingFinished()), this,
SLOT(UrlChanged()));
auto mainLayout = new QHBoxLayout();
mainLayout->addWidget(_actions);
mainLayout->addWidget(_text);
mainLayout->addWidget(_url);
setLayout(mainLayout);
_entryData = entryData;
UpdateEntryData();
_loading = false;
}
void MacroActionClipboardEdit::ActionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_action = static_cast<MacroActionClipboard::Action>(
_actions->itemData(index).toInt());
SetWidgetVisibility();
}
void MacroActionClipboardEdit::TextChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_text = _text->text().toStdString();
}
void MacroActionClipboardEdit::UrlChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_url = _url->text().toStdString();
}
void MacroActionClipboardEdit::SetWidgetVisibility()
{
_text->setVisible(_entryData->_action ==
MacroActionClipboard::Action::COPY_TEXT);
_url->setVisible(_entryData->_action ==
MacroActionClipboard::Action::COPY_IMAGE);
adjustSize();
updateGeometry();
}
void MacroActionClipboardEdit::UpdateEntryData()
{
if (!_entryData) {
return;
}
_actions->setCurrentIndex(
_actions->findData(static_cast<int>(_entryData->_action)));
_text->setText(_entryData->_text);
_url->setText(_entryData->_url);
SetWidgetVisibility();
}
} // namespace advss

View File

@@ -1,89 +0,0 @@
#pragma once
#include "macro-action-edit.hpp"
#include "filter-combo-box.hpp"
#include <variable-line-edit.hpp>
namespace advss {
struct ClipboardQueueParams {
std::string mimeTypePrimary;
std::string mimeTypeAll;
};
struct ClipboardTextQueueParams : ClipboardQueueParams {
StringVariable text;
};
struct ClipboardImageQueueParams : ClipboardQueueParams {
StringVariable url;
};
class MacroActionClipboard : public MacroAction {
public:
MacroActionClipboard(Macro *m) : MacroAction(m) {}
static std::shared_ptr<MacroAction> Create(Macro *m)
{
return std::make_shared<MacroActionClipboard>(m);
}
std::string GetId() const { return id; };
bool PerformAction();
bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj);
enum class Action {
COPY_TEXT,
COPY_IMAGE,
};
Action _action = Action::COPY_TEXT;
StringVariable _text = obs_module_text(
"AdvSceneSwitcher.action.clipboard.copy.text.text.placeholder");
StringVariable _url = obs_module_text(
"AdvSceneSwitcher.action.clipboard.copy.image.url.placeholder");
private:
void SetupTempVars();
void SetTempVarValues(const ClipboardQueueParams &params);
static bool _registered;
static const std::string id;
};
class MacroActionClipboardEdit : public QWidget {
Q_OBJECT
public:
MacroActionClipboardEdit(
QWidget *parent,
std::shared_ptr<MacroActionClipboard> entryData = nullptr);
static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroAction> action)
{
return new MacroActionClipboardEdit(
parent, std::dynamic_pointer_cast<MacroActionClipboard>(
action));
}
void UpdateEntryData();
protected:
std::shared_ptr<MacroActionClipboard> _entryData;
private slots:
void ActionChanged(int index);
void TextChanged();
void UrlChanged();
private:
void SetWidgetVisibility();
bool _loading = true;
FilterComboBox *_actions;
VariableLineEdit *_text;
VariableLineEdit *_url;
};
} // namespace advss

View File

@@ -1,15 +1,9 @@
#include "advanced-scene-switcher.hpp" #include "advanced-scene-switcher.hpp"
#include "switcher-data.hpp"
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "macro-action-scene-switch.hpp" #include "macro-action-scene-switch.hpp"
#include "section.hpp" #include "section.hpp"
#include "switch-button.hpp"
#include "utility.hpp" #include "utility.hpp"
#include <QGraphicsOpacityEffect>
namespace advss {
std::map<std::string, MacroActionInfo> &MacroActionFactory::GetMap() std::map<std::string, MacroActionInfo> &MacroActionFactory::GetMap()
{ {
static std::map<std::string, MacroActionInfo> _methods; static std::map<std::string, MacroActionInfo> _methods;
@@ -81,32 +75,26 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
std::shared_ptr<MacroAction> *entryData, std::shared_ptr<MacroAction> *entryData,
const std::string &id) const std::string &id)
: MacroSegmentEdit(switcher->macroProperties._highlightActions, parent), : MacroSegmentEdit(switcher->macroProperties._highlightActions, parent),
_actionSelection(new FilterComboBox()), _actionSelection(new QComboBox()),
_enable(new SwitchButton()),
_entryData(entryData) _entryData(entryData)
{ {
QWidget::connect(_actionSelection, QWidget::connect(_actionSelection,
SIGNAL(currentTextChanged(const QString &)), this, SIGNAL(currentTextChanged(const QString &)), this,
SLOT(ActionSelectionChanged(const QString &))); SLOT(ActionSelectionChanged(const QString &)));
QWidget::connect(_enable, SIGNAL(checked(bool)), this,
SLOT(ActionEnableChanged(bool)));
QWidget::connect(window(), SIGNAL(HighlightActionsChanged(bool)), this, QWidget::connect(window(), SIGNAL(HighlightActionsChanged(bool)), this,
SLOT(EnableHighlight(bool))); SLOT(EnableHighlight(bool)));
QWidget::connect(&_actionStateTimer, SIGNAL(timeout()), this,
SLOT(UpdateActionState()));
populateActionSelection(_actionSelection); populateActionSelection(_actionSelection);
_section->AddHeaderWidget(_enable);
_section->AddHeaderWidget(_actionSelection); _section->AddHeaderWidget(_actionSelection);
_section->AddHeaderWidget(_headerInfo); _section->AddHeaderWidget(_headerInfo);
auto actionLayout = new QVBoxLayout; QVBoxLayout *actionLayout = new QVBoxLayout;
actionLayout->setContentsMargins({7, 7, 7, 7}); actionLayout->setContentsMargins({7, 7, 7, 7});
actionLayout->addWidget(_section); actionLayout->addWidget(_section);
_contentLayout->addLayout(actionLayout); _contentLayout->addLayout(actionLayout);
auto mainLayout = new QHBoxLayout; QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0); mainLayout->setSpacing(0);
mainLayout->addWidget(_frame); mainLayout->addWidget(_frame);
@@ -115,7 +103,6 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
_entryData = entryData; _entryData = entryData;
UpdateEntryData(id); UpdateEntryData(id);
_actionStateTimer.start(300);
_loading = false; _loading = false;
} }
@@ -125,20 +112,15 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
return; return;
} }
std::string id = MacroActionFactory::GetIdByName(text);
if (id.empty()) {
return;
}
HeaderInfoChanged("");
auto idx = _entryData->get()->GetIndex(); auto idx = _entryData->get()->GetIndex();
auto macro = _entryData->get()->GetMacro(); auto macro = _entryData->get()->GetMacro();
std::string id = MacroActionFactory::GetIdByName(text);
HeaderInfoChanged("");
{ {
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->reset(); _entryData->reset();
*_entryData = MacroActionFactory::Create(id, macro); *_entryData = MacroActionFactory::Create(id, macro);
(*_entryData)->SetIndex(idx); (*_entryData)->SetIndex(idx);
(*_entryData)->PostLoad();
} }
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData); auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)), QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
@@ -151,9 +133,6 @@ void MacroActionEdit::UpdateEntryData(const std::string &id)
{ {
_actionSelection->setCurrentText( _actionSelection->setCurrentText(
obs_module_text(MacroActionFactory::GetActionName(id).c_str())); obs_module_text(MacroActionFactory::GetActionName(id).c_str()));
const bool enabled = (*_entryData)->Enabled();
_enable->setChecked(enabled);
SetDisableEffect(!enabled);
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData); auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)), QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
this, SLOT(HeaderInfoChanged(const QString &))); this, SLOT(HeaderInfoChanged(const QString &)));
@@ -168,51 +147,14 @@ void MacroActionEdit::SetEntryData(std::shared_ptr<MacroAction> *data)
_entryData = data; _entryData = data;
} }
void MacroActionEdit::SetDisableEffect(bool value) std::shared_ptr<MacroSegment> MacroActionEdit::Data()
{
if (value) {
auto effect = new QGraphicsOpacityEffect(this);
effect->setOpacity(0.5);
_section->setGraphicsEffect(effect);
} else {
_section->setGraphicsEffect(nullptr);
}
}
void MacroActionEdit::ActionEnableChanged(bool value)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
(*_entryData)->SetEnabled(value);
SetDisableEffect(!value);
}
void MacroActionEdit::UpdateActionState()
{
if (_loading || !_entryData) {
return;
}
SetEnableAppearance((*_entryData)->Enabled());
}
void MacroActionEdit::SetEnableAppearance(bool value)
{
_enable->setChecked(value);
SetDisableEffect(!value);
}
std::shared_ptr<MacroSegment> MacroActionEdit::Data() const
{ {
return *_entryData; return *_entryData;
} }
void AdvSceneSwitcher::AddMacroAction(int idx) void AdvSceneSwitcher::AddMacroAction(int idx)
{ {
auto macro = GetSelectedMacro(); auto macro = getSelectedMacro();
if (!macro) { if (!macro) {
return; return;
} }
@@ -237,11 +179,10 @@ void AdvSceneSwitcher::AddMacroAction(int idx)
auto data = obs_data_create(); auto data = obs_data_create();
macro->Actions().at(idx - 1)->Save(data); macro->Actions().at(idx - 1)->Save(data);
macro->Actions().at(idx)->Load(data); macro->Actions().at(idx)->Load(data);
macro->Actions().at(idx)->PostLoad();
obs_data_release(data); obs_data_release(data);
} }
macro->UpdateActionIndices(); macro->UpdateActionIndices();
ui->actionsList->Insert( actionsList->Insert(
idx, idx,
new MacroActionEdit(this, &macro->Actions()[idx], id)); new MacroActionEdit(this, &macro->Actions()[idx], id));
SetActionData(*macro); SetActionData(*macro);
@@ -252,7 +193,7 @@ void AdvSceneSwitcher::AddMacroAction(int idx)
void AdvSceneSwitcher::on_actionAdd_clicked() void AdvSceneSwitcher::on_actionAdd_clicked()
{ {
auto macro = GetSelectedMacro(); auto macro = getSelectedMacro();
if (!macro) { if (!macro) {
return; return;
} }
@@ -265,12 +206,12 @@ void AdvSceneSwitcher::on_actionAdd_clicked()
if (currentActionIdx != -1) { if (currentActionIdx != -1) {
MacroActionSelectionChanged(currentActionIdx + 1); MacroActionSelectionChanged(currentActionIdx + 1);
} }
ui->actionsList->SetHelpMsgVisible(false); actionsList->SetHelpMsgVisible(false);
} }
void AdvSceneSwitcher::RemoveMacroAction(int idx) void AdvSceneSwitcher::RemoveMacroAction(int idx)
{ {
auto macro = GetSelectedMacro(); auto macro = getSelectedMacro();
if (!macro) { if (!macro) {
return; return;
} }
@@ -281,7 +222,7 @@ void AdvSceneSwitcher::RemoveMacroAction(int idx)
{ {
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
ui->actionsList->Remove(idx); actionsList->Remove(idx);
macro->Actions().erase(macro->Actions().begin() + idx); macro->Actions().erase(macro->Actions().begin() + idx);
switcher->abortMacroWait = true; switcher->abortMacroWait = true;
switcher->macroWaitCv.notify_all(); switcher->macroWaitCv.notify_all();
@@ -296,7 +237,7 @@ void AdvSceneSwitcher::RemoveMacroAction(int idx)
void AdvSceneSwitcher::on_actionRemove_clicked() void AdvSceneSwitcher::on_actionRemove_clicked()
{ {
if (currentActionIdx == -1) { if (currentActionIdx == -1) {
auto macro = GetSelectedMacro(); auto macro = getSelectedMacro();
if (!macro) { if (!macro) {
return; return;
} }
@@ -307,113 +248,21 @@ void AdvSceneSwitcher::on_actionRemove_clicked()
MacroActionSelectionChanged(-1); MacroActionSelectionChanged(-1);
} }
void AdvSceneSwitcher::on_actionTop_clicked()
{
if (currentActionIdx == -1) {
return;
}
MacroActionReorder(0, currentActionIdx);
MacroActionSelectionChanged(0);
}
void AdvSceneSwitcher::on_actionUp_clicked() void AdvSceneSwitcher::on_actionUp_clicked()
{ {
if (currentActionIdx == -1 || currentActionIdx == 0) { if (currentActionIdx == -1) {
return; return;
} }
MoveMacroActionUp(currentActionIdx); MoveMacroActionUp(currentActionIdx);
MacroActionSelectionChanged(currentActionIdx - 1); MacroActionSelectionChanged(currentActionIdx - 1);
} }
void AdvSceneSwitcher::on_actionDown_clicked() void AdvSceneSwitcher::on_actionDown_clicked()
{
if (currentActionIdx == -1 ||
currentActionIdx == ui->actionsList->ContentLayout()->count() - 1) {
return;
}
MoveMacroActionDown(currentActionIdx);
MacroActionSelectionChanged(currentActionIdx + 1);
}
void AdvSceneSwitcher::on_actionBottom_clicked()
{ {
if (currentActionIdx == -1) { if (currentActionIdx == -1) {
return; return;
} }
const int newIdx = ui->actionsList->ContentLayout()->count() - 1; MoveMacroActionDown(currentActionIdx);
MacroActionReorder(newIdx, currentActionIdx); MacroActionSelectionChanged(currentActionIdx + 1);
MacroActionSelectionChanged(newIdx);
}
void AdvSceneSwitcher::on_elseActionAdd_clicked()
{
auto macro = GetSelectedMacro();
if (!macro) {
return;
}
if (currentElseActionIdx == -1) {
AddMacroElseAction((int)macro->ElseActions().size());
} else {
AddMacroElseAction(currentElseActionIdx + 1);
}
if (currentElseActionIdx != -1) {
MacroElseActionSelectionChanged(currentElseActionIdx + 1);
}
ui->elseActionsList->SetHelpMsgVisible(false);
}
void AdvSceneSwitcher::on_elseActionRemove_clicked()
{
if (currentElseActionIdx == -1) {
auto macro = GetSelectedMacro();
if (!macro) {
return;
}
RemoveMacroElseAction((int)macro->Actions().size() - 1);
} else {
RemoveMacroElseAction(currentElseActionIdx);
}
MacroElseActionSelectionChanged(-1);
}
void AdvSceneSwitcher::on_elseActionTop_clicked()
{
if (currentElseActionIdx == -1) {
return;
}
MacroElseActionReorder(0, currentElseActionIdx);
MacroElseActionSelectionChanged(0);
}
void AdvSceneSwitcher::on_elseActionUp_clicked()
{
if (currentElseActionIdx == -1 || currentElseActionIdx == 0) {
return;
}
MoveMacroElseActionUp(currentElseActionIdx);
MacroElseActionSelectionChanged(currentElseActionIdx - 1);
}
void AdvSceneSwitcher::on_elseActionDown_clicked()
{
if (currentElseActionIdx == -1 ||
currentElseActionIdx ==
ui->elseActionsList->ContentLayout()->count() - 1) {
return;
}
MoveMacroElseActionDown(currentElseActionIdx);
MacroElseActionSelectionChanged(currentElseActionIdx + 1);
}
void AdvSceneSwitcher::on_elseActionBottom_clicked()
{
if (currentElseActionIdx == -1) {
return;
}
const int newIdx = ui->elseActionsList->ContentLayout()->count() - 1;
MacroElseActionReorder(newIdx, currentElseActionIdx);
MacroElseActionSelectionChanged(newIdx);
} }
void AdvSceneSwitcher::SwapActions(Macro *m, int pos1, int pos2) void AdvSceneSwitcher::SwapActions(Macro *m, int pos1, int pos2)
@@ -429,18 +278,18 @@ void AdvSceneSwitcher::SwapActions(Macro *m, int pos1, int pos2)
iter_swap(m->Actions().begin() + pos1, m->Actions().begin() + pos2); iter_swap(m->Actions().begin() + pos1, m->Actions().begin() + pos2);
m->UpdateActionIndices(); m->UpdateActionIndices();
auto widget1 = static_cast<MacroActionEdit *>( auto widget1 = static_cast<MacroActionEdit *>(
ui->actionsList->ContentLayout()->takeAt(pos1)->widget()); actionsList->ContentLayout()->takeAt(pos1)->widget());
auto widget2 = static_cast<MacroActionEdit *>( auto widget2 = static_cast<MacroActionEdit *>(
ui->actionsList->ContentLayout()->takeAt(pos2 - 1)->widget()); actionsList->ContentLayout()->takeAt(pos2 - 1)->widget());
ui->actionsList->Insert(pos1, widget2); actionsList->Insert(pos1, widget2);
ui->actionsList->Insert(pos2, widget1); actionsList->Insert(pos2, widget1);
SetActionData(*m); SetActionData(*m);
emit(MacroSegmentOrderChanged()); emit(MacroSegmentOrderChanged());
} }
void AdvSceneSwitcher::MoveMacroActionUp(int idx) void AdvSceneSwitcher::MoveMacroActionUp(int idx)
{ {
auto macro = GetSelectedMacro(); auto macro = getSelectedMacro();
if (!macro) { if (!macro) {
return; return;
} }
@@ -455,7 +304,7 @@ void AdvSceneSwitcher::MoveMacroActionUp(int idx)
void AdvSceneSwitcher::MoveMacroActionDown(int idx) void AdvSceneSwitcher::MoveMacroActionDown(int idx)
{ {
auto macro = GetSelectedMacro(); auto macro = getSelectedMacro();
if (!macro) { if (!macro) {
return; return;
} }
@@ -468,170 +317,35 @@ void AdvSceneSwitcher::MoveMacroActionDown(int idx)
HighlightAction(idx + 1); HighlightAction(idx + 1);
} }
void AdvSceneSwitcher::MacroElseActionSelectionChanged(int idx)
{
SetupMacroSegmentSelection(MacroSection::ELSE_ACTIONS, idx);
}
void AdvSceneSwitcher::MacroElseActionReorder(int to, int from)
{
auto macro = GetSelectedMacro();
if (!macro) {
return;
}
if (to == from || from < 0 || from > (int)macro->ElseActions().size() ||
to < 0 || to > (int)macro->ElseActions().size()) {
return;
}
{
std::lock_guard<std::mutex> lock(switcher->m);
auto action = macro->ElseActions().at(from);
macro->ElseActions().erase(macro->ElseActions().begin() + from);
macro->ElseActions().insert(macro->ElseActions().begin() + to,
action);
macro->UpdateElseActionIndices();
ui->elseActionsList->ContentLayout()->insertItem(
to, ui->elseActionsList->ContentLayout()->takeAt(from));
SetElseActionData(*macro);
}
HighlightElseAction(to);
emit(MacroSegmentOrderChanged());
}
void AdvSceneSwitcher::AddMacroElseAction(int idx)
{
auto macro = GetSelectedMacro();
if (!macro) {
return;
}
if (idx < 0 || idx > (int)macro->ElseActions().size()) {
return;
}
std::string id;
if (idx - 1 >= 0) {
id = macro->ElseActions().at(idx - 1)->GetId();
} else {
MacroActionSwitchScene temp(nullptr);
id = temp.GetId();
}
{
std::lock_guard<std::mutex> lock(switcher->m);
macro->ElseActions().emplace(
macro->ElseActions().begin() + idx,
MacroActionFactory::Create(id, macro.get()));
if (idx - 1 >= 0) {
OBSDataAutoRelease data = obs_data_create();
macro->ElseActions().at(idx - 1)->Save(data);
macro->ElseActions().at(idx)->Load(data);
}
macro->ElseActions().at(idx)->PostLoad();
macro->UpdateElseActionIndices();
ui->elseActionsList->Insert(
idx, new MacroActionEdit(
this, &macro->ElseActions()[idx], id));
SetElseActionData(*macro);
}
HighlightElseAction(idx);
emit(MacroSegmentOrderChanged());
}
void AdvSceneSwitcher::RemoveMacroElseAction(int idx)
{
auto macro = GetSelectedMacro();
if (!macro) {
return;
}
if (idx < 0 || idx >= (int)macro->ElseActions().size()) {
return;
}
{
std::lock_guard<std::mutex> lock(switcher->m);
ui->elseActionsList->Remove(idx);
macro->ElseActions().erase(macro->ElseActions().begin() + idx);
switcher->abortMacroWait = true;
switcher->macroWaitCv.notify_all();
macro->UpdateElseActionIndices();
SetActionData(*macro);
}
MacroElseActionSelectionChanged(-1);
lastInteracted = MacroSection::ELSE_ACTIONS;
emit(MacroSegmentOrderChanged());
}
void AdvSceneSwitcher::SwapElseActions(Macro *m, int pos1, int pos2)
{
if (pos1 == pos2) {
return;
}
if (pos1 > pos2) {
std::swap(pos1, pos2);
}
std::lock_guard<std::mutex> lock(switcher->m);
iter_swap(m->ElseActions().begin() + pos1,
m->ElseActions().begin() + pos2);
m->UpdateElseActionIndices();
auto widget1 = static_cast<MacroActionEdit *>(
ui->elseActionsList->ContentLayout()->takeAt(pos1)->widget());
auto widget2 = static_cast<MacroActionEdit *>(
ui->elseActionsList->ContentLayout()
->takeAt(pos2 - 1)
->widget());
ui->elseActionsList->Insert(pos1, widget2);
ui->elseActionsList->Insert(pos2, widget1);
SetElseActionData(*m);
emit(MacroSegmentOrderChanged());
}
void AdvSceneSwitcher::MoveMacroElseActionUp(int idx)
{
auto macro = GetSelectedMacro();
if (!macro) {
return;
}
if (idx < 1 || idx >= (int)macro->ElseActions().size()) {
return;
}
SwapElseActions(macro.get(), idx, idx - 1);
HighlightElseAction(idx - 1);
}
void AdvSceneSwitcher::MoveMacroElseActionDown(int idx)
{
auto macro = GetSelectedMacro();
if (!macro) {
return;
}
if (idx < 0 || idx >= (int)macro->ElseActions().size() - 1) {
return;
}
SwapElseActions(macro.get(), idx, idx + 1);
HighlightElseAction(idx + 1);
}
void AdvSceneSwitcher::MacroActionSelectionChanged(int idx) void AdvSceneSwitcher::MacroActionSelectionChanged(int idx)
{ {
SetupMacroSegmentSelection(MacroSection::ACTIONS, idx); auto macro = getSelectedMacro();
if (!macro) {
return;
}
actionsList->SetSelection(idx);
conditionsList->SetSelection(-1);
if (idx < 0 || (unsigned)idx >= macro->Actions().size()) {
currentActionIdx = -1;
} else {
currentActionIdx = idx;
lastInteracted = MacroSection::ACTIONS;
}
currentConditionIdx = -1;
HighlightControls();
} }
void AdvSceneSwitcher::MacroActionReorder(int to, int from) void AdvSceneSwitcher::MacroActionReorder(int to, int from)
{ {
auto macro = GetSelectedMacro(); auto macro = getSelectedMacro();
if (!macro) { if (!macro) {
return; return;
} }
if (to == from || from < 0 || from > (int)macro->Actions().size() || if (from < 0 || from > (int)macro->Actions().size() || to < 0 ||
to < 0 || to > (int)macro->Actions().size()) { to > (int)macro->Actions().size()) {
return; return;
} }
{ {
@@ -640,12 +354,10 @@ void AdvSceneSwitcher::MacroActionReorder(int to, int from)
macro->Actions().erase(macro->Actions().begin() + from); macro->Actions().erase(macro->Actions().begin() + from);
macro->Actions().insert(macro->Actions().begin() + to, action); macro->Actions().insert(macro->Actions().begin() + to, action);
macro->UpdateActionIndices(); macro->UpdateActionIndices();
ui->actionsList->ContentLayout()->insertItem( actionsList->ContentLayout()->insertItem(
to, ui->actionsList->ContentLayout()->takeAt(from)); to, actionsList->ContentLayout()->takeAt(from));
SetActionData(*macro); SetActionData(*macro);
} }
HighlightAction(to); HighlightAction(to);
emit(MacroSegmentOrderChanged()); emit(MacroSegmentOrderChanged());
} }
} // namespace advss

View File

@@ -1,13 +1,9 @@
#pragma once #pragma once
#include "macro-action.hpp" #include "macro-action.hpp"
#include "filter-combo-box.hpp"
#include <QComboBox>
#include <memory> #include <memory>
namespace advss {
class SwitchButton;
struct MacroActionInfo { struct MacroActionInfo {
using TCreateMethod = std::shared_ptr<MacroAction> (*)(Macro *m); using TCreateMethod = std::shared_ptr<MacroAction> (*)(Macro *m);
using TCreateWidgetMethod = QWidget *(*)(QWidget *parent, using TCreateWidgetMethod = QWidget *(*)(QWidget *parent,
@@ -46,20 +42,12 @@ public:
private slots: private slots:
void ActionSelectionChanged(const QString &text); void ActionSelectionChanged(const QString &text);
void ActionEnableChanged(bool);
void UpdateActionState();
private: private:
std::shared_ptr<MacroSegment> Data() const; std::shared_ptr<MacroSegment> Data();
void SetDisableEffect(bool);
void SetEnableAppearance(bool);
FilterComboBox *_actionSelection; QComboBox *_actionSelection;
SwitchButton *_enable;
std::shared_ptr<MacroAction> *_entryData; std::shared_ptr<MacroAction> *_entryData;
QTimer _actionStateTimer;
bool _loading = true; bool _loading = true;
}; };
} // namespace advss

View File

@@ -1,12 +1,11 @@
#include "macro-action-file.hpp" #include "macro-action-file.hpp"
#include "advanced-scene-switcher.hpp"
#include "utility.hpp" #include "utility.hpp"
#include <QFile> #include <QFile>
#include <QTextStream> #include <QTextStream>
#include <QFileDialog> #include <QFileDialog>
namespace advss {
const std::string MacroActionFile::id = "file"; const std::string MacroActionFile::id = "file";
bool MacroActionFile::_registered = MacroActionFactory::Register( bool MacroActionFile::_registered = MacroActionFactory::Register(
@@ -56,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);
_file.Save(obj, "file"); obs_data_set_string(obj, "file", _file.c_str());
_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;
@@ -65,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.Load(obj, "file"); _file = obs_data_get_string(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;
@@ -73,7 +72,7 @@ bool MacroActionFile::Load(obs_data_t *obj)
std::string MacroActionFile::GetShortDesc() const std::string MacroActionFile::GetShortDesc() const
{ {
return _file.UnresolvedValue(); return _file;
} }
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
@@ -107,7 +106,7 @@ MacroActionFileEdit::MacroActionFileEdit(
{"{{matchText}}", _text}, {"{{matchText}}", _text},
{"{{actions}}", _actions}, {"{{actions}}", _actions},
}; };
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.file.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.action.file.entry"),
entryLayout, widgetPlaceholders); entryLayout, widgetPlaceholders);
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout;
@@ -140,7 +139,7 @@ void MacroActionFileEdit::PathChanged(const QString &text)
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_file = text.toUtf8().constData(); _entryData->_file = text.toUtf8().constData();
emit HeaderInfoChanged( emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc())); QString::fromStdString(_entryData->GetShortDesc()));
@@ -152,7 +151,7 @@ void MacroActionFileEdit::TextChanged()
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_text = _text->toPlainText().toStdString(); _entryData->_text = _text->toPlainText().toStdString();
adjustSize(); adjustSize();
@@ -165,8 +164,6 @@ void MacroActionFileEdit::ActionChanged(int value)
return; return;
} }
auto lock = LockContext(); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_action = static_cast<FileAction>(value); _entryData->_action = static_cast<FileAction>(value);
} }
} // namespace advss

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