mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-09-07 09:05:57 -05:00
Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ee6feb529 | ||
|
|
3b82b55090 | ||
|
|
071c3309c2 | ||
|
|
ee7ee7a846 | ||
|
|
d10300bd4b | ||
|
|
e262672876 | ||
|
|
392e775c7b | ||
|
|
f641c20564 | ||
|
|
39327be88e | ||
|
|
ed0963799c | ||
|
|
f9e73a2b8f | ||
|
|
dfaa704b71 | ||
|
|
d54edddde4 | ||
|
|
37cc289204 | ||
|
|
8d9519c849 | ||
|
|
0fd5f47982 | ||
|
|
62ce83a7f6 | ||
|
|
8ecee0070d | ||
|
|
a4970b1b07 | ||
|
|
140dc9c6f4 | ||
|
|
9a4d2935f8 | ||
|
|
335c964419 | ||
|
|
72b2a7a07a | ||
|
|
f863909f34 | ||
|
|
621ca201ef | ||
|
|
563ea1a5e7 | ||
|
|
2af6ee883b | ||
|
|
0e9875e6b5 | ||
|
|
c2d2e883c6 | ||
|
|
a196e56078 | ||
|
|
0536e4a60b | ||
|
|
55ab096e49 | ||
|
|
c39ea0854a | ||
|
|
aef080984e | ||
|
|
1aa2425e81 | ||
|
|
f5eadfa39c | ||
|
|
faa65facfe | ||
|
|
b60235d964 | ||
|
|
718b18248e | ||
|
|
4316e53039 | ||
|
|
790ac50385 | ||
|
|
3a87a8d155 | ||
|
|
91912f2aa5 | ||
|
|
624b841ca1 | ||
|
|
9eb4e90291 | ||
|
|
94263cc7a0 | ||
|
|
2d035758f4 | ||
|
|
86697002f7 | ||
|
|
2247152aa8 | ||
|
|
2528449c84 | ||
|
|
f2df3d18be | ||
|
|
c7c48d03e9 | ||
|
|
0906c6bb3f | ||
|
|
9f2daf1a15 | ||
|
|
6fb8619671 | ||
|
|
36fb83246b | ||
|
|
e729d15e97 | ||
|
|
7836298076 | ||
|
|
354880ad52 | ||
|
|
c1ac9bb890 | ||
|
|
49bf1ad379 | ||
|
|
a6e30a1e20 | ||
|
|
2f54c2ee62 | ||
|
|
6ccbaad41c | ||
|
|
57d78a996a | ||
|
|
2d3dada30e | ||
|
|
5bf20d155f | ||
|
|
2b95598958 | ||
|
|
b561a20dde | ||
|
|
835722af34 | ||
|
|
93efc7cab3 | ||
|
|
d69364ec19 | ||
|
|
d75066df5f | ||
|
|
863c84026e | ||
|
|
a523081d77 | ||
|
|
66534519d6 | ||
|
|
b3b2114c45 |
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,36 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Logs**
|
|
||||||
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.
|
|
||||||
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.
|
|
||||||
|
|
||||||
**Version information**
|
|
||||||
- OS: [e.g. Windows 10]
|
|
||||||
- OBS Version [e.g. 27.1.3]
|
|
||||||
- Plugin Version [e.g. 1.17.1]
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
||||||
111
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
111
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
# Based on the OBS issue templates
|
||||||
|
# https://github.com/obsproject/.github/tree/master/.github/ISSUE_TEMPLATE
|
||||||
|
|
||||||
|
name: Bug Report
|
||||||
|
description: Report a bug or crash
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
id: md_welcome
|
||||||
|
attributes:
|
||||||
|
value: This form is for reporting bugs for Advanced Scene Switcher!
|
||||||
|
- type: dropdown
|
||||||
|
id: os_info
|
||||||
|
attributes:
|
||||||
|
label: Operating System Info
|
||||||
|
description: What Operating System are you running?
|
||||||
|
options:
|
||||||
|
- Windows 11
|
||||||
|
- Windows 10
|
||||||
|
- macOS 14
|
||||||
|
- macOS 13
|
||||||
|
- macOS 12
|
||||||
|
- macOS 11
|
||||||
|
- Ubuntu 23.10
|
||||||
|
- Ubuntu 22.04
|
||||||
|
- Other
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: os_info_other
|
||||||
|
attributes:
|
||||||
|
label: Other OS
|
||||||
|
description: "If \"Other\" was selected above, what OS are you using?"
|
||||||
|
placeholder: "e.g., Arch Linux, FreeBSD"
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: obs_version
|
||||||
|
attributes:
|
||||||
|
label: OBS Studio Version
|
||||||
|
description: What version of OBS Studio are you using?
|
||||||
|
placeholder: 30.2.2
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: advss_version
|
||||||
|
attributes:
|
||||||
|
label: Advanced Scene Switcher Version
|
||||||
|
description: What version of the Advanced Scene Switcher are you using?
|
||||||
|
placeholder: 1.27.2
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: settings
|
||||||
|
attributes:
|
||||||
|
label: Plugin settings
|
||||||
|
description: |
|
||||||
|
Please provide the plugin settings used.
|
||||||
|
Either only [export the macros](https://github.com/WarmUpTill/SceneSwitcher/wiki/Exporting-and-importing-individual-macros) relevant to this issue or [export all settings](https://github.com/WarmUpTill/SceneSwitcher/wiki/Saving-and-loading-settings#how-to-create-and-import-a-backup-of-your-settings) on the General tab of the plugin.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: obs_log_url
|
||||||
|
attributes:
|
||||||
|
label: OBS Studio Log URL
|
||||||
|
description: Please provide the obsproject.com URL (from Help menu > Log Files > Upload Current/Previous Log File) to the OBS log file where this issue occurred.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: obs_crash_log_url
|
||||||
|
attributes:
|
||||||
|
label: OBS Studio Crash Log URL
|
||||||
|
description: If this is a crash report, please provide the obsproject.com URL to the OBS crash log file where this issue occurred.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: expected_behavior
|
||||||
|
attributes:
|
||||||
|
label: Expected Behavior
|
||||||
|
description: "What did you expect to happen?"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: current_behavior
|
||||||
|
attributes:
|
||||||
|
label: Current Behavior
|
||||||
|
description: "What actually happened?"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: steps_to_reproduce
|
||||||
|
attributes:
|
||||||
|
label: Steps to Reproduce
|
||||||
|
description: "How do you trigger this bug? Please walk us through it step by step."
|
||||||
|
placeholder: |
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
...
|
||||||
|
value: |
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: additional_notes
|
||||||
|
attributes:
|
||||||
|
label: Anything else we should know?
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
7
.github/ISSUE_TEMPLATE/config.yml
vendored
7
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +1,8 @@
|
|||||||
blank_issues_enabled: true
|
blank_issues_enabled: true
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Help/Support
|
- name: 📚 Wiki
|
||||||
url: https://github.com/WarmUpTill/SceneSwitcher/wiki
|
url: https://github.com/WarmUpTill/SceneSwitcher/wiki
|
||||||
about: For general questions about how to use and configure the plugin please have a look at the wiki (https://github.com/WarmUpTill/SceneSwitcher/wiki) or ask questions in the OBS forum (https://obsproject.com/forum/threads/advanced-scene-switcher.48264/)
|
about: For explanations on how the plugin works or to see example guides, check out the wiki.
|
||||||
|
- name: 💬 OBS Forum Thread
|
||||||
|
url: https://obsproject.com/forum/threads/advanced-scene-switcher.48264
|
||||||
|
about: To discuss the plugin or get assistance, feel free to use the OBS forum thread or the GitHub discussions page.
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
||||||
37
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
Normal file
37
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# Based on the OBS issue templates
|
||||||
|
# https://github.com/obsproject/.github/tree/master/.github/ISSUE_TEMPLATE
|
||||||
|
|
||||||
|
name: Feature request
|
||||||
|
description: Suggest an idea for this projectReport a bug or crash
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
id: md_welcome
|
||||||
|
attributes:
|
||||||
|
value: This form is for requesting new features for Advanced Scene Switcher!
|
||||||
|
- type: textarea
|
||||||
|
id: background
|
||||||
|
attributes:
|
||||||
|
label: Background
|
||||||
|
description: "Is your feature request related to a problem? Please describe."
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: solution
|
||||||
|
attributes:
|
||||||
|
label: Solution
|
||||||
|
description: "Describe the solution you'd like."
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: alternatives
|
||||||
|
attributes:
|
||||||
|
label: Alternatives
|
||||||
|
description: "Describe alternatives you've considered."
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: additional_notes
|
||||||
|
attributes:
|
||||||
|
label: Anything else we should know?
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
1
.github/scripts/.Brewfile
vendored
1
.github/scripts/.Brewfile
vendored
@@ -4,3 +4,4 @@ brew "cmake"
|
|||||||
brew "jq"
|
brew "jq"
|
||||||
brew "xcbeautify"
|
brew "xcbeautify"
|
||||||
brew "automake"
|
brew "automake"
|
||||||
|
brew "libtool"
|
||||||
|
|||||||
78
.github/scripts/.build-deps.zsh
vendored
78
.github/scripts/.build-deps.zsh
vendored
@@ -306,7 +306,7 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
log_info "Building OpenCV ..."
|
log_info "Building OpenCV ..."
|
||||||
cmake --build ${opencv_build_dir} --config Release
|
cmake --build ${opencv_build_dir} --config Release
|
||||||
|
|
||||||
log_info "Installing OpenCV..."
|
log_info "Installing OpenCV ..."
|
||||||
cmake --install ${opencv_build_dir} --prefix "${advss_dep_path}" --config Release || true
|
cmake --install ${opencv_build_dir} --prefix "${advss_dep_path}" --config Release || true
|
||||||
popd
|
popd
|
||||||
|
|
||||||
@@ -335,17 +335,22 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
log_info "Building Leptonica ..."
|
log_info "Building Leptonica ..."
|
||||||
cmake --build ${leptonica_build_dir} --config Release
|
cmake --build ${leptonica_build_dir} --config Release
|
||||||
|
|
||||||
log_info "Installing Leptonica..."
|
log_info "Installing Leptonica ..."
|
||||||
# Workaround for "unknown file attribute: H" errors when running install
|
# Workaround for "unknown file attribute: H" errors when running install
|
||||||
cmake --install ${leptonica_build_dir} --prefix "${advss_dep_path}" --config Release || :
|
cmake --install ${leptonica_build_dir} --prefix "${advss_dep_path}" --config Release || :
|
||||||
popd
|
popd
|
||||||
|
|
||||||
local tesseract_dir="${project_root}/deps/tesseract"
|
local tesseract_dir="${project_root}/deps/tesseract"
|
||||||
local tesseract_build_dir="${tesseract_dir}/build_${target##*-}"
|
local tesseract_build_dir_x86_64="${tesseract_dir}/build_x86_64"
|
||||||
|
|
||||||
|
pushd ${tesseract_dir}
|
||||||
|
log_info "Configure Tesseract (x86_64) ..."
|
||||||
|
|
||||||
local -a tesseract_cmake_args=(
|
local -a tesseract_cmake_args=(
|
||||||
-DCMAKE_BUILD_TYPE=Release
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
|
-DCMAKE_SYSTEM_NAME="Darwin"
|
||||||
|
-DCMAKE_OSX_ARCHITECTURES=x86_64
|
||||||
|
-DCMAKE_SYSTEM_PROCESSOR=x86_64
|
||||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
||||||
-DSW_BUILD=OFF
|
-DSW_BUILD=OFF
|
||||||
-DBUILD_TRAINING_TOOLS=OFF
|
-DBUILD_TRAINING_TOOLS=OFF
|
||||||
@@ -353,28 +358,40 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
-DCMAKE_INSTALL_PREFIX="${advss_dep_path}"
|
-DCMAKE_INSTALL_PREFIX="${advss_dep_path}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if [ "${target}" != "macos-x86_64" ]; then
|
cmake -S . -B ${tesseract_build_dir_x86_64} ${tesseract_cmake_args}
|
||||||
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 "Building Tesseract (x86_64) ..."
|
||||||
log_info "Configure Tesseract ..."
|
cmake --build ${tesseract_build_dir_x86_64} --config Release
|
||||||
cmake -S . -B ${tesseract_build_dir} ${tesseract_cmake_args}
|
|
||||||
|
|
||||||
log_info "Building Tesseract ..."
|
log_info "Configure Tesseract (arm64) ..."
|
||||||
cmake --build ${tesseract_build_dir} --config Release
|
|
||||||
|
git checkout .
|
||||||
|
|
||||||
|
local tesseract_build_dir_arm64="${tesseract_dir}/build_arm64"
|
||||||
|
local -a tesseract_cmake_args=(
|
||||||
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
|
-DCMAKE_SYSTEM_NAME="Darwin"
|
||||||
|
-DCMAKE_OSX_ARCHITECTURES=arm64
|
||||||
|
-DCMAKE_SYSTEM_PROCESSOR=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}"
|
||||||
|
)
|
||||||
|
|
||||||
|
cmake -S . -B ${tesseract_build_dir_arm64} ${tesseract_cmake_args}
|
||||||
|
|
||||||
|
log_info "Building Tesseract (arm64) ..."
|
||||||
|
cmake --build ${tesseract_build_dir_arm64} --config Release
|
||||||
|
|
||||||
|
log_info "Combine arm and x86 libtesseract binaries ..."
|
||||||
|
mv ${tesseract_build_dir_arm64}/libtesseract.a ${tesseract_build_dir_arm64}/libtesseract_arm.a
|
||||||
|
lipo -create ${tesseract_build_dir_x86_64}/libtesseract.a ${tesseract_build_dir_arm64}/libtesseract_arm.a -output ${tesseract_build_dir_arm64}/libtesseract.a
|
||||||
|
|
||||||
log_info "Installing Tesseract..."
|
log_info "Installing Tesseract..."
|
||||||
cmake --install ${tesseract_build_dir} --prefix "${advss_dep_path}" --config Release
|
cmake --install ${tesseract_build_dir_arm64} --prefix "${advss_dep_path}" --config Release
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
pushd ${advss_dep_path}
|
pushd ${advss_dep_path}
|
||||||
@@ -402,22 +419,29 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
lipo -create openssl_x86/libcrypto.a openssl_arm/libcrypto.a -output openssl-combined/libcrypto.a
|
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
|
lipo -create openssl_x86/libssl.a openssl_arm/libssl.a -output openssl-combined/libssl.a
|
||||||
|
|
||||||
log_info "Clean up openssl dir..."
|
log_info "Clean up openssl dir ..."
|
||||||
mv openssl_x86 openssl
|
mv openssl_x86 openssl
|
||||||
rm -rf openssl_arm
|
rm -rf openssl_arm
|
||||||
popd
|
popd
|
||||||
|
|
||||||
pushd ${project_root}/deps/libusb
|
pushd ${project_root}/deps/libusb
|
||||||
log_info "Prepare libusb ..."
|
|
||||||
|
|
||||||
log_info "Building libusb x86 (deps) ..."
|
log_info "Configure libusb x86 ..."
|
||||||
export MACOSX_DEPLOYMENT_TARGET=10.9
|
export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)
|
||||||
|
export CC=$(xcrun --sdk macosx --find clang)
|
||||||
|
export CXX=$(xcrun --sdk macosx --find clang++)
|
||||||
|
export CFLAGS="-arch x86_64 -isysroot $SDKROOT"
|
||||||
|
export CXXFLAGS="-arch x86_64 -isysroot $SDKROOT"
|
||||||
|
export LDFLAGS="-arch x86_64 -isysroot $SDKROOT"
|
||||||
|
export MACOSX_DEPLOYMENT_TARGET=10.15
|
||||||
|
|
||||||
|
log_info "Building libusb x86 ..."
|
||||||
mkdir ${project_root}/deps/libusb/out_x86
|
mkdir ${project_root}/deps/libusb/out_x86
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure --host=x86_64-apple-darwin --prefix=${advss_dep_path}
|
./configure --host=x86_64-apple-darwin --prefix=${advss_dep_path}
|
||||||
make && make install
|
make && make install
|
||||||
|
|
||||||
log_info "Building libusb x86 ..."
|
log_info "Configure libusb arm ..."
|
||||||
make clean
|
make clean
|
||||||
rm -r ${project_root}/deps/libusb/out_x86
|
rm -r ${project_root}/deps/libusb/out_x86
|
||||||
mkdir ${project_root}/deps/libusb/out_x86
|
mkdir ${project_root}/deps/libusb/out_x86
|
||||||
|
|||||||
2
.github/workflows/build-debian.yml
vendored
2
.github/workflows/build-debian.yml
vendored
@@ -50,7 +50,7 @@ jobs:
|
|||||||
mv ../*.deb .
|
mv ../*.deb .
|
||||||
- name: Publish
|
- name: Publish
|
||||||
if: success()
|
if: success()
|
||||||
uses: actions/upload-artifact@v2.2.1
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: "obs-scene-switcher.deb"
|
name: "obs-scene-switcher.deb"
|
||||||
path: ${{ github.workspace }}/*.deb
|
path: ${{ github.workspace }}/*.deb
|
||||||
|
|||||||
6
.github/workflows/build-project.yaml
vendored
6
.github/workflows/build-project.yaml
vendored
@@ -75,7 +75,7 @@ jobs:
|
|||||||
|
|
||||||
macos-build:
|
macos-build:
|
||||||
name: Build for macOS 🍏
|
name: Build for macOS 🍏
|
||||||
runs-on: macos-13
|
runs-on: macos-14
|
||||||
needs: check-event
|
needs: check-event
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
@@ -107,8 +107,8 @@ jobs:
|
|||||||
print "pluginName=${product_name}" >> $GITHUB_OUTPUT
|
print "pluginName=${product_name}" >> $GITHUB_OUTPUT
|
||||||
print "pluginVersion=${git_tag}" >> $GITHUB_OUTPUT
|
print "pluginVersion=${git_tag}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
print '::group::Select Xcode version'
|
print '::group::Enable Xcode 15.2'
|
||||||
sudo xcode-select --switch /Applications/Xcode_14.3.1.app
|
sudo xcode-select --switch /Applications/Xcode_15.2.app/Contents/Developer
|
||||||
print '::endgroup::'
|
print '::endgroup::'
|
||||||
|
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
|
|||||||
@@ -52,8 +52,6 @@ target_sources(
|
|||||||
${LIB_NAME}
|
${LIB_NAME}
|
||||||
PRIVATE lib/legacy/scene-group.cpp
|
PRIVATE lib/legacy/scene-group.cpp
|
||||||
lib/legacy/scene-group.hpp
|
lib/legacy/scene-group.hpp
|
||||||
lib/legacy/scene-trigger.cpp
|
|
||||||
lib/legacy/scene-trigger.hpp
|
|
||||||
lib/legacy/switch-audio.cpp
|
lib/legacy/switch-audio.cpp
|
||||||
lib/legacy/switch-audio.hpp
|
lib/legacy/switch-audio.hpp
|
||||||
lib/legacy/switch-executable.cpp
|
lib/legacy/switch-executable.cpp
|
||||||
@@ -66,8 +64,6 @@ target_sources(
|
|||||||
lib/legacy/switch-idle.hpp
|
lib/legacy/switch-idle.hpp
|
||||||
lib/legacy/switch-media.cpp
|
lib/legacy/switch-media.cpp
|
||||||
lib/legacy/switch-media.hpp
|
lib/legacy/switch-media.hpp
|
||||||
lib/legacy/switch-network.cpp
|
|
||||||
lib/legacy/switch-network.hpp
|
|
||||||
lib/legacy/switch-pause.cpp
|
lib/legacy/switch-pause.cpp
|
||||||
lib/legacy/switch-pause.hpp
|
lib/legacy/switch-pause.hpp
|
||||||
lib/legacy/switch-random.cpp
|
lib/legacy/switch-random.cpp
|
||||||
@@ -161,6 +157,8 @@ target_sources(
|
|||||||
lib/queue/action-queue.hpp
|
lib/queue/action-queue.hpp
|
||||||
lib/queue/action-queue-tab.cpp
|
lib/queue/action-queue-tab.cpp
|
||||||
lib/queue/action-queue-tab.hpp
|
lib/queue/action-queue-tab.hpp
|
||||||
|
lib/utils/auto-update-tooltip-label.cpp
|
||||||
|
lib/utils/auto-update-tooltip-label.hpp
|
||||||
lib/utils/backup.cpp
|
lib/utils/backup.cpp
|
||||||
lib/utils/backup.hpp
|
lib/utils/backup.hpp
|
||||||
lib/utils/condition-logic.cpp
|
lib/utils/condition-logic.cpp
|
||||||
@@ -255,12 +253,16 @@ target_sources(
|
|||||||
lib/utils/tab-helpers.hpp
|
lib/utils/tab-helpers.hpp
|
||||||
lib/utils/temp-variable.cpp
|
lib/utils/temp-variable.cpp
|
||||||
lib/utils/temp-variable.hpp
|
lib/utils/temp-variable.hpp
|
||||||
|
lib/utils/time-helpers.cpp
|
||||||
|
lib/utils/time-helpers.hpp
|
||||||
lib/utils/ui-helpers.cpp
|
lib/utils/ui-helpers.cpp
|
||||||
lib/utils/ui-helpers.hpp
|
lib/utils/ui-helpers.hpp
|
||||||
lib/utils/utility.cpp
|
lib/utils/utility.cpp
|
||||||
lib/utils/utility.hpp
|
lib/utils/utility.hpp
|
||||||
lib/utils/volume-control.cpp
|
lib/utils/volume-control.cpp
|
||||||
lib/utils/volume-control.hpp
|
lib/utils/volume-control.hpp
|
||||||
|
lib/utils/websocket-api.cpp
|
||||||
|
lib/utils/websocket-api.hpp
|
||||||
lib/variables/variable-line-edit.cpp
|
lib/variables/variable-line-edit.cpp
|
||||||
lib/variables/variable-line-edit.hpp
|
lib/variables/variable-line-edit.hpp
|
||||||
lib/variables/variable-number.hpp
|
lib/variables/variable-number.hpp
|
||||||
@@ -326,13 +328,9 @@ set_target_properties(${LIB_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
|||||||
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)
|
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)
|
||||||
target_compile_features(${LIB_NAME} PUBLIC cxx_std_17)
|
target_compile_features(${LIB_NAME} PUBLIC cxx_std_17)
|
||||||
|
|
||||||
add_definitions(-DASIO_STANDALONE)
|
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
${LIB_NAME}
|
${LIB_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/deps/obs-websocket/lib"
|
||||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
|
"${CMAKE_CURRENT_SOURCE_DIR}/deps/exprtk")
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/websocketpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/obs-websocket/lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/exprtk")
|
|
||||||
|
|
||||||
if(NOT nlohmann_json_DIR
|
if(NOT nlohmann_json_DIR
|
||||||
AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/deps/json/CMakeLists.txt")
|
AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/deps/json/CMakeLists.txt")
|
||||||
@@ -428,8 +426,7 @@ if(NOT OS_WINDOWS)
|
|||||||
target_compile_options(
|
target_compile_options(
|
||||||
${LIB_NAME}
|
${LIB_NAME}
|
||||||
PUBLIC -Wno-error=unused-parameter -Wno-error=conversion -Wno-error=shadow
|
PUBLIC -Wno-error=unused-parameter -Wno-error=conversion -Wno-error=shadow
|
||||||
-Wno-error=float-conversion -Wno-error=enum-conversion
|
-Wno-error=float-conversion -Wno-error=enum-conversion)
|
||||||
-Wno-error=deprecated-declarations)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# --- End of section ---
|
# --- End of section ---
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
defaultLocaleFile = "en-US.ini"
|
defaultLocaleFile = "en-US.ini"
|
||||||
|
commentChars = ";#"
|
||||||
|
|
||||||
|
|
||||||
class localeEntry:
|
class localeEntry:
|
||||||
@@ -21,6 +22,13 @@ class localeEntry:
|
|||||||
self.lineNum = lineNum
|
self.lineNum = lineNum
|
||||||
|
|
||||||
|
|
||||||
|
def isCommentLine(line):
|
||||||
|
for char in commentChars:
|
||||||
|
if line.startswith(char):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def getNonDefaultLocales(dir):
|
def getNonDefaultLocales(dir):
|
||||||
files = []
|
files = []
|
||||||
for filename in os.listdir(dir):
|
for filename in os.listdir(dir):
|
||||||
@@ -38,7 +46,7 @@ def getAllLocaleEntries(file):
|
|||||||
widgetPlaceholders = []
|
widgetPlaceholders = []
|
||||||
qStringArgs = []
|
qStringArgs = []
|
||||||
|
|
||||||
if line.startswith(";"):
|
if isCommentLine(line):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for word in line.split("{{"):
|
for word in line.split("{{"):
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"obs-studio": {
|
"obs-studio": {
|
||||||
"version": "30.0.2",
|
"version": "30.1.2",
|
||||||
"baseUrl": "https://github.com/obsproject/obs-studio/archive/refs/tags",
|
"baseUrl": "https://github.com/obsproject/obs-studio/archive/refs/tags",
|
||||||
"label": "OBS sources",
|
"label": "OBS sources",
|
||||||
"hashes": {
|
"hashes": {
|
||||||
"macos": "be12c3ad0a85713750d8325e4b1db75086223402d7080d0e3c2833d7c5e83c27",
|
"macos": "490bae1c392b3b344b0270afd8cb887da4bc50bd92c0c426e96713c1ccb9701a",
|
||||||
"windows-x64": "970058c49322cfa9cd6d620abb393fed89743ba7e74bd9dbb6ebe0ea8141d9c7"
|
"windows-x64": "c2dd03fa7fd01fad5beafce8f7156da11f9ed9a588373fd40b44a06f4c03b867"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"prebuilt": {
|
"prebuilt": {
|
||||||
"version": "2023-11-03",
|
"version": "2024-03-19",
|
||||||
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
|
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
|
||||||
"label": "Pre-Built obs-deps",
|
"label": "Pre-Built obs-deps",
|
||||||
"hashes": {
|
"hashes": {
|
||||||
"macos": "90c2fc069847ec2768dcc867c1c63b112c615ed845a907dc44acab7a97181974",
|
"macos": "2e9bfb55a5e0e4c1086fa1fda4cf268debfead473089df2aaea80e1c7a3ca7ff",
|
||||||
"windows-x64": "d0825a6fb65822c993a3059edfba70d72d2e632ef74893588cf12b1f0d329ce6"
|
"windows-x64": "6e86068371526a967e805f6f9903f9407adb683c21820db5f07da8f30d11e998"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"qt6": {
|
"qt6": {
|
||||||
"version": "2023-11-03",
|
"version": "2024-03-19",
|
||||||
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
|
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
|
||||||
"label": "Pre-Built Qt6",
|
"label": "Pre-Built Qt6",
|
||||||
"hashes": {
|
"hashes": {
|
||||||
"macos": "ba4a7152848da0053f63427a2a2cb0a199af3992997c0db08564df6f48c9db98",
|
"macos": "694f1e639c017e3b1f456f735330dc5afae287cbea85757101af1368de3142c8",
|
||||||
"windows-x64": "bc57dedf76b47119a6dce0435a2f21b35b08c8f2948b1cb34a157320f77732d1"
|
"windows-x64": "72d1df34a0ef7413a681d5fcc88cae81da60adc03dcd23ef17862ab170bcc0dd"
|
||||||
},
|
},
|
||||||
"debugSymbols": {
|
"debugSymbols": {
|
||||||
"windows-x64": "fd8ecd1d8cd2ef049d9f4d7fb5c134f784836d6020758094855dfa98bd025036"
|
"windows-x64": "fbddd1f659c360f2291911ac5709b67b6f8182e6bca519d24712e4f6fd3cc865"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ AdvSceneSwitcher.generalTab.status.autoStart.streaming="Streamen"
|
|||||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Aufnehmen oder Streamen"
|
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Aufnehmen oder Streamen"
|
||||||
AdvSceneSwitcher.generalTab.status.checkInterval="Teste Bedingungen alle"
|
AdvSceneSwitcher.generalTab.status.checkInterval="Teste Bedingungen alle"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior="Allgemeines Verhalten"
|
AdvSceneSwitcher.generalTab.generalBehavior="Allgemeines Verhalten"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="Wenn keine Bedingung erfüllt ist für "
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch="Wenn keine Bedingung erfüllt ist für "
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Kann nur so genau sein wie das eingestellte Interval zum Testen der Bedingungen."
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatchDelay.tooltip="Kann nur so genau sein wie das eingestellte Interval zum Testen der Bedingungen."
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Nicht wechseln"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.dontSwitch="Nicht wechseln"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Wechsle zu einer Szene auf dem Zufall-Tab"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchToRandom="Wechsle zu einer Szene auf dem Zufall-Tab"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Wechsle zu:"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchTo="Wechsle zu:"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Nach Ausführen von Aktionen überspringe das Ausführen von Aktionen für"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Nach Ausführen von Aktionen überspringe das Ausführen von Aktionen für"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="In diesem Zeitraum werden potentielle erfüllte Bedingungen ignoriert!"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="In diesem Zeitraum werden potentielle erfüllte Bedingungen ignoriert!"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Ausführliches Logging"
|
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Ausführliches Logging"
|
||||||
@@ -94,7 +94,7 @@ AdvSceneSwitcher.macroTab.highlightExecutedMacros="Kürzlich ausgeführte Makros
|
|||||||
AdvSceneSwitcher.macroTab.highlightTrueConditions="Bedingungen des aktuell ausgewählten Makros hervorheben, die kürzlich als wahr bewertet wurden"
|
AdvSceneSwitcher.macroTab.highlightTrueConditions="Bedingungen des aktuell ausgewählten Makros hervorheben, die kürzlich als wahr bewertet wurden"
|
||||||
AdvSceneSwitcher.macroTab.highlightPerformedActions="Zuletzt ausgeführte Aktionen des aktuell ausgewählten Makros hervorheben"
|
AdvSceneSwitcher.macroTab.highlightPerformedActions="Zuletzt ausgeführte Aktionen des aktuell ausgewählten Makros hervorheben"
|
||||||
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Hotkeys zur Steuerung des Pausen-Status neuer Makros registrieren"
|
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Hotkeys zur Steuerung des Pausen-Status neuer Makros registrieren"
|
||||||
AdvSceneSwitcher.macroTab.currentDisableHotkeys="Hotkeys zur Steuerung des Pausen-Status ausgewählter Makros registrieren"
|
AdvSceneSwitcher.macroTab.currentRegisterHotkeys="Hotkeys zur Steuerung des Pausen-Status ausgewählter Makros registrieren"
|
||||||
|
|
||||||
; Macro List
|
; Macro List
|
||||||
AdvSceneSwitcher.macroList.deleted="gelöscht"
|
AdvSceneSwitcher.macroList.deleted="gelöscht"
|
||||||
@@ -142,8 +142,6 @@ AdvSceneSwitcher.condition.scene.type.currentPattern="Aktuelle Szene entspricht"
|
|||||||
AdvSceneSwitcher.condition.scene.type.previousPattern="Vorherige Szene entspricht"
|
AdvSceneSwitcher.condition.scene.type.previousPattern="Vorherige Szene entspricht"
|
||||||
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Während des Übergangs die Ziel-Szene überprüfen"
|
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Während des Übergangs die Ziel-Szene überprüfen"
|
||||||
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Während des Übergangs die Quell-Szene überprüfen"
|
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Während des Übergangs die Quell-Szene überprüfen"
|
||||||
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
|
||||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
|
||||||
AdvSceneSwitcher.condition.window="Fenster"
|
AdvSceneSwitcher.condition.window="Fenster"
|
||||||
AdvSceneSwitcher.condition.file="Datei"
|
AdvSceneSwitcher.condition.file="Datei"
|
||||||
AdvSceneSwitcher.condition.file.type.match="entspricht"
|
AdvSceneSwitcher.condition.file.type.match="entspricht"
|
||||||
@@ -214,7 +212,6 @@ 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.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"
|
||||||
@@ -492,7 +489,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="Nach unten verschieben"
|
|||||||
AdvSceneSwitcher.action.sceneOrder.type.moveTop="An erste Stelle verschieben"
|
AdvSceneSwitcher.action.sceneOrder.type.moveTop="An erste Stelle verschieben"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="An letzte Stelle verschieben"
|
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="An letzte Stelle verschieben"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.movePosition="An Position verschieben"
|
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}}{{sources2}}{{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}}{{settingSelection}}{{singleSettingValue}}"
|
AdvSceneSwitcher.action.sceneTransform.entry="Auf{{scenes}}{{action}}{{rotation}}{{sources}}{{settingSelection}}{{singleSettingValue}}"
|
||||||
@@ -531,7 +528,7 @@ AdvSceneSwitcher.action.screenshot.type.source="Quelle"
|
|||||||
AdvSceneSwitcher.action.screenshot.type.scene="Szene"
|
AdvSceneSwitcher.action.screenshot.type.scene="Szene"
|
||||||
AdvSceneSwitcher.action.screenshot.mainOutput="OBS's Haupt-Ausgabe"
|
AdvSceneSwitcher.action.screenshot.mainOutput="OBS's Haupt-Ausgabe"
|
||||||
AdvSceneSwitcher.action.screenshot.blackscreenNote="Quellen oder Szenen, die nicht immer gerendert werden, können dazu führen, dass einige Teile der Screenshots leer bleiben."
|
AdvSceneSwitcher.action.screenshot.blackscreenNote="Quellen oder Szenen, die nicht immer gerendert werden, können dazu führen, dass einige Teile der Screenshots leer bleiben."
|
||||||
AdvSceneSwitcher.action.screenshot.entry="Screenshot{{targetType}}{{sources}}{{scenes}}und speichere in{{saveType}}Pfad"
|
AdvSceneSwitcher.action.screenshot.entry="Screenshot{{targetType}}{{sources}}{{scenes}}und speichere in{{saveType}}{{variables}}Pfad"
|
||||||
AdvSceneSwitcher.action.profile="Profil"
|
AdvSceneSwitcher.action.profile="Profil"
|
||||||
AdvSceneSwitcher.action.profile.entry="Aktives Profil umschalten auf {{profiles}}"
|
AdvSceneSwitcher.action.profile.entry="Aktives Profil umschalten auf {{profiles}}"
|
||||||
AdvSceneSwitcher.action.sceneCollection="Szenensammlung"
|
AdvSceneSwitcher.action.sceneCollection="Szenensammlung"
|
||||||
@@ -730,31 +727,6 @@ AdvSceneSwitcher.videoTab.ignoreInactiveSource="außer Video Quelle ist inaktiv"
|
|||||||
AdvSceneSwitcher.videoTab.entry="Wenn {{videoSources}} {{condition}} {{filePath}} {{browseButton}} für {{duration}} wechsle zu {{scenes}} mit {{transitions}} {{ignoreInactiveSource}}"
|
AdvSceneSwitcher.videoTab.entry="Wenn {{videoSources}} {{condition}} {{filePath}} {{browseButton}} für {{duration}} wechsle zu {{scenes}} mit {{transitions}} {{ignoreInactiveSource}}"
|
||||||
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Dieser Tab ermöglicht es basierend auf der Videoausgabe von Quellen scenen zu wechseln.<br/>Für eine noch bessere Implementierung dieser Funktionalität siehe <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a>.<br/><br/>Klicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen..</p></body></html>"
|
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Dieser Tab ermöglicht es basierend auf der Videoausgabe von Quellen scenen zu wechseln.<br/>Für eine noch bessere Implementierung dieser Funktionalität siehe <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a>.<br/><br/>Klicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen..</p></body></html>"
|
||||||
|
|
||||||
; Network Tab
|
|
||||||
AdvSceneSwitcher.networkTab.title="Netzwerk"
|
|
||||||
AdvSceneSwitcher.networkTab.description="Über diesen Tab kann die aktive Szene einer anderen OBS-Instanz ferngesteuert werden.\nBitte beachten, dass die Szenennamen auf allen OBS-Instanzen exakt übereinstimmen müssen."
|
|
||||||
AdvSceneSwitcher.networkTab.warning="Die Verwendung des Servers außerhalb eines lokalen Netzwerks kann dazu führen, dass die aktive Szene von dritten Personen ausgelesen werden kann."
|
|
||||||
AdvSceneSwitcher.networkTab.server="Server starten (Sendet Szenenwechselnachrichten zu allen verbundenen Clients)"
|
|
||||||
AdvSceneSwitcher.networkTab.server.port="Port"
|
|
||||||
AdvSceneSwitcher.networkTab.server.lockToIPv4="Nur IPv4 verwenden (deaktiviert IPv6)"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendSceneChange="Sende Nachrichten für Szenenwechsel"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Sende nur Szenenwechselnachrichten für automatisierte Szenenwechsel"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendPreview="Sende Nachrichten für Vorschau Szenenwechsel im Studio-Modus"
|
|
||||||
AdvSceneSwitcher.networkTab.startFailed.message="Der WebSocket-Server konnte nicht gestartet werden, mögliche Gründe:\n - Der TCP-Port %1 wird möglicherweise gerade von einem anderen Programm verwendet. Versuchen Sie einen anderen Port in den Websocket-Servereinstellungen zu setzen oder alle Programme zu beenden, die den Port möglicherweise verwenden.\n - Fehler: %2"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.currentStatus="Aktueller Status"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.notRunning="Nicht gestartet"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.starting="Startet"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.running="Server läuft"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restart="Server neu starten"
|
|
||||||
AdvSceneSwitcher.networkTab.client="Client starten (Empfängt Szenenwechselnachrichten )"
|
|
||||||
AdvSceneSwitcher.networkTab.client.address="Hostname oder IP-Adresse"
|
|
||||||
AdvSceneSwitcher.networkTab.client.port="Port"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.currentStatus="Aktueller status"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.disconnected="Verbindung getrennt"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connecting="Verbinde"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connected="Verbunden"
|
|
||||||
AdvSceneSwitcher.networkTab.client.reconnect="Erneutes Verbinden erzwingen"
|
|
||||||
|
|
||||||
; Scene Group Tab
|
; Scene Group Tab
|
||||||
AdvSceneSwitcher.sceneGroupTab.title="Szenengruppe"
|
AdvSceneSwitcher.sceneGroupTab.title="Szenengruppe"
|
||||||
AdvSceneSwitcher.sceneGroupTab.list="Szenengruppen"
|
AdvSceneSwitcher.sceneGroupTab.list="Szenengruppen"
|
||||||
@@ -775,30 +747,6 @@ AdvSceneSwitcher.sceneGroupTab.exists="Szenengruppen- oder Szenenname existiert
|
|||||||
AdvSceneSwitcher.sceneGroupTab.help="Szenengruppen können, genau wie reguläre Szenen, als Ziel eines Szenenwechsler Eintrags ausgewählt werden.\n\nSzenengruppen bestehen aus einer Liste von Szenen.\nDie aktive Szene der Szenengruppe schreitet abhängig von den konfigurierten Einstellungen durch die Liste der zugewiesenen Szenen fort.\n\nMögliche Einstellungen zum Fortschreiten der aktiven Szene sind:\nAnzahl der Szenenwechsel.\nZeit seit dem letzten Szenenwechsel in der Szenengruppe.\nOder zufällig.\n\nSo kann zum Beispiel eine Szenengruppe welche die folgenden Szenen enthält ...\nSzene 1\nSzene 2\nSzene 3 \n... beim erstem Mal zu \"Szene 1\" wechseln.\nBeim zweiten Mal zu \"Szene 2\".\nDie restlichem Male wechselt die Szenengruppe zu \"Szene 3\".\n\nKlicke auf das markierte Plus Symbol, um eine neuen Szenengruppe hinzuzufügen."
|
AdvSceneSwitcher.sceneGroupTab.help="Szenengruppen können, genau wie reguläre Szenen, als Ziel eines Szenenwechsler Eintrags ausgewählt werden.\n\nSzenengruppen bestehen aus einer Liste von Szenen.\nDie aktive Szene der Szenengruppe schreitet abhängig von den konfigurierten Einstellungen durch die Liste der zugewiesenen Szenen fort.\n\nMögliche Einstellungen zum Fortschreiten der aktiven Szene sind:\nAnzahl der Szenenwechsel.\nZeit seit dem letzten Szenenwechsel in der Szenengruppe.\nOder zufällig.\n\nSo kann zum Beispiel eine Szenengruppe welche die folgenden Szenen enthält ...\nSzene 1\nSzene 2\nSzene 3 \n... beim erstem Mal zu \"Szene 1\" wechseln.\nBeim zweiten Mal zu \"Szene 2\".\nDie restlichem Male wechselt die Szenengruppe zu \"Szene 3\".\n\nKlicke auf das markierte Plus Symbol, um eine neuen Szenengruppe hinzuzufügen."
|
||||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="Wähle die Szenengruppe, die du bearbeiten möchtest, auf der linken Seite aus.\n\nWähle oben eine Szene aus, die du zur Szenengruppe hinzufügen möchtest, und klicke das Plus Symbol.\n\nDie gleiche Szene kann mehrfach in derselben Szenengruppe auftauchen."
|
AdvSceneSwitcher.sceneGroupTab.scenes.help="Wähle die Szenengruppe, die du bearbeiten möchtest, auf der linken Seite aus.\n\nWähle oben eine Szene aus, die du zur Szenengruppe hinzufügen möchtest, und klicke das Plus Symbol.\n\nDie gleiche Szene kann mehrfach in derselben Szenengruppe auftauchen."
|
||||||
|
|
||||||
; Scene Trigger Tab
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.title="Szenen Trigger"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--Trigger auswählen--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="aktiv ist"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="nicht aktiv ist"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="verlassen wird"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--Aktion auswählen--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="Aufnahme starten"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="Aufnahme pausieren"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="Aufnahme fortsetzen"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="Aufnahme stoppen"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="Streamen stoppen"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="Streamen starten"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="Replay Buffer starten"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="Replay Buffer stoppen"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="Audio Quelle stumm schalten"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="Audio Quelle aktiv schalten"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="Szenenwechsler starten"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="Szenenwechsler stoppen"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="Virtuelle Kamera starten"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="Virtuelle Kamera stoppen"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.entry="Wenn {{scenes}} {{triggers}} {{actions}} {{audioSources}} nach {{duration}} "
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.help="Dieser Tab ermöglicht es automatisiert Handlungen, wie etwa das Stoppen von einer Aufnahme oder des Streamens, bei einem Szenenwechsel auszuführen."
|
|
||||||
|
|
||||||
; Hotkey
|
; Hotkey
|
||||||
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Starte den Erweiterten Szenenwechsler"
|
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Starte den Erweiterten Szenenwechsler"
|
||||||
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Stoppe den Erweiterten Szenenwechsler"
|
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Stoppe den Erweiterten Szenenwechsler"
|
||||||
@@ -895,7 +843,7 @@ AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Dies scheint das erste
|
|||||||
AdvSceneSwitcher.deprecatedTabWarning="Die Entwicklung für dieses Tab wurde gestoppt!\nBitte stattdessen zur Verwendung des Makros-Tab übergehen.\nDieser Hinweis kann im Allgemein-Tab deaktiviert werden."
|
AdvSceneSwitcher.deprecatedTabWarning="Die Entwicklung für dieses Tab wurde gestoppt!\nBitte stattdessen zur Verwendung des Makros-Tab übergehen.\nDieser Hinweis kann im Allgemein-Tab deaktiviert werden."
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="Millisekunden"
|
AdvSceneSwitcher.unit.milliseconds="Millisekunden"
|
||||||
AdvSceneSwitcher.unit.secends="Sekunden"
|
AdvSceneSwitcher.unit.seconds="Sekunden"
|
||||||
AdvSceneSwitcher.unit.minutes="Minuten"
|
AdvSceneSwitcher.unit.minutes="Minuten"
|
||||||
AdvSceneSwitcher.unit.hours="Stunden"
|
AdvSceneSwitcher.unit.hours="Stunden"
|
||||||
AdvSceneSwitcher.duration.condition.none="Kein Dauer-Modifikator"
|
AdvSceneSwitcher.duration.condition.none="Kein Dauer-Modifikator"
|
||||||
|
|||||||
@@ -18,17 +18,20 @@ AdvSceneSwitcher.generalTab.status.autoStart.recording="Recording"
|
|||||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Streaming"
|
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Streaming"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Recording or Streaming"
|
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Recording or Streaming"
|
||||||
AdvSceneSwitcher.generalTab.status.checkInterval="Check conditions every"
|
AdvSceneSwitcher.generalTab.status.checkInterval="Check conditions every"
|
||||||
|
AdvSceneSwitcher.generalTab.status.checkIntervalTooLow="⚠️ Conflict with macro \"%1\"!"
|
||||||
|
AdvSceneSwitcher.generalTab.status.checkIntervalTooLow.tooltip="Macro \"%1\" won't be able to check its condition at the desired interval of %2.\nEither change the condition check value on the General tab or in the settings of macro \"%3\"."
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior="General behavior"
|
AdvSceneSwitcher.generalTab.generalBehavior="General behavior"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="If no actions are performed for"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch="If no actions are performed for"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Will only ever be as accurate as the configured check interval."
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatchDelay.tooltip="Will only ever be as accurate as the configured check interval."
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Don't switch"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.dontSwitch="Don't switch"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Switch to any scene in Random tab"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchToRandom="Switch to any scene in Random tab"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Switch to:"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchTo="Switch to:"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="After performing actions skip performing actions for"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="After performing actions skip performing actions for"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="During this time potential matches will be ignored!"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="During this time potential matches will be ignored!"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.logLevel="Log level:"
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel="Log level:"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.default="Default"
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.default="Default"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.printActions="Log performed actions"
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.logMacro="Log executed macros"
|
||||||
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.logAction="Log performed actions"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.verbose="Verbose logging"
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.verbose="Verbose logging"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Enable verbose logging"
|
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Enable verbose logging"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Save window position and size"
|
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Save window position and size"
|
||||||
@@ -82,10 +85,8 @@ AdvSceneSwitcher.variableTab.value.header="Value"
|
|||||||
AdvSceneSwitcher.variableTab.saveLoadBehavior.header="Save/Load behavior"
|
AdvSceneSwitcher.variableTab.saveLoadBehavior.header="Save/Load behavior"
|
||||||
AdvSceneSwitcher.variableTab.saveLoadBehavior.text.default="Default to \"%1\""
|
AdvSceneSwitcher.variableTab.saveLoadBehavior.text.default="Default to \"%1\""
|
||||||
AdvSceneSwitcher.variableTab.lastUsed.header="Last used"
|
AdvSceneSwitcher.variableTab.lastUsed.header="Last used"
|
||||||
AdvSceneSwitcher.variableTab.lastUsed.text="%1 seconds ago"
|
|
||||||
AdvSceneSwitcher.variableTab.lastUsed.text.never="Never"
|
AdvSceneSwitcher.variableTab.lastUsed.text.never="Never"
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.header="Last changed"
|
AdvSceneSwitcher.variableTab.lastChanged.header="Last changed"
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.text="%1 seconds ago"
|
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.text.none="No change since launch"
|
AdvSceneSwitcher.variableTab.lastChanged.text.none="No change since launch"
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.tooltip="Times changed: %1\n\nPrevious value: %2"
|
AdvSceneSwitcher.variableTab.lastChanged.tooltip="Times changed: %1\n\nPrevious value: %2"
|
||||||
|
|
||||||
@@ -96,6 +97,7 @@ AdvSceneSwitcher.actionQueueTab.queueAddButton.tooltip="Add new action queue"
|
|||||||
AdvSceneSwitcher.actionQueueTab.queueRemoveButton.tooltip="Remove selected action queues"
|
AdvSceneSwitcher.actionQueueTab.queueRemoveButton.tooltip="Remove selected action queues"
|
||||||
AdvSceneSwitcher.actionQueueTab.name.header="Name"
|
AdvSceneSwitcher.actionQueueTab.name.header="Name"
|
||||||
AdvSceneSwitcher.actionQueueTab.size.header="Size"
|
AdvSceneSwitcher.actionQueueTab.size.header="Size"
|
||||||
|
AdvSceneSwitcher.actionQueueTab.lastEmpty.header="Last empty"
|
||||||
AdvSceneSwitcher.actionQueueTab.isRunning.header="Is running"
|
AdvSceneSwitcher.actionQueueTab.isRunning.header="Is running"
|
||||||
AdvSceneSwitcher.actionQueueTab.runOnStartup.header="Run on startup"
|
AdvSceneSwitcher.actionQueueTab.runOnStartup.header="Run on startup"
|
||||||
AdvSceneSwitcher.actionQueueTab.yes="Yes"
|
AdvSceneSwitcher.actionQueueTab.yes="Yes"
|
||||||
@@ -120,7 +122,7 @@ AdvSceneSwitcher.websocketConnectionTab.removeMultipleConnectionsPopup.text="Are
|
|||||||
# Twitch Connections Tab
|
# Twitch Connections Tab
|
||||||
AdvSceneSwitcher.twitchConnectionTab.title="Twitch Connections"
|
AdvSceneSwitcher.twitchConnectionTab.title="Twitch Connections"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.help="Twitch connections can be used to use Twitch events as triggers to execute actions or perform actions on the linked Twitch account.\n\nClick on the highlighted plus symbol to add a new connection."
|
AdvSceneSwitcher.twitchConnectionTab.help="Twitch connections can be used to use Twitch events as triggers to execute actions or perform actions on the linked Twitch account.\n\nClick on the highlighted plus symbol to add a new connection."
|
||||||
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionAddButton.tooltip.tooltip="Add new Twitch connection"
|
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionAddButton.tooltip="Add new Twitch connection"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionRemoveButton.tooltip="Remove selected Twitch connections"
|
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionRemoveButton.tooltip="Remove selected Twitch connections"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.name.header="Name"
|
AdvSceneSwitcher.twitchConnectionTab.name.header="Name"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.isValid.header="Is valid?"
|
AdvSceneSwitcher.twitchConnectionTab.isValid.header="Is valid?"
|
||||||
@@ -179,6 +181,7 @@ AdvSceneSwitcher.macroTab.segment.useCustomLabel="Use custom label"
|
|||||||
AdvSceneSwitcher.macroTab.segment.customLabelRename="Rename custom label"
|
AdvSceneSwitcher.macroTab.segment.customLabelRename="Rename custom label"
|
||||||
AdvSceneSwitcher.macroTab.segment.defaultCustomLabel="My label"
|
AdvSceneSwitcher.macroTab.segment.defaultCustomLabel="My label"
|
||||||
AdvSceneSwitcher.macroTab.segment.setCustomLabel="Set label ..."
|
AdvSceneSwitcher.macroTab.segment.setCustomLabel="Set label ..."
|
||||||
|
AdvSceneSwitcher.macroTab.segment.remove="Remove"
|
||||||
AdvSceneSwitcher.macroTab.segment.copy="Copy"
|
AdvSceneSwitcher.macroTab.segment.copy="Copy"
|
||||||
AdvSceneSwitcher.macroTab.segment.paste="Paste"
|
AdvSceneSwitcher.macroTab.segment.paste="Paste"
|
||||||
AdvSceneSwitcher.macroTab.segment.pasteAction="Paste as action"
|
AdvSceneSwitcher.macroTab.segment.pasteAction="Paste as action"
|
||||||
@@ -195,9 +198,20 @@ AdvSceneSwitcher.macroTab.highlightExecutedMacros="Highlight recently executed m
|
|||||||
AdvSceneSwitcher.macroTab.highlightTrueConditions="Highlight conditions of currently selected macro that evaluated to true recently"
|
AdvSceneSwitcher.macroTab.highlightTrueConditions="Highlight conditions of currently selected macro that evaluated to true recently"
|
||||||
AdvSceneSwitcher.macroTab.highlightPerformedActions="Highlight recently performed actions of currently selected macro"
|
AdvSceneSwitcher.macroTab.highlightPerformedActions="Highlight recently performed actions of currently selected macro"
|
||||||
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Register hotkeys to control the pause state of new macros"
|
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Register hotkeys to control the pause state of new macros"
|
||||||
AdvSceneSwitcher.macroTab.currentDisableHotkeys="Register hotkeys to control the pause state of selected macro"
|
AdvSceneSwitcher.macroTab.newMacroUseShortCircuitEvaluation="Enable short circuit evaluation of macro conditions for new macros"
|
||||||
|
AdvSceneSwitcher.macroTab.saveSettingsOnMacroChange="Save settings when selecting a new macro"
|
||||||
|
AdvSceneSwitcher.macroTab.saveSettingsOnMacroChange.tooltip="Saving the settings can be an expensive operation if you are working with a very large scene collection.\nIn this case, it might make sense to disable this option."
|
||||||
|
AdvSceneSwitcher.macroTab.currentRegisterHotkeys="Register hotkeys to control the pause state of selected macro"
|
||||||
|
AdvSceneSwitcher.macroTab.currentUseShortCircuitEvaluation="Enable short circuit evaluation of macro conditions for currently selected macro"
|
||||||
|
AdvSceneSwitcher.macroTab.shortCircuit.tooltip="Enabling short circuit evaluation might improve the performance, as some condition checks are skipped, if the overall macro cannot be evaluated to \"true\" anymore.\nHowever, please note that condition checks, which are skipped over, will also not update their duration modifier checks."
|
||||||
|
AdvSceneSwitcher.macroTab.currentUseCustomConditionCheckInterval="Check conditions of the currently selected macro at custom interval:"
|
||||||
|
AdvSceneSwitcher.macroTab.currentUseCustomConditionCheckIntervalWarning="⚠️ The selected value is lower than the interval configured on the General tab.\nThe configured value not have any effect!"
|
||||||
AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup="Skip execution of actions of current macro on startup"
|
AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup="Skip execution of actions of current macro on startup"
|
||||||
AdvSceneSwitcher.macroTab.currentStopActionsIfNotDone="Stop and rerun actions of the currently selected macro, if the actions are still running, when a new execution is triggered"
|
AdvSceneSwitcher.macroTab.currentStopActionsIfNotDone="Stop and rerun actions of the currently selected macro, if the actions are still running, when a new execution is triggered"
|
||||||
|
AdvSceneSwitcher.macroTab.pauseStateSaveBehavior="On startup set the pause state of the current macro to:"
|
||||||
|
AdvSceneSwitcher.macroTab.pauseStateSaveBehavior.persist="The state the macro was last in"
|
||||||
|
AdvSceneSwitcher.macroTab.pauseStateSaveBehavior.pause="Paused"
|
||||||
|
AdvSceneSwitcher.macroTab.pauseStateSaveBehavior.unpause="Unpaused"
|
||||||
AdvSceneSwitcher.macroTab.currentRegisterDock="Register dock widget to control the pause state of selected macro or run it manually"
|
AdvSceneSwitcher.macroTab.currentRegisterDock="Register dock widget to control the pause state of selected macro or run it manually"
|
||||||
AdvSceneSwitcher.macroTab.currentDockAddRunButton="Add button to run the macro"
|
AdvSceneSwitcher.macroTab.currentDockAddRunButton="Add button to run the macro"
|
||||||
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="Add button to pause or unpause the macro"
|
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="Add button to pause or unpause the macro"
|
||||||
@@ -291,7 +305,7 @@ AdvSceneSwitcher.condition.scene.type.previousPattern="Previous scene matches"
|
|||||||
AdvSceneSwitcher.condition.scene.type.previewPattern="Preview scene matches"
|
AdvSceneSwitcher.condition.scene.type.previewPattern="Preview scene matches"
|
||||||
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="During transition check for transition target scene"
|
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="During transition check for transition target scene"
|
||||||
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="During transition check for transition source scene"
|
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="During transition check for transition source scene"
|
||||||
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}{{regex}}"
|
||||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
||||||
AdvSceneSwitcher.condition.window="Window"
|
AdvSceneSwitcher.condition.window="Window"
|
||||||
AdvSceneSwitcher.condition.window.entry.window="{{checkTitle}}Window title matches{{windowRegex}}{{windows}}"
|
AdvSceneSwitcher.condition.window.entry.window="{{checkTitle}}Window title matches{{windowRegex}}{{windows}}"
|
||||||
@@ -398,13 +412,17 @@ AdvSceneSwitcher.condition.video.selectArea="Select area"
|
|||||||
AdvSceneSwitcher.condition.video.selectArea.status="Only highlighted area will be checked"
|
AdvSceneSwitcher.condition.video.selectArea.status="Only highlighted area will be checked"
|
||||||
AdvSceneSwitcher.condition.video.width="Width"
|
AdvSceneSwitcher.condition.video.width="Width"
|
||||||
AdvSceneSwitcher.condition.video.height="Height"
|
AdvSceneSwitcher.condition.video.height="Height"
|
||||||
|
AdvSceneSwitcher.condition.video.screenshot.selectArea="Highlight the area of the screenshot you want to keep:"
|
||||||
AdvSceneSwitcher.condition.stream="Streaming"
|
AdvSceneSwitcher.condition.stream="Streaming"
|
||||||
AdvSceneSwitcher.condition.stream.state.start="Stream running"
|
AdvSceneSwitcher.condition.stream.state.start="Stream running"
|
||||||
AdvSceneSwitcher.condition.stream.state.stop="Stream stopped"
|
AdvSceneSwitcher.condition.stream.state.stop="Stream stopped"
|
||||||
AdvSceneSwitcher.condition.stream.state.starting="Stream starting"
|
AdvSceneSwitcher.condition.stream.state.starting="Stream starting"
|
||||||
AdvSceneSwitcher.condition.stream.state.stopping="Stream stopping"
|
AdvSceneSwitcher.condition.stream.state.stopping="Stream stopping"
|
||||||
AdvSceneSwitcher.condition.stream.state.keyFrameInterval="Keyframe interval equals"
|
AdvSceneSwitcher.condition.stream.state.keyFrameInterval="Keyframe interval equals"
|
||||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
|
AdvSceneSwitcher.condition.stream.state.streamKey="Stream key is"
|
||||||
|
AdvSceneSwitcher.condition.stream.state.service="Service name matches"
|
||||||
|
AdvSceneSwitcher.condition.stream.service.tooltip="Current service name: %1"
|
||||||
|
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}{{streamKey}}{{serviceName}}{{regex}}{{currentService}}"
|
||||||
AdvSceneSwitcher.condition.record="Recording"
|
AdvSceneSwitcher.condition.record="Recording"
|
||||||
AdvSceneSwitcher.condition.record.state.start="Recording running"
|
AdvSceneSwitcher.condition.record.state.start="Recording running"
|
||||||
AdvSceneSwitcher.condition.record.state.pause="Recording paused"
|
AdvSceneSwitcher.condition.record.state.pause="Recording paused"
|
||||||
@@ -471,7 +489,7 @@ AdvSceneSwitcher.condition.source.sizeCompare.less="Smaller than"
|
|||||||
AdvSceneSwitcher.condition.source.sizeCompare.equal="Equals"
|
AdvSceneSwitcher.condition.source.sizeCompare.equal="Equals"
|
||||||
AdvSceneSwitcher.condition.source.sizeCompare.more="Bigger than"
|
AdvSceneSwitcher.condition.source.sizeCompare.more="Bigger than"
|
||||||
AdvSceneSwitcher.condition.source.refresh="Refresh"
|
AdvSceneSwitcher.condition.source.refresh="Refresh"
|
||||||
AdvSceneSwitcher.condition.source.refreshTooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value."
|
AdvSceneSwitcher.condition.source.refresh.tooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value."
|
||||||
AdvSceneSwitcher.condition.source.sceneVisibilityHint="Scene specific visibility can be checked using the \"Scene item visibility\" condition"
|
AdvSceneSwitcher.condition.source.sceneVisibilityHint="Scene specific visibility can be checked using the \"Scene item visibility\" condition"
|
||||||
AdvSceneSwitcher.condition.source.getSettings="Get current settings"
|
AdvSceneSwitcher.condition.source.getSettings="Get current settings"
|
||||||
AdvSceneSwitcher.condition.source.entry.line1="{{sources}}{{conditions}}{{settingSelection}}{{refresh}}{{sizeCompareMethods}}{{size}}"
|
AdvSceneSwitcher.condition.source.entry.line1="{{sources}}{{conditions}}{{settingSelection}}{{refresh}}{{sizeCompareMethods}}{{size}}"
|
||||||
@@ -489,7 +507,7 @@ AdvSceneSwitcher.condition.filter.type.settingsChanged="Settings changed"
|
|||||||
AdvSceneSwitcher.condition.filter.type.individualSettingMatches="Settings value matches"
|
AdvSceneSwitcher.condition.filter.type.individualSettingMatches="Settings value matches"
|
||||||
AdvSceneSwitcher.condition.filter.type.individualSettingChanged="Settings value changed"
|
AdvSceneSwitcher.condition.filter.type.individualSettingChanged="Settings value changed"
|
||||||
AdvSceneSwitcher.condition.filter.refresh="Refresh"
|
AdvSceneSwitcher.condition.filter.refresh="Refresh"
|
||||||
AdvSceneSwitcher.condition.filter.refreshTooltip="Repopulate the filter settings selection with the settings of the filter which's name matches the variable value."
|
AdvSceneSwitcher.condition.filter.refresh.tooltip="Repopulate the filter settings selection with the settings of the filter which's name matches the variable value."
|
||||||
AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
|
AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
|
||||||
AdvSceneSwitcher.condition.filter.entry.line1="On{{sources}}{{filters}}{{conditions}}{{settingSelection}}{{refresh}}"
|
AdvSceneSwitcher.condition.filter.entry.line1="On{{sources}}{{filters}}{{conditions}}{{settingSelection}}{{refresh}}"
|
||||||
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
||||||
@@ -555,6 +573,7 @@ AdvSceneSwitcher.condition.transition.type.current="Current transition type is"
|
|||||||
AdvSceneSwitcher.condition.transition.type.duration="Current transition duration is"
|
AdvSceneSwitcher.condition.transition.type.duration="Current transition duration is"
|
||||||
AdvSceneSwitcher.condition.transition.type.started="Transition started"
|
AdvSceneSwitcher.condition.transition.type.started="Transition started"
|
||||||
AdvSceneSwitcher.condition.transition.type.ended="Transition ended"
|
AdvSceneSwitcher.condition.transition.type.ended="Transition ended"
|
||||||
|
AdvSceneSwitcher.condition.transition.type.videoEnded="Transition video ended"
|
||||||
AdvSceneSwitcher.condition.transition.type.transitionSource="Transitioning from"
|
AdvSceneSwitcher.condition.transition.type.transitionSource="Transitioning from"
|
||||||
AdvSceneSwitcher.condition.transition.type.transitionTarget="Transitioning to"
|
AdvSceneSwitcher.condition.transition.type.transitionTarget="Transitioning to"
|
||||||
AdvSceneSwitcher.condition.transition.durationSuffix="seconds"
|
AdvSceneSwitcher.condition.transition.durationSuffix="seconds"
|
||||||
@@ -633,7 +652,7 @@ AdvSceneSwitcher.condition.slideshow="Slide Show"
|
|||||||
AdvSceneSwitcher.condition.slideshow.condition.slideChanged="Slide changed"
|
AdvSceneSwitcher.condition.slideshow.condition.slideChanged="Slide changed"
|
||||||
AdvSceneSwitcher.condition.slideshow.condition.slideIndex="Current slide number is"
|
AdvSceneSwitcher.condition.slideshow.condition.slideIndex="Current slide number is"
|
||||||
AdvSceneSwitcher.condition.slideshow.condition.slidePath="Current slide path is"
|
AdvSceneSwitcher.condition.slideshow.condition.slidePath="Current slide path is"
|
||||||
AdvSceneSwitcher.condition.slideshow.updateIntervalTooltip="Information about the slide show status will only be updated based on the configured time between slides"
|
AdvSceneSwitcher.condition.slideshow.updateInterval.tooltip="Information about the slide show status will only be updated based on the configured time between slides"
|
||||||
AdvSceneSwitcher.condition.slideshow.entry="{{sources}}{{conditions}}{{index}}{{path}}{{regex}}"
|
AdvSceneSwitcher.condition.slideshow.entry="{{sources}}{{conditions}}{{index}}{{path}}{{regex}}"
|
||||||
AdvSceneSwitcher.condition.twitch="Twitch"
|
AdvSceneSwitcher.condition.twitch="Twitch"
|
||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online="Stream went online"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online="Stream went online"
|
||||||
@@ -686,6 +705,20 @@ AdvSceneSwitcher.condition.twitch.type.polling.channel.live="Stream is currently
|
|||||||
AdvSceneSwitcher.condition.twitch.type.polling.channel.title="Current title matches"
|
AdvSceneSwitcher.condition.twitch.type.polling.channel.title="Current title matches"
|
||||||
AdvSceneSwitcher.condition.twitch.type.polling.channel.category="Current category is"
|
AdvSceneSwitcher.condition.twitch.type.polling.channel.category="Current category is"
|
||||||
AdvSceneSwitcher.condition.twitch.type.chat.message="Chat message received"
|
AdvSceneSwitcher.condition.twitch.type.chat.message="Chat message received"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties="Chat message properties:"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.select="Select chat message property:"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.firstMessage="Is first message"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.emoteOnly="Is only using emotes"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.mod="Is moderator"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.subscriber="Is subscriber"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.turbo="Is Turbo user"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.vip="Is VIP"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.color="Color matches"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.displayName="Display name matches"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.loginName="User name matches"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.badge="User has badge"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.userJoined="User joined the chat"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.userLeft="User left the chat"
|
||||||
AdvSceneSwitcher.condition.twitch.categorySelectionDisabled="Cannot select category without selecting a Twitch account first!"
|
AdvSceneSwitcher.condition.twitch.categorySelectionDisabled="Cannot select category without selecting a Twitch account first!"
|
||||||
AdvSceneSwitcher.condition.twitch.entry="Channel{{channel}}{{conditions}}{{pointsReward}}{{streamTitle}}{{regex}}{{category}}"
|
AdvSceneSwitcher.condition.twitch.entry="Channel{{channel}}{{conditions}}{{pointsReward}}{{streamTitle}}{{regex}}{{category}}"
|
||||||
AdvSceneSwitcher.condition.twitch.entry.account="Check using account{{account}}"
|
AdvSceneSwitcher.condition.twitch.entry.account="Check using account{{account}}"
|
||||||
@@ -699,7 +732,7 @@ AdvSceneSwitcher.condition.queue.entry.startStop="Queue{{queues}}is{{conditions}
|
|||||||
AdvSceneSwitcher.condition.queue.entry.size="Queue{{queues}}{{conditions}}is less than{{size}}"
|
AdvSceneSwitcher.condition.queue.entry.size="Queue{{queues}}{{conditions}}is less than{{size}}"
|
||||||
AdvSceneSwitcher.condition.clipboard="Clipboard"
|
AdvSceneSwitcher.condition.clipboard="Clipboard"
|
||||||
AdvSceneSwitcher.condition.clipboard.placeholder="Clipboard text"
|
AdvSceneSwitcher.condition.clipboard.placeholder="Clipboard text"
|
||||||
AdvSceneSwitcher.condition.clipboard.urlTooltip="Depending on the OS files might be represented as URLs also!"
|
AdvSceneSwitcher.condition.clipboard.url.tooltip="Depending on the OS files might be represented as URLs also!"
|
||||||
AdvSceneSwitcher.condition.clipboard.condition.changed="Clipboard content changed"
|
AdvSceneSwitcher.condition.clipboard.condition.changed="Clipboard content changed"
|
||||||
AdvSceneSwitcher.condition.clipboard.condition.isText="Clipboard contains text"
|
AdvSceneSwitcher.condition.clipboard.condition.isText="Clipboard contains text"
|
||||||
AdvSceneSwitcher.condition.clipboard.condition.isImage="Clipboard contains an image"
|
AdvSceneSwitcher.condition.clipboard.condition.isImage="Clipboard contains an image"
|
||||||
@@ -727,6 +760,15 @@ AdvSceneSwitcher.condition.usb.vendorName="Vendor Name:"
|
|||||||
AdvSceneSwitcher.condition.usb.productName="Product Name:"
|
AdvSceneSwitcher.condition.usb.productName="Product Name:"
|
||||||
AdvSceneSwitcher.condition.usb.serialNumber="Serial Number:"
|
AdvSceneSwitcher.condition.usb.serialNumber="Serial Number:"
|
||||||
AdvSceneSwitcher.condition.noDevicesFoundWarning="No USB devices detected!\nThe plugin might not have the required permissions to check for USB devices."
|
AdvSceneSwitcher.condition.noDevicesFoundWarning="No USB devices detected!\nThe plugin might not have the required permissions to check for USB devices."
|
||||||
|
AdvSceneSwitcher.condition.streamDeck="Stream Deck"
|
||||||
|
AdvSceneSwitcher.condition.streamDeck.checkKeyState="Check key state"
|
||||||
|
AdvSceneSwitcher.condition.streamDeck.keyState.pressed="Pressed"
|
||||||
|
AdvSceneSwitcher.condition.streamDeck.keyState.released="Released"
|
||||||
|
AdvSceneSwitcher.condition.streamDeck.checkKeyPosition="Check key position"
|
||||||
|
AdvSceneSwitcher.condition.streamDeck.checkData="Check data field"
|
||||||
|
AdvSceneSwitcher.condition.streamDeck.startListen="Start listening"
|
||||||
|
AdvSceneSwitcher.condition.streamDeck.stopListen="Stop listening"
|
||||||
|
AdvSceneSwitcher.condition.streamDeck.pluginDownload="<html><head/><body><p>The Stream Deck plugin can be found <a href=\"https://github.com/WarmUpTill/advanced-scene-switcher-streamdeck-plugin/releases\"><span style=\" text-decoration: underline; color:#268bd2;\">here on GitHub</span></a>.</p></body></html>"
|
||||||
|
|
||||||
# Macro Actions
|
# Macro Actions
|
||||||
AdvSceneSwitcher.action.unknown="Unknown action"
|
AdvSceneSwitcher.action.unknown="Unknown action"
|
||||||
@@ -805,7 +847,7 @@ AdvSceneSwitcher.action.filter.type.toggle="Toggle"
|
|||||||
AdvSceneSwitcher.action.filter.type.settings="Set settings"
|
AdvSceneSwitcher.action.filter.type.settings="Set settings"
|
||||||
AdvSceneSwitcher.action.filter.type.pressSettingsButton="Press settings button"
|
AdvSceneSwitcher.action.filter.type.pressSettingsButton="Press settings button"
|
||||||
AdvSceneSwitcher.action.filter.refresh="Refresh"
|
AdvSceneSwitcher.action.filter.refresh="Refresh"
|
||||||
AdvSceneSwitcher.action.filter.refreshTooltip="Repopulate the filter settings selection with the settings of the filter which's name matches the variable value."
|
AdvSceneSwitcher.action.filter.refresh.tooltip="Repopulate the filter settings selection with the settings of the filter which's name matches the variable value."
|
||||||
AdvSceneSwitcher.action.filter.entry="On{{sources}}{{actions}}{{filters}}{{refresh}}{{settingsButtons}}"
|
AdvSceneSwitcher.action.filter.entry="On{{sources}}{{actions}}{{filters}}{{refresh}}{{settingsButtons}}"
|
||||||
AdvSceneSwitcher.action.filter.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}"
|
AdvSceneSwitcher.action.filter.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}"
|
||||||
AdvSceneSwitcher.action.filter.getSettings="Get current settings"
|
AdvSceneSwitcher.action.filter.getSettings="Get current settings"
|
||||||
@@ -843,7 +885,7 @@ AdvSceneSwitcher.action.source.inputMethod.individualManual="Set to fixed value"
|
|||||||
AdvSceneSwitcher.action.source.inputMethod.individualTempvar="Set to macro property"
|
AdvSceneSwitcher.action.source.inputMethod.individualTempvar="Set to macro property"
|
||||||
AdvSceneSwitcher.action.source.inputMethod.json="Set setting JSON string"
|
AdvSceneSwitcher.action.source.inputMethod.json="Set setting JSON string"
|
||||||
AdvSceneSwitcher.action.source.refresh="Refresh"
|
AdvSceneSwitcher.action.source.refresh="Refresh"
|
||||||
AdvSceneSwitcher.action.source.refreshTooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value."
|
AdvSceneSwitcher.action.source.refresh.tooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value."
|
||||||
AdvSceneSwitcher.action.media="Media"
|
AdvSceneSwitcher.action.media="Media"
|
||||||
AdvSceneSwitcher.action.media.type.play="Play"
|
AdvSceneSwitcher.action.media.type.play="Play"
|
||||||
AdvSceneSwitcher.action.media.type.pause="Pause"
|
AdvSceneSwitcher.action.media.type.pause="Pause"
|
||||||
@@ -853,6 +895,7 @@ AdvSceneSwitcher.action.media.type.next="Next"
|
|||||||
AdvSceneSwitcher.action.media.type.previous="Previous"
|
AdvSceneSwitcher.action.media.type.previous="Previous"
|
||||||
AdvSceneSwitcher.action.media.type.seek.duration="Seek to duration"
|
AdvSceneSwitcher.action.media.type.seek.duration="Seek to duration"
|
||||||
AdvSceneSwitcher.action.media.type.seek.percentage="Seek to percentage"
|
AdvSceneSwitcher.action.media.type.seek.percentage="Seek to percentage"
|
||||||
|
AdvSceneSwitcher.action.media.type.waitForPlaybackStop="Wait for playback to stop"
|
||||||
AdvSceneSwitcher.action.media.selectionType.source="Source"
|
AdvSceneSwitcher.action.media.selectionType.source="Source"
|
||||||
AdvSceneSwitcher.action.media.selectionType.sceneItem="Scene item"
|
AdvSceneSwitcher.action.media.selectionType.sceneItem="Scene item"
|
||||||
AdvSceneSwitcher.action.media.entry="{{actions}}{{seekDuration}}{{seekPercentage}}{{selectionTypes}}{{mediaSources}}{{scenes}}{{sceneItems}}"
|
AdvSceneSwitcher.action.media.entry="{{actions}}{{seekDuration}}{{seekPercentage}}{{selectionTypes}}{{mediaSources}}{{scenes}}{{sceneItems}}"
|
||||||
@@ -917,7 +960,9 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="Move down"
|
|||||||
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Move to top"
|
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Move to top"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Move to bottom"
|
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Move to bottom"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Move to position"
|
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Move to position"
|
||||||
AdvSceneSwitcher.action.sceneOrder.entry="On{{scenes}}{{actions}}{{sources}}{{position}}"
|
AdvSceneSwitcher.action.sceneOrder.type.above="Move above"
|
||||||
|
AdvSceneSwitcher.action.sceneOrder.type.below="Move below"
|
||||||
|
AdvSceneSwitcher.action.sceneOrder.entry="On{{scenes}}{{actions}}{{sources}}{{position}}{{sources2}}"
|
||||||
AdvSceneSwitcher.action.sceneTransform="Scene item transform"
|
AdvSceneSwitcher.action.sceneTransform="Scene item transform"
|
||||||
AdvSceneSwitcher.action.sceneTransform.type.manual="Set transform string"
|
AdvSceneSwitcher.action.sceneTransform.type.manual="Set transform string"
|
||||||
AdvSceneSwitcher.action.sceneTransform.type.setSingleSetting="Set transform setting"
|
AdvSceneSwitcher.action.sceneTransform.type.setSingleSetting="Set transform setting"
|
||||||
@@ -967,13 +1012,14 @@ AdvSceneSwitcher.action.systray.icon="Icon:"
|
|||||||
AdvSceneSwitcher.action.systray.iconHint="Leave blank to use the default icon"
|
AdvSceneSwitcher.action.systray.iconHint="Leave blank to use the default icon"
|
||||||
AdvSceneSwitcher.action.systray.disabled="System tray notifications seem to be disabled in the OBS settings!"
|
AdvSceneSwitcher.action.systray.disabled="System tray notifications seem to be disabled in the OBS settings!"
|
||||||
AdvSceneSwitcher.action.screenshot="Screenshot"
|
AdvSceneSwitcher.action.screenshot="Screenshot"
|
||||||
AdvSceneSwitcher.action.screenshot.save.default="Default"
|
AdvSceneSwitcher.action.screenshot.save.default="Default OBS path"
|
||||||
AdvSceneSwitcher.action.screenshot.save.custom="Custom"
|
AdvSceneSwitcher.action.screenshot.save.custom="Custom file path"
|
||||||
|
AdvSceneSwitcher.action.screenshot.save.variable="Variable (base64 encoded PNG)"
|
||||||
AdvSceneSwitcher.action.screenshot.type.source="Source"
|
AdvSceneSwitcher.action.screenshot.type.source="Source"
|
||||||
AdvSceneSwitcher.action.screenshot.type.scene="Scene"
|
AdvSceneSwitcher.action.screenshot.type.scene="Scene"
|
||||||
AdvSceneSwitcher.action.screenshot.mainOutput="OBS's main output"
|
AdvSceneSwitcher.action.screenshot.mainOutput="OBS's main output"
|
||||||
AdvSceneSwitcher.action.screenshot.blackscreenNote="Sources or scenes, which are not always rendered, may result in some parts of screenshots to remain blank."
|
AdvSceneSwitcher.action.screenshot.blackscreenNote="Sources or scenes, which are not always rendered, may result in some parts of screenshots to remain blank."
|
||||||
AdvSceneSwitcher.action.screenshot.entry="Screenshot{{targetType}}{{sources}}{{scenes}}and save to{{saveType}}location"
|
AdvSceneSwitcher.action.screenshot.entry="Screenshot{{targetType}}{{sources}}{{scenes}}and save to{{saveType}}{{variables}}"
|
||||||
AdvSceneSwitcher.action.profile="Profile"
|
AdvSceneSwitcher.action.profile="Profile"
|
||||||
AdvSceneSwitcher.action.profile.entry="Switch active profile to{{profiles}}"
|
AdvSceneSwitcher.action.profile.entry="Switch active profile to{{profiles}}"
|
||||||
AdvSceneSwitcher.action.sceneCollection="Scene collection"
|
AdvSceneSwitcher.action.sceneCollection="Scene collection"
|
||||||
@@ -1030,6 +1076,12 @@ AdvSceneSwitcher.action.variable.type.sceneItemName="Set to scene item name at i
|
|||||||
AdvSceneSwitcher.action.variable.type.padValue="Pad current value"
|
AdvSceneSwitcher.action.variable.type.padValue="Pad current value"
|
||||||
AdvSceneSwitcher.action.variable.type.truncateValue="Truncate current value"
|
AdvSceneSwitcher.action.variable.type.truncateValue="Truncate current value"
|
||||||
AdvSceneSwitcher.action.variable.type.swapValues="Swap variable values"
|
AdvSceneSwitcher.action.variable.type.swapValues="Swap variable values"
|
||||||
|
AdvSceneSwitcher.action.variable.type.trim="Trim whitespace"
|
||||||
|
AdvSceneSwitcher.action.variable.type.changeCase="Change case"
|
||||||
|
AdvSceneSwitcher.action.variable.case.type.lowerCase="lowercase"
|
||||||
|
AdvSceneSwitcher.action.variable.case.type.upperCase="UPPERCASE"
|
||||||
|
AdvSceneSwitcher.action.variable.case.type.capitalized="Capitalized"
|
||||||
|
AdvSceneSwitcher.action.variable.case.type.startCase="Start Case"
|
||||||
AdvSceneSwitcher.action.variable.truncateOrPadDirection.left="Left"
|
AdvSceneSwitcher.action.variable.truncateOrPadDirection.left="Left"
|
||||||
AdvSceneSwitcher.action.variable.truncateOrPadDirection.right="Right"
|
AdvSceneSwitcher.action.variable.truncateOrPadDirection.right="Right"
|
||||||
AdvSceneSwitcher.action.variable.askForValuePromptDefault="Assign value to variable \"%1\":"
|
AdvSceneSwitcher.action.variable.askForValuePromptDefault="Assign value to variable \"%1\":"
|
||||||
@@ -1037,13 +1089,14 @@ AdvSceneSwitcher.action.variable.askForValuePrompt="Assign value to variable:"
|
|||||||
AdvSceneSwitcher.action.variable.mathExpression.example="( 1 + 2 * 3 ) / 4"
|
AdvSceneSwitcher.action.variable.mathExpression.example="( 1 + 2 * 3 ) / 4"
|
||||||
AdvSceneSwitcher.action.variable.findAndReplace.find="Text to find"
|
AdvSceneSwitcher.action.variable.findAndReplace.find="Text to find"
|
||||||
AdvSceneSwitcher.action.variable.findAndReplace.replace="Text to replace with"
|
AdvSceneSwitcher.action.variable.findAndReplace.replace="Text to replace with"
|
||||||
|
AdvSceneSwitcher.action.variable.findAndReplace.replace.tooltip="Using \1, \2, etc. to represent first, second, etc. capture groups is supported."
|
||||||
AdvSceneSwitcher.action.variable.subString.begin="Beginning"
|
AdvSceneSwitcher.action.variable.subString.begin="Beginning"
|
||||||
AdvSceneSwitcher.action.variable.subString.all="All"
|
AdvSceneSwitcher.action.variable.subString.all="All"
|
||||||
AdvSceneSwitcher.action.variable.invalidSelection="Invalid selection!"
|
AdvSceneSwitcher.action.variable.invalidSelection="Invalid selection!"
|
||||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Getting variable values from %1 actions is not supported!"
|
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Getting variable values from %1 actions is not supported!"
|
||||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Getting variable values from %1 conditions is not supported!"
|
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Getting variable values from %1 conditions is not supported!"
|
||||||
AdvSceneSwitcher.action.variable.currentSegmentValue="Current value:"
|
AdvSceneSwitcher.action.variable.currentSegmentValue="Current value:"
|
||||||
AdvSceneSwitcher.action.variable.entry.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{tempVarsHelp}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}"
|
AdvSceneSwitcher.action.variable.entry.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{tempVarsHelp}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}{{caseType}}"
|
||||||
AdvSceneSwitcher.action.variable.entry.pad="{{actions}}of{{variables}}to length{{stringLength}}by adding{{paddingCharSelection}}to the{{direction}}"
|
AdvSceneSwitcher.action.variable.entry.pad="{{actions}}of{{variables}}to length{{stringLength}}by adding{{paddingCharSelection}}to the{{direction}}"
|
||||||
AdvSceneSwitcher.action.variable.entry.truncate="{{actions}}of{{variables}}to length{{stringLength}}by removing characters from the{{direction}}"
|
AdvSceneSwitcher.action.variable.entry.truncate="{{actions}}of{{variables}}to length{{stringLength}}by removing characters from the{{direction}}"
|
||||||
AdvSceneSwitcher.action.variable.entry.substringIndex="Substring start:{{subStringStart}}Substring size:{{subStringSize}}"
|
AdvSceneSwitcher.action.variable.entry.substringIndex="Substring start:{{subStringStart}}Substring size:{{subStringSize}}"
|
||||||
@@ -1354,14 +1407,14 @@ AdvSceneSwitcher.twitch.selection.points.reward.tooltip.error="Can't select poin
|
|||||||
AdvSceneSwitcher.tempVar.select="--select value--"
|
AdvSceneSwitcher.tempVar.select="--select value--"
|
||||||
AdvSceneSwitcher.tempVar.selectionInfo.lastValues="Last values:"
|
AdvSceneSwitcher.tempVar.selectionInfo.lastValues="Last values:"
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_id="Twitch broadcaster user id"
|
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_id="Twitch broadcaster user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_id.description="The numerical Twitch user ID of the broadcaster."
|
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_id.description="The numerical Twitch user ID of the broadcaster."
|
||||||
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_login="Twitch broadcaster user login"
|
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_login="Twitch broadcaster user login"
|
||||||
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_login.description="The Twitch user login of the broadcaster"
|
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_login.description="The Twitch user login of the broadcaster"
|
||||||
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_name="Twitch broadcaster user name"
|
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_name="Twitch broadcaster user name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_name.description="The Twitch user name of the broadcaster"
|
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_name.description="The Twitch user name of the broadcaster"
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.follow="Follower Twitch user id"
|
AdvSceneSwitcher.tempVar.twitch.user_id.follow="Follower Twitch user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.follow.description="The user ID for the user now following the specified channel."
|
AdvSceneSwitcher.tempVar.twitch.user_id.follow.description="The user ID for the user now following the specified channel."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.follow="Follower Twitch user login"
|
AdvSceneSwitcher.tempVar.twitch.user_login.follow="Follower Twitch user login"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.follow.description="The user login for the user now following the specified channel."
|
AdvSceneSwitcher.tempVar.twitch.user_login.follow.description="The user login for the user now following the specified channel."
|
||||||
@@ -1370,7 +1423,7 @@ AdvSceneSwitcher.tempVar.twitch.user_name.follow.description="The user display n
|
|||||||
AdvSceneSwitcher.tempVar.twitch.followed_at="Twitch follow timestamp"
|
AdvSceneSwitcher.tempVar.twitch.followed_at="Twitch follow timestamp"
|
||||||
AdvSceneSwitcher.tempVar.twitch.followed_at.description="The timestamp of when the Twitch follow event occurred"
|
AdvSceneSwitcher.tempVar.twitch.followed_at.description="The timestamp of when the Twitch follow event occurred"
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.id.stream.online="Twitch stream id"
|
AdvSceneSwitcher.tempVar.twitch.id.stream.online="Twitch stream ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.type.stream.online="Twitch stream type"
|
AdvSceneSwitcher.tempVar.twitch.type.stream.online="Twitch stream type"
|
||||||
AdvSceneSwitcher.tempVar.twitch.type.stream.online.description="The stream type. Valid values are: live, playlist, watch_party, premiere, rerun."
|
AdvSceneSwitcher.tempVar.twitch.type.stream.online.description="The stream type. Valid values are: live, playlist, watch_party, premiere, rerun."
|
||||||
AdvSceneSwitcher.tempVar.twitch.started_at.stream.online="Twitch stream start timestamp"
|
AdvSceneSwitcher.tempVar.twitch.started_at.stream.online="Twitch stream start timestamp"
|
||||||
@@ -1379,12 +1432,12 @@ AdvSceneSwitcher.tempVar.twitch.started_at.stream.online.description="The timest
|
|||||||
AdvSceneSwitcher.tempVar.twitch.title="Twitch stream title"
|
AdvSceneSwitcher.tempVar.twitch.title="Twitch stream title"
|
||||||
AdvSceneSwitcher.tempVar.twitch.language="Twitch stream language code"
|
AdvSceneSwitcher.tempVar.twitch.language="Twitch stream language code"
|
||||||
AdvSceneSwitcher.tempVar.twitch.language.description="The broadcaster’s preferred language. The value is an ISO 639-1 two-letter language code (for example, en for English). The value is set to “other” if the language is not a Twitch supported language."
|
AdvSceneSwitcher.tempVar.twitch.language.description="The broadcaster’s preferred language. The value is an ISO 639-1 two-letter language code (for example, en for English). The value is set to “other” if the language is not a Twitch supported language."
|
||||||
AdvSceneSwitcher.tempVar.twitch.category_id="Twitch stream category id"
|
AdvSceneSwitcher.tempVar.twitch.category_id="Twitch stream category ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.category_id.description="Numerical id identifying each Twitch streaming category"
|
AdvSceneSwitcher.tempVar.twitch.category_id.description="Numerical ID identifying each Twitch streaming category"
|
||||||
AdvSceneSwitcher.tempVar.twitch.category_name="Twitch stream category name"
|
AdvSceneSwitcher.tempVar.twitch.category_name="Twitch stream category name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.content_classification_labels="Twitch stream classification labels"
|
AdvSceneSwitcher.tempVar.twitch.content_classification_labels="Twitch stream classification labels"
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe="Subscriber Twitch user id"
|
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe="Subscriber Twitch user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.description="The user ID for the user now subscribed to the specified channel."
|
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.description="The user ID for the user now subscribed to the specified channel."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe="Subscriber Twitch user login"
|
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe="Subscriber Twitch user login"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.description="The user login for the user now subscribed to the specified channel."
|
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.description="The user login for the user now subscribed to the specified channel."
|
||||||
@@ -1395,7 +1448,7 @@ AdvSceneSwitcher.tempVar.twitch.tier.subscribe.description="The tier of the subs
|
|||||||
AdvSceneSwitcher.tempVar.twitch.is_gift.subscribe="Is gifted Twitch subscription"
|
AdvSceneSwitcher.tempVar.twitch.is_gift.subscribe="Is gifted Twitch subscription"
|
||||||
AdvSceneSwitcher.tempVar.twitch.is_gift.subscribe.description="Valid values are true and false."
|
AdvSceneSwitcher.tempVar.twitch.is_gift.subscribe.description="Valid values are true and false."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.end="Subscriber Twitch user id"
|
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.end="Subscriber Twitch user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.end.description="The user ID for the user no longer subscribed to the specified channel."
|
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.end.description="The user ID for the user no longer subscribed to the specified channel."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.end="Subscriber Twitch user login"
|
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.end="Subscriber Twitch user login"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.end.description="The user login for the user no longer subscribed to the specified channel."
|
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.end.description="The user login for the user no longer subscribed to the specified channel."
|
||||||
@@ -1404,7 +1457,7 @@ AdvSceneSwitcher.tempVar.twitch.user_name.subscribe.end.description="The user di
|
|||||||
AdvSceneSwitcher.tempVar.twitch.is_gift.subscribe="Was gifted Twitch subscription"
|
AdvSceneSwitcher.tempVar.twitch.is_gift.subscribe="Was gifted Twitch subscription"
|
||||||
AdvSceneSwitcher.tempVar.twitch.is_gift.subscribe.description="Valid values are true and false."
|
AdvSceneSwitcher.tempVar.twitch.is_gift.subscribe.description="Valid values are true and false."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.gift="Subscriber Twitch user id"
|
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.gift="Subscriber Twitch user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.gift.description="The user ID of the user who sent the subscription gift. Set to null if it was an anonymous subscription gift."
|
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.gift.description="The user ID of the user who sent the subscription gift. Set to null if it was an anonymous subscription gift."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.gift="Subscriber Twitch user login"
|
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.gift="Subscriber Twitch user login"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.gift.description="The user login of the user who sent the gift. Set to null if it was an anonymous subscription gift."
|
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.gift.description="The user login of the user who sent the gift. Set to null if it was an anonymous subscription gift."
|
||||||
@@ -1417,7 +1470,7 @@ AdvSceneSwitcher.tempVar.twitch.cumulative_total.subscribe.description="The numb
|
|||||||
AdvSceneSwitcher.tempVar.twitch.is_anonymous.subscribe="Was anonymous Twitch subscription gift"
|
AdvSceneSwitcher.tempVar.twitch.is_anonymous.subscribe="Was anonymous Twitch subscription gift"
|
||||||
AdvSceneSwitcher.tempVar.twitch.is_anonymous.subscribe.description="Valid values are true and false."
|
AdvSceneSwitcher.tempVar.twitch.is_anonymous.subscribe.description="Valid values are true and false."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.message="Subscriber Twitch user id"
|
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.message="Subscriber Twitch user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.message.description="The user ID of the user who sent a resubscription chat message."
|
AdvSceneSwitcher.tempVar.twitch.user_id.subscribe.message.description="The user ID of the user who sent a resubscription chat message."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.message="Subscriber Twitch user login"
|
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.message="Subscriber Twitch user login"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.message.description="The user login of the user who sent a resubscription chat message."
|
AdvSceneSwitcher.tempVar.twitch.user_login.subscribe.message.description="The user login of the user who sent a resubscription chat message."
|
||||||
@@ -1432,7 +1485,7 @@ AdvSceneSwitcher.tempVar.twitch.streak_months.subscribe.description="The number
|
|||||||
AdvSceneSwitcher.tempVar.twitch.duration_months.subscribe="Subscription duration"
|
AdvSceneSwitcher.tempVar.twitch.duration_months.subscribe="Subscription duration"
|
||||||
AdvSceneSwitcher.tempVar.twitch.duration_months.subscribe.description="The month duration of the subscription."
|
AdvSceneSwitcher.tempVar.twitch.duration_months.subscribe.description="The month duration of the subscription."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.cheer="Cheerer Twitch user id"
|
AdvSceneSwitcher.tempVar.twitch.user_id.cheer="Cheerer Twitch user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.cheer.description="The user ID for the user who cheered on the specified channel. This is null if is_anonymous is true."
|
AdvSceneSwitcher.tempVar.twitch.user_id.cheer.description="The user ID for the user who cheered on the specified channel. This is null if is_anonymous is true."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.cheer="Cheerer Twitch user login"
|
AdvSceneSwitcher.tempVar.twitch.user_login.cheer="Cheerer Twitch user login"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.cheer.description="The user login for the user who cheered on the specified channel. This is null if is_anonymous is true."
|
AdvSceneSwitcher.tempVar.twitch.user_login.cheer.description="The user login for the user who cheered on the specified channel. This is null if is_anonymous is true."
|
||||||
@@ -1536,8 +1589,8 @@ AdvSceneSwitcher.tempVar.twitch.viewer_count.shoutoutReceived.description="The n
|
|||||||
AdvSceneSwitcher.tempVar.twitch.started_at.shoutoutReceived="Shoutout time"
|
AdvSceneSwitcher.tempVar.twitch.started_at.shoutoutReceived="Shoutout time"
|
||||||
AdvSceneSwitcher.tempVar.twitch.started_at.shoutoutReceived.description="The UTC timestamp (in RFC3339 format) of when the moderator sent the Shoutout."
|
AdvSceneSwitcher.tempVar.twitch.started_at.shoutoutReceived.description="The UTC timestamp (in RFC3339 format) of when the moderator sent the Shoutout."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.id.reward="Reward id"
|
AdvSceneSwitcher.tempVar.twitch.id.reward="Reward ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.reward="User id redeeming the reward"
|
AdvSceneSwitcher.tempVar.twitch.user_id.reward="User ID redeeming the reward"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.reward="User login redeeming the reward"
|
AdvSceneSwitcher.tempVar.twitch.user_login.reward="User login redeeming the reward"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.reward="User name redeeming the reward"
|
AdvSceneSwitcher.tempVar.twitch.user_name.reward="User name redeeming the reward"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_input.reward="User input for reward"
|
AdvSceneSwitcher.tempVar.twitch.user_input.reward="User input for reward"
|
||||||
@@ -1578,9 +1631,9 @@ AdvSceneSwitcher.tempVar.twitch.charity_name="Charity name"
|
|||||||
AdvSceneSwitcher.tempVar.twitch.charity_description="Charity description"
|
AdvSceneSwitcher.tempVar.twitch.charity_description="Charity description"
|
||||||
AdvSceneSwitcher.tempVar.twitch.charity_logo="Charity logo"
|
AdvSceneSwitcher.tempVar.twitch.charity_logo="Charity logo"
|
||||||
AdvSceneSwitcher.tempVar.twitch.charity_logo.description="A URL to an image of the charity’s logo. The image’s type is PNG and its size is 100px X 100px."
|
AdvSceneSwitcher.tempVar.twitch.charity_logo.description="A URL to an image of the charity’s logo. The image’s type is PNG and its size is 100px X 100px."
|
||||||
AdvSceneSwitcher.tempVar.twitch.id.charity="Charity id"
|
AdvSceneSwitcher.tempVar.twitch.id.charity="Charity ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.id.charity.description="An ID that identifies the donation. The ID is unique across campaigns."
|
AdvSceneSwitcher.tempVar.twitch.id.charity.description="An ID that identifies the donation. The ID is unique across campaigns."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.charity="Donor user id"
|
AdvSceneSwitcher.tempVar.twitch.user_id.charity="Donor user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.charity.description="An ID that identifies the user that donated to the campaign."
|
AdvSceneSwitcher.tempVar.twitch.user_id.charity.description="An ID that identifies the user that donated to the campaign."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.charity="Donor login name"
|
AdvSceneSwitcher.tempVar.twitch.user_login.charity="Donor login name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.charity.description="The user login that identifies the user that donated to the campaign."
|
AdvSceneSwitcher.tempVar.twitch.user_login.charity.description="The user login that identifies the user that donated to the campaign."
|
||||||
@@ -1625,13 +1678,13 @@ AdvSceneSwitcher.tempVar.twitch.thumbnail_url.description="A URL to an image of
|
|||||||
AdvSceneSwitcher.tempVar.twitch.viewer_count.live="Viewer count"
|
AdvSceneSwitcher.tempVar.twitch.viewer_count.live="Viewer count"
|
||||||
AdvSceneSwitcher.tempVar.twitch.viewer_count.live.description="The number of users watching the stream."
|
AdvSceneSwitcher.tempVar.twitch.viewer_count.live.description="The number of users watching the stream."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.ban="Banned user id"
|
AdvSceneSwitcher.tempVar.twitch.user_id.ban="Banned user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.ban.description="The user ID for the user who was banned on the specified channel."
|
AdvSceneSwitcher.tempVar.twitch.user_id.ban.description="The user ID for the user who was banned on the specified channel."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.ban="Banned login name"
|
AdvSceneSwitcher.tempVar.twitch.user_login.ban="Banned login name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.ban.description="The user login for the user who was banned on the specified channel."
|
AdvSceneSwitcher.tempVar.twitch.user_login.ban.description="The user login for the user who was banned on the specified channel."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.ban="Banned user name"
|
AdvSceneSwitcher.tempVar.twitch.user_name.ban="Banned user name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.ban.description="The user display name for the user who was banned on the specified channel."
|
AdvSceneSwitcher.tempVar.twitch.user_name.ban.description="The user display name for the user who was banned on the specified channel."
|
||||||
AdvSceneSwitcher.tempVar.twitch.moderator_user_id.ban="Moderator user id"
|
AdvSceneSwitcher.tempVar.twitch.moderator_user_id.ban="Moderator user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.moderator_user_id.ban.description="The user ID of the issuer of the ban."
|
AdvSceneSwitcher.tempVar.twitch.moderator_user_id.ban.description="The user ID of the issuer of the ban."
|
||||||
AdvSceneSwitcher.tempVar.twitch.moderator_user_login.ban="Moderator login name"
|
AdvSceneSwitcher.tempVar.twitch.moderator_user_login.ban="Moderator login name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.moderator_user_login.ban.description="The user login of the issuer of the ban."
|
AdvSceneSwitcher.tempVar.twitch.moderator_user_login.ban.description="The user login of the issuer of the ban."
|
||||||
@@ -1643,36 +1696,88 @@ AdvSceneSwitcher.tempVar.twitch.ends_at.ban.description="The UTC date and time (
|
|||||||
AdvSceneSwitcher.tempVar.twitch.is_permanent.ban="Is permanent ban"
|
AdvSceneSwitcher.tempVar.twitch.is_permanent.ban="Is permanent ban"
|
||||||
AdvSceneSwitcher.tempVar.twitch.is_permanent.ban.description="Indicates whether the ban is permanent (true) or a timeout (false). If true, ends_at will be null."
|
AdvSceneSwitcher.tempVar.twitch.is_permanent.ban.description="Indicates whether the ban is permanent (true) or a timeout (false). If true, ends_at will be null."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.unban="Banned user id"
|
AdvSceneSwitcher.tempVar.twitch.user_id.unban="Banned user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.unban.description="The user ID for the user who was unbanned on the specified channel."
|
AdvSceneSwitcher.tempVar.twitch.user_id.unban.description="The user ID for the user who was unbanned on the specified channel."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.unban="Banned login name"
|
AdvSceneSwitcher.tempVar.twitch.user_login.unban="Banned login name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.unban.description="The user login for the user who was unbanned on the specified channel."
|
AdvSceneSwitcher.tempVar.twitch.user_login.unban.description="The user login for the user who was unbanned on the specified channel."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.unban="Banned user name"
|
AdvSceneSwitcher.tempVar.twitch.user_name.unban="Banned user name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.unban.description="The user display name for the user who was unbanned on the specified channel."
|
AdvSceneSwitcher.tempVar.twitch.user_name.unban.description="The user display name for the user who was unbanned on the specified channel."
|
||||||
AdvSceneSwitcher.tempVar.twitch.moderator_user_id.unban="Moderator user id"
|
AdvSceneSwitcher.tempVar.twitch.moderator_user_id.unban="Moderator user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.moderator_user_id.unban.description="The user ID of the issuer of the unban."
|
AdvSceneSwitcher.tempVar.twitch.moderator_user_id.unban.description="The user ID of the issuer of the unban."
|
||||||
AdvSceneSwitcher.tempVar.twitch.moderator_user_login.unban="Moderator login name"
|
AdvSceneSwitcher.tempVar.twitch.moderator_user_login.unban="Moderator login name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.moderator_user_login.unban.description="The user login of the issuer of the unban."
|
AdvSceneSwitcher.tempVar.twitch.moderator_user_login.unban.description="The user login of the issuer of the unban."
|
||||||
AdvSceneSwitcher.tempVar.twitch.moderator_user_name.unban="Moderator user name"
|
AdvSceneSwitcher.tempVar.twitch.moderator_user_name.unban="Moderator user name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.moderator_user_name.unban.description="The user name of the issuer of the unban."
|
AdvSceneSwitcher.tempVar.twitch.moderator_user_name.unban.description="The user name of the issuer of the unban."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.addMod="User id"
|
AdvSceneSwitcher.tempVar.twitch.user_id.addMod="User ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.addMod.description="The user ID of the new moderator."
|
AdvSceneSwitcher.tempVar.twitch.user_id.addMod.description="The user ID of the new moderator."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.addMod="Login name"
|
AdvSceneSwitcher.tempVar.twitch.user_login.addMod="Login name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.addMod.description="The user login of the new moderator."
|
AdvSceneSwitcher.tempVar.twitch.user_login.addMod.description="The user login of the new moderator."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.addMod="User name"
|
AdvSceneSwitcher.tempVar.twitch.user_name.addMod="User name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.addMod.description="The display name of the new moderator."
|
AdvSceneSwitcher.tempVar.twitch.user_name.addMod.description="The display name of the new moderator."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.removeMod="User id"
|
AdvSceneSwitcher.tempVar.twitch.user_id.removeMod="User ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.removeMod.description="The user ID of the removed moderator."
|
AdvSceneSwitcher.tempVar.twitch.user_id.removeMod.description="The user ID of the removed moderator."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.removeMod="Login name"
|
AdvSceneSwitcher.tempVar.twitch.user_login.removeMod="Login name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.removeMod.description="The user login of the removed moderator."
|
AdvSceneSwitcher.tempVar.twitch.user_login.removeMod.description="The user login of the removed moderator."
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.removeMod="User name"
|
AdvSceneSwitcher.tempVar.twitch.user_name.removeMod="User name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.removeMod.description="The display name of the removed moderator."
|
AdvSceneSwitcher.tempVar.twitch.user_name.removeMod.description="The display name of the removed moderator."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.chatter="User login"
|
AdvSceneSwitcher.tempVar.twitch.id.chatReceive="Chat message ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.chatter.description="The user login of the person who sent the chat message."
|
AdvSceneSwitcher.tempVar.twitch.id.chatReceive.description="The ID of the message, formatted as UUID."
|
||||||
AdvSceneSwitcher.tempVar.twitch.chat_message="Chat message"
|
AdvSceneSwitcher.tempVar.twitch.chat_message.chatReceive="Chat message body"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_id.chatReceive="User ID"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_id.chatReceive.description="The user ID of the person who sent the chat message."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_login.chatReceive="User login"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_login.chatReceive.description="The user login of the person who sent the chat message."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_name.chatReceive="User name"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_name.chatReceive.description="The display name of the person who sent the chat message."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_type.chatReceive="User type"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_type.chatReceive.description="The type of the Twitch user - e.g. 'admin' for Twitch administrator, 'global_mod' for global moderator and 'staff' for Twitch staff."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reply_parent_id.chatReceive="Reply parent message ID"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reply_parent_id.chatReceive.description="The ID of the closest parent message, formatted as UUID, if one exists."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reply_parent_message.chatReceive="Reply parent message body"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reply_parent_message.chatReceive.description="The body of the closest parent message, if one exists."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reply_parent_user_id.chatReceive="Reply parent user ID"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reply_parent_user_id.chatReceive.description="The ID of the author of the closest parent message, if one exists."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reply_parent_user_login.chatReceive="Reply parent user login"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reply_parent_user_login.chatReceive.description="The login of the author of the closest parent message, if one exists."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reply_parent_user_name.chatReceive="Reply parent user name"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reply_parent_user_name.chatReceive.description="The display name of the author of the closest parent message, if one exists."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.root_parent_id.chatReceive="Root parent message ID"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.root_parent_id.chatReceive.description="The ID of the furthest parent message that started a discussion, formatted as UUID, if one exists."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.root_parent_user_login.chatReceive="Root parent user login"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.root_parent_user_login.chatReceive.description="The login of the author of the furthest parent message, if one exists."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.badge_info.chatReceive="Chatter badges' info"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.badge_info.chatReceive.description="A string describing the metadata of some of the badges available to this user.\nFor example, this means user has been subscribed for 8 months: subscriber/8"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.badges.chatReceive="Chatter badges"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.badges.chatReceive.description="A string describing all the badges of the user and their version.\nFor example: vip/1,subscriber/42,hype-train/1"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.bits.chatReceive="Chat message bits"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.bits.chatReceive.description="Number of bits that the user cheered along with the message."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.color.chatReceive="Chatter color"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.color.chatReceive.description="Hexadecimal color of user's display name, if they set one, otherwise empty string. Starts with #.\nFor example: #123456"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.emotes.chatReceive="Chatter badges"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.emotes.chatReceive.description="A string describing all the emotes in the message - the emote ID and comma-separated all positions of emotes with that ID.\nFor example: 25:0-4,12-16/1902:6-10"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.timestamp.chatReceive="Chat message timestamp"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.timestamp.chatReceive.description="The Unix timestamp representing when the chat message was sent, in milliseconds."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_emotes_only.chatReceive="Is using only emotes"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_emotes_only.chatReceive.description="'true' if the message consists only of emotes, 'false' otherwise."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_first_message.chatReceive="Is chatter's first message"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_first_message.chatReceive.description="'true' if the chatter has never sent messages in the channel before, 'false' otherwise."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_mod.chatReceive="Is chatter a moderator"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_mod.chatReceive.description="'true' if the chatter is a moderator of the channel, 'false' otherwise."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_subscriber.chatReceive="Is chatter a subscriber"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_subscriber.chatReceive.description="'true' if the chatter is a subscriber of the channel, 'false' otherwise."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_turbo.chatReceive="Is chatter a Turbo user"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_turbo.chatReceive.description="'true' if the chatter is a Twitch Turbo user, 'false' otherwise."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_vip.chatReceive="Is chatter a VIP"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_vip.chatReceive.description="'true' if the chatter is a VIP in the channel, 'false' otherwise."
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_login.chatJoin="User login"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_login.chatJoin.description="The user login of the person who joined the chat room."
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_login.chatLeave="User login"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_login.chatLeave.description="The user login of the person who left the chat room."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid="Raid creator user ID"
|
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid="Raid creator user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid.description="The broadcaster ID that created the raid."
|
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid.description="The broadcaster ID that created the raid."
|
||||||
@@ -1746,6 +1851,9 @@ AdvSceneSwitcher.tempVar.run.process.stream.output="Process standard output stre
|
|||||||
AdvSceneSwitcher.tempVar.run.process.stream.output.description="Full standard output stream, usually numbered 1 and what you see in CLI after running the command."
|
AdvSceneSwitcher.tempVar.run.process.stream.output.description="Full standard output stream, usually numbered 1 and what you see in CLI after running the command."
|
||||||
AdvSceneSwitcher.tempVar.run.process.stream.error="Process standard error stream"
|
AdvSceneSwitcher.tempVar.run.process.stream.error="Process standard error stream"
|
||||||
AdvSceneSwitcher.tempVar.run.process.stream.error.description="Full standard error stream, usually numbered 2."
|
AdvSceneSwitcher.tempVar.run.process.stream.error.description="Full standard error stream, usually numbered 2."
|
||||||
|
AdvSceneSwitcher.tempVar.run.process.none.description="Full standard error stream, usually numbered 2."
|
||||||
|
AdvSceneSwitcher.tempVar.run.process.none="No variables available for the \"Run\" action!"
|
||||||
|
AdvSceneSwitcher.tempVar.run.process.none.description="When not waiting for the action to finish no variables will be available.\nThe option to wait for the action to complete can be found in the advanced settings."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.recording.durationSeconds="Recording duration"
|
AdvSceneSwitcher.tempVar.recording.durationSeconds="Recording duration"
|
||||||
AdvSceneSwitcher.tempVar.recording.durationSeconds.description="Recording duration in seconds.\nThis value does not change while the recording is paused and will be reset to zero if the recording is stopped."
|
AdvSceneSwitcher.tempVar.recording.durationSeconds.description="Recording duration in seconds.\nThis value does not change while the recording is paused and will be reset to zero if the recording is stopped."
|
||||||
@@ -1775,8 +1883,11 @@ AdvSceneSwitcher.tempVar.display.height.description="The height of the display w
|
|||||||
|
|
||||||
AdvSceneSwitcher.tempVar.streaming.keyframeInterval="Stream keyframe interval"
|
AdvSceneSwitcher.tempVar.streaming.keyframeInterval="Stream keyframe interval"
|
||||||
AdvSceneSwitcher.tempVar.streaming.keyframeInterval.description="Stream keyframe interval configured in the OBS settings."
|
AdvSceneSwitcher.tempVar.streaming.keyframeInterval.description="Stream keyframe interval configured in the OBS settings."
|
||||||
|
AdvSceneSwitcher.tempVar.streaming.streamKey="Stream key"
|
||||||
AdvSceneSwitcher.tempVar.streaming.durationSeconds="Stream duration"
|
AdvSceneSwitcher.tempVar.streaming.durationSeconds="Stream duration"
|
||||||
AdvSceneSwitcher.tempVar.streaming.durationSeconds.description="Seconds passed since the stream was started.\nThis value will be zero if the stream is stopped."
|
AdvSceneSwitcher.tempVar.streaming.durationSeconds.description="Seconds passed since the stream was started.\nThis value will be zero if the stream is stopped."
|
||||||
|
AdvSceneSwitcher.tempVar.streaming.serviceName="Service"
|
||||||
|
AdvSceneSwitcher.tempVar.streaming.serviceName.description="The name of the streaming service being streamed to (e.g. Twitch)"
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.clipboard.text="Clipboard text"
|
AdvSceneSwitcher.tempVar.clipboard.text="Clipboard text"
|
||||||
AdvSceneSwitcher.tempVar.clipboard.text.description="The text contained in the clipboard.\nWill be empty if the clipboard does not contain text."
|
AdvSceneSwitcher.tempVar.clipboard.text.description="The text contained in the clipboard.\nWill be empty if the clipboard does not contain text."
|
||||||
@@ -1816,6 +1927,50 @@ AdvSceneSwitcher.tempVar.usb.serialNumber="Serial Number"
|
|||||||
AdvSceneSwitcher.tempVar.transform.setting="Setting value"
|
AdvSceneSwitcher.tempVar.transform.setting="Setting value"
|
||||||
AdvSceneSwitcher.tempVar.transform.settings="Settings string"
|
AdvSceneSwitcher.tempVar.transform.settings="Settings string"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.media.state="State"
|
||||||
|
AdvSceneSwitcher.tempVar.media.state.description="The current media state represented as an integer value:\n0 being 'None'\n1 being 'Playing'\n2 being 'Opening'\n3 being 'Buffering'\n4 being 'Paused'\n5 being 'Stopped'\n6 being 'Ended'\n7 being 'Error'"
|
||||||
|
AdvSceneSwitcher.tempVar.media.time="Current time"
|
||||||
|
AdvSceneSwitcher.tempVar.media.time.description="Elapsed time in milliseconds since media playback began.\nIf the source supports playlists, this time is respective to the current playlist item being played and not the overall playlist.\nNote that this value might not be exactly zero if the playback is stopped or ended."
|
||||||
|
AdvSceneSwitcher.tempVar.media.duration="Duration"
|
||||||
|
AdvSceneSwitcher.tempVar.media.duration.description="The duration of the media file being played in milliseconds.\nIf the source supports playlists, this time is respective to the current playlist item being played and not the overall playlist."
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.title="Title (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.artist="Artist (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.genre="Genre (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.copyright="Copyright (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.album="Album (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.track_number="Track number (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.description="Description (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.rating="Rating (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.date="Date (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.setting="Setting (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.url="URL (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.language="Language (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.now_playing="Now playing (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.publisher="Publisher (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.encoded_by="Encoded by (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.artwork_url="Artwork URL (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.track_id="Track id (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.director="Director (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.season="Season (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.episode="Episode (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.show_name="Show name (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.actors="Actors (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.album_artist="Album artist (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.disc_number="Disc number (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.disc_total="Disc total (VLC)"
|
||||||
|
AdvSceneSwitcher.tempVar.media.vlc.metadata.description="This property is exposed by the VLC Source type.\nNot all of these might be applicable to every file.\nIn case the metadata is not available an empty string will be returned."
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.streamDeck.keyPressed="Key pressed"
|
||||||
|
AdvSceneSwitcher.tempVar.streamDeck.keyPressed.description="Will return \"0\" when the key is pressed, and \"1\" otherwise."
|
||||||
|
AdvSceneSwitcher.tempVar.streamDeck.row="Key row"
|
||||||
|
AdvSceneSwitcher.tempVar.streamDeck.column="Key column"
|
||||||
|
AdvSceneSwitcher.tempVar.streamDeck.data="Data"
|
||||||
|
AdvSceneSwitcher.tempVar.streamDeck.data.description="The value of the \"Data\" field configured in the action on the Stream Deck side."
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.queue.size="Size"
|
||||||
|
AdvSceneSwitcher.tempVar.queue.running="Is running"
|
||||||
|
AdvSceneSwitcher.tempVar.queue.running.description="Returns \"true\" if the queue is started and \"false\" if it is stopped."
|
||||||
|
|
||||||
AdvSceneSwitcher.selectScene="--select scene--"
|
AdvSceneSwitcher.selectScene="--select scene--"
|
||||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||||
@@ -1883,8 +2038,10 @@ AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="Variable name"
|
|||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable.entry="{{nameConflictIndex}}{{variable}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable.entry="{{nameConflictIndex}}{{variable}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="Source name matches pattern"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="Source name matches pattern"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.entry="{{nameConflictIndex}}matching{{pattern}}{{regex}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.entry="{{nameConflictIndex}}matching{{pattern}}{{regex}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup="Sources of type"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup="Sources in source group"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup.entry="Source type{{nameConflictIndex}}{{sourceGroups}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup.entry="Sources in{{sourceGroups}}"
|
||||||
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType="Sources of type"
|
||||||
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType.entry="Source type{{nameConflictIndex}}{{sourceTypes}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index="Source with index"
|
AdvSceneSwitcher.sceneItemSelection.type.index="Source with index"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index.entry="{{index}}source"
|
AdvSceneSwitcher.sceneItemSelection.type.index.entry="{{index}}source"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.indexRange="Sources in index range"
|
AdvSceneSwitcher.sceneItemSelection.type.indexRange="Sources in index range"
|
||||||
@@ -1906,15 +2063,21 @@ AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>This seems to be the fi
|
|||||||
AdvSceneSwitcher.deprecatedTabWarning="Development for this tab stopped!\nPlease consider transitioning to using Macros instead.\nThis hint can be disabled on the General tab."
|
AdvSceneSwitcher.deprecatedTabWarning="Development for this tab stopped!\nPlease consider transitioning to using Macros instead.\nThis hint can be disabled on the General tab."
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="milliseconds"
|
AdvSceneSwitcher.unit.milliseconds="milliseconds"
|
||||||
AdvSceneSwitcher.unit.secends="seconds"
|
AdvSceneSwitcher.unit.seconds="seconds"
|
||||||
AdvSceneSwitcher.unit.minutes="minutes"
|
AdvSceneSwitcher.unit.minutes="minutes"
|
||||||
AdvSceneSwitcher.unit.hours="hours"
|
AdvSceneSwitcher.unit.hours="hours"
|
||||||
|
AdvSceneSwitcher.unit.days="days"
|
||||||
|
AdvSceneSwitcher.unit.weeks="weeks"
|
||||||
|
AdvSceneSwitcher.unit.months="months"
|
||||||
|
AdvSceneSwitcher.unit.years="years"
|
||||||
AdvSceneSwitcher.duration.condition.none="No duration modifier"
|
AdvSceneSwitcher.duration.condition.none="No duration modifier"
|
||||||
AdvSceneSwitcher.duration.condition.more="For at least"
|
AdvSceneSwitcher.duration.condition.more="For at least"
|
||||||
AdvSceneSwitcher.duration.condition.equal="For exactly"
|
AdvSceneSwitcher.duration.condition.equal="For exactly"
|
||||||
AdvSceneSwitcher.duration.condition.less="For at most"
|
AdvSceneSwitcher.duration.condition.less="For at most"
|
||||||
AdvSceneSwitcher.duration.condition.within="Within the last"
|
AdvSceneSwitcher.duration.condition.within="Within the last"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.time.relative="%1 %2 ago"
|
||||||
|
|
||||||
AdvSceneSwitcher.audio.monitor.none="Monitor Off"
|
AdvSceneSwitcher.audio.monitor.none="Monitor Off"
|
||||||
AdvSceneSwitcher.audio.monitor.monitorOnly="Monitor Only (mute output)"
|
AdvSceneSwitcher.audio.monitor.monitorOnly="Monitor Only (mute output)"
|
||||||
AdvSceneSwitcher.audio.monitor.both="Monitor and Output"
|
AdvSceneSwitcher.audio.monitor.both="Monitor and Output"
|
||||||
@@ -2124,31 +2287,6 @@ AdvSceneSwitcher.videoTab.ignoreInactiveSource="unless source is inactive"
|
|||||||
AdvSceneSwitcher.videoTab.entry="When{{videoSources}}{{condition}}{{filePath}}{{browseButton}}for{{duration}}switch to{{scenes}}using{{transitions}}{{ignoreInactiveSource}}"
|
AdvSceneSwitcher.videoTab.entry="When{{videoSources}}{{condition}}{{filePath}}{{browseButton}}for{{duration}}switch to{{scenes}}using{{transitions}}{{ignoreInactiveSource}}"
|
||||||
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>This tab will allow you to switch scenes based on the current video output of selected sources.<br/>Make sure to check out <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> for an even better implementation of this functionality.<br/><br/> Click on the highlighted plus symbol to continue.</p></body></html>"
|
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>This tab will allow you to switch scenes based on the current video output of selected sources.<br/>Make sure to check out <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> for an even better implementation of this functionality.<br/><br/> Click on the highlighted plus symbol to continue.</p></body></html>"
|
||||||
|
|
||||||
# Network Tab
|
|
||||||
AdvSceneSwitcher.networkTab.title="Network"
|
|
||||||
AdvSceneSwitcher.networkTab.description="This tab will allow you to remotely control the active scene of another OBS instance.\nPlease note that the scene names have to match exactly on all OBS instances."
|
|
||||||
AdvSceneSwitcher.networkTab.warning="Running the server outside of a local network will allow third parties to read the active scene."
|
|
||||||
AdvSceneSwitcher.networkTab.server="Start server (Sends scene switch messages to all connected clients)"
|
|
||||||
AdvSceneSwitcher.networkTab.server.port="Port"
|
|
||||||
AdvSceneSwitcher.networkTab.server.lockToIPv4="Lock server to only using IPv4"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendSceneChange="Send messages for scene changes"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Only send messages for automated scene switches"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendPreview="Send messages for preview scene change when running in Studio mode"
|
|
||||||
AdvSceneSwitcher.networkTab.startFailed.message="The WebSockets server failed to start, maybe because:\n - TCP port %1 may currently be in use elsewhere on this system, possibly by another application. Try setting a different TCP port in the WebSocket server settings, or stop any application that could be using this port.\n - Error message: %2"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.currentStatus="Current status"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.notRunning="Not running"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.starting="Starting"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.running="Running"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restart="Restart server"
|
|
||||||
AdvSceneSwitcher.networkTab.client="Start client (Receives scene switches messages)"
|
|
||||||
AdvSceneSwitcher.networkTab.client.address="Hostname or IP address"
|
|
||||||
AdvSceneSwitcher.networkTab.client.port="Port"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.currentStatus="Current status"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.disconnected="Disconnected"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connecting="Connecting"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connected="Connected"
|
|
||||||
AdvSceneSwitcher.networkTab.client.reconnect="Force reconnect"
|
|
||||||
|
|
||||||
# Scene Group Tab
|
# Scene Group Tab
|
||||||
AdvSceneSwitcher.sceneGroupTab.title="Scene Group"
|
AdvSceneSwitcher.sceneGroupTab.title="Scene Group"
|
||||||
AdvSceneSwitcher.sceneGroupTab.list="Scene Groups"
|
AdvSceneSwitcher.sceneGroupTab.list="Scene Groups"
|
||||||
@@ -2168,27 +2306,3 @@ AdvSceneSwitcher.sceneGroupTab.defaultname="Scene Group %1"
|
|||||||
AdvSceneSwitcher.sceneGroupTab.exists="Scene Group or Scene name exists already"
|
AdvSceneSwitcher.sceneGroupTab.exists="Scene Group or Scene name exists already"
|
||||||
AdvSceneSwitcher.sceneGroupTab.help="Scene Groups can be selected as a target just like a regular scene.\n\nAs the name suggests a scene group is a collection of multiple scenes.\nThe scene group will advance through the list of its assigned scenes depending on the configured settings, which can be found on the right side.\n\nYou can configure the scene group to advance to the next scene in the list:\nAfter a number of times the scene group is selected as a target.\nAfter a certain amount of time has passed.\nOr randomly.\n\nFor example, a scene group containing the scenes ...\nScene 1\nScene 2\nScene 3 \n... will activate \"Scene 1\" the first time it is selected as a target.\nThe second time it will activate \"Scene 2\".\nThe remaining times \"Scene 3\" will be activated.\n\nClick the highlighted plus symbol below to add a new scene group."
|
AdvSceneSwitcher.sceneGroupTab.help="Scene Groups can be selected as a target just like a regular scene.\n\nAs the name suggests a scene group is a collection of multiple scenes.\nThe scene group will advance through the list of its assigned scenes depending on the configured settings, which can be found on the right side.\n\nYou can configure the scene group to advance to the next scene in the list:\nAfter a number of times the scene group is selected as a target.\nAfter a certain amount of time has passed.\nOr randomly.\n\nFor example, a scene group containing the scenes ...\nScene 1\nScene 2\nScene 3 \n... will activate \"Scene 1\" the first time it is selected as a target.\nThe second time it will activate \"Scene 2\".\nThe remaining times \"Scene 3\" will be activated.\n\nClick the highlighted plus symbol below to add a new scene group."
|
||||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="Select the scene group you want to modify on the left.\n\nSelect a scene to add to this scene group by selecting the scene above and clicking the plus symbol below.\n\nA scene can be added multiple times to the same scene group."
|
AdvSceneSwitcher.sceneGroupTab.scenes.help="Select the scene group you want to modify on the left.\n\nSelect a scene to add to this scene group by selecting the scene above and clicking the plus symbol below.\n\nA scene can be added multiple times to the same scene group."
|
||||||
|
|
||||||
# Scene Trigger Tab
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.title="Scene Triggers"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--select trigger--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="is active"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="is not active"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="switched away from"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--select action--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="start recording"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="pause recording"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="unpause recording"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="stop recording"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="stop streaming"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="start streaming"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="start replay buffer"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="stop replay buffer"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="mute source"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="unmute source"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="start the scene switcher"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="stop the scene switcher"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="start virtual camera"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="stop virtual camera"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.entry="When{{scenes}}{{triggers}}{{actions}}{{audioSources}}after{{duration}}"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.help="This tab allows you to trigger actions on scene changes, like stopping recording or streaming."
|
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ AdvSceneSwitcher.generalTab.status.autoStart.streaming="Emitiendo"
|
|||||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Grabando o emitiendo"
|
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Grabando o emitiendo"
|
||||||
AdvSceneSwitcher.generalTab.status.checkInterval="Comprobar las condiciones de cambio cada"
|
AdvSceneSwitcher.generalTab.status.checkInterval="Comprobar las condiciones de cambio cada"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior="Comportamiento general"
|
AdvSceneSwitcher.generalTab.generalBehavior="Comportamiento general"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="Si no se cumple ninguna condición por"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch="Si no se cumple ninguna condición por"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Solo será tan preciso como el intervalo de comprobación configurado."
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatchDelay.tooltip="Solo será tan preciso como el intervalo de comprobación configurado."
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="No cambiar"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.dontSwitch="No cambiar"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Cambiar a una escena aleatoria"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchToRandom="Cambiar a una escena aleatoria"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Cambiar a:"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchTo="Cambiar a:"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="¡Durante este tiempo, se ignorarán las posibles coincidencias!"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="¡Durante este tiempo, se ignorarán las posibles coincidencias!"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Habilitar el registro detallado"
|
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Habilitar el registro detallado"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Guardar la posición y el tamaño de la ventana"
|
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Guardar la posición y el tamaño de la ventana"
|
||||||
@@ -117,8 +117,6 @@ AdvSceneSwitcher.condition.scene.type.changed="Escena cambiada"
|
|||||||
AdvSceneSwitcher.condition.scene.type.notChanged="La escena no ha cambiado"
|
AdvSceneSwitcher.condition.scene.type.notChanged="La escena no ha cambiado"
|
||||||
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Durante la transición, verifique la escena de destino de la transición"
|
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Durante la transición, verifique la escena de destino de la transición"
|
||||||
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Durante la transición, verifique la escena de origen de la transición"
|
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Durante la transición, verifique la escena de origen de la transición"
|
||||||
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
|
||||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
|
||||||
AdvSceneSwitcher.condition.window="Ventana"
|
AdvSceneSwitcher.condition.window="Ventana"
|
||||||
AdvSceneSwitcher.condition.file="Archivo"
|
AdvSceneSwitcher.condition.file="Archivo"
|
||||||
AdvSceneSwitcher.condition.file.entry.line1="Contenido de{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
AdvSceneSwitcher.condition.file.entry.line1="Contenido de{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
@@ -174,7 +172,6 @@ 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.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"
|
||||||
@@ -409,7 +406,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="Mover hacia abajo"
|
|||||||
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Mover al principio"
|
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Mover al principio"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Mover al final"
|
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Mover al final"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Mover a la posición"
|
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}}{{sources2}}{{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}}{{settingSelection}}{{singleSettingValue}}"
|
AdvSceneSwitcher.action.sceneTransform.entry="En{{scenes}}{{action}}{{rotation}}{{sources}}{{settingSelection}}{{singleSettingValue}}"
|
||||||
@@ -618,31 +615,6 @@ AdvSceneSwitcher.videoTab.ignoreInactiveSource="a menos que la fuente esté inac
|
|||||||
AdvSceneSwitcher.videoTab.entry="Cuando {{videoSources}} {{condition}} {{filePath}} {{browseButton}} durante {{duration}} cambiar a {{scenes}} usando {{transitions}} {{ignoreInactiveSource}}"
|
AdvSceneSwitcher.videoTab.entry="Cuando {{videoSources}} {{condition}} {{filePath}} {{browseButton}} durante {{duration}} cambiar a {{scenes}} usando {{transitions}} {{ignoreInactiveSource}}"
|
||||||
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Esta pestaña te permitirá cambiar escenas según la salida de vídeo actual de las fuentes seleccionadas.<br/>Asegúrate de revisar <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> para una implementación aún mejor de esta funcionalidad.<br/><br/> Haz clic en el símbolo más resaltado para continuar.</p></body></html>"
|
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Esta pestaña te permitirá cambiar escenas según la salida de vídeo actual de las fuentes seleccionadas.<br/>Asegúrate de revisar <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> para una implementación aún mejor de esta funcionalidad.<br/><br/> Haz clic en el símbolo más resaltado para continuar.</p></body></html>"
|
||||||
|
|
||||||
; Network Tab
|
|
||||||
AdvSceneSwitcher.networkTab.title="Red"
|
|
||||||
AdvSceneSwitcher.networkTab.description="Esta pestaña le permitirá controlar de forma remota la escena activa de otra instancia de OBS.\nTenga en cuenta que los nombres de las escenas deben coincidir exactamente en todas las instancias de OBS".
|
|
||||||
AdvSceneSwitcher.networkTab.warning="Ejecutar el servidor fuera de una red local permitirá que terceros lean la escena activa".
|
|
||||||
AdvSceneSwitcher.networkTab.server="Iniciar servidor (envía mensajes de cambio de escena a todos los clientes conectados)"
|
|
||||||
AdvSceneSwitcher.networkTab.server.port="Puerto"
|
|
||||||
AdvSceneSwitcher.networkTab.server.lockToIPv4="Bloquear servidor para usar solo IPv4"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendSceneChange="Enviar mensajes para cambios de escena"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Solo enviar mensajes para cambios de escena automatizados"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendPreview="Enviar mensajes para obtener una vista previa del cambio de escena cuando se ejecuta en Modo Estudio"
|
|
||||||
AdvSceneSwitcher.networkTab.startFailed.message="El servidor WebSockets no pudo iniciarse, tal vez porque:\n - El puerto TCP %1 puede estar actualmente en uso en otro lugar de este sistema, posiblemente por otra aplicación. Intente configurar un puerto TCP diferente en el WebSocket configuración del servidor o detenga cualquier aplicación que pueda estar usando este puerto.\n - Mensaje de error: %2"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.currentStatus="Estado actual"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.notRunning="Desconectado"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.starting="Iniciando"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.running="En ejecución"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restart="Reiniciar servidor"
|
|
||||||
AdvSceneSwitcher.networkTab.client="Iniciar cliente (Recibe mensajes de cambios de escena)"
|
|
||||||
AdvSceneSwitcher.networkTab.client.address="Nombre de host o dirección IP"
|
|
||||||
AdvSceneSwitcher.networkTab.client.port="Puerto"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.currentStatus="Estado actual"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.disconnected="Desconectado"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connecting="Conectando"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connected="Conectado"
|
|
||||||
AdvSceneSwitcher.networkTab.client.reconnect="Forzar reconexión"
|
|
||||||
|
|
||||||
; Scene Group Tab
|
; Scene Group Tab
|
||||||
AdvSceneSwitcher.sceneGroupTab.title="Grupo de escenas"
|
AdvSceneSwitcher.sceneGroupTab.title="Grupo de escenas"
|
||||||
AdvSceneSwitcher.sceneGroupTab.list="Grupos de escenas"
|
AdvSceneSwitcher.sceneGroupTab.list="Grupos de escenas"
|
||||||
@@ -663,30 +635,6 @@ AdvSceneSwitcher.sceneGroupTab.exists="El grupo de escenas o el nombre de la esc
|
|||||||
AdvSceneSwitcher.sceneGroupTab.help="Los grupos de escenas se pueden seleccionar como un objetivo al igual que una escena normal.\n\nComo sugiere el nombre, un grupo de escenas es una colección de varias escenas.\nEl grupo de escenas avanzará a través de la lista de sus escenas asignadas según los ajustes configurados, que se puede encontrar en el lado derecho.\n\nPuedes configurar el grupo de escenas para avanzar a la siguiente escena en la lista:\nDespués de varias veces, el grupo de escenas se selecciona como objetivo.\nDespués de que un cierto período de tiempo haya pasado.\nO al azar.\n\nPor ejemplo, un grupo de escenas que contiene las escenas ... \nEscena 1 \nEscena 2 \nEscena 3 \n ... activará la \"Escena 1 \" la primera vez que se seleccione como objetivo. \nLa segunda vez se activará \"Escena 2 \". \nLas veces restantes \"Escena 3 \" se activarán. \n\nHaz clic en el símbolo más resaltado a continuación para agregar un nuevo grupo de escenas."
|
AdvSceneSwitcher.sceneGroupTab.help="Los grupos de escenas se pueden seleccionar como un objetivo al igual que una escena normal.\n\nComo sugiere el nombre, un grupo de escenas es una colección de varias escenas.\nEl grupo de escenas avanzará a través de la lista de sus escenas asignadas según los ajustes configurados, que se puede encontrar en el lado derecho.\n\nPuedes configurar el grupo de escenas para avanzar a la siguiente escena en la lista:\nDespués de varias veces, el grupo de escenas se selecciona como objetivo.\nDespués de que un cierto período de tiempo haya pasado.\nO al azar.\n\nPor ejemplo, un grupo de escenas que contiene las escenas ... \nEscena 1 \nEscena 2 \nEscena 3 \n ... activará la \"Escena 1 \" la primera vez que se seleccione como objetivo. \nLa segunda vez se activará \"Escena 2 \". \nLas veces restantes \"Escena 3 \" se activarán. \n\nHaz clic en el símbolo más resaltado a continuación para agregar un nuevo grupo de escenas."
|
||||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="Selecciona el grupo de escenas que deseas modificar a la izquierda. \n\nSelecciona una escena para agregar a este grupo de escenas seleccionando la escena de arriba y haciendo clic en el símbolo más a continuación. \n\nSe puede agregar una escena varias veces al mismo grupo de escenas."
|
AdvSceneSwitcher.sceneGroupTab.scenes.help="Selecciona el grupo de escenas que deseas modificar a la izquierda. \n\nSelecciona una escena para agregar a este grupo de escenas seleccionando la escena de arriba y haciendo clic en el símbolo más a continuación. \n\nSe puede agregar una escena varias veces al mismo grupo de escenas."
|
||||||
|
|
||||||
; Scene Trigger Tab
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.title="Activadores de escena"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--selecciona el activador--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="esté activo"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="no esté activo"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="cambie a otra escena"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--Selecciona la acción--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="empezar a grabar"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="pausar la grabación"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="reanudar grabación"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="detener grabación"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="detener transmisión"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="iniciar transmisión"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="iniciar búfer de repetición"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="detener búfer de repetición"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="silenciar fuente"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="dejar de silenciar fuente"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="iniciar el selector de escenas"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="detener el selector de escenas"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="Iniciar Camara Virtual"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="Detener Camara Virtual"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.entry="Cuando {{scenes}} {{triggers}} {{actions}} {{audioSources}} después de {{duration}}"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.help="Esta pestaña te permite activar acciones sobre cambios de escena, como detener la grabación o la transmisión."
|
|
||||||
|
|
||||||
; Hotkey
|
; Hotkey
|
||||||
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Iniciar Advanced Scene Switcher"
|
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Iniciar Advanced Scene Switcher"
|
||||||
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Detener Advanced Scene Switcher"
|
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Detener Advanced Scene Switcher"
|
||||||
@@ -740,7 +688,7 @@ AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Esta parece ser la prim
|
|||||||
AdvSceneSwitcher.deprecatedTabWarning="¡Se detuvo el desarrollo de esta pestaña!\nConsidere cambiar a macros en su lugar.\nEsta sugerencia se puede desactivar en la pestaña General".
|
AdvSceneSwitcher.deprecatedTabWarning="¡Se detuvo el desarrollo de esta pestaña!\nConsidere cambiar a macros en su lugar.\nEsta sugerencia se puede desactivar en la pestaña General".
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="milisegundos"
|
AdvSceneSwitcher.unit.milliseconds="milisegundos"
|
||||||
AdvSceneSwitcher.unit.secends="segundos"
|
AdvSceneSwitcher.unit.seconds="segundos"
|
||||||
AdvSceneSwitcher.unit.minutes="minutos"
|
AdvSceneSwitcher.unit.minutes="minutos"
|
||||||
AdvSceneSwitcher.unit.hours="horas"
|
AdvSceneSwitcher.unit.hours="horas"
|
||||||
AdvSceneSwitcher.duration.condition.none="Sin límite de tiempo"
|
AdvSceneSwitcher.duration.condition.none="Sin límite de tiempo"
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ AdvSceneSwitcher.generalTab.status.autoStart.streaming="Diffusion en continu"
|
|||||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Enregistrement ou Diffusion en continu"
|
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Enregistrement ou Diffusion en continu"
|
||||||
AdvSceneSwitcher.generalTab.status.checkInterval="Vérifier les conditions toutes les"
|
AdvSceneSwitcher.generalTab.status.checkInterval="Vérifier les conditions toutes les"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior="Comportement général"
|
AdvSceneSwitcher.generalTab.generalBehavior="Comportement général"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="Si aucune action n'est effectuée pendant"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch="Si aucune action n'est effectuée pendant"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Sera aussi précis que l'intervalle de vérification configuré."
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatchDelay.tooltip="Sera aussi précis que l'intervalle de vérification configuré."
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Ne pas basculer"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.dontSwitch="Ne pas basculer"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Basculer vers n'importe quelle scène dans l'onglet Aléatoire"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchToRandom="Basculer vers n'importe quelle scène dans l'onglet Aléatoire"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Basculer vers :"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchTo="Basculer vers :"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Après avoir effectué des actions, sauter l'exécution d'actions pendant"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Après avoir effectué des actions, sauter l'exécution d'actions pendant"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="Pendant cette période, les correspondances potentielles seront ignorées !"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="Pendant cette période, les correspondances potentielles seront ignorées !"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Activer les journaux détaillés"
|
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Activer les journaux détaillés"
|
||||||
@@ -109,7 +109,7 @@ AdvSceneSwitcher.macroTab.highlightExecutedMacros="Mettre en surbrillance les ma
|
|||||||
AdvSceneSwitcher.macroTab.highlightTrueConditions="Mettre en surbrillance les conditions de la macro actuellement sélectionnée qui ont évalué à vrai récemment"
|
AdvSceneSwitcher.macroTab.highlightTrueConditions="Mettre en surbrillance les conditions de la macro actuellement sélectionnée qui ont évalué à vrai récemment"
|
||||||
AdvSceneSwitcher.macroTab.highlightPerformedActions="Mettre en surbrillance les actions récemment effectuées de la macro actuellement sélectionnée"
|
AdvSceneSwitcher.macroTab.highlightPerformedActions="Mettre en surbrillance les actions récemment effectuées de la macro actuellement sélectionnée"
|
||||||
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Enregistrer des raccourcis clavier pour contrôler l'état de pause des nouvelles macros"
|
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Enregistrer des raccourcis clavier pour contrôler l'état de pause des nouvelles macros"
|
||||||
AdvSceneSwitcher.macroTab.currentDisableHotkeys="Enregistrer des raccourcis clavier pour contrôler l'état de pause de la macro sélectionnée"
|
AdvSceneSwitcher.macroTab.currentRegisterHotkeys="Enregistrer des raccourcis clavier pour contrôler l'état de pause de la macro sélectionnée"
|
||||||
AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup="Ignorer l'exécution des actions de la macro actuelle au démarrage"
|
AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup="Ignorer l'exécution des actions de la macro actuelle au démarrage"
|
||||||
AdvSceneSwitcher.macroTab.currentRegisterDock="Enregistrer le widget du dock pour contrôler l'état de pause de la macro sélectionnée ou l'exécuter manuellement"
|
AdvSceneSwitcher.macroTab.currentRegisterDock="Enregistrer le widget du dock pour contrôler l'état de pause de la macro sélectionnée ou l'exécuter manuellement"
|
||||||
AdvSceneSwitcher.macroTab.currentDockAddRunButton="Ajouter un bouton pour exécuter la macro"
|
AdvSceneSwitcher.macroTab.currentDockAddRunButton="Ajouter un bouton pour exécuter la macro"
|
||||||
@@ -454,7 +454,7 @@ AdvSceneSwitcher.condition.slideshow="Diaporama"
|
|||||||
AdvSceneSwitcher.condition.slideshow.condition.slideChanged="Diapositive changée"
|
AdvSceneSwitcher.condition.slideshow.condition.slideChanged="Diapositive changée"
|
||||||
AdvSceneSwitcher.condition.slideshow.condition.slideIndex="Le numéro de la diapositive actuelle est"
|
AdvSceneSwitcher.condition.slideshow.condition.slideIndex="Le numéro de la diapositive actuelle est"
|
||||||
AdvSceneSwitcher.condition.slideshow.condition.slidePath="Le chemin de la diapositive actuelle est"
|
AdvSceneSwitcher.condition.slideshow.condition.slidePath="Le chemin de la diapositive actuelle est"
|
||||||
AdvSceneSwitcher.condition.slideshow.updateIntervalTooltip="Les informations sur l'état du diaporama ne seront mises à jour qu'en fonction du temps configuré entre les diapositives"
|
AdvSceneSwitcher.condition.slideshow.updateInterval.tooltip="Les informations sur l'état du diaporama ne seront mises à jour qu'en fonction du temps configuré entre les diapositives"
|
||||||
|
|
||||||
; Macro Actions
|
; Macro Actions
|
||||||
AdvSceneSwitcher.action.scene="Changer de scène"
|
AdvSceneSwitcher.action.scene="Changer de scène"
|
||||||
@@ -597,7 +597,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="Déplacer vers le bas"
|
|||||||
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Déplacer en haut"
|
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Déplacer en haut"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Déplacer en bas"
|
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Déplacer en bas"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Déplacer à la position"
|
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Déplacer à la position"
|
||||||
AdvSceneSwitcher.action.sceneOrder.entry="Sur{{scenes}}{{actions}}{{sources}}{{position}}"
|
AdvSceneSwitcher.action.sceneOrder.entry="Sur{{scenes}}{{actions}}{{sources}}{{sources2}}{{position}}"
|
||||||
AdvSceneSwitcher.action.sceneTransform="Transformation de l'élément de la scène"
|
AdvSceneSwitcher.action.sceneTransform="Transformation de l'élément de la scène"
|
||||||
AdvSceneSwitcher.action.sceneTransform.type.manual="Transform"
|
AdvSceneSwitcher.action.sceneTransform.type.manual="Transform"
|
||||||
AdvSceneSwitcher.action.sceneTransform.type.reset="Réinitialiser la transformation"
|
AdvSceneSwitcher.action.sceneTransform.type.reset="Réinitialiser la transformation"
|
||||||
@@ -649,7 +649,7 @@ AdvSceneSwitcher.action.screenshot.type.source="Source"
|
|||||||
AdvSceneSwitcher.action.screenshot.type.scene="Scène"
|
AdvSceneSwitcher.action.screenshot.type.scene="Scène"
|
||||||
AdvSceneSwitcher.action.screenshot.mainOutput="Sortie principale d'OBS"
|
AdvSceneSwitcher.action.screenshot.mainOutput="Sortie principale d'OBS"
|
||||||
AdvSceneSwitcher.action.screenshot.blackscreenNote="Les sources ou les scènes qui ne sont pas toujours rendues peuvent entraîner des parties de captures d'écran vides."
|
AdvSceneSwitcher.action.screenshot.blackscreenNote="Les sources ou les scènes qui ne sont pas toujours rendues peuvent entraîner des parties de captures d'écran vides."
|
||||||
AdvSceneSwitcher.action.screenshot.entry="Capturer{{targetType}}{{sources}}{{scenes}}et enregistrer à l'emplacement{{saveType}}"
|
AdvSceneSwitcher.action.screenshot.entry="Capturer{{targetType}}{{sources}}{{scenes}}et enregistrer à l'emplacement{{saveType}}{{variables}}"
|
||||||
AdvSceneSwitcher.action.profile="Profil"
|
AdvSceneSwitcher.action.profile="Profil"
|
||||||
AdvSceneSwitcher.action.profile.entry="Changer le profil actif vers{{profiles}}"
|
AdvSceneSwitcher.action.profile.entry="Changer le profil actif vers{{profiles}}"
|
||||||
AdvSceneSwitcher.action.sceneCollection="Collection de scènes"
|
AdvSceneSwitcher.action.sceneCollection="Collection de scènes"
|
||||||
@@ -897,31 +897,6 @@ AdvSceneSwitcher.videoTab.ignoreInactiveSource="sauf si la source est inactive"
|
|||||||
AdvSceneSwitcher.videoTab.entry="Lorsque{{videoSources}}{{condition}}{{filePath}}{{browseButton}}pendant{{duration}}, passez à{{scenes}}en utilisant{{transitions}}{{ignoreInactiveSource}}"
|
AdvSceneSwitcher.videoTab.entry="Lorsque{{videoSources}}{{condition}}{{filePath}}{{browseButton}}pendant{{duration}}, passez à{{scenes}}en utilisant{{transitions}}{{ignoreInactiveSource}}"
|
||||||
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Cet onglet vous permettra de basculer entre les scènes en fonction de la sortie vidéo actuelle des sources sélectionnées.<br/>Assurez-vous de consulter <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> pour une implémentation encore meilleure de cette fonctionnalité.<br/><br/> Cliquez sur le symbole plus en surbrillance pour continuer.</p></body></html>"
|
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Cet onglet vous permettra de basculer entre les scènes en fonction de la sortie vidéo actuelle des sources sélectionnées.<br/>Assurez-vous de consulter <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> pour une implémentation encore meilleure de cette fonctionnalité.<br/><br/> Cliquez sur le symbole plus en surbrillance pour continuer.</p></body></html>"
|
||||||
|
|
||||||
; Network Tab
|
|
||||||
AdvSceneSwitcher.networkTab.title="Réseau"
|
|
||||||
AdvSceneSwitcher.networkTab.description="Cet onglet vous permettra de contrôler à distance la scène active d'une autre instance OBS.\nVeuillez noter que les noms de scènes doivent correspondre exactement sur toutes les instances OBS."
|
|
||||||
AdvSceneSwitcher.networkTab.warning="Exécuter le serveur en dehors d'un réseau local permettra à des tiers de lire la scène active."
|
|
||||||
AdvSceneSwitcher.networkTab.server="Démarrer le serveur (Envoie des messages de changement de scène à tous les clients connectés)"
|
|
||||||
AdvSceneSwitcher.networkTab.server.port="Port"
|
|
||||||
AdvSceneSwitcher.networkTab.server.lockToIPv4="Verrouiller le serveur pour n'utiliser que IPv4"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendSceneChange="Envoyer des messages pour les changements de scène"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Envoyer uniquement des messages pour les changements de scène automatisés"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendPreview="Envoyer des messages pour le changement de prévisualisation de scène lors de l'exécution en mode Studio"
|
|
||||||
AdvSceneSwitcher.networkTab.startFailed.message="Le serveur WebSocket n'a pas pu démarrer, peut-être parce que :\n - Le port TCP %1 est peut-être déjà utilisé ailleurs sur ce système, éventuellement par une autre application. Essayez de définir un port TCP différent dans les paramètres du serveur WebSocket, ou arrêtez toute application qui pourrait utiliser ce port.\n - Message d'erreur : %2"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.currentStatus="État actuel"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.notRunning="Non démarré"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.starting="Démarrage"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.running="En cours d'exécution"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restart="Redémarrer le serveur"
|
|
||||||
AdvSceneSwitcher.networkTab.client="Démarrer le client (Reçoit des messages de changement de scène)"
|
|
||||||
AdvSceneSwitcher.networkTab.client.address="Nom d'hôte ou adresse IP"
|
|
||||||
AdvSceneSwitcher.networkTab.client.port="Port"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.currentStatus="État actuel"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.disconnected="Déconnecté"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connecting="Connexion"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connected="Connecté"
|
|
||||||
AdvSceneSwitcher.networkTab.client.reconnect="Forcer la reconnexion"
|
|
||||||
|
|
||||||
; Scene Group Tab
|
; Scene Group Tab
|
||||||
AdvSceneSwitcher.sceneGroupTab.title="Groupe de Scènes"
|
AdvSceneSwitcher.sceneGroupTab.title="Groupe de Scènes"
|
||||||
AdvSceneSwitcher.sceneGroupTab.list="Groupes de Scènes"
|
AdvSceneSwitcher.sceneGroupTab.list="Groupes de Scènes"
|
||||||
@@ -942,30 +917,6 @@ AdvSceneSwitcher.sceneGroupTab.exists="Le nom du Groupe de Scènes ou de la Scè
|
|||||||
AdvSceneSwitcher.sceneGroupTab.help="Les Groupes de Scènes peuvent être sélectionnés comme une cible, tout comme une scène régulière.\n\nComme son nom l'indique, un Groupe de Scènes est une collection de plusieurs scènes.\nLe Groupe de Scènes avancera dans la liste de ses scènes attribuées en fonction des paramètres configurés, que vous pouvez trouver à droite.\n\nVous pouvez configurer le Groupe de Scènes pour passer à la scène suivante dans la liste :\nAprès un certain nombre de fois où le Groupe de Scènes est sélectionné comme cible.\nAprès qu'un certain laps de temps se soit écoulé.\nOu au hasard.\n\nPar exemple, un Groupe de Scènes contenant les scènes...\nScène 1\nScène 2\nScène 3\n... activera "Scène 1" la première fois qu'il est sélectionné comme cible.\nLa deuxième fois, il activera "Scène 2".\nLes fois suivantes, "Scène 3" sera activée.\n\nCliquez sur le symbole plus en surbrillance ci-dessous pour ajouter un nouveau Groupe de Scènes."
|
AdvSceneSwitcher.sceneGroupTab.help="Les Groupes de Scènes peuvent être sélectionnés comme une cible, tout comme une scène régulière.\n\nComme son nom l'indique, un Groupe de Scènes est une collection de plusieurs scènes.\nLe Groupe de Scènes avancera dans la liste de ses scènes attribuées en fonction des paramètres configurés, que vous pouvez trouver à droite.\n\nVous pouvez configurer le Groupe de Scènes pour passer à la scène suivante dans la liste :\nAprès un certain nombre de fois où le Groupe de Scènes est sélectionné comme cible.\nAprès qu'un certain laps de temps se soit écoulé.\nOu au hasard.\n\nPar exemple, un Groupe de Scènes contenant les scènes...\nScène 1\nScène 2\nScène 3\n... activera "Scène 1" la première fois qu'il est sélectionné comme cible.\nLa deuxième fois, il activera "Scène 2".\nLes fois suivantes, "Scène 3" sera activée.\n\nCliquez sur le symbole plus en surbrillance ci-dessous pour ajouter un nouveau Groupe de Scènes."
|
||||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="Sélectionnez le groupe de scènes que vous souhaitez modifier à gauche.\n\nSélectionnez une scène à ajouter à ce groupe de scènes en sélectionnant la scène ci-dessus et en cliquant sur le symbole plus ci-dessous.\n\nUne scène peut être ajoutée plusieurs fois au même groupe de scènes."
|
AdvSceneSwitcher.sceneGroupTab.scenes.help="Sélectionnez le groupe de scènes que vous souhaitez modifier à gauche.\n\nSélectionnez une scène à ajouter à ce groupe de scènes en sélectionnant la scène ci-dessus et en cliquant sur le symbole plus ci-dessous.\n\nUne scène peut être ajoutée plusieurs fois au même groupe de scènes."
|
||||||
|
|
||||||
; Scene Trigger Tab
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.title="Déclencheurs de Scène"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--sélectionnez un déclencheur--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="est active"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="n'est pas active"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="passé à autre chose"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--sélectionnez une action--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="démarrer l'enregistrement"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="mettre en pause l'enregistrement"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="reprendre l'enregistrement"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="arrêter l'enregistrement"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="arrêter la diffusion"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="démarrer la diffusion"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="démarrer le tampon de répétition"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="arrêter le tampon de répétition"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="mettre la source en sourdine"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="annuler la mise en sourdine de la source"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="démarrer le commutateur de scènes avancé"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="arrêter le commutateur de scènes avancé"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="démarrer la caméra virtuelle"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="arrêter la caméra virtuelle"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.entry="Lorsque{{scenes}}{{triggers}}{{actions}}{{audioSources}}après{{duration}}"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.help="Cet onglet vous permet de déclencher des actions lors des changements de scènes, comme l'arrêt de l'enregistrement ou de la diffusion."
|
|
||||||
|
|
||||||
; Hotkey
|
; Hotkey
|
||||||
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Démarrer le commutateur de scènes avancé"
|
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Démarrer le commutateur de scènes avancé"
|
||||||
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Arrêter le commutateur de scènes avancé"
|
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Arrêter le commutateur de scènes avancé"
|
||||||
@@ -1161,8 +1112,8 @@ AdvSceneSwitcher.sceneItemSelection.type.sourceName="Nom de la source"
|
|||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="Nom de la variable"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="Nom de la variable"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="Le nom de la source correspond au motif"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="Le nom de la source correspond au motif"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.entry="{{nameConflictIndex}}correspondant à{{pattern}}{{regex}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.entry="{{nameConflictIndex}}correspondant à{{pattern}}{{regex}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup="Sources de type"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType="Sources de type"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup.entry="{{nameConflictIndex}}Type de source{{sourceGroups}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType.entry="{{nameConflictIndex}}Type de source{{sourceTypes}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index="Source avec index"
|
AdvSceneSwitcher.sceneItemSelection.type.index="Source avec index"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index.entry="{{index}}source"
|
AdvSceneSwitcher.sceneItemSelection.type.index.entry="{{index}}source"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.indexRange="Sources dans la plage d'index"
|
AdvSceneSwitcher.sceneItemSelection.type.indexRange="Sources dans la plage d'index"
|
||||||
@@ -1182,7 +1133,7 @@ AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Il semble que ce soit l
|
|||||||
AdvSceneSwitcher.deprecatedTabWarning="Le développement de cet onglet est terminé !\nVeuillez envisager de passer à l'utilisation des Macros à la place.\nCette astuce peut être désactivée dans l'onglet Général."
|
AdvSceneSwitcher.deprecatedTabWarning="Le développement de cet onglet est terminé !\nVeuillez envisager de passer à l'utilisation des Macros à la place.\nCette astuce peut être désactivée dans l'onglet Général."
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="millisecondes"
|
AdvSceneSwitcher.unit.milliseconds="millisecondes"
|
||||||
AdvSceneSwitcher.unit.secends="secondes"
|
AdvSceneSwitcher.unit.seconds="secondes"
|
||||||
AdvSceneSwitcher.unit.minutes="minutes"
|
AdvSceneSwitcher.unit.minutes="minutes"
|
||||||
AdvSceneSwitcher.unit.hours="heures"
|
AdvSceneSwitcher.unit.hours="heures"
|
||||||
AdvSceneSwitcher.duration.condition.none="Aucun modificateur de durée"
|
AdvSceneSwitcher.duration.condition.none="Aucun modificateur de durée"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
AdvSceneSwitcher.pluginName="高機能シーンスイッチャー"
|
AdvSceneSwitcher.pluginName="高機能シーンスイッチャー"
|
||||||
AdvSceneSwitcher.windowTitle="高機能シーンスイッチャー"
|
AdvSceneSwitcher.windowTitle="高機能シーンスイッチャー"
|
||||||
|
|
||||||
; General Tab
|
# General Tab
|
||||||
AdvSceneSwitcher.generalTab.title="全般"
|
AdvSceneSwitcher.generalTab.title="全般"
|
||||||
AdvSceneSwitcher.generalTab.status="ステータス"
|
AdvSceneSwitcher.generalTab.status="ステータス"
|
||||||
AdvSceneSwitcher.generalTab.status.hotkeytips="OBS設定でホットキーを定義可能"
|
AdvSceneSwitcher.generalTab.status.hotkeytips="OBS設定でホットキーを定義可能"
|
||||||
@@ -19,16 +19,16 @@ AdvSceneSwitcher.generalTab.status.autoStart.streaming="配信を開始した時
|
|||||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="録画開始時または配信開始時"
|
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="録画開始時または配信開始時"
|
||||||
AdvSceneSwitcher.generalTab.status.checkInterval="イベント条件を確認する頻度"
|
AdvSceneSwitcher.generalTab.status.checkInterval="イベント条件を確認する頻度"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior="一般"
|
AdvSceneSwitcher.generalTab.generalBehavior="一般"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="何も操作を行わなかった場合"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch="何も操作を行わなかった場合"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="設定されたチェック間隔と同程度の精度のみが保証されます。"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatchDelay.tooltip="設定されたチェック間隔と同程度の精度のみが保証されます。"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="切り替えないでください"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.dontSwitch="切り替えないでください"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="ランダムタブで任意のシーンに切り替え"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchToRandom="ランダムタブで任意のシーンに切り替え"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="切り替え先:"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchTo="切り替え先:"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="アクションを実行した後、次のアクションをスキップする時間"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="アクションを実行した後、次のアクションをスキップする時間"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="この間、潜在的な一致は無視されます!"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="この間、潜在的な一致は無視されます!"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.logLevel="ログレベル:"
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel="ログレベル:"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.default="デフォルト"
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.default="デフォルト"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.printActions="実行されたアクションのログ"
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.logAction="実行されたアクションのログ"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.verbose="詳細ログ(Verbose)"
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.verbose="詳細ログ(Verbose)"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="詳細ログを有効にする(生成されるログファイルのサイズが増加します)"
|
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="詳細ログを有効にする(生成されるログファイルのサイズが増加します)"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="ウィンドウのサイズと位置を記憶する"
|
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="ウィンドウのサイズと位置を記憶する"
|
||||||
@@ -37,6 +37,7 @@ AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="UIヒントを無効
|
|||||||
AdvSceneSwitcher.generalTab.generalBehavior.comboBoxFilterDisable="ドロップダウンメニューでの文字入力によるフィルタリングを無効にする"
|
AdvSceneSwitcher.generalTab.generalBehavior.comboBoxFilterDisable="ドロップダウンメニューでの文字入力によるフィルタリングを無効にする"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailure="プラグインが読み込めない場合に警告を表示"
|
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailure="プラグインが読み込めない場合に警告を表示"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage="<html><body>次のプラグイン ライブラリの読み込みに失敗したため、一部の高機能シーンスイッチャーが利用できなくなる可能性があります:%1詳細については、OBS ログを確認してください。<br>このメッセージは、[全般] タブで無効にすることができます。 </body></html>"
|
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage="<html><body>次のプラグイン ライブラリの読み込みに失敗したため、一部の高機能シーンスイッチャーが利用できなくなる可能性があります:%1詳細については、OBS ログを確認してください。<br>このメッセージは、[全般] タブで無効にすることができます。 </body></html>"
|
||||||
|
AdvSceneSwitcher.generalTab.generalBehavior.warnCorruptedInstallMessage="プラグインが正しくインストールできておらずクラッシュする可能性があります!\nプラグインが正しくインストールされているか確認してください!"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="旧来型マクロ設定のタブを非表示にする(廃止予定タブ)"
|
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="旧来型マクロ設定のタブを非表示にする(廃止予定タブ)"
|
||||||
AdvSceneSwitcher.generalTab.matchBehavior="マッチした場合の動作(廃止予定の設定項目)"
|
AdvSceneSwitcher.generalTab.matchBehavior="マッチした場合の動作(廃止予定の設定項目)"
|
||||||
AdvSceneSwitcher.generalTab.priority="優先順位"
|
AdvSceneSwitcher.generalTab.priority="優先順位"
|
||||||
@@ -46,11 +47,11 @@ AdvSceneSwitcher.generalTab.priority.threadPriorityNotice="(優先度を \"Norma
|
|||||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings="設定の保存・読み込み"
|
AdvSceneSwitcher.generalTab.saveOrLoadsettings="設定の保存・読み込み"
|
||||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.export="エクスポート"
|
AdvSceneSwitcher.generalTab.saveOrLoadsettings.export="エクスポート"
|
||||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.import="インポート"
|
AdvSceneSwitcher.generalTab.saveOrLoadsettings.import="インポート"
|
||||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle="高度なシーンスイッチャーの設定をファイルにエクスポート..."
|
AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle="高機能シーンスイッチャーの設定をファイルにエクスポート..."
|
||||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle="高度なシーンスイッチャーの設定をファイルからインポート..."
|
AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle="高機能シーンスイッチャーの設定をファイルからインポート..."
|
||||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType="テキストファイル(*.txt)"
|
AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType="テキストファイル(*.txt)"
|
||||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadFail="高機能シーンスイッチャーの設定インポートに失敗しました"
|
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadFail="高機能シーンスイッチャーの設定インポートに失敗しました"
|
||||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadSuccess="シーンスイッチャーの高度な設定が正常にインポートされました"
|
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadSuccess="高機能シーンスイッチャーの設定が正常にインポートされました"
|
||||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportSensitiveDataWarning="警告:\nエクスポートされたデータにはセンシティブ情報が含まれている可能性があります!"
|
AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportSensitiveDataWarning="警告:\nエクスポートされたデータにはセンシティブ情報が含まれている可能性があります!"
|
||||||
AdvSceneSwitcher.generalTab.priority.fileContent="ファイル内容"
|
AdvSceneSwitcher.generalTab.priority.fileContent="ファイル内容"
|
||||||
AdvSceneSwitcher.generalTab.priority.sceneSequence="シーンシーケンス"
|
AdvSceneSwitcher.generalTab.priority.sceneSequence="シーンシーケンス"
|
||||||
@@ -69,7 +70,7 @@ AdvSceneSwitcher.generalTab.transitionOverride="トランジションオーバ
|
|||||||
AdvSceneSwitcher.generalTab.adjustActiveTransitionType="アクティブトランジションタイプを調整する"
|
AdvSceneSwitcher.generalTab.adjustActiveTransitionType="アクティブトランジションタイプを調整する"
|
||||||
AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="少なくとも1つのオプションが有効であること:\n\n - トランジションオーバーライドの使用\n\n - アクティブなトランジションタイプを変更する"
|
AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="少なくとも1つのオプションが有効であること:\n\n - トランジションオーバーライドの使用\n\n - アクティブなトランジションタイプを変更する"
|
||||||
|
|
||||||
; Variables Tab
|
# Variables Tab
|
||||||
AdvSceneSwitcher.variableTab.title="変数"
|
AdvSceneSwitcher.variableTab.title="変数"
|
||||||
AdvSceneSwitcher.variableTab.help="変数はプラグイン内の様々な場所で使用できます。\n\n強調表示されたプラス記号をクリックすると、新しい変数を追加できます。"
|
AdvSceneSwitcher.variableTab.help="変数はプラグイン内の様々な場所で使用できます。\n\n強調表示されたプラス記号をクリックすると、新しい変数を追加できます。"
|
||||||
AdvSceneSwitcher.variableTab.variableAddButton.tooltip="新しい変数を追加する"
|
AdvSceneSwitcher.variableTab.variableAddButton.tooltip="新しい変数を追加する"
|
||||||
@@ -81,14 +82,12 @@ AdvSceneSwitcher.variableTab.value.header="値"
|
|||||||
AdvSceneSwitcher.variableTab.saveLoadBehavior.header="保存・読み込みの動作"
|
AdvSceneSwitcher.variableTab.saveLoadBehavior.header="保存・読み込みの動作"
|
||||||
AdvSceneSwitcher.variableTab.saveLoadBehavior.text.default="デフォルト\"%1\""
|
AdvSceneSwitcher.variableTab.saveLoadBehavior.text.default="デフォルト\"%1\""
|
||||||
AdvSceneSwitcher.variableTab.lastUsed.header="最後に使用された"
|
AdvSceneSwitcher.variableTab.lastUsed.header="最後に使用された"
|
||||||
AdvSceneSwitcher.variableTab.lastUsed.text="%1 秒前"
|
; AdvSceneSwitcher.variableTab.lastUsed.text.never="Never"
|
||||||
; AdvSceneSwitcher.variableTab.lastUsed.text.never="決して"
|
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.header="最終変更"
|
AdvSceneSwitcher.variableTab.lastChanged.header="最終変更"
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.text="%1 秒前"
|
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.text.none="起動以来変更なし"
|
AdvSceneSwitcher.variableTab.lastChanged.text.none="起動以来変更なし"
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.tooltip="変更された時間: %1\n\n以前の値: %2"
|
AdvSceneSwitcher.variableTab.lastChanged.tooltip="変更された時間: %1\n\n以前の値: %2"
|
||||||
|
|
||||||
; Action Queue Tab
|
# Action Queue Tab
|
||||||
AdvSceneSwitcher.actionQueueTab.title="アクションキュー"
|
AdvSceneSwitcher.actionQueueTab.title="アクションキュー"
|
||||||
AdvSceneSwitcher.actionQueueTab.help="アクションキューは、マクロシステムのリセットと並行して順次実行されます。"
|
AdvSceneSwitcher.actionQueueTab.help="アクションキューは、マクロシステムのリセットと並行して順次実行されます。"
|
||||||
AdvSceneSwitcher.actionQueueTab.queueAddButton.tooltip="新しいアクションキューを追加する"
|
AdvSceneSwitcher.actionQueueTab.queueAddButton.tooltip="新しいアクションキューを追加する"
|
||||||
@@ -102,7 +101,7 @@ AdvSceneSwitcher.actionQueueTab.no="いいえ"
|
|||||||
AdvSceneSwitcher.actionQueueTab.removeSingleQueuePopup.text="本当に \"%1\"を削除しますか?"
|
AdvSceneSwitcher.actionQueueTab.removeSingleQueuePopup.text="本当に \"%1\"を削除しますか?"
|
||||||
AdvSceneSwitcher.actionQueueTab.removeMultipleQueuesPopup.text="アクション・キュー %1 を削除しますか?"
|
AdvSceneSwitcher.actionQueueTab.removeMultipleQueuesPopup.text="アクション・キュー %1 を削除しますか?"
|
||||||
|
|
||||||
; Websocket Connections Tab
|
# Websocket Connections Tab
|
||||||
AdvSceneSwitcher.websocketConnectionTab.title="Websocket接続"
|
AdvSceneSwitcher.websocketConnectionTab.title="Websocket接続"
|
||||||
AdvSceneSwitcher.websocketConnectionTab.help="Websocket接続は、他のOBSインスタンスまたはプログラムと通信するために使用できます。"
|
AdvSceneSwitcher.websocketConnectionTab.help="Websocket接続は、他のOBSインスタンスまたはプログラムと通信するために使用できます。"
|
||||||
AdvSceneSwitcher.websocketConnectionTab.websocketConnectionAddButton.tooltip="新しいWebsocket接続を追加する"
|
AdvSceneSwitcher.websocketConnectionTab.websocketConnectionAddButton.tooltip="新しいWebsocket接続を追加する"
|
||||||
@@ -116,10 +115,10 @@ AdvSceneSwitcher.websocketConnectionTab.protocol.no="いいえ"
|
|||||||
AdvSceneSwitcher.websocketConnectionTab.removeSingleConnectionPopup.text="本当に\"%1\"を削除しますか?"
|
AdvSceneSwitcher.websocketConnectionTab.removeSingleConnectionPopup.text="本当に\"%1\"を削除しますか?"
|
||||||
AdvSceneSwitcher.websocketConnectionTab.removeMultipleConnectionsPopup.text="本当に%1接続を削除しますか?"
|
AdvSceneSwitcher.websocketConnectionTab.removeMultipleConnectionsPopup.text="本当に%1接続を削除しますか?"
|
||||||
|
|
||||||
; Twitch Connections Tab
|
# Twitch Connections Tab
|
||||||
AdvSceneSwitcher.twitchConnectionTab.title="Twitch接続"
|
AdvSceneSwitcher.twitchConnectionTab.title="Twitch接続"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.help="Twitch接続を使用すると、Twitchイベントをトリガーとしてアクションを実行したり、リンク先のTwitchアカウントでアクションを実行したりできます。"
|
AdvSceneSwitcher.twitchConnectionTab.help="Twitch接続を使用すると、Twitchイベントをトリガーとしてアクションを実行したり、リンク先のTwitchアカウントでアクションを実行したりできます。"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionAddButton.tooltip.tooltip="新しいTwitch接続を追加する"
|
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionAddButton.tooltip="新しいTwitch接続を追加する"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionRemoveButton.tooltip="選択したTwitch接続を削除する"
|
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionRemoveButton.tooltip="選択したTwitch接続を削除する"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.name.header="名前"
|
AdvSceneSwitcher.twitchConnectionTab.name.header="名前"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.isValid.header="有効ですか?"
|
AdvSceneSwitcher.twitchConnectionTab.isValid.header="有効ですか?"
|
||||||
@@ -129,7 +128,7 @@ AdvSceneSwitcher.twitchConnectionTab.no="いいえ"
|
|||||||
AdvSceneSwitcher.twitchConnectionTab.removeSingleConnectionPopup.text="本当に\"%1\"を削除しますか?"
|
AdvSceneSwitcher.twitchConnectionTab.removeSingleConnectionPopup.text="本当に\"%1\"を削除しますか?"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.removeMultipleConnectionsPopup.text="本当に%1 Twitch接続を削除しますか?"
|
AdvSceneSwitcher.twitchConnectionTab.removeMultipleConnectionsPopup.text="本当に%1 Twitch接続を削除しますか?"
|
||||||
|
|
||||||
; Macro Tab
|
# Macro Tab
|
||||||
AdvSceneSwitcher.macroTab.title="マクロ"
|
AdvSceneSwitcher.macroTab.title="マクロ"
|
||||||
AdvSceneSwitcher.macroTab.macros="マクロ"
|
AdvSceneSwitcher.macroTab.macros="マクロ"
|
||||||
AdvSceneSwitcher.macroTab.priorityWarning="注意: マクロを最優先機能に設定することをお勧めします。\nこの設定は [全般] タブで変更できます。"
|
AdvSceneSwitcher.macroTab.priorityWarning="注意: マクロを最優先機能に設定することをお勧めします。\nこの設定は [全般] タブで変更できます。"
|
||||||
@@ -175,10 +174,13 @@ AdvSceneSwitcher.macroTab.collapseAll="すべて折りたたむ"
|
|||||||
AdvSceneSwitcher.macroTab.maximize="最大化"
|
AdvSceneSwitcher.macroTab.maximize="最大化"
|
||||||
AdvSceneSwitcher.macroTab.minimize="最小化"
|
AdvSceneSwitcher.macroTab.minimize="最小化"
|
||||||
AdvSceneSwitcher.macroTab.segment.useCustomLabel="カスタムラベルの使用"
|
AdvSceneSwitcher.macroTab.segment.useCustomLabel="カスタムラベルの使用"
|
||||||
|
AdvSceneSwitcher.macroTab.segment.customLabelRename="カスタムラベルの名前を変更する"
|
||||||
AdvSceneSwitcher.macroTab.segment.defaultCustomLabel="マイ・ラベル"
|
AdvSceneSwitcher.macroTab.segment.defaultCustomLabel="マイ・ラベル"
|
||||||
AdvSceneSwitcher.macroTab.segment.setCustomLabel="ラベルを設定 ..."
|
AdvSceneSwitcher.macroTab.segment.setCustomLabel="ラベルを設定 ..."
|
||||||
AdvSceneSwitcher.macroTab.segment.copy="コピー"
|
AdvSceneSwitcher.macroTab.segment.copy="コピー"
|
||||||
AdvSceneSwitcher.macroTab.segment.paste="貼り付け"
|
AdvSceneSwitcher.macroTab.segment.paste="貼り付け"
|
||||||
|
AdvSceneSwitcher.macroTab.segment.pasteAction="アクションとして貼り付ける"
|
||||||
|
AdvSceneSwitcher.macroTab.segment.pasteElseAction="elseアクションとして貼り付ける"
|
||||||
AdvSceneSwitcher.macroTab.highlightSettings="ビジュアル設定"
|
AdvSceneSwitcher.macroTab.highlightSettings="ビジュアル設定"
|
||||||
AdvSceneSwitcher.macroTab.hotkeySettings="ホットキー設定"
|
AdvSceneSwitcher.macroTab.hotkeySettings="ホットキー設定"
|
||||||
AdvSceneSwitcher.macroTab.generalSettings="一般設定"
|
AdvSceneSwitcher.macroTab.generalSettings="一般設定"
|
||||||
@@ -191,7 +193,7 @@ AdvSceneSwitcher.macroTab.highlightExecutedMacros="最近実行したマクロ
|
|||||||
AdvSceneSwitcher.macroTab.highlightTrueConditions="現在選択されているマクロのうち、最近 true と評価された条件を強調表示します"
|
AdvSceneSwitcher.macroTab.highlightTrueConditions="現在選択されているマクロのうち、最近 true と評価された条件を強調表示します"
|
||||||
AdvSceneSwitcher.macroTab.highlightPerformedActions="現在選択されているマクロの最近実行されたアクションを強調表示します"
|
AdvSceneSwitcher.macroTab.highlightPerformedActions="現在選択されているマクロの最近実行されたアクションを強調表示します"
|
||||||
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="新規マクロの一時停止状態を制御するホットキーを登録"
|
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="新規マクロの一時停止状態を制御するホットキーを登録"
|
||||||
AdvSceneSwitcher.macroTab.currentDisableHotkeys="選択したマクロの一時停止状態を制御するホットキーを登録"
|
AdvSceneSwitcher.macroTab.currentRegisterHotkeys="選択したマクロの一時停止状態を制御するホットキーを登録"
|
||||||
AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup="起動時に現在のマクロのアクションの実行をスキップします"
|
AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup="起動時に現在のマクロのアクションの実行をスキップします"
|
||||||
AdvSceneSwitcher.macroTab.currentStopActionsIfNotDone="新しい実行がトリガーされたときに、現在選択されているマクロのアクションがまだ実行中であれば、アクションを停止して再実行する。"
|
AdvSceneSwitcher.macroTab.currentStopActionsIfNotDone="新しい実行がトリガーされたときに、現在選択されているマクロのアクションがまだ実行中であれば、アクションを停止して再実行する。"
|
||||||
AdvSceneSwitcher.macroTab.currentRegisterDock="ドックウィジェットを登録して、選択したマクロの一時停止状態を制御したり、手動で実行したりできます"
|
AdvSceneSwitcher.macroTab.currentRegisterDock="ドックウィジェットを登録して、選択したマクロの一時停止状態を制御したり、手動で実行したりできます"
|
||||||
@@ -238,11 +240,11 @@ AdvSceneSwitcher.macroDock.run="実行"
|
|||||||
AdvSceneSwitcher.macroDock.statusLabel.true="結果はturuでした。"
|
AdvSceneSwitcher.macroDock.statusLabel.true="結果はturuでした。"
|
||||||
AdvSceneSwitcher.macroDock.statusLabel.false="結果はfalseでした。"
|
AdvSceneSwitcher.macroDock.statusLabel.false="結果はfalseでした。"
|
||||||
|
|
||||||
; Macro List
|
# Macro List
|
||||||
AdvSceneSwitcher.macroList.deleted="削除"
|
AdvSceneSwitcher.macroList.deleted="削除"
|
||||||
AdvSceneSwitcher.macroList.duplicate="\"%1\" はすでに選択されています!"
|
AdvSceneSwitcher.macroList.duplicate="\"%1\" はすでに選択されています!"
|
||||||
|
|
||||||
; Macro Logic
|
# Macro Logic
|
||||||
AdvSceneSwitcher.logic.none="入力無視"
|
AdvSceneSwitcher.logic.none="入力無視"
|
||||||
; AdvSceneSwitcher.logic.and="And"
|
; AdvSceneSwitcher.logic.and="And"
|
||||||
; AdvSceneSwitcher.logic.or="Or"
|
; AdvSceneSwitcher.logic.or="Or"
|
||||||
@@ -251,7 +253,8 @@ AdvSceneSwitcher.logic.none="入力無視"
|
|||||||
; AdvSceneSwitcher.logic.rootNone="If"
|
; AdvSceneSwitcher.logic.rootNone="If"
|
||||||
; AdvSceneSwitcher.logic.not="If not"
|
; AdvSceneSwitcher.logic.not="If not"
|
||||||
|
|
||||||
; Macro Conditions
|
# Macro Conditions
|
||||||
|
AdvSceneSwitcher.condition.unknown="不明な状態"
|
||||||
AdvSceneSwitcher.condition.audio="音声"
|
AdvSceneSwitcher.condition.audio="音声"
|
||||||
AdvSceneSwitcher.condition.audio.state.below="以下"
|
AdvSceneSwitcher.condition.audio.state.below="以下"
|
||||||
AdvSceneSwitcher.condition.audio.state.exact="同じ"
|
AdvSceneSwitcher.condition.audio.state.exact="同じ"
|
||||||
@@ -265,9 +268,9 @@ AdvSceneSwitcher.condition.audio.type.monitor="オーディオモニタリング
|
|||||||
AdvSceneSwitcher.condition.audio.type.balance="オーディオバランス"
|
AdvSceneSwitcher.condition.audio.type.balance="オーディオバランス"
|
||||||
AdvSceneSwitcher.condition.audio.entry="{{audioSources}}の{{checkType}}は{{condition}}{{volume}}{{volumeDB}}{{percentDBToggle}}{{syncOffset}}{{monitorTypes}}です"
|
AdvSceneSwitcher.condition.audio.entry="{{audioSources}}の{{checkType}}は{{condition}}{{volume}}{{volumeDB}}{{percentDBToggle}}{{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.type.click="をクリックした場合"
|
||||||
AdvSceneSwitcher.condition.cursor.button.left="マウスの左ボタン"
|
AdvSceneSwitcher.condition.cursor.button.left="マウスの左ボタン"
|
||||||
AdvSceneSwitcher.condition.cursor.button.middle="マウスの中ボタン"
|
AdvSceneSwitcher.condition.cursor.button.middle="マウスの中ボタン"
|
||||||
AdvSceneSwitcher.condition.cursor.button.right="マウスの右ボタン"
|
AdvSceneSwitcher.condition.cursor.button.right="マウスの右ボタン"
|
||||||
@@ -307,10 +310,13 @@ AdvSceneSwitcher.condition.file.local="ローカルファイル"
|
|||||||
; AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
; AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
; AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
; AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Media"
|
AdvSceneSwitcher.condition.media="Media"
|
||||||
|
AdvSceneSwitcher.condition.media.checkType.state="状態が一致する"
|
||||||
|
AdvSceneSwitcher.condition.media.checkType.time="時間制限にマッチ"
|
||||||
AdvSceneSwitcher.condition.media.source="ソース"
|
AdvSceneSwitcher.condition.media.source="ソース"
|
||||||
AdvSceneSwitcher.condition.media.anyOnScene="あらゆるメディアソース"
|
AdvSceneSwitcher.condition.media.anyOnScene="あらゆるメディアソース"
|
||||||
AdvSceneSwitcher.condition.media.allOnScene="すべてのメディアソースはこちら"
|
AdvSceneSwitcher.condition.media.allOnScene="すべてのメディアソースはこちら"
|
||||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="残念ながら、すべてのメディア ソース タイプが同じように動作するわけではありません (例: メディア ソースと VLC ビデオ ソースの \"Stopped\" 状態)。\nそのため、ご自身のセットアップに適したものを試してみてください。"
|
AdvSceneSwitcher.condition.media.inconsistencyInfo="残念ながら、すべてのメディア ソース タイプが同じように動作するわけではありません (例: メディア ソースと VLC ビデオ ソースの \"Stopped\" 状態)。\nそのため、ご自身のセットアップに適したものを試してみてください。"
|
||||||
|
; AdvSceneSwitcher.condition.media.layout="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}{{states}}{{timeRestrictions}}{{time}}"
|
||||||
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}の状態は{{states}}かつ{{timeRestrictions}}{{time}}"
|
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}の状態は{{states}}かつ{{timeRestrictions}}{{time}}"
|
||||||
AdvSceneSwitcher.condition.video="動画"
|
AdvSceneSwitcher.condition.video="動画"
|
||||||
AdvSceneSwitcher.condition.video.condition.match="完全一致"
|
AdvSceneSwitcher.condition.video.condition.match="完全一致"
|
||||||
@@ -463,7 +469,7 @@ AdvSceneSwitcher.condition.source.sizeCompare.less="より小さい"
|
|||||||
AdvSceneSwitcher.condition.source.sizeCompare.equal="等しい"
|
AdvSceneSwitcher.condition.source.sizeCompare.equal="等しい"
|
||||||
AdvSceneSwitcher.condition.source.sizeCompare.more="より大きい"
|
AdvSceneSwitcher.condition.source.sizeCompare.more="より大きい"
|
||||||
AdvSceneSwitcher.condition.source.refresh="更新"
|
AdvSceneSwitcher.condition.source.refresh="更新"
|
||||||
AdvSceneSwitcher.condition.source.refreshTooltip="名前が変数値と一致するソースの設定でソース設定の選択を再入力します。"
|
AdvSceneSwitcher.condition.source.refresh.tooltip="名前が変数値と一致するソースの設定でソース設定の選択を再入力します。"
|
||||||
AdvSceneSwitcher.condition.source.sceneVisibilityHint="シーン固有の可視性は \"Scene item visibility\" 条件で確認可能"
|
AdvSceneSwitcher.condition.source.sceneVisibilityHint="シーン固有の可視性は \"Scene item visibility\" 条件で確認可能"
|
||||||
AdvSceneSwitcher.condition.source.getSettings="現在の設定を取得する"
|
AdvSceneSwitcher.condition.source.getSettings="現在の設定を取得する"
|
||||||
; AdvSceneSwitcher.condition.source.entry.line1="{{sources}}{{conditions}}{{settingSelection}}{{refresh}}{{sizeCompareMethods}}{{size}}"
|
; AdvSceneSwitcher.condition.source.entry.line1="{{sources}}{{conditions}}{{settingSelection}}{{refresh}}{{sizeCompareMethods}}{{size}}"
|
||||||
@@ -481,7 +487,7 @@ AdvSceneSwitcher.condition.filter.type.settingsChanged="設定変更"
|
|||||||
AdvSceneSwitcher.condition.filter.type.individualSettingMatches="設定値が一致"
|
AdvSceneSwitcher.condition.filter.type.individualSettingMatches="設定値が一致"
|
||||||
AdvSceneSwitcher.condition.filter.type.individualSettingChanged="設定値が変更されました"
|
AdvSceneSwitcher.condition.filter.type.individualSettingChanged="設定値が変更されました"
|
||||||
AdvSceneSwitcher.condition.filter.refresh="更新"
|
AdvSceneSwitcher.condition.filter.refresh="更新"
|
||||||
AdvSceneSwitcher.condition.filter.refreshTooltip="変数値と一致する名前のフィルターの設定でフィルター設定の選択を再入力します。"
|
AdvSceneSwitcher.condition.filter.refresh.tooltip="変数値と一致する名前のフィルターの設定でフィルター設定の選択を再入力します。"
|
||||||
AdvSceneSwitcher.condition.filter.getSettings="現在の設定を取得する"
|
AdvSceneSwitcher.condition.filter.getSettings="現在の設定を取得する"
|
||||||
; AdvSceneSwitcher.condition.filter.entry.line1="On{{sources}}{{filters}}{{conditions}}{{settingSelection}}{{refresh}}"
|
; AdvSceneSwitcher.condition.filter.entry.line1="On{{sources}}{{filters}}{{conditions}}{{settingSelection}}{{refresh}}"
|
||||||
; AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
; AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
||||||
@@ -531,8 +537,17 @@ AdvSceneSwitcher.condition.date.entry.pattern="現在の日付「{{currentDate}}
|
|||||||
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}}繰り返しの場合、選択した日付を繰り返しの日付に更新します"
|
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}}繰り返しの場合、選択した日付を繰り返しの日付に更新します"
|
||||||
; AdvSceneSwitcher.condition.sceneTransform="Scene item transform"
|
; AdvSceneSwitcher.condition.sceneTransform="Scene item transform"
|
||||||
; AdvSceneSwitcher.condition.sceneTransform.getTransform="Get transform"
|
; AdvSceneSwitcher.condition.sceneTransform.getTransform="Get transform"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.getCurrentValue="現在の値を取得"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.settingsType.all="全て"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.settingsType.single="単一"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.condition.match="マッチトランスフォーム"
|
AdvSceneSwitcher.condition.sceneTransform.condition.match="マッチトランスフォーム"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.condition.changed="変わりました"
|
AdvSceneSwitcher.condition.sceneTransform.condition.changed="変わりました"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.compare.less="より小さい"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.compare.equal="等しい"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.compare.more="より大きい"
|
||||||
|
; AdvSceneSwitcher.condition.sceneTransform.entry="On{{scenes}}{{settingsType}}transform setting of{{sources}}{{conditions}}"
|
||||||
|
; AdvSceneSwitcher.condition.sceneTransform.entry.singleSettingCompare="{{setting}}{{compare}}{{singleSettingValue}}"
|
||||||
|
; AdvSceneSwitcher.condition.sceneTransform.entry.options="{{regex}}{{getSettings}}{{getCurrentValue}}"
|
||||||
; AdvSceneSwitcher.condition.transition="Transition"
|
; AdvSceneSwitcher.condition.transition="Transition"
|
||||||
; AdvSceneSwitcher.condition.transition.type.current="Current transition type is"
|
; AdvSceneSwitcher.condition.transition.type.current="Current transition type is"
|
||||||
AdvSceneSwitcher.condition.transition.type.duration="Current transition duration is"
|
AdvSceneSwitcher.condition.transition.type.duration="Current transition duration is"
|
||||||
@@ -616,7 +631,7 @@ AdvSceneSwitcher.condition.slideshow="スライドショー"
|
|||||||
AdvSceneSwitcher.condition.slideshow.condition.slideChanged="スライド変更しました"
|
AdvSceneSwitcher.condition.slideshow.condition.slideChanged="スライド変更しました"
|
||||||
AdvSceneSwitcher.condition.slideshow.condition.slideIndex="現在のスライド番号は"
|
AdvSceneSwitcher.condition.slideshow.condition.slideIndex="現在のスライド番号は"
|
||||||
AdvSceneSwitcher.condition.slideshow.condition.slidePath="現在のスライドパスは"
|
AdvSceneSwitcher.condition.slideshow.condition.slidePath="現在のスライドパスは"
|
||||||
AdvSceneSwitcher.condition.slideshow.updateIntervalTooltip="スライド ショーのステータスに関する情報は、設定されたスライド間の時間に基づいてのみ更新されます"
|
AdvSceneSwitcher.condition.slideshow.updateInterval.tooltip="スライド ショーのステータスに関する情報は、設定されたスライド間の時間に基づいてのみ更新されます"
|
||||||
; AdvSceneSwitcher.condition.slideshow.entry="{{sources}}{{conditions}}{{index}}{{path}}"
|
; AdvSceneSwitcher.condition.slideshow.entry="{{sources}}{{conditions}}{{index}}{{path}}"
|
||||||
; AdvSceneSwitcher.condition.twitch="Twitch"
|
; AdvSceneSwitcher.condition.twitch="Twitch"
|
||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online="配信がオンラインになりました"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online="配信がオンラインになりました"
|
||||||
@@ -669,6 +684,16 @@ AdvSceneSwitcher.condition.twitch.type.polling.channel.live="配信中です"
|
|||||||
AdvSceneSwitcher.condition.twitch.type.polling.channel.title="現在のタイトルマッチ"
|
AdvSceneSwitcher.condition.twitch.type.polling.channel.title="現在のタイトルマッチ"
|
||||||
AdvSceneSwitcher.condition.twitch.type.polling.channel.category="現在のカテゴリーは"
|
AdvSceneSwitcher.condition.twitch.type.polling.channel.category="現在のカテゴリーは"
|
||||||
AdvSceneSwitcher.condition.twitch.type.chat.message="チャットメッセージ受信済み"
|
AdvSceneSwitcher.condition.twitch.type.chat.message="チャットメッセージ受信済み"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties="チャットメッセージプロパティ:"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.select="チャットメッセージプロパティを選択します:"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.firstMessage="最初のメッセージ"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.emoteOnly="エモートのみ使用"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.mod="モデレータ"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.subscriber="サブスクライバー"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.turbo="ターボ・ユーザー"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.displayName="表示名が一致"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.loginName="ユーザー名が一致"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.chat.properties.badge="ユーザーがバッジを持っている"
|
||||||
AdvSceneSwitcher.condition.twitch.categorySelectionDisabled="Twitchアカウントを選択しないとカテゴリを選択できません!"
|
AdvSceneSwitcher.condition.twitch.categorySelectionDisabled="Twitchアカウントを選択しないとカテゴリを選択できません!"
|
||||||
AdvSceneSwitcher.condition.twitch.entry="チャンネル{{channel}}{{conditions}}{{pointsReward}}{{streamTitle}}{{regex}}{{category}}"
|
AdvSceneSwitcher.condition.twitch.entry="チャンネル{{channel}}{{conditions}}{{pointsReward}}{{streamTitle}}{{regex}}{{category}}"
|
||||||
AdvSceneSwitcher.condition.twitch.entry.account="アカウント{{account}}で確認してください"
|
AdvSceneSwitcher.condition.twitch.entry.account="アカウント{{account}}で確認してください"
|
||||||
@@ -682,7 +707,7 @@ AdvSceneSwitcher.condition.queue.entry.startStop="キュー{{queues}}は{{condit
|
|||||||
AdvSceneSwitcher.condition.queue.entry.size="キュー{{queues}}{{conditions}}は{{size}}未満です"
|
AdvSceneSwitcher.condition.queue.entry.size="キュー{{queues}}{{conditions}}は{{size}}未満です"
|
||||||
AdvSceneSwitcher.condition.clipboard="クリップボード"
|
AdvSceneSwitcher.condition.clipboard="クリップボード"
|
||||||
AdvSceneSwitcher.condition.clipboard.placeholder="クリップボードのテキスト"
|
AdvSceneSwitcher.condition.clipboard.placeholder="クリップボードのテキスト"
|
||||||
AdvSceneSwitcher.condition.clipboard.urlTooltip="OS によっては、ファイルが URL として表されることもあります"
|
AdvSceneSwitcher.condition.clipboard.url.tooltip="OS によっては、ファイルが URL として表されることもあります"
|
||||||
AdvSceneSwitcher.condition.clipboard.condition.changed="クリップボードの内容が変更されました"
|
AdvSceneSwitcher.condition.clipboard.condition.changed="クリップボードの内容が変更されました"
|
||||||
AdvSceneSwitcher.condition.clipboard.condition.isText="クリップボードにテキストが含まれています"
|
AdvSceneSwitcher.condition.clipboard.condition.isText="クリップボードにテキストが含まれています"
|
||||||
AdvSceneSwitcher.condition.clipboard.condition.isImage="クリップボードに画像が含まれています"
|
AdvSceneSwitcher.condition.clipboard.condition.isImage="クリップボードに画像が含まれています"
|
||||||
@@ -697,11 +722,22 @@ AdvSceneSwitcher.condition.folder.condition.fileChange="ファイルが変更さ
|
|||||||
AdvSceneSwitcher.condition.folder.condition.fileRemove="ファイルが削除されました"
|
AdvSceneSwitcher.condition.folder.condition.fileRemove="ファイルが削除されました"
|
||||||
AdvSceneSwitcher.condition.folder.condition.folderAdd="ディレクトリが追加されました"
|
AdvSceneSwitcher.condition.folder.condition.folderAdd="ディレクトリが追加されました"
|
||||||
AdvSceneSwitcher.condition.folder.condition.folderRemove="ディレクトリが削除されました"
|
AdvSceneSwitcher.condition.folder.condition.folderRemove="ディレクトリが削除されました"
|
||||||
; ; AdvSceneSwitcher.condition.folder.entry="{{conditions}}in{{folder}}{{tooltip}}"
|
; AdvSceneSwitcher.condition.folder.entry="{{conditions}}in{{folder}}{{tooltip}}"
|
||||||
AdvSceneSwitcher.condition.folder.enableFilter="変更パスがパターンに一致する場合にのみtrueと評価されます"
|
AdvSceneSwitcher.condition.folder.enableFilter="変更パスがパターンに一致する場合にのみtrueと評価されます"
|
||||||
; ; AdvSceneSwitcher.condition.folder.entry.filter="{{filter}}{{regex}}"
|
; AdvSceneSwitcher.condition.folder.entry.filter="{{filter}}{{regex}}"
|
||||||
|
; AdvSceneSwitcher.condition.usb="USB"
|
||||||
|
AdvSceneSwitcher.condition.usb.description="以下のプロパティに一致するUSBデバイスが接続されています:"
|
||||||
|
; AdvSceneSwitcher.condition.usb.vendorID="Vendor ID:"
|
||||||
|
; AdvSceneSwitcher.condition.usb.productID="Product ID:"
|
||||||
|
; AdvSceneSwitcher.condition.usb.busNumber="Bus Number:"
|
||||||
|
; AdvSceneSwitcher.condition.usb.deviceAddress="Device Address:"
|
||||||
|
; AdvSceneSwitcher.condition.usb.vendorName="Vendor Name:"
|
||||||
|
; AdvSceneSwitcher.condition.usb.productName="Product Name:"
|
||||||
|
; AdvSceneSwitcher.condition.usb.serialNumber="Serial Number:"
|
||||||
|
AdvSceneSwitcher.condition.noDevicesFoundWarning="USBデバイスが検出されません!\nプラグインがUSBデバイスをチェックするのに必要な権限を持っていない可能性があります。"
|
||||||
|
|
||||||
; Macro Actions
|
# Macro Actions
|
||||||
|
AdvSceneSwitcher.action.unknown="不明なアクション"
|
||||||
AdvSceneSwitcher.action.scene="シーン切り替え"
|
AdvSceneSwitcher.action.scene="シーン切り替え"
|
||||||
AdvSceneSwitcher.action.scene.type.program="プログラム"
|
AdvSceneSwitcher.action.scene.type.program="プログラム"
|
||||||
AdvSceneSwitcher.action.scene.type.preview="プレビュー"
|
AdvSceneSwitcher.action.scene.type.preview="プレビュー"
|
||||||
@@ -745,9 +781,11 @@ AdvSceneSwitcher.action.recording.split.hint="まずOBS設定で自動ファイ
|
|||||||
; AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
; AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
AdvSceneSwitcher.action.replay="リプレイバッファー"
|
AdvSceneSwitcher.action.replay="リプレイバッファー"
|
||||||
AdvSceneSwitcher.action.replay.saveWarn="警告: 頻繁に保存しすぎると、リプレイ バッファーが実際には保存されなくなる可能性があります。"
|
AdvSceneSwitcher.action.replay.saveWarn="警告: 頻繁に保存しすぎると、リプレイ バッファーが実際には保存されなくなる可能性があります。"
|
||||||
|
AdvSceneSwitcher.action.replay.durationWarn="警告: 最大再生時間を変更すると、次に再生バッファが起動したときにのみ適用されます!"
|
||||||
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="配信停止"
|
||||||
@@ -775,7 +813,7 @@ AdvSceneSwitcher.action.filter.type.toggle="切り替え"
|
|||||||
AdvSceneSwitcher.action.filter.type.settings="設定を行う"
|
AdvSceneSwitcher.action.filter.type.settings="設定を行う"
|
||||||
AdvSceneSwitcher.action.filter.type.pressSettingsButton="設定ボタンを押します"
|
AdvSceneSwitcher.action.filter.type.pressSettingsButton="設定ボタンを押します"
|
||||||
AdvSceneSwitcher.action.filter.refresh="更新"
|
AdvSceneSwitcher.action.filter.refresh="更新"
|
||||||
AdvSceneSwitcher.action.filter.refreshTooltip="変数値と一致する名前のフィルターの設定でフィルター設定の選択を再入力します。"
|
AdvSceneSwitcher.action.filter.refresh.tooltip="変数値と一致する名前のフィルターの設定でフィルター設定の選択を再入力します。"
|
||||||
; AdvSceneSwitcher.action.filter.entry="On{{sources}}{{actions}}{{filters}}{{refresh}}{{settingsButtons}}"
|
; AdvSceneSwitcher.action.filter.entry="On{{sources}}{{actions}}{{filters}}{{refresh}}{{settingsButtons}}"
|
||||||
; AdvSceneSwitcher.action.filter.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}"
|
; AdvSceneSwitcher.action.filter.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}"
|
||||||
AdvSceneSwitcher.action.filter.getSettings="現在の設定を取得する"
|
AdvSceneSwitcher.action.filter.getSettings="現在の設定を取得する"
|
||||||
@@ -813,7 +851,7 @@ AdvSceneSwitcher.action.source.inputMethod.individualManual="固定値に設定"
|
|||||||
AdvSceneSwitcher.action.source.inputMethod.individualTempvar="マクロプロパティに設定"
|
AdvSceneSwitcher.action.source.inputMethod.individualTempvar="マクロプロパティに設定"
|
||||||
AdvSceneSwitcher.action.source.inputMethod.json="設定用JSON文字列を設定します"
|
AdvSceneSwitcher.action.source.inputMethod.json="設定用JSON文字列を設定します"
|
||||||
AdvSceneSwitcher.action.source.refresh="更新"
|
AdvSceneSwitcher.action.source.refresh="更新"
|
||||||
AdvSceneSwitcher.action.source.refreshTooltip="名前が変数値と一致するソースの設定でソース設定の選択を再入力します。"
|
AdvSceneSwitcher.action.source.refresh.tooltip="名前が変数値と一致するソースの設定でソース設定の選択を再入力します。"
|
||||||
; AdvSceneSwitcher.action.media="Media"
|
; AdvSceneSwitcher.action.media="Media"
|
||||||
AdvSceneSwitcher.action.media.type.play="再生"
|
AdvSceneSwitcher.action.media.type.play="再生"
|
||||||
AdvSceneSwitcher.action.media.type.pause="一時停止"
|
AdvSceneSwitcher.action.media.type.pause="一時停止"
|
||||||
@@ -850,7 +888,7 @@ AdvSceneSwitcher.action.macro.type.toggleAction="トグルアクション"
|
|||||||
; AdvSceneSwitcher.action.macro.entry.run.condition="{{conditionBehaviors}}of{{conditionMacros}}"
|
; AdvSceneSwitcher.action.macro.entry.run.condition="{{conditionBehaviors}}of{{conditionMacros}}"
|
||||||
; AdvSceneSwitcher.action.macro.entry.other="{{actions}}{{actionIndex}}{{macros}}"
|
; AdvSceneSwitcher.action.macro.entry.other="{{actions}}{{actionIndex}}{{macros}}"
|
||||||
AdvSceneSwitcher.action.pluginState="プラグインの状態"
|
AdvSceneSwitcher.action.pluginState="プラグインの状態"
|
||||||
AdvSceneSwitcher.action.pluginState.type.stop="Advanced Scene Switcherプラグインの停止"
|
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="注意:設定ウィンドウを開いている間はアクションは無視されます。"
|
||||||
@@ -887,9 +925,10 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="下へ移動"
|
|||||||
AdvSceneSwitcher.action.sceneOrder.type.moveTop="トップへ移動"
|
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}}{{sources2}}{{position}}"
|
||||||
AdvSceneSwitcher.action.sceneTransform="シーンアイテムの変形"
|
AdvSceneSwitcher.action.sceneTransform="シーンアイテムの変形"
|
||||||
AdvSceneSwitcher.action.sceneTransform.type.manual="変形"
|
AdvSceneSwitcher.action.sceneTransform.type.manual="変形"
|
||||||
|
AdvSceneSwitcher.action.sceneTransform.type.setSingleSetting="トランスフォーム設定を行う"
|
||||||
AdvSceneSwitcher.action.sceneTransform.type.reset="変形をリセット"
|
AdvSceneSwitcher.action.sceneTransform.type.reset="変形をリセット"
|
||||||
AdvSceneSwitcher.action.sceneTransform.type.rotate="回転させます"
|
AdvSceneSwitcher.action.sceneTransform.type.rotate="回転させます"
|
||||||
AdvSceneSwitcher.action.sceneTransform.type.flipHorizontal="左右反転"
|
AdvSceneSwitcher.action.sceneTransform.type.flipHorizontal="左右反転"
|
||||||
@@ -900,6 +939,8 @@ AdvSceneSwitcher.action.sceneTransform.type.centerToScreen="画面中央から"
|
|||||||
AdvSceneSwitcher.action.sceneTransform.type.centerVertically="縦方向中央に配置"
|
AdvSceneSwitcher.action.sceneTransform.type.centerVertically="縦方向中央に配置"
|
||||||
AdvSceneSwitcher.action.sceneTransform.type.centerHorizontally="水平方向に中央揃え"
|
AdvSceneSwitcher.action.sceneTransform.type.centerHorizontally="水平方向に中央揃え"
|
||||||
AdvSceneSwitcher.action.sceneTransform.getTransform="変形を取得"
|
AdvSceneSwitcher.action.sceneTransform.getTransform="変形を取得"
|
||||||
|
AdvSceneSwitcher.action.sceneTransform.getCurrentValue="現在の値を取得"
|
||||||
|
; AdvSceneSwitcher.action.sceneTransform.entry="On{{scenes}}{{action}}{{rotation}}{{sources}}{{settingSelection}}{{singleSettingValue}}"
|
||||||
AdvSceneSwitcher.action.file="ファイル"
|
AdvSceneSwitcher.action.file="ファイル"
|
||||||
; AdvSceneSwitcher.action.file.type.write="Write"
|
; AdvSceneSwitcher.action.file.type.write="Write"
|
||||||
; AdvSceneSwitcher.action.file.type.append="Append"
|
; AdvSceneSwitcher.action.file.type.append="Append"
|
||||||
@@ -940,7 +981,7 @@ AdvSceneSwitcher.action.screenshot.save.custom="カスタム"
|
|||||||
AdvSceneSwitcher.action.screenshot.type.scene="シーン"
|
AdvSceneSwitcher.action.screenshot.type.scene="シーン"
|
||||||
AdvSceneSwitcher.action.screenshot.mainOutput="OBSの主な出力"
|
AdvSceneSwitcher.action.screenshot.mainOutput="OBSの主な出力"
|
||||||
AdvSceneSwitcher.action.screenshot.blackscreenNote="常にレンダリングされるわけではないソースやシーンにより、スクリーンショットの一部が空白のままになる場合があります。"
|
AdvSceneSwitcher.action.screenshot.blackscreenNote="常にレンダリングされるわけではないソースやシーンにより、スクリーンショットの一部が空白のままになる場合があります。"
|
||||||
AdvSceneSwitcher.action.screenshot.entry="スクリーンショット{{targetType}}{{sources}}{{scenes}}を作成し、{{saveType}}の場所に保存します"
|
AdvSceneSwitcher.action.screenshot.entry="スクリーンショット{{targetType}}{{sources}}{{scenes}}を作成し、{{saveType}}{{variables}}の場所に保存します"
|
||||||
AdvSceneSwitcher.action.profile="プロファイル"
|
AdvSceneSwitcher.action.profile="プロファイル"
|
||||||
AdvSceneSwitcher.action.profile.entry="アクティブなプロファイルを{{profiles}}に切り替えます"
|
AdvSceneSwitcher.action.profile.entry="アクティブなプロファイルを{{profiles}}に切り替えます"
|
||||||
; AdvSceneSwitcher.action.sceneCollection="Scene collection"
|
; AdvSceneSwitcher.action.sceneCollection="Scene collection"
|
||||||
@@ -1086,10 +1127,10 @@ AdvSceneSwitcher.action.log="ログ"
|
|||||||
AdvSceneSwitcher.action.log.placeholder="私のログメッセージ!"
|
AdvSceneSwitcher.action.log.placeholder="私のログメッセージ!"
|
||||||
AdvSceneSwitcher.action.log.entry="OBS ログに書き込む:{{logMessage}}"
|
AdvSceneSwitcher.action.log.entry="OBS ログに書き込む:{{logMessage}}"
|
||||||
|
|
||||||
; Hotkey
|
# Hotkey
|
||||||
AdvSceneSwitcher.hotkey.startSwitcherHotkey="アドバンストシーンスイッチャーの起動"
|
AdvSceneSwitcher.hotkey.startSwitcherHotkey="高機能シーンスイッチャーの起動"
|
||||||
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="アドバンストシーンスイッチャーの停止"
|
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="高機能シーンスイッチャーの停止"
|
||||||
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="アドバンストシーンスイッチャーの開始/停止切り替え"
|
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="高機能シーンスイッチャーの開始/停止切り替え"
|
||||||
AdvSceneSwitcher.hotkey.macro.pause="マクロ %1 を一時停止します"
|
AdvSceneSwitcher.hotkey.macro.pause="マクロ %1 を一時停止します"
|
||||||
AdvSceneSwitcher.hotkey.macro.unpause="マクロ %1 の一時停止を解除します"
|
AdvSceneSwitcher.hotkey.macro.unpause="マクロ %1 の一時停止を解除します"
|
||||||
AdvSceneSwitcher.hotkey.macro.togglePause="マクロ %1 の一時停止を切り替えます"
|
AdvSceneSwitcher.hotkey.macro.togglePause="マクロ %1 の一時停止を切り替えます"
|
||||||
@@ -1097,7 +1138,7 @@ AdvSceneSwitcher.hotkey.upMacroSegmentHotkey="マクロセグメント選択を
|
|||||||
AdvSceneSwitcher.hotkey.downMacroSegmentHotkey="マクロセグメント選択を下に移動"
|
AdvSceneSwitcher.hotkey.downMacroSegmentHotkey="マクロセグメント選択を下に移動"
|
||||||
AdvSceneSwitcher.hotkey.removeMacroSegmentHotkey="選択したマクロセグメントを削除"
|
AdvSceneSwitcher.hotkey.removeMacroSegmentHotkey="選択したマクロセグメントを削除"
|
||||||
|
|
||||||
AdvSceneSwitcher.askBackup="Advanced Scene Switcherの新しいバージョンが検出されました。\n古い設定のバックアップを作成する必要がありますか?"
|
AdvSceneSwitcher.askBackup="高機能シーンスイッチャーの新しいバージョンが検出されました。\n古い設定のバックアップを作成する必要がありますか?"
|
||||||
AdvSceneSwitcher.askForMacro="マクロ選択{{macroSelection}}"
|
AdvSceneSwitcher.askForMacro="マクロ選択{{macroSelection}}"
|
||||||
|
|
||||||
AdvSceneSwitcher.close="閉じる"
|
AdvSceneSwitcher.close="閉じる"
|
||||||
@@ -1113,6 +1154,11 @@ AdvSceneSwitcher.item.emptyName="空の名前は使用できません!"
|
|||||||
AdvSceneSwitcher.item.nameNotAvailable="名前がありません!"
|
AdvSceneSwitcher.item.nameNotAvailable="名前がありません!"
|
||||||
AdvSceneSwitcher.item.nameReserved="名前は使用済みです!"
|
AdvSceneSwitcher.item.nameReserved="名前は使用済みです!"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.listControls.add="追加"
|
||||||
|
AdvSceneSwitcher.listControls.remove="削除"
|
||||||
|
AdvSceneSwitcher.listControls.up="上へ"
|
||||||
|
AdvSceneSwitcher.listControls.down="下へ"
|
||||||
|
|
||||||
AdvSceneSwitcher.macroSegmentSelection.invalid="選択が無効です!"
|
AdvSceneSwitcher.macroSegmentSelection.invalid="選択が無効です!"
|
||||||
|
|
||||||
AdvSceneSwitcher.validation.text.maxLength="このフィールドには %1 文字のみを使用できます!"
|
AdvSceneSwitcher.validation.text.maxLength="このフィールドには %1 文字のみを使用できます!"
|
||||||
@@ -1436,7 +1482,7 @@ AdvSceneSwitcher.tempVar.twitch.status.prediction.description="チャネルポ
|
|||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.id.goal="目標ID"
|
AdvSceneSwitcher.tempVar.twitch.id.goal="目標ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.type.goal="ゴールタイプ"
|
AdvSceneSwitcher.tempVar.twitch.type.goal="ゴールタイプ"
|
||||||
AdvSceneSwitcher.tempVar.twitch.type.goal.description="ゴールの種類。可能な値は次のとおりです:\n follow — 目標はフォロワーを増やすことです。\n subscription — 目標はサブスクリプションを増やすことです。このタイプは、サブスクリプションに関連付けられたティアポイントの純増または減少を示します。\n subscription_count — 目標はサブスクリプションを増やすことです。このタイプは、サブスクリプション数の純増または減少を示します。\n new_subscription — 目標はサブスクリプションを増やすことです。このタイプは、サブスクリプションに関連付けられたティアポイントの純増のみを示します (目標開始後にサブスクリプションを解除したユーザーは考慮されません)。\n new_subscription_count — 目標はサブスクリプションを増やすことです。このタイプは、サブスクリプション数の純増のみを示します (目標開始後にサブスクリプションを解除したユーザーは考慮されません)。"
|
AdvSceneSwitcher.tempVar.twitch.type.goal.description="ゴールの種類。可能な値は次のとおりです:\n
|
||||||
AdvSceneSwitcher.tempVar.twitch.description.goal="目標説明"
|
AdvSceneSwitcher.tempVar.twitch.description.goal="目標説明"
|
||||||
AdvSceneSwitcher.tempVar.twitch.description.goal.description="指定されている場合、目標の説明。説明文は40文字以内です。"
|
AdvSceneSwitcher.tempVar.twitch.description.goal.description="指定されている場合、目標の説明。説明文は40文字以内です。"
|
||||||
AdvSceneSwitcher.tempVar.twitch.is_achieved.goal="目標達成"
|
AdvSceneSwitcher.tempVar.twitch.is_achieved.goal="目標達成"
|
||||||
@@ -1632,9 +1678,13 @@ AdvSceneSwitcher.tempVar.twitch.user_login.removeMod.description="削除され
|
|||||||
AdvSceneSwitcher.tempVar.twitch.user_name.removeMod="ユーザー名"
|
AdvSceneSwitcher.tempVar.twitch.user_name.removeMod="ユーザー名"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.removeMod.description="削除されたモデレーターの表示名"
|
AdvSceneSwitcher.tempVar.twitch.user_name.removeMod.description="削除されたモデレーターの表示名"
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.chatter="ユーザーログイン"
|
AdvSceneSwitcher.tempVar.twitch.user_login.chatReceive="ユーザーログイン"
|
||||||
AdvSceneSwitcher.tempVar.twitch.chatter.description="チャットメッセージを送信した人のユーザーログイン情報"
|
AdvSceneSwitcher.tempVar.twitch.user_login.chatReceive.description="チャットメッセージを送信した人のユーザーログイン情報"
|
||||||
AdvSceneSwitcher.tempVar.twitch.chat_message="チャットメッセージ"
|
AdvSceneSwitcher.tempVar.twitch.user_name.chatReceive="ユーザー名"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.user_name.chatReceive.description="チャットメッセージを送信した人の表示名です。"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.chat_message.chatReceive="チャットメッセージ"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.badges.chatReceive="チャットバッジ"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.badges.chatReceive.description="このユーザーが使用できるバッジとその状態を表す文字列。\n例: vip/1,subscriber/42,hype-train/1"
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid="RaidクリエイターユーザーID"
|
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid="RaidクリエイターユーザーID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid.description="レイドを作成した配信者ID"
|
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid.description="レイドを作成した配信者ID"
|
||||||
@@ -1760,6 +1810,24 @@ AdvSceneSwitcher.tempVar.source.settings="設定文字列"
|
|||||||
AdvSceneSwitcher.tempVar.filter.setting="設定値"
|
AdvSceneSwitcher.tempVar.filter.setting="設定値"
|
||||||
AdvSceneSwitcher.tempVar.filter.settings="設定文字列"
|
AdvSceneSwitcher.tempVar.filter.settings="設定文字列"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.slideShow.index="スライドインデックス"
|
||||||
|
AdvSceneSwitcher.tempVar.slideShow.index.description="現在表示されているスライドのインデックス。\nインデックスを決定できない場合、-1が返されます。"
|
||||||
|
AdvSceneSwitcher.tempVar.slideShow.path="スライドパス"
|
||||||
|
AdvSceneSwitcher.tempVar.slideShow.path.description="現在表示されているスライドのファイルシステムパス。"
|
||||||
|
AdvSceneSwitcher.tempVar.slideShow.fileName="スライドファイル名"
|
||||||
|
AdvSceneSwitcher.tempVar.slideShow.fileName.description="現在表示されているスライドのファイル名です。"
|
||||||
|
|
||||||
|
; AdvSceneSwitcher.tempVar.usb.vendorID="ベンダーID"
|
||||||
|
; AdvSceneSwitcher.tempVar.usb.productID="プロダクトID"
|
||||||
|
; AdvSceneSwitcher.tempVar.usb.busNumber="バス番号"
|
||||||
|
; AdvSceneSwitcher.tempVar.usb.deviceAddress="デバイスアドレス"
|
||||||
|
; AdvSceneSwitcher.tempVar.usb.vendorName="ベンダー名"
|
||||||
|
; AdvSceneSwitcher.tempVar.usb.productName="製品名"
|
||||||
|
; AdvSceneSwitcher.tempVar.usb.serialNumber="シリアル番号"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.transform.setting="設定値"
|
||||||
|
AdvSceneSwitcher.tempVar.transform.settings="設定文字列"
|
||||||
|
|
||||||
AdvSceneSwitcher.selectScene="--シーンを選択--"
|
AdvSceneSwitcher.selectScene="--シーンを選択--"
|
||||||
AdvSceneSwitcher.selectPreviousScene="前のシーン"
|
AdvSceneSwitcher.selectPreviousScene="前のシーン"
|
||||||
AdvSceneSwitcher.selectCurrentScene="現在のシーン"
|
AdvSceneSwitcher.selectCurrentScene="現在のシーン"
|
||||||
@@ -1804,6 +1872,20 @@ AdvSceneSwitcher.settings.suffix.type.frameRate="(フレーム レート)"
|
|||||||
AdvSceneSwitcher.settings.suffix.type.group="(グループ)"
|
AdvSceneSwitcher.settings.suffix.type.group="(グループ)"
|
||||||
AdvSceneSwitcher.settings.suffix.type.colorAlpha="(カラーアルファ)"
|
AdvSceneSwitcher.settings.suffix.type.colorAlpha="(カラーアルファ)"
|
||||||
; AdvSceneSwitcher.setting.select="--select setting--"
|
; AdvSceneSwitcher.setting.select="--select setting--"
|
||||||
|
AdvSceneSwitcher.setting.transform.alignment="位置合わせ"
|
||||||
|
AdvSceneSwitcher.setting.transform.cropBottom="[クロップ]下"
|
||||||
|
AdvSceneSwitcher.setting.transform.cropLeft="[クロップ]左"
|
||||||
|
AdvSceneSwitcher.setting.transform.cropRight="[クロップ]右"
|
||||||
|
AdvSceneSwitcher.setting.transform.cropTop="[クロップ]上"
|
||||||
|
AdvSceneSwitcher.setting.transform.boundingBoxType="バウンディングボックスの種類"
|
||||||
|
AdvSceneSwitcher.setting.transform.boundingBoxAlign="バウンディングボックス内の配置"
|
||||||
|
AdvSceneSwitcher.setting.transform.boundingBoxSize="バウンディングボックスのサイズ"
|
||||||
|
AdvSceneSwitcher.setting.transform.rotation="回転"
|
||||||
|
AdvSceneSwitcher.setting.transform.scale="拡大率"
|
||||||
|
AdvSceneSwitcher.setting.transform.size="サイズ"
|
||||||
|
AdvSceneSwitcher.setting.transform.position="位置"
|
||||||
|
AdvSceneSwitcher.setting.transform.height="高さ"
|
||||||
|
AdvSceneSwitcher.setting.transform.width="幅"
|
||||||
|
|
||||||
|
|
||||||
AdvSceneSwitcher.sceneItemSelection.configure="シーン項目選択タイプの設定"
|
AdvSceneSwitcher.sceneItemSelection.configure="シーン項目選択タイプの設定"
|
||||||
@@ -1813,8 +1895,8 @@ AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="変数名"
|
|||||||
; AdvSceneSwitcher.sceneItemSelection.type.sourceVariable.entry="{{nameConflictIndex}}{{variable}}"
|
; AdvSceneSwitcher.sceneItemSelection.type.sourceVariable.entry="{{nameConflictIndex}}{{variable}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="ソース名に一致するパターン"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="ソース名に一致するパターン"
|
||||||
; AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.entry="{{nameConflictIndex}}matching{{pattern}}{{regex}}"
|
; AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.entry="{{nameConflictIndex}}matching{{pattern}}{{regex}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup="ソースの種類"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType="ソースの種類"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup.entry="ソースタイプ{{nameConflictIndex}}{{sourceGroups}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType.entry="ソースタイプ{{nameConflictIndex}}{{sourceTypes}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index="ソースインデックス(上から順)"
|
AdvSceneSwitcher.sceneItemSelection.type.index="ソースインデックス(上から順)"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index.entry="ソース{{index}}"
|
AdvSceneSwitcher.sceneItemSelection.type.index.entry="ソース{{index}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.indexRange="複数のソースインデックス(上から順)"
|
AdvSceneSwitcher.sceneItemSelection.type.indexRange="複数のソースインデックス(上から順)"
|
||||||
@@ -1831,12 +1913,12 @@ AdvSceneSwitcher.status.inactive="停止中"
|
|||||||
AdvSceneSwitcher.running="プラグイン実行中"
|
AdvSceneSwitcher.running="プラグイン実行中"
|
||||||
AdvSceneSwitcher.stopped="プラグイン停止しました"
|
AdvSceneSwitcher.stopped="プラグイン停止しました"
|
||||||
|
|
||||||
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Advanced Scene Switcherが初めて起動したようです。<br>ガイドと例のリストについては <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> をご覧ください。<br>質問は <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">OBSフォーラムのプラグインのスレッド</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>質問は <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">OBSフォーラムのプラグインのスレッド</span></a> で遠慮なくどうぞ!</p></body></html>"
|
||||||
|
|
||||||
AdvSceneSwitcher.deprecatedTabWarning="このタブの開発は停止しました!\n代わりにマクロの使用に移行することを検討してください。\nこのヒントは [全般] タブで無効にすることができます。"
|
AdvSceneSwitcher.deprecatedTabWarning="このタブの開発は停止しました!\n代わりにマクロの使用に移行することを検討してください。\nこのヒントは [全般] タブで無効にすることができます。"
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="ミリ秒"
|
AdvSceneSwitcher.unit.milliseconds="ミリ秒"
|
||||||
AdvSceneSwitcher.unit.secends="秒"
|
AdvSceneSwitcher.unit.seconds="秒"
|
||||||
AdvSceneSwitcher.unit.minutes="分"
|
AdvSceneSwitcher.unit.minutes="分"
|
||||||
AdvSceneSwitcher.unit.hours="時間"
|
AdvSceneSwitcher.unit.hours="時間"
|
||||||
AdvSceneSwitcher.duration.condition.none="期間修飾子なし"
|
AdvSceneSwitcher.duration.condition.none="期間修飾子なし"
|
||||||
@@ -1851,8 +1933,46 @@ AdvSceneSwitcher.audio.monitor.both="モニターと出力"
|
|||||||
|
|
||||||
AdvSceneSwitcher.noSettingsButtons="ボタンが見つかりません!"
|
AdvSceneSwitcher.noSettingsButtons="ボタンが見つかりません!"
|
||||||
|
|
||||||
; Legacy tabs below - please don't waste your time adding translations for these :)以下の従来のタブ - これらの翻訳の追加に時間を無駄にしないでください。
|
AdvSceneSwitcher.clearBufferOnMatch="マッチするメッセージが見つかったらメッセージバッファをクリアする"
|
||||||
; Transition Tab
|
|
||||||
|
AdvSceneSwitcher.script.settings="設定"
|
||||||
|
AdvSceneSwitcher.script.timeout="スクリプトタイムアウト:{{timeout}}"
|
||||||
|
|
||||||
|
# This secion is copied from the OBS locale files
|
||||||
|
|
||||||
|
# commonly shared locale
|
||||||
|
Browse="ブラウズ"
|
||||||
|
Show="表示"
|
||||||
|
Hide="隠す"
|
||||||
|
|
||||||
|
|
||||||
|
# properties window
|
||||||
|
; Basic.PropertiesWindow="Properties for '%1'"
|
||||||
|
Basic.PropertiesWindow.AutoSelectFormat="%1 (自動選択: %2)"
|
||||||
|
Basic.PropertiesWindow.SelectColor="色を選択"
|
||||||
|
Basic.PropertiesWindow.SelectFont="フォントを選択"
|
||||||
|
Basic.PropertiesWindow.SelectFont.WindowTitle="フォントを選ぶ"
|
||||||
|
Basic.PropertiesWindow.ConfirmTitle="変更された設定"
|
||||||
|
Basic.PropertiesWindow.Confirm="未保存の変更があります。保存しますか?"
|
||||||
|
Basic.PropertiesWindow.NoProperties="プロパティがありません"
|
||||||
|
Basic.PropertiesWindow.AddFiles="ファイルを追加"
|
||||||
|
Basic.PropertiesWindow.AddDir="ディレクトリを追加"
|
||||||
|
Basic.PropertiesWindow.AddURL="パス/URL を追加"
|
||||||
|
Basic.PropertiesWindow.AddEditableListDir="ディレクトリを以下に追加 '%1'"
|
||||||
|
Basic.PropertiesWindow.AddEditableListFiles="ファイルを以下に '%1'"
|
||||||
|
Basic.PropertiesWindow.AddEditableListEntry="エントリを以下に '%1'"
|
||||||
|
Basic.PropertiesWindow.EditEditableListEntry="エントリを以下に '%1'"
|
||||||
|
|
||||||
|
# properties view
|
||||||
|
; Basic.PropertiesView.FPS.Simple="Simple FPS Values"
|
||||||
|
; Basic.PropertiesView.FPS.Rational="Rational FPS Values"
|
||||||
|
; Basic.PropertiesView.FPS.ValidFPSRanges="Valid FPS Ranges:"
|
||||||
|
Basic.PropertiesView.UrlButton.Text="このリンクをデフォルトウェブブラウザで開きますか?"
|
||||||
|
Basic.PropertiesView.UrlButton.Text.Url="URL: %1"
|
||||||
|
Basic.PropertiesView.UrlButton.OpenUrl="URLを開く
|
||||||
|
|
||||||
|
# Legacy tabs below - please don't waste your time adding translations for these :)以下は従来のタブ - これらの翻訳の追加に時間を無駄にしないでください。
|
||||||
|
# Transition Tab
|
||||||
AdvSceneSwitcher.transitionTab.title="トランジションの変更"
|
AdvSceneSwitcher.transitionTab.title="トランジションの変更"
|
||||||
AdvSceneSwitcher.transitionTab.transitionForAToB="シーンAからシーンBへの自動シーン切り替えにはトランジションを使用します"
|
AdvSceneSwitcher.transitionTab.transitionForAToB="シーンAからシーンBへの自動シーン切り替えにはトランジションを使用します"
|
||||||
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body><p>これらの設定は、シーン・スイッチャーによって引き起こされるトランジションに<span style=\"font-style:italic;\">のみ</span>影響します - マニュアルのシーン変更のために設定したい場合は、<a href=\"https://obsproject.com/forum/resources/transition-table.1174/\"><span style=\" text-decoration: underline; color:#268bd2;\">Transition Table</span></a>をチェックしてください。<br/>ここで定義された設定は、シーン・スイッチャーの他の場所で設定されたトランジション設定よりも優先されます。<br/><br/>新しいエントリーを追加するには、下のプラスマークをクリックしてください。</p></body></html>"
|
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body><p>これらの設定は、シーン・スイッチャーによって引き起こされるトランジションに<span style=\"font-style:italic;\">のみ</span>影響します - マニュアルのシーン変更のために設定したい場合は、<a href=\"https://obsproject.com/forum/resources/transition-table.1174/\"><span style=\" text-decoration: underline; color:#268bd2;\">Transition Table</span></a>をチェックしてください。<br/>ここで定義された設定は、シーン・スイッチャーの他の場所で設定されたトランジション設定よりも優先されます。<br/><br/>新しいエントリーを追加するには、下のプラスマークをクリックしてください。</p></body></html>"
|
||||||
@@ -1863,7 +1983,7 @@ AdvSceneSwitcher.transitionTab.defaultTransitionsHelp="プラス記号をクリ
|
|||||||
AdvSceneSwitcher.transitionTab.defaultTransition.delay="シーン切り替え後のトランジション{{defTransitionDelay}}を切り替えます。"
|
AdvSceneSwitcher.transitionTab.defaultTransition.delay="シーン切り替え後のトランジション{{defTransitionDelay}}を切り替えます。"
|
||||||
AdvSceneSwitcher.transitionTab.defaultTransition.delay.help="遅延は、トランジションの進行中にトランジション タイプが変更された場合に発生する可能性がある、キャンセルされたシーンの切り替えを回避するために使用されます。"
|
AdvSceneSwitcher.transitionTab.defaultTransition.delay.help="遅延は、トランジションの進行中にトランジション タイプが変更された場合に発生する可能性がある、キャンセルされたシーンの切り替えを回避するために使用されます。"
|
||||||
|
|
||||||
; Pause Scenes Tab
|
# Pause Scenes Tab
|
||||||
AdvSceneSwitcher.pauseTab.title="ポーズ"
|
AdvSceneSwitcher.pauseTab.title="ポーズ"
|
||||||
AdvSceneSwitcher.pauseTab.pauseOnScene="シーンスイッチャーをシーン上で一時停止する"
|
AdvSceneSwitcher.pauseTab.pauseOnScene="シーンスイッチャーをシーン上で一時停止する"
|
||||||
AdvSceneSwitcher.pauseTab.pauseInFocus1="シーンスイッチャーを一時停止する場合"
|
AdvSceneSwitcher.pauseTab.pauseInFocus1="シーンスイッチャーを一時停止する場合"
|
||||||
@@ -1874,11 +1994,11 @@ AdvSceneSwitcher.pauseTab.pauseTargetAll="すべて"
|
|||||||
AdvSceneSwitcher.pauseTab.pauseEntry="一時停止{{pauseTargets}}がチェックするタイミング{{pauseTypes}}{{scenes}}{{windows}}"
|
AdvSceneSwitcher.pauseTab.pauseEntry="一時停止{{pauseTargets}}がチェックするタイミング{{pauseTypes}}{{scenes}}{{windows}}"
|
||||||
AdvSceneSwitcher.pauseTab.help="このタブでは、シーンがアクティブであるかウィンドウにフォーカスがある場合に、個々の切り替え方法を一時停止するように設定できます。\n\n続行するには、強調表示されたプラス記号をクリックしてください。"
|
AdvSceneSwitcher.pauseTab.help="このタブでは、シーンがアクティブであるかウィンドウにフォーカスがある場合に、個々の切り替え方法を一時停止するように設定できます。\n\n続行するには、強調表示されたプラス記号をクリックしてください。"
|
||||||
|
|
||||||
; Window Title Tab
|
# Window Title Tab
|
||||||
AdvSceneSwitcher.windowTitleTab.title="ウィンドウタイトル"
|
AdvSceneSwitcher.windowTitleTab.title="ウィンドウタイトル"
|
||||||
AdvSceneSwitcher.windowTitleTab.regexrDescription="<html><head/><body><p>ウィンドウタイトルを直接入力するか、有効な正規表現を入力します。<a href=\"https://regexr.com\"><span style=\" text-decoration: underline; color:#268bd2;\">RegExr</span></a>を使って正規表現の構文とマッチをチェックすることができます。</p></body></html>"
|
AdvSceneSwitcher.windowTitleTab.regexrDescription="<html><head/><body><p>ウィンドウタイトルを直接入力するか、有効な正規表現を入力します。<a href=\"https://regexr.com\"><span style=\" text-decoration: underline; color:#268bd2;\">RegExr</span></a>を使って正規表現の構文とマッチをチェックすることができます。</p></body></html>"
|
||||||
AdvSceneSwitcher.windowTitleTab.stayInFocus1="このウィンドウ名は無視してください"
|
AdvSceneSwitcher.windowTitleTab.stayInFocus1="このウィンドウ名は無視してください"
|
||||||
AdvSceneSwitcher.windowTitleTab.stayInFocus2=""
|
AdvSceneSwitcher.windowTitleTab.stayInFocus2=" "
|
||||||
AdvSceneSwitcher.windowTitleTab.fullscreen="フルスクリーン時にシーン転換"
|
AdvSceneSwitcher.windowTitleTab.fullscreen="フルスクリーン時にシーン転換"
|
||||||
AdvSceneSwitcher.windowTitleTab.maximized="ウィンドウを最大化するとシーン転換"
|
AdvSceneSwitcher.windowTitleTab.maximized="ウィンドウを最大化するとシーン転換"
|
||||||
AdvSceneSwitcher.windowTitleTab.focused="ウィンドウにフォーカスするとシーン転換"
|
AdvSceneSwitcher.windowTitleTab.focused="ウィンドウにフォーカスするとシーン転換"
|
||||||
@@ -1886,14 +2006,14 @@ AdvSceneSwitcher.windowTitleTab.focused="ウィンドウにフォーカスする
|
|||||||
AdvSceneSwitcher.windowTitleTab.windowsHelp="実行中のアプリケーションのウィンドウタイトルに基づいてシーンを切り替えます。\n次の追加条件を選択できます。\nウィンドウがフルスクリーンである\nウィンドウが最大化されている\nウィンドウがフォーカスされている\n\n強調表示されたプラス記号をクリックして続行します。"
|
AdvSceneSwitcher.windowTitleTab.windowsHelp="実行中のアプリケーションのウィンドウタイトルに基づいてシーンを切り替えます。\n次の追加条件を選択できます。\nウィンドウがフルスクリーンである\nウィンドウが最大化されている\nウィンドウがフォーカスされている\n\n強調表示されたプラス記号をクリックして続行します。"
|
||||||
AdvSceneSwitcher.windowTitleTab.ignoreWindowsHelp="ウィンドウ タイトルが無視された場合、シーン スイッチャーは、以前に選択したウィンドウにまだフォーカスがあるかのように動作します。\n これにより、別のウィンドウに頻繁に切り替える場合に、シーンの切り替えを回避できます。これにより、シーンがトリガーされなくなります。変更します。\n\nウィンドウを選択するか、上にウィンドウのタイトルを入力し、下のプラス記号をクリックしてリストに追加します。"
|
AdvSceneSwitcher.windowTitleTab.ignoreWindowsHelp="ウィンドウ タイトルが無視された場合、シーン スイッチャーは、以前に選択したウィンドウにまだフォーカスがあるかのように動作します。\n これにより、別のウィンドウに頻繁に切り替える場合に、シーンの切り替えを回避できます。これにより、シーンがトリガーされなくなります。変更します。\n\nウィンドウを選択するか、上にウィンドウのタイトルを入力し、下のプラス記号をクリックしてリストに追加します。"
|
||||||
|
|
||||||
; Executable Tab
|
# Executable Tab
|
||||||
AdvSceneSwitcher.executableTab.title="実行中のプログラム"
|
AdvSceneSwitcher.executableTab.title="実行中のプログラム"
|
||||||
AdvSceneSwitcher.executableTab.implemented="dasOvenによる実装"
|
AdvSceneSwitcher.executableTab.implemented="dasOvenによる実装"
|
||||||
AdvSceneSwitcher.executableTab.requiresFocus="集中している場合のみ"
|
AdvSceneSwitcher.executableTab.requiresFocus="集中している場合のみ"
|
||||||
AdvSceneSwitcher.executableTab.entry="{{processes}}が実行中の場合は、{{transitions}}{{requiresFocus}}を使用した{{scenes}}に切り替えます"
|
AdvSceneSwitcher.executableTab.entry="{{processes}}が実行中の場合は、{{transitions}}{{requiresFocus}}を使用した{{scenes}}に切り替えます"
|
||||||
AdvSceneSwitcher.executableTab.help="このタブを使用すると、プロセスが実行中の場合にシーンを自動的に切り替えることができます。\nこれは、ウィンドウ名が変更される可能性がある場合やウィンドウ名が不明な場合に役立ちます。\n\n続行するには、強調表示されたプラス記号をクリックしてください。 ."
|
AdvSceneSwitcher.executableTab.help="このタブを使用すると、プロセスが実行中の場合にシーンを自動的に切り替えることができます。\nこれは、ウィンドウ名が変更される可能性がある場合やウィンドウ名が不明な場合に役立ちます。\n\n続行するには、強調表示されたプラス記号をクリックしてください。 ."
|
||||||
|
|
||||||
; Screen Region Tab
|
# Screen Region Tab
|
||||||
AdvSceneSwitcher.screenRegionTab.title="マウスカーソルの位置"
|
AdvSceneSwitcher.screenRegionTab.title="マウスカーソルの位置"
|
||||||
AdvSceneSwitcher.screenRegionTab.currentPosition="カーソルの現在位置:"
|
AdvSceneSwitcher.screenRegionTab.currentPosition="カーソルの現在位置:"
|
||||||
AdvSceneSwitcher.screenRegionTab.showGuideFrames="ガイド枠を表示する"
|
AdvSceneSwitcher.screenRegionTab.showGuideFrames="ガイド枠を表示する"
|
||||||
@@ -1902,7 +2022,7 @@ AdvSceneSwitcher.screenRegionTab.excludeScenes.None="選択なし"
|
|||||||
AdvSceneSwitcher.screenRegionTab.entry="カーソルが{{minX}}{{minY}}x{{maxX}}{{maxY}}にある場合、{{excludeScenes}}でない限り、{{transitions}}を使用して{{scenes}}に切り替えます"
|
AdvSceneSwitcher.screenRegionTab.entry="カーソルが{{minX}}{{minY}}x{{maxX}}{{maxY}}にある場合、{{excludeScenes}}でない限り、{{transitions}}を使用して{{scenes}}に切り替えます"
|
||||||
AdvSceneSwitcher.screenRegionTab.help="このタブでは、マウス カーソルの現在位置に基づいてシーンを自動的に切り替えることができます。\n\n次に進むには、強調表示されたプラス記号をクリックしてください。"
|
AdvSceneSwitcher.screenRegionTab.help="このタブでは、マウス カーソルの現在位置に基づいてシーンを自動的に切り替えることができます。\n\n次に進むには、強調表示されたプラス記号をクリックしてください。"
|
||||||
|
|
||||||
; Media Tab
|
# Media Tab
|
||||||
AdvSceneSwitcher.mediaTab.title="メディア"
|
AdvSceneSwitcher.mediaTab.title="メディア"
|
||||||
; AdvSceneSwitcher.mediaTab.implemented="Implemented by Exeldro"
|
; AdvSceneSwitcher.mediaTab.implemented="Implemented by Exeldro"
|
||||||
AdvSceneSwitcher.mediaTab.states.none="なし"
|
AdvSceneSwitcher.mediaTab.states.none="なし"
|
||||||
@@ -1923,7 +2043,7 @@ AdvSceneSwitcher.mediaTab.timeRestriction.remainLonger="残り時間が長くな
|
|||||||
AdvSceneSwitcher.mediaTab.entry="{{mediaSources}}の状態が{{states}}で、{{timeRestrictions}}{{time}}が{{transitions}}を使用して{{scenes}}に切り替わるとき"
|
AdvSceneSwitcher.mediaTab.entry="{{mediaSources}}の状態が{{states}}で、{{timeRestrictions}}{{time}}が{{transitions}}を使用して{{scenes}}に切り替わるとき"
|
||||||
AdvSceneSwitcher.mediaTab.help="このタブでは、メディア ソースの状態に基づいてシーンを切り替えることができます。\nたとえば、選択したメディア ソースの再生が終了すると、自動的に前のシーンに切り替えることができます。\n\n続行するにはプラス記号を強調表示します。"
|
AdvSceneSwitcher.mediaTab.help="このタブでは、メディア ソースの状態に基づいてシーンを切り替えることができます。\nたとえば、選択したメディア ソースの再生が終了すると、自動的に前のシーンに切り替えることができます。\n\n続行するにはプラス記号を強調表示します。"
|
||||||
|
|
||||||
; File Tab
|
# File Tab
|
||||||
AdvSceneSwitcher.fileTab.title="ファイルの内容"
|
AdvSceneSwitcher.fileTab.title="ファイルの内容"
|
||||||
AdvSceneSwitcher.fileTab.readWriteSceneFile="シーンをファイルから読み書きする/ファイルに書き込む"
|
AdvSceneSwitcher.fileTab.readWriteSceneFile="シーンをファイルから読み書きする/ファイルに書き込む"
|
||||||
AdvSceneSwitcher.fileTab.currentSceneOutputFile="現在のシーンの名前をこのファイルに書き込みます:"
|
AdvSceneSwitcher.fileTab.currentSceneOutputFile="現在のシーンの名前をこのファイルに書き込みます:"
|
||||||
@@ -1948,13 +2068,13 @@ AdvSceneSwitcher.fileTab.entry="{{fileType}}{{filePath}}{{browseButton}}の内
|
|||||||
; AdvSceneSwitcher.fileTab.entry3="{{useRegex}}{{checkModificationDate}}{{checkFileContent}}"
|
; AdvSceneSwitcher.fileTab.entry3="{{useRegex}}{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.fileTab.help="このタブでは、リモートまたはローカル ファイルの内容に基づいてシーンを自動的に切り替えることができます。\n\n続行するには、強調表示されたプラス記号をクリックしてください。"
|
AdvSceneSwitcher.fileTab.help="このタブでは、リモートまたはローカル ファイルの内容に基づいてシーンを自動的に切り替えることができます。\n\n続行するには、強調表示されたプラス記号をクリックしてください。"
|
||||||
|
|
||||||
; Random Tab
|
# Random Tab
|
||||||
AdvSceneSwitcher.randomTab.title="ランダム"
|
AdvSceneSwitcher.randomTab.title="ランダム"
|
||||||
AdvSceneSwitcher.randomTab.randomDisabledWarning="機能無効 - 有効にするには、全般タブの「切り替え条件が満たされない場合はランダムタブの任意のシーンに切り替える」を選択してください"
|
AdvSceneSwitcher.randomTab.randomDisabledWarning="機能無効 - 有効にするには、全般タブの「切り替え条件が満たされない場合はランダムタブの任意のシーンに切り替える」を選択してください"
|
||||||
AdvSceneSwitcher.randomTab.entry="切り替え条件が満たされない場合は、{{delay}}の間、{{transitions}}を使用して{{scenes}}に切り替えます"
|
AdvSceneSwitcher.randomTab.entry="切り替え条件が満たされない場合は、{{delay}}の間、{{transitions}}を使用して{{scenes}}に切り替えます"
|
||||||
AdvSceneSwitcher.randomTab.help="シーン スイッチャーは、設定された時間の間、このタブ上のエントリをランダムに選択して切り替えます。\n同じエントリが連続して 2 回選択されることはないことに注意してください。\n\n強調表示されたプラス記号をクリックすると、続けます。"
|
AdvSceneSwitcher.randomTab.help="シーン スイッチャーは、設定された時間の間、このタブ上のエントリをランダムに選択して切り替えます。\n同じエントリが連続して 2 回選択されることはないことに注意してください。\n\n強調表示されたプラス記号をクリックすると、続けます。"
|
||||||
|
|
||||||
; Time Tab
|
# Time Tab
|
||||||
AdvSceneSwitcher.timeTab.title="時間指定"
|
AdvSceneSwitcher.timeTab.title="時間指定"
|
||||||
AdvSceneSwitcher.timeTab.anyDay="いつでも"
|
AdvSceneSwitcher.timeTab.anyDay="いつでも"
|
||||||
AdvSceneSwitcher.timeTab.mondays="月曜日"
|
AdvSceneSwitcher.timeTab.mondays="月曜日"
|
||||||
@@ -1969,22 +2089,22 @@ AdvSceneSwitcher.timeTab.afterstart.tip="配信/録画開始からの相対時
|
|||||||
AdvSceneSwitcher.timeTab.entry="{{triggers}}時{{time}}で{{transitions}}を使用して{{scenes}}に切り替えます"
|
AdvSceneSwitcher.timeTab.entry="{{triggers}}時{{time}}で{{transitions}}を使用して{{scenes}}に切り替えます"
|
||||||
AdvSceneSwitcher.timeTab.help="このタブを使用すると、現在の現地時間に基づいて別のシーンに自動的に切り替えることができます。\n\nシーン スイッチャーは、指定した正確な時刻にのみシーンを切り替えることに注意してください。\n設定が完了していることを確認してください。他の切り替え方法が優先されて選択した時点が失われることがないように、[全般] タブの優先順位を好みに合わせて設定します。\n\n強調表示されたプラス記号をクリックして続行します。"
|
AdvSceneSwitcher.timeTab.help="このタブを使用すると、現在の現地時間に基づいて別のシーンに自動的に切り替えることができます。\n\nシーン スイッチャーは、指定した正確な時刻にのみシーンを切り替えることに注意してください。\n設定が完了していることを確認してください。他の切り替え方法が優先されて選択した時点が失われることがないように、[全般] タブの優先順位を好みに合わせて設定します。\n\n強調表示されたプラス記号をクリックして続行します。"
|
||||||
|
|
||||||
; Idle Tab
|
# Idle Tab
|
||||||
AdvSceneSwitcher.idleTab.title="アイドル"
|
AdvSceneSwitcher.idleTab.title="アイドル"
|
||||||
AdvSceneSwitcher.idleTab.enable="アイドル検知を有効にする"
|
AdvSceneSwitcher.idleTab.enable="アイドル検知を有効にする"
|
||||||
AdvSceneSwitcher.idleTab.idleswitch="キーボードやマウスの入力がない状態が{{duration}}続いた後、{{transitions}}を使用してシーン{{scenes}}に切り替わります"
|
AdvSceneSwitcher.idleTab.idleswitch="キーボードやマウスの入力がない状態が{{duration}}続いた後、{{transitions}}を使用してシーン{{scenes}}に切り替わります"
|
||||||
AdvSceneSwitcher.idleTab.dontSwitchIfFocus1="次の場合は切り替えないでください"
|
AdvSceneSwitcher.idleTab.dontSwitchIfFocus1="次の場合は切り替えないでください"
|
||||||
AdvSceneSwitcher.idleTab.dontSwitchIfFocus2="ピントが合っています"
|
AdvSceneSwitcher.idleTab.dontSwitchIfFocus2="ピントが合っています"
|
||||||
|
|
||||||
; Scene Sequence Tab
|
# Scene Sequence Tab
|
||||||
AdvSceneSwitcher.sceneSequenceTab.title="シーケンス"
|
AdvSceneSwitcher.sceneSequenceTab.title="シーケンス"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.description="一連の自動シーン切り替えは、シーンスイッチャーの一時停止/停止、または手動で別のシーンに切り替えることでキャンセルできます"
|
AdvSceneSwitcher.sceneSequenceTab.description="一連の自動シーン切り替えは、シーンスイッチャーの一時停止/停止、または手動で別のシーンに切り替えることでキャンセルできます"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.save="シーンシーケンスをファイルに保存"
|
AdvSceneSwitcher.sceneSequenceTab.save="シーンシーケンスをファイルに保存"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.load="ファイルからシーンシーケンスをロード"
|
AdvSceneSwitcher.sceneSequenceTab.load="ファイルからシーンシーケンスをロード"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.saveTitle="シーンシーケンスをファイルに保存…"
|
AdvSceneSwitcher.sceneSequenceTab.saveTitle="シーンシーケンスをファイルに保存…"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.loadTitle="シーンシーケンスを読み込むファイルを選択してください…"
|
AdvSceneSwitcher.sceneSequenceTab.loadTitle="シーンシーケンスを読み込むファイルを選択してください…"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.loadFail="Advanced Scene Switcherで設定のインポートに失敗しました!"
|
AdvSceneSwitcher.sceneSequenceTab.loadFail="高機能シーンスイッチャーの設定インポートに失敗しました!"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="Scene Switcherの高度な設定がインポートされました!"
|
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="高機能シーンスイッチャーの設定がインポートされました!"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.fileType="テキストファイル(*.txt)"
|
AdvSceneSwitcher.sceneSequenceTab.fileType="テキストファイル(*.txt)"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.interruptible="中断可能"
|
AdvSceneSwitcher.sceneSequenceTab.interruptible="中断可能"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="このシーンシーケンスを中断する他の切り替え方法が許可されます"
|
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="このシーンシーケンスを中断する他の切り替え方法が許可されます"
|
||||||
@@ -1993,7 +2113,7 @@ AdvSceneSwitcher.sceneSequenceTab.extendEdit="拡張シーケンス"
|
|||||||
AdvSceneSwitcher.sceneSequenceTab.extendEntry="{{delay}}後、{{transitions}}を使用して{{scenes}}に切り替えてください"
|
AdvSceneSwitcher.sceneSequenceTab.extendEntry="{{delay}}後、{{transitions}}を使用して{{scenes}}に切り替えてください"
|
||||||
AdvSceneSwitcher.sceneSequenceTab.help="このタブを使用すると、シーンが設定された期間アクティブだった場合に、別のシーンに自動的に切り替えることができます。\nたとえば、2 つのシーンを自動的に行き来できます。\n\nクリック強調表示されたプラス記号をクリックして続行します。"
|
AdvSceneSwitcher.sceneSequenceTab.help="このタブを使用すると、シーンが設定された期間アクティブだった場合に、別のシーンに自動的に切り替えることができます。\nたとえば、2 つのシーンを自動的に行き来できます。\n\nクリック強調表示されたプラス記号をクリックして続行します。"
|
||||||
|
|
||||||
; Audio Tab
|
# Audio Tab
|
||||||
AdvSceneSwitcher.audioTab.title="音声"
|
AdvSceneSwitcher.audioTab.title="音声"
|
||||||
AdvSceneSwitcher.audioTab.condition.above="以上"
|
AdvSceneSwitcher.audioTab.condition.above="以上"
|
||||||
AdvSceneSwitcher.audioTab.condition.below="以下"
|
AdvSceneSwitcher.audioTab.condition.below="以下"
|
||||||
@@ -2003,7 +2123,7 @@ AdvSceneSwitcher.audioTab.multiMatchfallbackCondition="複数のエントリが
|
|||||||
AdvSceneSwitcher.audioTab.multiMatchfallback="...{{duration}}秒間、{{transitions}}を使用して{{scenes}}に切り替えます"
|
AdvSceneSwitcher.audioTab.multiMatchfallback="...{{duration}}秒間、{{transitions}}を使用して{{scenes}}に切り替えます"
|
||||||
AdvSceneSwitcher.audioTab.help="このタブでは、ソースの音量に基づいてシーンを切り替えることができます。\nたとえば、マイクの音量が特定のしきい値に達した場合に、自動的に別のシーンに切り替えることができます。\n\n続行するにはプラス記号を強調表示します。"
|
AdvSceneSwitcher.audioTab.help="このタブでは、ソースの音量に基づいてシーンを切り替えることができます。\nたとえば、マイクの音量が特定のしきい値に達した場合に、自動的に別のシーンに切り替えることができます。\n\n続行するにはプラス記号を強調表示します。"
|
||||||
|
|
||||||
; Video Tab
|
# Video Tab
|
||||||
AdvSceneSwitcher.videoTab.title="Video"
|
AdvSceneSwitcher.videoTab.title="Video"
|
||||||
AdvSceneSwitcher.videoTab.getScreenshot="選択したエントリのスクリーンショットを取得"
|
AdvSceneSwitcher.videoTab.getScreenshot="選択したエントリのスクリーンショットを取得"
|
||||||
AdvSceneSwitcher.videoTab.getScreenshotHelp="現在選択されているエントリーのビデオソースのスクリーンショットを取得し、自動的に対象画像として設定します"
|
AdvSceneSwitcher.videoTab.getScreenshotHelp="現在選択されているエントリーのビデオソースのスクリーンショットを取得し、自動的に対象画像として設定します"
|
||||||
@@ -2016,31 +2136,6 @@ AdvSceneSwitcher.videoTab.ignoreInactiveSource="ソースが非アクティブ
|
|||||||
AdvSceneSwitcher.videoTab.entry="{{videoSources}}{{condition}}{{filePath}}{{browseButton}}が{{duration}}の間、{{transitions}}{{ignoreInactiveSource}}を使用して{{scenes}}に切り替わるとき"
|
AdvSceneSwitcher.videoTab.entry="{{videoSources}}{{condition}}{{filePath}}{{browseButton}}が{{duration}}の間、{{transitions}}{{ignoreInactiveSource}}を使用して{{scenes}}に切り替わるとき"
|
||||||
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>このタブでは、選択したソースの現在のビデオ出力に基づいてシーンを切り替えることができます。<br/>この機能のさらに優れた実装については、<a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a>を確認してください。<br/><br/> このタブでは、選択したソースの現在のビデオ出力に基づいてシーンを切り替えることができます。</p></body></html>"
|
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>このタブでは、選択したソースの現在のビデオ出力に基づいてシーンを切り替えることができます。<br/>この機能のさらに優れた実装については、<a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a>を確認してください。<br/><br/> このタブでは、選択したソースの現在のビデオ出力に基づいてシーンを切り替えることができます。</p></body></html>"
|
||||||
|
|
||||||
; Network Tab
|
|
||||||
AdvSceneSwitcher.networkTab.title="Network"
|
|
||||||
AdvSceneSwitcher.networkTab.description="このタブを使用すると、別の OBS インスタンスのアクティブなシーンをリモートで制御できます。\nシーン名はすべての OBS インスタンスで正確に一致する必要があることに注意してください。"
|
|
||||||
AdvSceneSwitcher.networkTab.warning="ローカルネットワーク外でサーバーを実行すると、第三者がアクティブシーンを読み取ることができます。"
|
|
||||||
AdvSceneSwitcher.networkTab.server="サーバー起動(接続中の全クライアントにシーン切り替えメッセージを送信)"
|
|
||||||
AdvSceneSwitcher.networkTab.server.port="港"
|
|
||||||
AdvSceneSwitcher.networkTab.server.lockToIPv4="サーバーをIPv4のみにロックする"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendSceneChange="場面転換時のメッセージ送信"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="自動シーン切り替えのメッセージのみ送信"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendPreview="スタジオモード実行時のプレビューシーン変更メッセージ送信"
|
|
||||||
AdvSceneSwitcher.networkTab.startFailed.message="WebSocket サーバーの起動に失敗しました。おそらく次の理由が考えられます:\n - TCP ポート %1 は現在、このシステム上の別の場所 (おそらく別のアプリケーション) で使用されている可能性があります。 WebSocket サーバー設定で別の TCP ポートを設定してみるか、このポートを使用している可能性のあるアプリケーションを停止してください。\n - エラー メッセージ: %2"
|
|
||||||
; AdvSceneSwitcher.networkTab.server.status.currentStatus="Current status"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.notRunning="動いていない"
|
|
||||||
; AdvSceneSwitcher.networkTab.server.status.starting="Starting"
|
|
||||||
; AdvSceneSwitcher.networkTab.server.status.running="Running"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restart="サーバーの再起動"
|
|
||||||
AdvSceneSwitcher.networkTab.client="クライアント起動(シーン切り替えメッセージ受信)"
|
|
||||||
AdvSceneSwitcher.networkTab.client.address="ホスト名またはIPアドレス"
|
|
||||||
; AdvSceneSwitcher.networkTab.client.port="Port"
|
|
||||||
; AdvSceneSwitcher.networkTab.client.status.currentStatus="Current status"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.disconnected="切断されました"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connecting="接続中"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connected="接続した"
|
|
||||||
AdvSceneSwitcher.networkTab.client.reconnect="強制再接続"
|
|
||||||
|
|
||||||
; Scene Group Tab
|
; Scene Group Tab
|
||||||
AdvSceneSwitcher.sceneGroupTab.title="シーンのグループ化"
|
AdvSceneSwitcher.sceneGroupTab.title="シーンのグループ化"
|
||||||
AdvSceneSwitcher.sceneGroupTab.list="シーングループ集"
|
AdvSceneSwitcher.sceneGroupTab.list="シーングループ集"
|
||||||
@@ -2060,27 +2155,3 @@ AdvSceneSwitcher.sceneGroupTab.defaultname="シーングループ %1"
|
|||||||
AdvSceneSwitcher.sceneGroupTab.exists="シーングループまたはシーン名が既に存在します"
|
AdvSceneSwitcher.sceneGroupTab.exists="シーングループまたはシーン名が既に存在します"
|
||||||
AdvSceneSwitcher.sceneGroupTab.help="シーン グループは、通常のシーンと同様に対象として選択できます。\n\nシーン グループは、名前が示すように、複数のシーンの集合です。\nシーン グループは、割り当てられたシーンのリストを順に進みます。構成された設定に応じて、右側に表示されます。\n\nリスト内の次のシーンに進むようにシーン グループを構成できます:\nシーン グループが何度も選択された後\n一定時間経過後。\nまたはランダム。\n\nたとえば、シーンを含むシーングループ...\nシーン1\nシーン2 \nシーン 3 \n... 初めてターゲットとして選択されると、「シーン 1」がアクティブになります。\n2 回目には、「シーン 2」がアクティブになります。\n残りの回「シーン 3」が有効になります。\n\n下の強調表示されたプラス記号をクリックして、新しいシーン グループを追加します。"
|
AdvSceneSwitcher.sceneGroupTab.help="シーン グループは、通常のシーンと同様に対象として選択できます。\n\nシーン グループは、名前が示すように、複数のシーンの集合です。\nシーン グループは、割り当てられたシーンのリストを順に進みます。構成された設定に応じて、右側に表示されます。\n\nリスト内の次のシーンに進むようにシーン グループを構成できます:\nシーン グループが何度も選択された後\n一定時間経過後。\nまたはランダム。\n\nたとえば、シーンを含むシーングループ...\nシーン1\nシーン2 \nシーン 3 \n... 初めてターゲットとして選択されると、「シーン 1」がアクティブになります。\n2 回目には、「シーン 2」がアクティブになります。\n残りの回「シーン 3」が有効になります。\n\n下の強調表示されたプラス記号をクリックして、新しいシーン グループを追加します。"
|
||||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="左側で変更したいシーングループを選択します。\n\n上のシーンを選択し、下のプラス記号をクリックして、このシーングループに追加するシーンを選択します。\n\nシーンは次のとおりです。同じシーングループに複数回追加しました。"
|
AdvSceneSwitcher.sceneGroupTab.scenes.help="左側で変更したいシーングループを選択します。\n\n上のシーンを選択し、下のプラス記号をクリックして、このシーングループに追加するシーンを選択します。\n\nシーンは次のとおりです。同じシーングループに複数回追加しました。"
|
||||||
|
|
||||||
; Scene Trigger Tab
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.title="シーントリガー"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--トリガーを選択--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="アクティブです"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="活動していません"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="から切り替えた"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--アクションを選択--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="録画開始"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="録画一時停止"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="録画の一時停止を解除"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="録画停止"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="配信停止"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="配信開始"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="リプレイバッファ開始"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="リプレイバッファ停止"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="ソースをミュート"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="ソースのミュートを解除"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="シーンスイッチャーを起動します"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="シーンスイッチャーを停止する"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="仮想カメラ起動"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="仮想カメラ停止"
|
|
||||||
; AdvSceneSwitcher.sceneTriggerTab.entry="When{{scenes}}{{triggers}}{{actions}}{{audioSources}}after{{duration}}"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.help="このタブでは、録画や配信の停止など、シーンの変更時にアクションをトリガーできます。"
|
|
||||||
@@ -19,16 +19,16 @@ AdvSceneSwitcher.generalTab.status.autoStart.streaming="Transmitindo"
|
|||||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Gravando ou Transmitindo"
|
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Gravando ou Transmitindo"
|
||||||
AdvSceneSwitcher.generalTab.status.checkInterval="Verificar condições a cada"
|
AdvSceneSwitcher.generalTab.status.checkInterval="Verificar condições a cada"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior="Comportamento geral"
|
AdvSceneSwitcher.generalTab.generalBehavior="Comportamento geral"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="Se nenhuma ação for executada por"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch="Se nenhuma ação for executada por"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Será sempre tão preciso quanto o intervalo de verificação configurado."
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatchDelay.tooltip="Será sempre tão preciso quanto o intervalo de verificação configurado."
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Não trocar"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.dontSwitch="Não trocar"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Trocar para qualquer cena na guia Aleatória"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchToRandom="Trocar para qualquer cena na guia Aleatória"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Trocar para:"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchTo="Trocar para:"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Após realizar ações, pular a execução de ações por"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Após realizar ações, pular a execução de ações por"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="Durante este tempo, correspondências potenciais serão ignoradas!"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="Durante este tempo, correspondências potenciais serão ignoradas!"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.logLevel="Nível de log:"
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel="Nível de log:"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.default="Padrão"
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.default="Padrão"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.printActions="Registrar ações executadas"
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.logAction="Registrar ações executadas"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.verbose="Registro detalhado"
|
AdvSceneSwitcher.generalTab.generalBehavior.logLevel.verbose="Registro detalhado"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Ativar registro detalhado"
|
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Ativar registro detalhado"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Salvar posição e tamanho da janela"
|
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Salvar posição e tamanho da janela"
|
||||||
@@ -82,10 +82,8 @@ AdvSceneSwitcher.variableTab.value.header="Valor"
|
|||||||
AdvSceneSwitcher.variableTab.saveLoadBehavior.header="Comportamento de Salvar/Carregar"
|
AdvSceneSwitcher.variableTab.saveLoadBehavior.header="Comportamento de Salvar/Carregar"
|
||||||
AdvSceneSwitcher.variableTab.saveLoadBehavior.text.default="Padrão para \"%1\""
|
AdvSceneSwitcher.variableTab.saveLoadBehavior.text.default="Padrão para \"%1\""
|
||||||
AdvSceneSwitcher.variableTab.lastUsed.header="Último uso"
|
AdvSceneSwitcher.variableTab.lastUsed.header="Último uso"
|
||||||
AdvSceneSwitcher.variableTab.lastUsed.text="%1 segundos atrás"
|
|
||||||
AdvSceneSwitcher.variableTab.lastUsed.text.never="Nunca"
|
AdvSceneSwitcher.variableTab.lastUsed.text.never="Nunca"
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.header="Última alteração"
|
AdvSceneSwitcher.variableTab.lastChanged.header="Última alteração"
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.text="%1 segundos atrás"
|
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.text.none="Sem alterações desde o lançamento"
|
AdvSceneSwitcher.variableTab.lastChanged.text.none="Sem alterações desde o lançamento"
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.tooltip="Vezes alteradas: %1\n\nValor anterior: %2"
|
AdvSceneSwitcher.variableTab.lastChanged.tooltip="Vezes alteradas: %1\n\nValor anterior: %2"
|
||||||
|
|
||||||
@@ -120,7 +118,7 @@ AdvSceneSwitcher.websocketConnectionTab.removeMultipleConnectionsPopup.text="Tem
|
|||||||
; Twitch Connections Tab
|
; Twitch Connections Tab
|
||||||
AdvSceneSwitcher.twitchConnectionTab.title="Conexões Twitch"
|
AdvSceneSwitcher.twitchConnectionTab.title="Conexões Twitch"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.help="As conexões Twitch podem ser usadas para utilizar eventos do Twitch como gatilhos para executar ações ou realizar ações na conta do Twitch vinculada.\n\nClique no símbolo de mais destacado para adicionar uma nova conexão."
|
AdvSceneSwitcher.twitchConnectionTab.help="As conexões Twitch podem ser usadas para utilizar eventos do Twitch como gatilhos para executar ações ou realizar ações na conta do Twitch vinculada.\n\nClique no símbolo de mais destacado para adicionar uma nova conexão."
|
||||||
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionAddButton.tooltip.tooltip="Adicionar nova conexão Twitch"
|
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionAddButton.tooltip="Adicionar nova conexão Twitch"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionRemoveButton.tooltip="Remover conexões Twitch selecionadas"
|
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionRemoveButton.tooltip="Remover conexões Twitch selecionadas"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.name.header="Nome"
|
AdvSceneSwitcher.twitchConnectionTab.name.header="Nome"
|
||||||
AdvSceneSwitcher.twitchConnectionTab.isValid.header="É válida?"
|
AdvSceneSwitcher.twitchConnectionTab.isValid.header="É válida?"
|
||||||
@@ -192,7 +190,7 @@ AdvSceneSwitcher.macroTab.highlightExecutedMacros="Destacar macros executadas re
|
|||||||
AdvSceneSwitcher.macroTab.highlightTrueConditions="Destacar condições da macro selecionada que avaliaram como verdadeiras recentemente"
|
AdvSceneSwitcher.macroTab.highlightTrueConditions="Destacar condições da macro selecionada que avaliaram como verdadeiras recentemente"
|
||||||
AdvSceneSwitcher.macroTab.highlightPerformedActions="Destacar ações recentemente realizadas da macro selecionada"
|
AdvSceneSwitcher.macroTab.highlightPerformedActions="Destacar ações recentemente realizadas da macro selecionada"
|
||||||
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Registrar teclas de atalho para controlar o estado de pausa das novas macros"
|
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Registrar teclas de atalho para controlar o estado de pausa das novas macros"
|
||||||
AdvSceneSwitcher.macroTab.currentDisableHotkeys="Registrar teclas de atalho para controlar o estado de pausa da macro selecionada"
|
AdvSceneSwitcher.macroTab.currentRegisterHotkeys="Registrar teclas de atalho para controlar o estado de pausa da macro selecionada"
|
||||||
AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup="Pular a execução das ações da macro atual na inicialização"
|
AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup="Pular a execução das ações da macro atual na inicialização"
|
||||||
AdvSceneSwitcher.macroTab.currentStopActionsIfNotDone="Parar e reexecutar ações da macro atualmente selecionada, se as ações ainda estiverem em execução, quando uma nova execução for acionada"
|
AdvSceneSwitcher.macroTab.currentStopActionsIfNotDone="Parar e reexecutar ações da macro atualmente selecionada, se as ações ainda estiverem em execução, quando uma nova execução for acionada"
|
||||||
AdvSceneSwitcher.macroTab.currentRegisterDock="Registrar widget de dock para controlar o estado de pausa da macro selecionada ou executá-la manualmente"
|
AdvSceneSwitcher.macroTab.currentRegisterDock="Registrar widget de dock para controlar o estado de pausa da macro selecionada ou executá-la manualmente"
|
||||||
@@ -286,8 +284,6 @@ AdvSceneSwitcher.condition.scene.type.previousPattern="A cena anterior correspon
|
|||||||
AdvSceneSwitcher.condition.scene.type.previewPattern="A cena de pré-visualização corresponde"
|
AdvSceneSwitcher.condition.scene.type.previewPattern="A cena de pré-visualização corresponde"
|
||||||
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Durante a transição, verificar a cena de destino da transição"
|
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Durante a transição, verificar a cena de destino da transição"
|
||||||
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Durante a transição, verificar a cena de origem da transição"
|
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Durante a transição, verificar a cena de origem da transição"
|
||||||
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
|
||||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
|
||||||
AdvSceneSwitcher.condition.window="Janela"
|
AdvSceneSwitcher.condition.window="Janela"
|
||||||
AdvSceneSwitcher.condition.window.entry.window="{{checkTitle}}O título da janela corresponde{{windowRegex}}{{windows}}"
|
AdvSceneSwitcher.condition.window.entry.window="{{checkTitle}}O título da janela corresponde{{windowRegex}}{{windows}}"
|
||||||
AdvSceneSwitcher.condition.window.entry.fullscreen="{{fullscreen}}A janela está em tela cheia"
|
AdvSceneSwitcher.condition.window.entry.fullscreen="{{fullscreen}}A janela está em tela cheia"
|
||||||
@@ -399,7 +395,6 @@ AdvSceneSwitcher.condition.stream.state.stop="Streaming parado"
|
|||||||
AdvSceneSwitcher.condition.stream.state.starting="Iniciando o streaming"
|
AdvSceneSwitcher.condition.stream.state.starting="Iniciando o streaming"
|
||||||
AdvSceneSwitcher.condition.stream.state.stopping="Parando o streaming"
|
AdvSceneSwitcher.condition.stream.state.stopping="Parando o streaming"
|
||||||
AdvSceneSwitcher.condition.stream.state.keyFrameInterval="Intervalo de keyframe igual a"
|
AdvSceneSwitcher.condition.stream.state.keyFrameInterval="Intervalo de keyframe igual a"
|
||||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
|
|
||||||
AdvSceneSwitcher.condition.record="Gravação"
|
AdvSceneSwitcher.condition.record="Gravação"
|
||||||
AdvSceneSwitcher.condition.record.state.start="Gravação em execução"
|
AdvSceneSwitcher.condition.record.state.start="Gravação em execução"
|
||||||
AdvSceneSwitcher.condition.record.state.pause="Gravação pausada"
|
AdvSceneSwitcher.condition.record.state.pause="Gravação pausada"
|
||||||
@@ -466,7 +461,7 @@ AdvSceneSwitcher.condition.source.sizeCompare.less="Menor que"
|
|||||||
AdvSceneSwitcher.condition.source.sizeCompare.equal="Igual a"
|
AdvSceneSwitcher.condition.source.sizeCompare.equal="Igual a"
|
||||||
AdvSceneSwitcher.condition.source.sizeCompare.more="Maior que"
|
AdvSceneSwitcher.condition.source.sizeCompare.more="Maior que"
|
||||||
AdvSceneSwitcher.condition.source.refresh="Atualizar"
|
AdvSceneSwitcher.condition.source.refresh="Atualizar"
|
||||||
AdvSceneSwitcher.condition.source.refreshTooltip="Repopule a seleção de configurações da fonte com as configurações da fonte cujo nome corresponde ao valor da variável."
|
AdvSceneSwitcher.condition.source.refresh.tooltip="Repopule a seleção de configurações da fonte com as configurações da fonte cujo nome corresponde ao valor da variável."
|
||||||
AdvSceneSwitcher.condition.source.sceneVisibilityHint="A visibilidade específica da cena pode ser verificada usando a condição \"Visibilidade do item da cena\""
|
AdvSceneSwitcher.condition.source.sceneVisibilityHint="A visibilidade específica da cena pode ser verificada usando a condição \"Visibilidade do item da cena\""
|
||||||
AdvSceneSwitcher.condition.source.getSettings="Obter configurações atuais"
|
AdvSceneSwitcher.condition.source.getSettings="Obter configurações atuais"
|
||||||
AdvSceneSwitcher.condition.source.entry.line1="{{sources}}{{conditions}}{{settingSelection}}{{refresh}}{{sizeCompareMethods}}{{size}}"
|
AdvSceneSwitcher.condition.source.entry.line1="{{sources}}{{conditions}}{{settingSelection}}{{refresh}}{{sizeCompareMethods}}{{size}}"
|
||||||
@@ -484,7 +479,7 @@ AdvSceneSwitcher.condition.filter.type.settingsChanged="Configurações alterada
|
|||||||
AdvSceneSwitcher.condition.filter.type.individualSettingMatches="Valor das configurações coincide"
|
AdvSceneSwitcher.condition.filter.type.individualSettingMatches="Valor das configurações coincide"
|
||||||
AdvSceneSwitcher.condition.filter.type.individualSettingChanged="Valor das configurações alterado"
|
AdvSceneSwitcher.condition.filter.type.individualSettingChanged="Valor das configurações alterado"
|
||||||
AdvSceneSwitcher.condition.filter.refresh="Atualizar"
|
AdvSceneSwitcher.condition.filter.refresh="Atualizar"
|
||||||
AdvSceneSwitcher.condition.filter.refreshTooltip="Repopule a seleção de configurações do filtro com as configurações do filtro cujo nome corresponda ao valor da variável."
|
AdvSceneSwitcher.condition.filter.refresh.tooltip="Repopule a seleção de configurações do filtro com as configurações do filtro cujo nome corresponda ao valor da variável."
|
||||||
AdvSceneSwitcher.condition.filter.getSettings="Obter configurações atuais"
|
AdvSceneSwitcher.condition.filter.getSettings="Obter configurações atuais"
|
||||||
AdvSceneSwitcher.condition.filter.entry.line1="Em{{sources}}{{filters}}{{conditions}}{{settingSelection}}{{refresh}}"
|
AdvSceneSwitcher.condition.filter.entry.line1="Em{{sources}}{{filters}}{{conditions}}{{settingSelection}}{{refresh}}"
|
||||||
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
||||||
@@ -628,7 +623,7 @@ AdvSceneSwitcher.condition.slideshow="Apresentação de slides"
|
|||||||
AdvSceneSwitcher.condition.slideshow.condition.slideChanged="Slide alterado"
|
AdvSceneSwitcher.condition.slideshow.condition.slideChanged="Slide alterado"
|
||||||
AdvSceneSwitcher.condition.slideshow.condition.slideIndex="Número do slide atual é"
|
AdvSceneSwitcher.condition.slideshow.condition.slideIndex="Número do slide atual é"
|
||||||
AdvSceneSwitcher.condition.slideshow.condition.slidePath="Caminho do slide atual é"
|
AdvSceneSwitcher.condition.slideshow.condition.slidePath="Caminho do slide atual é"
|
||||||
AdvSceneSwitcher.condition.slideshow.updateIntervalTooltip="As informações sobre o status da apresentação de slides serão atualizadas apenas com base no tempo configurado entre os slides"
|
AdvSceneSwitcher.condition.slideshow.updateInterval.tooltip="As informações sobre o status da apresentação de slides serão atualizadas apenas com base no tempo configurado entre os slides"
|
||||||
AdvSceneSwitcher.condition.slideshow.entry="{{sources}}{{conditions}}{{index}}{{path}}{{regex}}"
|
AdvSceneSwitcher.condition.slideshow.entry="{{sources}}{{conditions}}{{index}}{{path}}{{regex}}"
|
||||||
AdvSceneSwitcher.condition.twitch="Twitch"
|
AdvSceneSwitcher.condition.twitch="Twitch"
|
||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online="Transmissão foi online"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online="Transmissão foi online"
|
||||||
@@ -694,7 +689,7 @@ AdvSceneSwitcher.condition.queue.entry.startStop="Fila{{queues}}está{{condition
|
|||||||
AdvSceneSwitcher.condition.queue.entry.size="Fila{{queues}}{{conditions}}é menor que{{size}}"
|
AdvSceneSwitcher.condition.queue.entry.size="Fila{{queues}}{{conditions}}é menor que{{size}}"
|
||||||
AdvSceneSwitcher.condition.clipboard="Área de transferência"
|
AdvSceneSwitcher.condition.clipboard="Área de transferência"
|
||||||
AdvSceneSwitcher.condition.clipboard.placeholder="Texto da área de transferência"
|
AdvSceneSwitcher.condition.clipboard.placeholder="Texto da área de transferência"
|
||||||
AdvSceneSwitcher.condition.clipboard.urlTooltip="Dependendo do SO, arquivos podem ser representados também como URLs!"
|
AdvSceneSwitcher.condition.clipboard.url.tooltip="Dependendo do SO, arquivos podem ser representados também como URLs!"
|
||||||
AdvSceneSwitcher.condition.clipboard.condition.changed="Conteúdo da área de transferência alterado"
|
AdvSceneSwitcher.condition.clipboard.condition.changed="Conteúdo da área de transferência alterado"
|
||||||
AdvSceneSwitcher.condition.clipboard.condition.isText="Área de transferência contém texto"
|
AdvSceneSwitcher.condition.clipboard.condition.isText="Área de transferência contém texto"
|
||||||
AdvSceneSwitcher.condition.clipboard.condition.isImage="Área de transferência contém uma imagem"
|
AdvSceneSwitcher.condition.clipboard.condition.isImage="Área de transferência contém uma imagem"
|
||||||
@@ -798,7 +793,7 @@ AdvSceneSwitcher.action.filter.type.toggle="Alternar"
|
|||||||
AdvSceneSwitcher.action.filter.type.settings="Definir configurações"
|
AdvSceneSwitcher.action.filter.type.settings="Definir configurações"
|
||||||
AdvSceneSwitcher.action.filter.type.pressSettingsButton="Pressionar botão de configurações"
|
AdvSceneSwitcher.action.filter.type.pressSettingsButton="Pressionar botão de configurações"
|
||||||
AdvSceneSwitcher.action.filter.refresh="Atualizar"
|
AdvSceneSwitcher.action.filter.refresh="Atualizar"
|
||||||
AdvSceneSwitcher.action.filter.refreshTooltip="Repovoar a seleção de configurações do filtro com as configurações do filtro cujo nome corresponda ao valor da variável."
|
AdvSceneSwitcher.action.filter.refresh.tooltip="Repovoar a seleção de configurações do filtro com as configurações do filtro cujo nome corresponda ao valor da variável."
|
||||||
AdvSceneSwitcher.action.filter.entry="Em{{sources}}{{actions}}{{filters}}{{refresh}}{{settingsButtons}}"
|
AdvSceneSwitcher.action.filter.entry="Em{{sources}}{{actions}}{{filters}}{{refresh}}{{settingsButtons}}"
|
||||||
AdvSceneSwitcher.action.filter.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}"
|
AdvSceneSwitcher.action.filter.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}"
|
||||||
AdvSceneSwitcher.action.filter.getSettings="Obter configurações atuais"
|
AdvSceneSwitcher.action.filter.getSettings="Obter configurações atuais"
|
||||||
@@ -836,7 +831,7 @@ AdvSceneSwitcher.action.source.inputMethod.individualManual="Definir valor fixo"
|
|||||||
AdvSceneSwitcher.action.source.inputMethod.individualTempvar="Definir propriedade de macro"
|
AdvSceneSwitcher.action.source.inputMethod.individualTempvar="Definir propriedade de macro"
|
||||||
AdvSceneSwitcher.action.source.inputMethod.json="Definir string JSON de configuração"
|
AdvSceneSwitcher.action.source.inputMethod.json="Definir string JSON de configuração"
|
||||||
AdvSceneSwitcher.action.source.refresh="Atualizar"
|
AdvSceneSwitcher.action.source.refresh="Atualizar"
|
||||||
AdvSceneSwitcher.action.source.refreshTooltip="Repovoar a seleção de configurações da fonte com as configurações da fonte cujo nome corresponda ao valor da variável."
|
AdvSceneSwitcher.action.source.refresh.tooltip="Repovoar a seleção de configurações da fonte com as configurações da fonte cujo nome corresponda ao valor da variável."
|
||||||
AdvSceneSwitcher.action.media="Mídia"
|
AdvSceneSwitcher.action.media="Mídia"
|
||||||
; Macro Actions
|
; Macro Actions
|
||||||
AdvSceneSwitcher.action.media.type.play="Reproduzir"
|
AdvSceneSwitcher.action.media.type.play="Reproduzir"
|
||||||
@@ -911,7 +906,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="Mover para baixo"
|
|||||||
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Mover para o topo"
|
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Mover para o topo"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Mover para o fundo"
|
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Mover para o fundo"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Mover para posição"
|
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Mover para posição"
|
||||||
AdvSceneSwitcher.action.sceneOrder.entry="Em{{scenes}}{{actions}}{{sources}}{{position}}"
|
AdvSceneSwitcher.action.sceneOrder.entry="Em{{scenes}}{{actions}}{{sources}}{{sources2}}{{position}}"
|
||||||
AdvSceneSwitcher.action.sceneTransform="Transformação de item de cena"
|
AdvSceneSwitcher.action.sceneTransform="Transformação de item de cena"
|
||||||
AdvSceneSwitcher.action.sceneTransform.type.manual="Definir string de transformação"
|
AdvSceneSwitcher.action.sceneTransform.type.manual="Definir string de transformação"
|
||||||
AdvSceneSwitcher.action.sceneTransform.type.setSingleSetting="Definir configuração de transformação"
|
AdvSceneSwitcher.action.sceneTransform.type.setSingleSetting="Definir configuração de transformação"
|
||||||
@@ -967,7 +962,7 @@ AdvSceneSwitcher.action.screenshot.type.source="Fonte"
|
|||||||
AdvSceneSwitcher.action.screenshot.type.scene="Cena"
|
AdvSceneSwitcher.action.screenshot.type.scene="Cena"
|
||||||
AdvSceneSwitcher.action.screenshot.mainOutput="Saída principal do OBS"
|
AdvSceneSwitcher.action.screenshot.mainOutput="Saída principal do OBS"
|
||||||
AdvSceneSwitcher.action.screenshot.blackscreenNote="Fontes ou cenas, que nem sempre são renderizadas, podem resultar em algumas partes das capturas de tela permanecendo em branco."
|
AdvSceneSwitcher.action.screenshot.blackscreenNote="Fontes ou cenas, que nem sempre são renderizadas, podem resultar em algumas partes das capturas de tela permanecendo em branco."
|
||||||
AdvSceneSwitcher.action.screenshot.entry="Captura de tela{{targetType}}{{sources}}{{scenes}}e salvar em{{saveType}}localização"
|
AdvSceneSwitcher.action.screenshot.entry="Captura de tela{{targetType}}{{sources}}{{scenes}}e salvar em{{saveType}}{{variables}}localização"
|
||||||
AdvSceneSwitcher.action.profile="Perfil"
|
AdvSceneSwitcher.action.profile="Perfil"
|
||||||
AdvSceneSwitcher.action.profile.entry="Mudar perfil ativo para{{profiles}}"
|
AdvSceneSwitcher.action.profile.entry="Mudar perfil ativo para{{profiles}}"
|
||||||
AdvSceneSwitcher.action.sceneCollection="Coleção de cenas"
|
AdvSceneSwitcher.action.sceneCollection="Coleção de cenas"
|
||||||
@@ -1038,7 +1033,6 @@ AdvSceneSwitcher.action.variable.invalidSelection="Seleção inválida!"
|
|||||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Obter valores de variáveis das ações %1 não é suportado!"
|
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Obter valores de variáveis das ações %1 não é suportado!"
|
||||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Obter valores de variáveis das condições %1 não é suportado!"
|
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Obter valores de variáveis das condições %1 não é suportado!"
|
||||||
AdvSceneSwitcher.action.variable.currentSegmentValue="Valor atual:"
|
AdvSceneSwitcher.action.variable.currentSegmentValue="Valor atual:"
|
||||||
AdvSceneSwitcher.action.variable.entry.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{tempVarsHelp}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}"
|
|
||||||
AdvSceneSwitcher.action.variable.entry.pad="{{actions}}de{{variables}}para comprimento{{stringLength}}adicionando{{paddingCharSelection}}ao{{direction}}"
|
AdvSceneSwitcher.action.variable.entry.pad="{{actions}}de{{variables}}para comprimento{{stringLength}}adicionando{{paddingCharSelection}}ao{{direction}}"
|
||||||
AdvSceneSwitcher.action.variable.entry.truncate="{{actions}}de{{variables}}para comprimento{{stringLength}}removendo caracteres da{{direction}}"
|
AdvSceneSwitcher.action.variable.entry.truncate="{{actions}}de{{variables}}para comprimento{{stringLength}}removendo caracteres da{{direction}}"
|
||||||
AdvSceneSwitcher.action.variable.entry.substringIndex="Início da substring:{{subStringStart}}Tamanho da substring:{{subStringSize}}"
|
AdvSceneSwitcher.action.variable.entry.substringIndex="Início da substring:{{subStringStart}}Tamanho da substring:{{subStringSize}}"
|
||||||
@@ -1657,9 +1651,9 @@ AdvSceneSwitcher.tempVar.twitch.user_login.removeMod.description="O login do usu
|
|||||||
AdvSceneSwitcher.tempVar.twitch.user_name.removeMod="Nome de usuário"
|
AdvSceneSwitcher.tempVar.twitch.user_name.removeMod="Nome de usuário"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.removeMod.description="O nome de exibição do usuário que foi removido como moderador."
|
AdvSceneSwitcher.tempVar.twitch.user_name.removeMod.description="O nome de exibição do usuário que foi removido como moderador."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.chatter="Nome de login do usuário"
|
AdvSceneSwitcher.tempVar.twitch.user_login.chatReceive="Nome de login do usuário"
|
||||||
AdvSceneSwitcher.tempVar.twitch.chatter.description="O nome de login da pessoa que enviou a mensagem de chat."
|
AdvSceneSwitcher.tempVar.twitch.user_login.chatReceive.description="O nome de login da pessoa que enviou a mensagem de chat."
|
||||||
AdvSceneSwitcher.tempVar.twitch.chat_message="Mensagem de chat"
|
AdvSceneSwitcher.tempVar.twitch.chat_message.chatReceive="Mensagem de chat"
|
||||||
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid="ID do usuário criador do raid"
|
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid="ID do usuário criador do raid"
|
||||||
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid.description="O ID do broadcaster que criou o raid."
|
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid.description="O ID do broadcaster que criou o raid."
|
||||||
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_login.raid="Nome de login do criador do raid"
|
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_login.raid="Nome de login do criador do raid"
|
||||||
@@ -1866,8 +1860,8 @@ AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="Nome da variável"
|
|||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable.entry="{{nameConflictIndex}}{{variable}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable.entry="{{nameConflictIndex}}{{variable}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="Nome da fonte corresponde ao padrão"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="Nome da fonte corresponde ao padrão"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.entry="{{nameConflictIndex}}correspondendo{{pattern}}{{regex}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.entry="{{nameConflictIndex}}correspondendo{{pattern}}{{regex}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup="Fontes do tipo"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType="Fontes do tipo"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup.entry="Tipo de fonte{{nameConflictIndex}}{{sourceGroups}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType.entry="Tipo de fonte{{nameConflictIndex}}{{sourceTypes}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index="Fonte com índice"
|
AdvSceneSwitcher.sceneItemSelection.type.index="Fonte com índice"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index.entry="{{index}}fonte"
|
AdvSceneSwitcher.sceneItemSelection.type.index.entry="{{index}}fonte"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.indexRange="Fontes no intervalo de índices"
|
AdvSceneSwitcher.sceneItemSelection.type.indexRange="Fontes no intervalo de índices"
|
||||||
@@ -1889,7 +1883,7 @@ AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Parece que esta é a pr
|
|||||||
AdvSceneSwitcher.deprecatedTabWarning="Desenvolvimento para esta aba interrompido!\nPor favor, considere a transição para o uso de Macros em vez disso.\nEsta dica pode ser desativada na aba Geral."
|
AdvSceneSwitcher.deprecatedTabWarning="Desenvolvimento para esta aba interrompido!\nPor favor, considere a transição para o uso de Macros em vez disso.\nEsta dica pode ser desativada na aba Geral."
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="milissegundos"
|
AdvSceneSwitcher.unit.milliseconds="milissegundos"
|
||||||
AdvSceneSwitcher.unit.secends="segundos"
|
AdvSceneSwitcher.unit.seconds="segundos"
|
||||||
AdvSceneSwitcher.unit.minutes="minutos"
|
AdvSceneSwitcher.unit.minutes="minutos"
|
||||||
AdvSceneSwitcher.unit.hours="horas"
|
AdvSceneSwitcher.unit.hours="horas"
|
||||||
AdvSceneSwitcher.duration.condition.none="Nenhum modificador de duração"
|
AdvSceneSwitcher.duration.condition.none="Nenhum modificador de duração"
|
||||||
@@ -2069,30 +2063,6 @@ AdvSceneSwitcher.videoTab.condition.hasChanged="mudou"
|
|||||||
AdvSceneSwitcher.videoTab.ignoreInactiveSource="a menos que a fonte esteja inativa"
|
AdvSceneSwitcher.videoTab.ignoreInactiveSource="a menos que a fonte esteja inativa"
|
||||||
AdvSceneSwitcher.videoTab.entry="Quando{{videoSources}}{{condition}}{{filePath}}{{browseButton}}por{{duration}}trocar para{{scenes}}usando{{transitions}}{{ignoreInactiveSource}}"
|
AdvSceneSwitcher.videoTab.entry="Quando{{videoSources}}{{condition}}{{filePath}}{{browseButton}}por{{duration}}trocar para{{scenes}}usando{{transitions}}{{ignoreInactiveSource}}"
|
||||||
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Esta aba permitirá que você troque cenas com base na saída de vídeo atual das fontes selecionadas.<br/>Certifique-se de conferir <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> para uma implementação ainda melhor dessa funcionalidade.<br/><br/> Clique no símbolo de mais destacado para continuar.</p></body></html>"
|
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Esta aba permitirá que você troque cenas com base na saída de vídeo atual das fontes selecionadas.<br/>Certifique-se de conferir <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> para uma implementação ainda melhor dessa funcionalidade.<br/><br/> Clique no símbolo de mais destacado para continuar.</p></body></html>"
|
||||||
; Network Tab
|
|
||||||
AdvSceneSwitcher.networkTab.title="Rede"
|
|
||||||
AdvSceneSwitcher.networkTab.description="Esta aba permitirá que você controle remotamente a cena ativa de outra instância do OBS.\nObserve que os nomes das cenas devem corresponder exatamente em todas as instâncias do OBS."
|
|
||||||
AdvSceneSwitcher.networkTab.warning="Executar o servidor fora de uma rede local permitirá que terceiros leiam a cena ativa."
|
|
||||||
AdvSceneSwitcher.networkTab.server="Iniciar servidor (Envia mensagens de troca de cena para todos os clientes conectados)"
|
|
||||||
AdvSceneSwitcher.networkTab.server.port="Porta"
|
|
||||||
AdvSceneSwitcher.networkTab.server.lockToIPv4="Bloquear servidor para usar apenas IPv4"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendSceneChange="Enviar mensagens para mudanças de cena"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Enviar mensagens apenas para trocas de cena automatizadas"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendPreview="Enviar mensagens para mudança de cena de pré-visualização ao executar no modo Studio"
|
|
||||||
AdvSceneSwitcher.networkTab.startFailed.message="O servidor WebSockets falhou ao iniciar, talvez porque:\n - A porta TCP %1 pode estar atualmente em uso em outro lugar neste sistema, possivelmente por outro aplicativo. Tente definir uma porta TCP diferente nas configurações do servidor WebSocket, ou pare qualquer aplicativo que possa estar usando esta porta.\n - Mensagem de erro: %2"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.currentStatus="Status atual"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.notRunning="Não está em execução"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.starting="Iniciando"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.running="Em execução"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restart="Reiniciar servidor"
|
|
||||||
AdvSceneSwitcher.networkTab.client="Iniciar cliente (Recebe mensagens de trocas de cena)"
|
|
||||||
AdvSceneSwitcher.networkTab.client.address="Nome do host ou endereço IP"
|
|
||||||
AdvSceneSwitcher.networkTab.client.port="Porta"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.currentStatus="Status atual"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.disconnected="Desconectado"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connecting="Conectando"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connected="Conectado"
|
|
||||||
AdvSceneSwitcher.networkTab.client.reconnect="Forçar reconexão"
|
|
||||||
|
|
||||||
; Scene Group Tab
|
; Scene Group Tab
|
||||||
AdvSceneSwitcher.sceneGroupTab.title="Grupo de Cenas"
|
AdvSceneSwitcher.sceneGroupTab.title="Grupo de Cenas"
|
||||||
@@ -2114,26 +2084,3 @@ AdvSceneSwitcher.sceneGroupTab.exists="Grupo de Cenas ou Nome de Cena já existe
|
|||||||
AdvSceneSwitcher.sceneGroupTab.help="Os Grupos de Cenas podem ser selecionados como um alvo, assim como uma cena normal.\n\nComo o nome sugere, um grupo de cenas é uma coleção de várias cenas.\nO grupo de cenas avançará pela lista de suas cenas atribuídas dependendo das configurações configuradas, que podem ser encontradas no lado direito.\n\nVocê pode configurar o grupo de cenas para avançar para a próxima cena na lista:\nApós um número de vezes em que o grupo de cenas é selecionado como alvo.\nApós um certo período de tempo ter passado.\nOu aleatoriamente.\n\nPor exemplo, um grupo de cenas contendo as cenas ...\nCena 1\nCena 2\nCena 3\n... ativará \"Cena 1\" na primeira vez que for selecionado como alvo.\nNa segunda vez, ativará \"Cena 2\".\nAs vezes restantes, \"Cena 3\" será ativada.\n\nClique no símbolo de mais destacado abaixo para adicionar um novo grupo de cenas."
|
AdvSceneSwitcher.sceneGroupTab.help="Os Grupos de Cenas podem ser selecionados como um alvo, assim como uma cena normal.\n\nComo o nome sugere, um grupo de cenas é uma coleção de várias cenas.\nO grupo de cenas avançará pela lista de suas cenas atribuídas dependendo das configurações configuradas, que podem ser encontradas no lado direito.\n\nVocê pode configurar o grupo de cenas para avançar para a próxima cena na lista:\nApós um número de vezes em que o grupo de cenas é selecionado como alvo.\nApós um certo período de tempo ter passado.\nOu aleatoriamente.\n\nPor exemplo, um grupo de cenas contendo as cenas ...\nCena 1\nCena 2\nCena 3\n... ativará \"Cena 1\" na primeira vez que for selecionado como alvo.\nNa segunda vez, ativará \"Cena 2\".\nAs vezes restantes, \"Cena 3\" será ativada.\n\nClique no símbolo de mais destacado abaixo para adicionar um novo grupo de cenas."
|
||||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="Selecione o grupo de cenas que você deseja modificar à esquerda.\n\nSelecione uma cena para adicionar a este grupo de cenas selecionando a cena acima e clicando no símbolo de mais abaixo.\n\nUma cena pode ser adicionada várias vezes ao mesmo grupo de cenas."
|
AdvSceneSwitcher.sceneGroupTab.scenes.help="Selecione o grupo de cenas que você deseja modificar à esquerda.\n\nSelecione uma cena para adicionar a este grupo de cenas selecionando a cena acima e clicando no símbolo de mais abaixo.\n\nUma cena pode ser adicionada várias vezes ao mesmo grupo de cenas."
|
||||||
|
|
||||||
; Scene Trigger Tab
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.title="Gatilhos de Cena"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--selecione gatilho--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="está ativa"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="não está ativa"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="foi trocada"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--selecione ação--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="iniciar gravação"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="pausar gravação"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="retomar gravação"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="parar gravação"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="parar transmissão"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="iniciar transmissão"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="iniciar buffer de replay"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="parar buffer de replay"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="silenciar fonte"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="desilenciar fonte"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="iniciar o switcher de cena"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="parar o switcher de cena"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="iniciar câmera virtual"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="parar câmera virtual"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.entry="Quando{{scenes}}{{triggers}}{{actions}}{{audioSources}}após{{duration}}"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.help="Esta aba permite que você acione ações nas mudanças de cena, como parar a gravação ou a transmissão."
|
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ AdvSceneSwitcher.generalTab.status.autoStart.streaming="Вещание"
|
|||||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Запись или потоковое вещание"
|
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Запись или потоковое вещание"
|
||||||
AdvSceneSwitcher.generalTab.status.checkInterval="Проверять условия переключения каждый раз"
|
AdvSceneSwitcher.generalTab.status.checkInterval="Проверять условия переключения каждый раз"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior="Общее поведение"
|
AdvSceneSwitcher.generalTab.generalBehavior="Общее поведение"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="Если не выполняется условие переключения для"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch="Если не выполняется условие переключения для"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Будет только настолько точным, насколько настроен интервал проверки."
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatchDelay.tooltip="Будет только настолько точным, насколько настроен интервал проверки."
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Не переключаться"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.dontSwitch="Не переключаться"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Переключиться на любую сцену на вкладке Random"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchToRandom="Переключиться на любую сцену на вкладке Random"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Переключиться на:"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchTo="Переключиться на:"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="В течение этого времени потенциальные совпадения будут игнорироваться!"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="В течение этого времени потенциальные совпадения будут игнорироваться!"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Включить ведение подробного журнала"
|
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Включить ведение подробного журнала"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Сохранять положение и размер окна"
|
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Сохранять положение и размер окна"
|
||||||
@@ -307,28 +307,6 @@ AdvSceneSwitcher.videoTab.ignoreInactiveSource="если источник неа
|
|||||||
AdvSceneSwitcher.videoTab.entry="Когда {{videoSources}} {{condition}} {{filePath}} {{browseButton}} для {{duration}} переключиться на {{scenes}} используя {{transitions}} {{ignoreInactiveSource}}"
|
AdvSceneSwitcher.videoTab.entry="Когда {{videoSources}} {{condition}} {{filePath}} {{browseButton}} для {{duration}} переключиться на {{scenes}} используя {{transitions}} {{ignoreInactiveSource}}"
|
||||||
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Эта вкладка позволит вам переключать сцены на основе текущего видеовыхода выбранных источников.<br/>Обязательно проверьте <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> для еще лучшей реализации этой функциональности.<br/><br/> Нажмите на выделенный символ плюса, чтобы продолжить.</p></body></html>"
|
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Эта вкладка позволит вам переключать сцены на основе текущего видеовыхода выбранных источников.<br/>Обязательно проверьте <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> для еще лучшей реализации этой функциональности.<br/><br/> Нажмите на выделенный символ плюса, чтобы продолжить.</p></body></html>"
|
||||||
|
|
||||||
; Network Tab
|
|
||||||
AdvSceneSwitcher.networkTab.title="Сеть"
|
|
||||||
AdvSceneSwitcher.networkTab.warning="Запуск сервера вне локальной сети позволит третьим лицам читать активную сцену."
|
|
||||||
AdvSceneSwitcher.networkTab.server="Запустить сервер (отправляет сообщения о переключении сцены всем подключенным клиентам)"
|
|
||||||
AdvSceneSwitcher.networkTab.server.port="Порт"
|
|
||||||
AdvSceneSwitcher.networkTab.server.lockToIPv4="Заблокировать сервер на использование только IPv4"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Отправлять сообщения только для автоматических переключателей сцен"
|
|
||||||
AdvSceneSwitcher.networkTab.startFailed.message="Сервер WebSockets не удалось запустить, возможно потому, что:\n - TCP порт %1 может в настоящее время использоваться в другом месте в этой системе, возможно, другим приложением. Попробуйте установить другой TCP порт в настройках сервера WebSocket, или остановите любое приложение, которое может использовать этот порт.\n - Сообщение об ошибке: %2"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.currentStatus="Текущий статус"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.notRunning="Не запущен"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.starting="Запуск"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.running="Работает"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restart="Перезапустить сервер"
|
|
||||||
AdvSceneSwitcher.networkTab.client="Запустить клиент (Получает сообщения о переключении сцен)"
|
|
||||||
AdvSceneSwitcher.networkTab.client.address="Имя хоста или IP-адрес"
|
|
||||||
AdvSceneSwitcher.networkTab.client.port="Порт"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.currentStatus="Текущий статус"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.disconnected="Отключено"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connecting="Подключение"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connected="Подключено"
|
|
||||||
AdvSceneSwitcher.networkTab.client.reconnect="Принудительное переподключение"
|
|
||||||
|
|
||||||
; Scene Group Tab
|
; Scene Group Tab
|
||||||
AdvSceneSwitcher.sceneGroupTab.title="Группа сцен"
|
AdvSceneSwitcher.sceneGroupTab.title="Группа сцен"
|
||||||
AdvSceneSwitcher.sceneGroupTab.list="Группы сцен"
|
AdvSceneSwitcher.sceneGroupTab.list="Группы сцен"
|
||||||
@@ -349,28 +327,6 @@ AdvSceneSwitcher.sceneGroupTab.exists="Группа сцен или назван
|
|||||||
AdvSceneSwitcher.sceneGroupTab.help="Группы сцен могут быть выбраны в качестве цели так же, как и обычные сцены.\n\nКак следует из названия, группа сцен представляет собой набор из нескольких сцен.\nГруппа сцен будет продвигаться по списку назначенных ей сцен в зависимости от настроенных параметров, которые можно найти справа.\n\nВы можете настроить группу сцен на переход к следующей сцене в списке:\nПосле определенного количества раз, когда группа сцен выбрана в качестве цели.\nПо истечении определенного времени.\nИли случайным образом.\n\nНапример, группа сцен, содержащая сцены ...\nScene 1\nScene 2\nScene 3 \n... активирует \"Scene 1\" в первый раз, когда он выбран в качестве цели.\nВо второй раз он активируется \"Scene 2\".\nОставшееся время \"Scene 3\" будет активирован.\n\nНажмите на выделенный символ плюса ниже, чтобы добавить новую группу сцен."
|
AdvSceneSwitcher.sceneGroupTab.help="Группы сцен могут быть выбраны в качестве цели так же, как и обычные сцены.\n\nКак следует из названия, группа сцен представляет собой набор из нескольких сцен.\nГруппа сцен будет продвигаться по списку назначенных ей сцен в зависимости от настроенных параметров, которые можно найти справа.\n\nВы можете настроить группу сцен на переход к следующей сцене в списке:\nПосле определенного количества раз, когда группа сцен выбрана в качестве цели.\nПо истечении определенного времени.\nИли случайным образом.\n\nНапример, группа сцен, содержащая сцены ...\nScene 1\nScene 2\nScene 3 \n... активирует \"Scene 1\" в первый раз, когда он выбран в качестве цели.\nВо второй раз он активируется \"Scene 2\".\nОставшееся время \"Scene 3\" будет активирован.\n\nНажмите на выделенный символ плюса ниже, чтобы добавить новую группу сцен."
|
||||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="Выберите группу сцен, которую вы хотите изменить слева.\n\nВыберите сцену для добавления в эту группу сцен, выбрав сцену выше и нажав на символ плюса ниже.\n\nСцена может быть добавлена несколько раз в одну и ту же группу сцен."
|
AdvSceneSwitcher.sceneGroupTab.scenes.help="Выберите группу сцен, которую вы хотите изменить слева.\n\nВыберите сцену для добавления в эту группу сцен, выбрав сцену выше и нажав на символ плюса ниже.\n\nСцена может быть добавлена несколько раз в одну и ту же группу сцен."
|
||||||
|
|
||||||
; Scene Trigger Tab
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.title="Триггеры сцены"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--выбрать триггер--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="активен"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="не активен"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="переключился с"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--выбрать действие--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="начать запись"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="приостановить запись"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="отменить паузу записи"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="остановить запись"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="остановить потоковое вещание"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="начать потоковое вещание"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="запустить буфер воспроизведения"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="остановить буфер воспроизведения"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="отключить источник"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="включить источник"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="запустить переключатель сцены"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="остановить переключатель сцены"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.entry="Когда {{scenes}} {{triggers}} {{actions}} {{audioSources}} после {{duration}}"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.help="Эта вкладка позволяет запускать действия при изменении сцены, например, остановку записи или потоковой передачи."
|
|
||||||
|
|
||||||
; Hotkey
|
; Hotkey
|
||||||
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Запустить Advanced Scene Switcher"
|
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Запустить Advanced Scene Switcher"
|
||||||
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="становить Advanced Scene Switcher"
|
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="становить Advanced Scene Switcher"
|
||||||
@@ -399,6 +355,6 @@ AdvSceneSwitcher.status.active="Активный"
|
|||||||
AdvSceneSwitcher.status.inactive="Неактивен"
|
AdvSceneSwitcher.status.inactive="Неактивен"
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="миллисекунды"
|
AdvSceneSwitcher.unit.milliseconds="миллисекунды"
|
||||||
AdvSceneSwitcher.unit.secends="секунды"
|
AdvSceneSwitcher.unit.seconds="секунды"
|
||||||
AdvSceneSwitcher.unit.minutes="минуты"
|
AdvSceneSwitcher.unit.minutes="минуты"
|
||||||
AdvSceneSwitcher.unit.hours="часы"
|
AdvSceneSwitcher.unit.hours="часы"
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ AdvSceneSwitcher.generalTab.status.autoStart.streaming="Yayın"
|
|||||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Kayıt veya Yayın"
|
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Kayıt veya Yayın"
|
||||||
AdvSceneSwitcher.generalTab.status.checkInterval="Anahtar koşullarını her seferinde kontrol edin"
|
AdvSceneSwitcher.generalTab.status.checkInterval="Anahtar koşullarını her seferinde kontrol edin"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior="Genel davranış"
|
AdvSceneSwitcher.generalTab.generalBehavior="Genel davranış"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="...için herhangi bir işlem yapılmazsa"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch="...için herhangi bir işlem yapılmazsa"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Yalnızca yapılandırılmış kontrol aralığı kadar doğru olacaktır."
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatchDelay.tooltip="Yalnızca yapılandırılmış kontrol aralığı kadar doğru olacaktır."
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Geçiş Yapma"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.dontSwitch="Geçiş Yapma"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Rastgele sekmesinde herhangi bir sahneye geçin"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchToRandom="Rastgele sekmesinde herhangi bir sahneye geçin"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Değiştirmek:"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchTo="Değiştirmek:"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Bir eşleşmeden sonra aşağıdakiler için işlem yapmayın:"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Bir eşleşmeden sonra aşağıdakiler için işlem yapmayın:"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="Bu süre zarfında olası eşleşmeler göz ardı edilecektir!"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="Bu süre zarfında olası eşleşmeler göz ardı edilecektir!"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Ayrıntılı günlük kaydını etkinleştir"
|
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Ayrıntılı günlük kaydını etkinleştir"
|
||||||
@@ -107,8 +107,6 @@ AdvSceneSwitcher.condition.scene.type.previous="Önceki Sahne"
|
|||||||
AdvSceneSwitcher.condition.scene.type.changed="Sahne değişti"
|
AdvSceneSwitcher.condition.scene.type.changed="Sahne değişti"
|
||||||
AdvSceneSwitcher.condition.scene.type.notChanged="Sahne değişmedi"
|
AdvSceneSwitcher.condition.scene.type.notChanged="Sahne değişmedi"
|
||||||
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Geçiş hedefi sahnesi için geçiş kontrolü sırasında"
|
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Geçiş hedefi sahnesi için geçiş kontrolü sırasında"
|
||||||
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
|
||||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
|
||||||
AdvSceneSwitcher.condition.window="Pencere"
|
AdvSceneSwitcher.condition.window="Pencere"
|
||||||
AdvSceneSwitcher.condition.file="Dosya"
|
AdvSceneSwitcher.condition.file="Dosya"
|
||||||
AdvSceneSwitcher.condition.file.entry.line1="İçerik{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
AdvSceneSwitcher.condition.file.entry.line1="İçerik{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
@@ -151,7 +149,6 @@ 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.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ı"
|
||||||
@@ -338,7 +335,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="Aşağı indir"
|
|||||||
AdvSceneSwitcher.action.sceneOrder.type.moveTop="En üste taşı"
|
AdvSceneSwitcher.action.sceneOrder.type.moveTop="En üste taşı"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Aşağıya taşı"
|
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Aşağıya taşı"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Konuma taşı"
|
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}}{{sources2}}{{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}}{{settingSelection}}{{singleSettingValue}}"
|
AdvSceneSwitcher.action.sceneTransform.entry="Açık{{scenes}}{{action}}{{rotation}}{{sources}}{{settingSelection}}{{singleSettingValue}}"
|
||||||
@@ -529,31 +526,6 @@ AdvSceneSwitcher.videoTab.ignoreInactiveSource="Kaynak etkin olmadığı sürece
|
|||||||
AdvSceneSwitcher.videoTab.entry="Zaman {{videoSources}} {{condition}} {{filePath}} {{browseButton}} için {{duration}} şuna dönüştür {{scenes}} kullan {{transitions}} {{ignoreInactiveSource}}"
|
AdvSceneSwitcher.videoTab.entry="Zaman {{videoSources}} {{condition}} {{filePath}} {{browseButton}} için {{duration}} şuna dönüştür {{scenes}} kullan {{transitions}} {{ignoreInactiveSource}}"
|
||||||
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Bu sekme, seçilen kaynakların mevcut video çıkışına göre sahneler arasında geçiş yapmanızı sağlar.<br/><a href=\"https:// adresini kontrol ettiğinizden emin olun. obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> bu işlevin daha da iyi bir şekilde uygulanması için.<br/><br/> Devam etmek için vurgulanan artı simgesini tıklayın.</p></body></html>"
|
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Bu sekme, seçilen kaynakların mevcut video çıkışına göre sahneler arasında geçiş yapmanızı sağlar.<br/><a href=\"https:// adresini kontrol ettiğinizden emin olun. obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> bu işlevin daha da iyi bir şekilde uygulanması için.<br/><br/> Devam etmek için vurgulanan artı simgesini tıklayın.</p></body></html>"
|
||||||
|
|
||||||
; Network Tab
|
|
||||||
AdvSceneSwitcher.networkTab.title="Ağ"
|
|
||||||
AdvSceneSwitcher.networkTab.description="Bu sekme, başka bir OBS örneğinin etkin sahnesini uzaktan kontrol etmenizi sağlar.\nSahne adlarının tüm OBS örneklerinde tam olarak eşleşmesi gerektiğini lütfen unutmayın."
|
|
||||||
AdvSceneSwitcher.networkTab.warning="Sunucuyu yerel bir ağın dışında çalıştırmak, üçüncü tarafların aktif sahneyi okumasına izin verecektir."
|
|
||||||
AdvSceneSwitcher.networkTab.server="Sunucuyu başlat (Bağlı tüm istemcilere sahne değiştirme mesajları gönderir)"
|
|
||||||
AdvSceneSwitcher.networkTab.server.port="Port"
|
|
||||||
AdvSceneSwitcher.networkTab.server.lockToIPv4="Sunucuyu yalnızca IPv4 kullanacak şekilde kilitleyin"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendSceneChange="Sahne değişiklikleri için mesaj gönder"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Yalnızca otomatik sahne anahtarları için mesaj gönder"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendPreview="Stüdyo modunda çalışırken önizleme sahnesi değişikliği için mesajlar gönderin"
|
|
||||||
AdvSceneSwitcher.networkTab.startFailed.message="WebSockets sunucusu başlatılamadı, bunun nedeni şunlar olabilir:\n - %1 TCP bağlantı noktası şu anda bu sistemde başka bir yerde, muhtemelen başka bir uygulama tarafından kullanılıyor olabilir. WebSocket sunucu ayarlarında farklı bir TCP bağlantı noktası ayarlamayı deneyin veya bu bağlantı noktasını kullanabilecek herhangi bir uygulamayı durdurun.\n - Hata mesajı: %2"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.currentStatus="Şu anki durum"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.notRunning="Çalışmıyor"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.starting="Başlangıç"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.running="Çalışıyor"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restart="Sunucuyu yeniden başlat"
|
|
||||||
AdvSceneSwitcher.networkTab.client="İstemciyi başlat (Sahne değiştirme mesajlarını alır)"
|
|
||||||
AdvSceneSwitcher.networkTab.client.address="Ana makine adı veya IP adresi"
|
|
||||||
AdvSceneSwitcher.networkTab.client.port="Port"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.currentStatus="Şu anki durum"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.disconnected="Bağlantı kesildi"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connecting="Bağlanıyor"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connected="Bağlandı"
|
|
||||||
AdvSceneSwitcher.networkTab.client.reconnect="Yeniden bağlanmaya zorla"
|
|
||||||
|
|
||||||
; Scene Group Tab
|
; Scene Group Tab
|
||||||
AdvSceneSwitcher.sceneGroupTab.title="Sahne Grubu"
|
AdvSceneSwitcher.sceneGroupTab.title="Sahne Grubu"
|
||||||
AdvSceneSwitcher.sceneGroupTab.list="Sahne Grupları"
|
AdvSceneSwitcher.sceneGroupTab.list="Sahne Grupları"
|
||||||
@@ -574,30 +546,6 @@ AdvSceneSwitcher.sceneGroupTab.exists="Sahne Grubu veya Sahne adı zaten var"
|
|||||||
AdvSceneSwitcher.sceneGroupTab.help="Sahne Grupları, normal bir sahne gibi bir hedef olarak seçilebilir.\n\nAdından da anlaşılacağı gibi, bir sahne grubu birden fazla sahneden oluşan bir koleksiyondur.\nSahne grubu, yapılandırılmış ayarlara bağlı olarak kendisine atanan sahneler listesinde ilerleyecektir. sağ tarafta bulunabilir.\n\nSahne grubunu listedeki bir sonraki sahneye geçecek şekilde yapılandırabilirsiniz:\nSahne grubu birkaç kez hedef olarak seçildikten sonra.\nBelirli bir süre sonra geçti.\nVeya rastgele.\n\nÖrneğin, sahneleri içeren bir sahne grubu ...\nSahne 1\nSahne 2\nSahne 3 \n... ilk seçildiğinde \"Sahne 1\"i etkinleştirecek bir hedef olarak.\nİkinci kez \"Sahne 2\"yi etkinleştirecek.\nKalan zamanlar \"Scene 3\" etkinleştirilecek.\n\nYeni bir sahne grubu eklemek için aşağıdaki vurgulanan artı sembolüne tıklayın."
|
AdvSceneSwitcher.sceneGroupTab.help="Sahne Grupları, normal bir sahne gibi bir hedef olarak seçilebilir.\n\nAdından da anlaşılacağı gibi, bir sahne grubu birden fazla sahneden oluşan bir koleksiyondur.\nSahne grubu, yapılandırılmış ayarlara bağlı olarak kendisine atanan sahneler listesinde ilerleyecektir. sağ tarafta bulunabilir.\n\nSahne grubunu listedeki bir sonraki sahneye geçecek şekilde yapılandırabilirsiniz:\nSahne grubu birkaç kez hedef olarak seçildikten sonra.\nBelirli bir süre sonra geçti.\nVeya rastgele.\n\nÖrneğin, sahneleri içeren bir sahne grubu ...\nSahne 1\nSahne 2\nSahne 3 \n... ilk seçildiğinde \"Sahne 1\"i etkinleştirecek bir hedef olarak.\nİkinci kez \"Sahne 2\"yi etkinleştirecek.\nKalan zamanlar \"Scene 3\" etkinleştirilecek.\n\nYeni bir sahne grubu eklemek için aşağıdaki vurgulanan artı sembolüne tıklayın."
|
||||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="Soldan değiştirmek istediğiniz sahne grubunu seçin.\n\nYukarıdaki sahneyi seçip aşağıdaki artı simgesini tıklayarak bu sahne grubuna eklemek için bir sahne seçin.\n\nAynı sahneye birden fazla sahne eklenebilir grup."
|
AdvSceneSwitcher.sceneGroupTab.scenes.help="Soldan değiştirmek istediğiniz sahne grubunu seçin.\n\nYukarıdaki sahneyi seçip aşağıdaki artı simgesini tıklayarak bu sahne grubuna eklemek için bir sahne seçin.\n\nAynı sahneye birden fazla sahne eklenebilir grup."
|
||||||
|
|
||||||
; Scene Trigger Tab
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.title="Sahne Tetikleyicileri"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--tetikleyiciyi seçin--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="aktif"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="aktif değil"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="uzaklaştı"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--eylemi seç--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="Kayda başla"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="Kaydı duraklat"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="kaydı duraklatma"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="Kaydetmeyi bırak"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="Akışı durdur"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="Akışı başlat"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="Yeniden oynatma arabelleğini başlat"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="Tekrar arabelleğini durdur"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="Kaynağı sessize al"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="Kaynağı sesi aç"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="Sahne değiştiriciyi başlat"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="Sahne değiştiriciyi durdur"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="Sanal kamerayı başlat"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="Sanal kamerayı durdur"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.entry="Şundan {{scenes}} {{triggers}} {{actions}} {{audioSources}} sonra {{duration}}"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.help="Bu sekme, kaydı veya akışı durdurma gibi sahne değişikliklerinde eylemleri tetiklemenize olanak tanır."
|
|
||||||
|
|
||||||
; Hotkey
|
; Hotkey
|
||||||
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Advanced Scene Switcher'ı başlatın"
|
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Advanced Scene Switcher'ı başlatın"
|
||||||
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Gelişmiş Sahne Değiştiriciyi Durdurun"
|
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Gelişmiş Sahne Değiştiriciyi Durdurun"
|
||||||
@@ -645,7 +593,7 @@ AdvSceneSwitcher.stopped="Eklenti durdu"
|
|||||||
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Gelişmiş Sahne Değiştirici ilk kez başlatılıyor gibi görünüyor.<br>Lütfen <a href=\"https://github.com/ adresine bir göz atın. WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> için kılavuzlar ve örnekler listesi.<br>Yapmayın. eklentinin <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:# sayfasında soru sormaktan çekinmeyin OBS forumlarında 268bd2;\">konu</span></a>!</p></body></html>"
|
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Gelişmiş Sahne Değiştirici ilk kez başlatılıyor gibi görünüyor.<br>Lütfen <a href=\"https://github.com/ adresine bir göz atın. WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> için kılavuzlar ve örnekler listesi.<br>Yapmayın. eklentinin <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:# sayfasında soru sormaktan çekinmeyin OBS forumlarında 268bd2;\">konu</span></a>!</p></body></html>"
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="millisaniye"
|
AdvSceneSwitcher.unit.milliseconds="millisaniye"
|
||||||
AdvSceneSwitcher.unit.secends="saniye"
|
AdvSceneSwitcher.unit.seconds="saniye"
|
||||||
AdvSceneSwitcher.unit.minutes="dakika"
|
AdvSceneSwitcher.unit.minutes="dakika"
|
||||||
AdvSceneSwitcher.unit.hours="saat"
|
AdvSceneSwitcher.unit.hours="saat"
|
||||||
AdvSceneSwitcher.duration.condition.none="Zaman kısıtlaması yok"
|
AdvSceneSwitcher.duration.condition.none="Zaman kısıtlaması yok"
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ AdvSceneSwitcher.generalTab.status.autoStart.streaming="推流"
|
|||||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="录制和推流"
|
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="录制和推流"
|
||||||
AdvSceneSwitcher.generalTab.status.checkInterval="检查切换条件时间间隔"
|
AdvSceneSwitcher.generalTab.status.checkInterval="检查切换条件时间间隔"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior="全局行为"
|
AdvSceneSwitcher.generalTab.generalBehavior="全局行为"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="如果不符合任何切换条件"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch="如果不符合任何切换条件"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="时间精度最高只能达到配置的轮询间隔"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatchDelay.tooltip="时间精度最高只能达到配置的轮询间隔"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="不切换"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.dontSwitch="不切换"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="切换到随机场景列表中任意随机场景"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchToRandom="切换到随机场景列表中任意随机场景"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="切换到"
|
AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchTo="切换到"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="执行完操作后,跳过执行操作,为"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="执行完操作后,跳过执行操作,为"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="在此期间,可能的匹配项将被忽略!"
|
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="在此期间,可能的匹配项将被忽略!"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="详细日志输出"
|
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="详细日志输出"
|
||||||
@@ -101,7 +101,7 @@ 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.currentRegisterHotkeys="使用快捷键控制所选宏的暂停状态"
|
||||||
AdvSceneSwitcher.macroTab.currentRegisterDock="注册停靠小部件以控制所选宏的暂停状态或手动运行它"
|
AdvSceneSwitcher.macroTab.currentRegisterDock="注册停靠小部件以控制所选宏的暂停状态或手动运行它"
|
||||||
AdvSceneSwitcher.macroTab.currentDockAddRunButton="添加按钮以运行宏"
|
AdvSceneSwitcher.macroTab.currentDockAddRunButton="添加按钮以运行宏"
|
||||||
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="添加按钮以暂停或取消暂停宏"
|
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="添加按钮以暂停或取消暂停宏"
|
||||||
@@ -159,8 +159,6 @@ AdvSceneSwitcher.condition.scene.type.currentPattern="当前场景匹配"
|
|||||||
AdvSceneSwitcher.condition.scene.type.previousPattern="上一个场景匹配"
|
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.line2="{{useTransitionTargetScene}}"
|
|
||||||
AdvSceneSwitcher.condition.window="窗口"
|
AdvSceneSwitcher.condition.window="窗口"
|
||||||
AdvSceneSwitcher.condition.window.entry.window="{{checkTitle}}窗口标题匹配{{windowRegex}}{{windows}}"
|
AdvSceneSwitcher.condition.window.entry.window="{{checkTitle}}窗口标题匹配{{windowRegex}}{{windows}}"
|
||||||
AdvSceneSwitcher.condition.window.entry.fullscreen="{{fullscreen}}窗口为全屏"
|
AdvSceneSwitcher.condition.window.entry.fullscreen="{{fullscreen}}窗口为全屏"
|
||||||
@@ -259,7 +257,6 @@ 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.state.keyFrameInterval="关键帧间隔等于"
|
||||||
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="录制暂停"
|
||||||
@@ -549,7 +546,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="下移"
|
|||||||
AdvSceneSwitcher.action.sceneOrder.type.moveTop="顶部"
|
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}}{{sources2}}{{position}}"
|
||||||
AdvSceneSwitcher.action.sceneTransform="场景项目转换"
|
AdvSceneSwitcher.action.sceneTransform="场景项目转换"
|
||||||
AdvSceneSwitcher.action.sceneTransform.getTransform="获得转换"
|
AdvSceneSwitcher.action.sceneTransform.getTransform="获得转换"
|
||||||
AdvSceneSwitcher.action.sceneTransform.entry="在{{scenes}}{{action}}{{rotation}}{{sources}}{{settingSelection}}{{singleSettingValue}}"
|
AdvSceneSwitcher.action.sceneTransform.entry="在{{scenes}}{{action}}{{rotation}}{{sources}}{{settingSelection}}{{singleSettingValue}}"
|
||||||
@@ -592,7 +589,7 @@ AdvSceneSwitcher.action.screenshot.type.source="来源"
|
|||||||
AdvSceneSwitcher.action.screenshot.type.scene="场景"
|
AdvSceneSwitcher.action.screenshot.type.scene="场景"
|
||||||
AdvSceneSwitcher.action.screenshot.mainOutput="OBS 预览画面"
|
AdvSceneSwitcher.action.screenshot.mainOutput="OBS 预览画面"
|
||||||
AdvSceneSwitcher.action.screenshot.blackscreenNote="源和场景并不总是呈现,可能会导致屏幕截图的某些部分保持空白。"
|
AdvSceneSwitcher.action.screenshot.blackscreenNote="源和场景并不总是呈现,可能会导致屏幕截图的某些部分保持空白。"
|
||||||
AdvSceneSwitcher.action.screenshot.entry="截图{{targetType}}{{sources}}{{scenes}}保存在{{saveType}}位置"
|
AdvSceneSwitcher.action.screenshot.entry="截图{{targetType}}{{sources}}{{scenes}}保存在{{saveType}}{{variables}}位置"
|
||||||
AdvSceneSwitcher.action.profile="配置文件"
|
AdvSceneSwitcher.action.profile="配置文件"
|
||||||
AdvSceneSwitcher.action.profile.entry="将活动配置文件切换到 {{profiles}}"
|
AdvSceneSwitcher.action.profile.entry="将活动配置文件切换到 {{profiles}}"
|
||||||
AdvSceneSwitcher.action.sceneCollection="场景集合"
|
AdvSceneSwitcher.action.sceneCollection="场景集合"
|
||||||
@@ -820,31 +817,6 @@ AdvSceneSwitcher.videoTab.entry="当 {{videoSources}} {{condition}} {{filePath}}
|
|||||||
AdvSceneSwitcher.videoTab.ignoreInactiveSource="除非源处于非活动状态"
|
AdvSceneSwitcher.videoTab.ignoreInactiveSource="除非源处于非活动状态"
|
||||||
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>此选项卡将允许您根据选定源的当前视频输出切换场景。<br/>请确保退出 <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> 以便更好地实现此功能.<br/><br/> 单击高亮显示的加号继续.</p></body></html>"
|
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>此选项卡将允许您根据选定源的当前视频输出切换场景。<br/>请确保退出 <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> 以便更好地实现此功能.<br/><br/> 单击高亮显示的加号继续.</p></body></html>"
|
||||||
|
|
||||||
; Network Tab
|
|
||||||
AdvSceneSwitcher.networkTab.title="网络"
|
|
||||||
AdvSceneSwitcher.networkTab.description="此选项卡将允许您远程控制另一个OBS实例的活动场景。\n请注意,所有OBS实例上的场景名称必须完全匹配."
|
|
||||||
AdvSceneSwitcher.networkTab.warning="在本地网络之外运行服务器将允许第三方读取活动场景."
|
|
||||||
AdvSceneSwitcher.networkTab.server="启动服务器(向所有连接的客户端发送场景切换消息)"
|
|
||||||
AdvSceneSwitcher.networkTab.server.port="端口"
|
|
||||||
AdvSceneSwitcher.networkTab.server.lockToIPv4="锁定为仅使用IPv4将服务器"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendSceneChange="发送更改场景的消息"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="仅为自动场景切换发送消息"
|
|
||||||
AdvSceneSwitcher.networkTab.server.sendPreview="在Studio模式下运行时发送预览场景更改消息"
|
|
||||||
AdvSceneSwitcher.networkTab.startFailed.message="WebSockets服务器无法启动,可能是因为:\n-TCP端口%1当前可能正在该系统的其他位置使用,可能是由其他应用程序使用。请尝试在WebSocket服务器设置中设置其他TCP端口,或停止可能正在使用此端口的任何应用程序。\n-错误消息: %2"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.currentStatus="状态"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.notRunning="未运行"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.starting="启动中"
|
|
||||||
AdvSceneSwitcher.networkTab.server.status.running="运行中"
|
|
||||||
AdvSceneSwitcher.networkTab.server.restart="重新启动服务"
|
|
||||||
AdvSceneSwitcher.networkTab.client="启动客户端(接收场景切换消息)"
|
|
||||||
AdvSceneSwitcher.networkTab.client.address="主机名或IP地址"
|
|
||||||
AdvSceneSwitcher.networkTab.client.port="端口"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.currentStatus="状态"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.disconnected="未连接"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connecting="连接中"
|
|
||||||
AdvSceneSwitcher.networkTab.client.status.connected="已连接"
|
|
||||||
AdvSceneSwitcher.networkTab.client.reconnect="强制重新连接"
|
|
||||||
|
|
||||||
; Scene Group Tab
|
; Scene Group Tab
|
||||||
AdvSceneSwitcher.sceneGroupTab.title="场景组"
|
AdvSceneSwitcher.sceneGroupTab.title="场景组"
|
||||||
AdvSceneSwitcher.sceneGroupTab.list="场景组"
|
AdvSceneSwitcher.sceneGroupTab.list="场景组"
|
||||||
@@ -865,30 +837,6 @@ AdvSceneSwitcher.sceneGroupTab.exists="场景组或场景名称已存在"
|
|||||||
AdvSceneSwitcher.sceneGroupTab.help="可以选择场景组作为目标,就像选择常规场景一样。\n\n名称表明场景组是多个场景的集合。\n场景组将根据配置的设置在其指定场景的列表中前进,可以在右侧找到。\n\n您可以将场景组配置为前进到列表中的下一个场景:\n在多次选择场景组作为目标后。\n在经过一定时间后。\n也可以是随机的。\n\n例如,包含场景的场景组…\n场景1\n场景2\n场景3\n。。。将在第一次选择“场景1”作为目标时激活它。\n第二次将激活“场景2”\n剩余时间将激活“场景3”。\n\n单击下面突出显示的加号以添加新的场景组."
|
AdvSceneSwitcher.sceneGroupTab.help="可以选择场景组作为目标,就像选择常规场景一样。\n\n名称表明场景组是多个场景的集合。\n场景组将根据配置的设置在其指定场景的列表中前进,可以在右侧找到。\n\n您可以将场景组配置为前进到列表中的下一个场景:\n在多次选择场景组作为目标后。\n在经过一定时间后。\n也可以是随机的。\n\n例如,包含场景的场景组…\n场景1\n场景2\n场景3\n。。。将在第一次选择“场景1”作为目标时激活它。\n第二次将激活“场景2”\n剩余时间将激活“场景3”。\n\n单击下面突出显示的加号以添加新的场景组."
|
||||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="在左侧选择要修改的场景组。\n\n通过选择上面的场景并单击下面的加号,选择要添加到此场景组的场景。\n\n可以多次将场景添加到同一场景组."
|
AdvSceneSwitcher.sceneGroupTab.scenes.help="在左侧选择要修改的场景组。\n\n通过选择上面的场景并单击下面的加号,选择要添加到此场景组的场景。\n\n可以多次将场景添加到同一场景组."
|
||||||
|
|
||||||
; Scene Trigger Tab
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.title="场景触发器"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--选择触发器--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="已激活"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="未激活"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="离开"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--选择动作--"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="开始录制"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="暂停录制"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="取消暂停录制"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="停止录制"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="停止推流"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="开始推流"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="启动重播缓冲区"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="停止重放缓冲区"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="静音源"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="取消静音源"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="启动场景切换程序"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="停止场景切换"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="启动虚拟摄像机"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="停止虚拟摄像机"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.entry="当 {{scenes}} {{triggers}} {{actions}} {{audioSources}} 在 {{duration}} 后"
|
|
||||||
AdvSceneSwitcher.sceneTriggerTab.help="此选项卡允许您在场景更改时触发操作,如停止录制或流式处理."
|
|
||||||
|
|
||||||
; Hotkey
|
; Hotkey
|
||||||
AdvSceneSwitcher.hotkey.startSwitcherHotkey="启动高级场景切换器"
|
AdvSceneSwitcher.hotkey.startSwitcherHotkey="启动高级场景切换器"
|
||||||
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="停止高级场景切换器"
|
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="停止高级场景切换器"
|
||||||
@@ -1048,7 +996,7 @@ AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>这似乎是第一次
|
|||||||
AdvSceneSwitcher.deprecatedTabWarning="此选项卡的开发已停止!请考虑转换为使用宏来代替。\n可以在“常规”选项卡上禁用此提示."
|
AdvSceneSwitcher.deprecatedTabWarning="此选项卡的开发已停止!请考虑转换为使用宏来代替。\n可以在“常规”选项卡上禁用此提示."
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="毫秒"
|
AdvSceneSwitcher.unit.milliseconds="毫秒"
|
||||||
AdvSceneSwitcher.unit.secends="秒"
|
AdvSceneSwitcher.unit.seconds="秒"
|
||||||
AdvSceneSwitcher.unit.minutes="分钟"
|
AdvSceneSwitcher.unit.minutes="分钟"
|
||||||
AdvSceneSwitcher.unit.hours="小时"
|
AdvSceneSwitcher.unit.hours="小时"
|
||||||
AdvSceneSwitcher.duration.condition.none="没有时间限制"
|
AdvSceneSwitcher.duration.condition.none="没有时间限制"
|
||||||
|
|||||||
73
deps/obs-websocket/lib/obs-websocket-api.h
vendored
73
deps/obs-websocket/lib/obs-websocket-api.h
vendored
@@ -29,7 +29,8 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void *obs_websocket_vendor;
|
typedef void *obs_websocket_vendor;
|
||||||
typedef void (*obs_websocket_request_callback_function)(obs_data_t *, obs_data_t *, void *);
|
typedef void (*obs_websocket_request_callback_function)(obs_data_t *,
|
||||||
|
obs_data_t *, void *);
|
||||||
|
|
||||||
struct obs_websocket_request_response {
|
struct obs_websocket_request_response {
|
||||||
unsigned int status_code;
|
unsigned int status_code;
|
||||||
@@ -44,7 +45,7 @@ struct obs_websocket_request_callback {
|
|||||||
void *priv_data;
|
void *priv_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline proc_handler_t *_ph;
|
static proc_handler_t *_ph;
|
||||||
|
|
||||||
/* ==================== INTERNAL API FUNCTIONS ==================== */
|
/* ==================== INTERNAL API FUNCTIONS ==================== */
|
||||||
|
|
||||||
@@ -53,9 +54,10 @@ static inline proc_handler_t *obs_websocket_get_ph(void)
|
|||||||
proc_handler_t *global_ph = obs_get_proc_handler();
|
proc_handler_t *global_ph = obs_get_proc_handler();
|
||||||
assert(global_ph != NULL);
|
assert(global_ph != NULL);
|
||||||
|
|
||||||
calldata_t cd = {0};
|
calldata_t cd = {0, 0, 0, 0};
|
||||||
if (!proc_handler_call(global_ph, "obs_websocket_api_get_ph", &cd))
|
if (!proc_handler_call(global_ph, "obs_websocket_api_get_ph", &cd))
|
||||||
blog(LOG_DEBUG, "Unable to fetch obs-websocket proc handler object. obs-websocket not installed?");
|
blog(LOG_DEBUG,
|
||||||
|
"Unable to fetch obs-websocket proc handler object. obs-websocket not installed?");
|
||||||
proc_handler_t *ret = (proc_handler_t *)calldata_ptr(&cd, "ph");
|
proc_handler_t *ret = (proc_handler_t *)calldata_ptr(&cd, "ph");
|
||||||
calldata_free(&cd);
|
calldata_free(&cd);
|
||||||
|
|
||||||
@@ -69,7 +71,9 @@ static inline bool obs_websocket_ensure_ph(void)
|
|||||||
return _ph != NULL;
|
return _ph != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool obs_websocket_vendor_run_simple_proc(obs_websocket_vendor vendor, const char *proc_name, calldata_t *cd)
|
static inline bool
|
||||||
|
obs_websocket_vendor_run_simple_proc(obs_websocket_vendor vendor,
|
||||||
|
const char *proc_name, calldata_t *cd)
|
||||||
{
|
{
|
||||||
if (!obs_websocket_ensure_ph())
|
if (!obs_websocket_ensure_ph())
|
||||||
return false;
|
return false;
|
||||||
@@ -91,12 +95,12 @@ static inline unsigned int obs_websocket_get_api_version(void)
|
|||||||
if (!obs_websocket_ensure_ph())
|
if (!obs_websocket_ensure_ph())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
calldata_t cd = {0};
|
calldata_t cd = {0, 0, 0, 0};
|
||||||
|
|
||||||
if (!proc_handler_call(_ph, "get_api_version", &cd))
|
if (!proc_handler_call(_ph, "get_api_version", &cd))
|
||||||
return 1; // API v1 does not include get_api_version
|
return 1; // API v1 does not include get_api_version
|
||||||
|
|
||||||
unsigned int ret = calldata_int(&cd, "version");
|
unsigned int ret = (unsigned int)calldata_int(&cd, "version");
|
||||||
|
|
||||||
calldata_free(&cd);
|
calldata_free(&cd);
|
||||||
|
|
||||||
@@ -104,7 +108,12 @@ static inline unsigned int obs_websocket_get_api_version(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calls an obs-websocket request. Free response with `obs_websocket_request_response_free()`
|
// Calls an obs-websocket request. Free response with `obs_websocket_request_response_free()`
|
||||||
static inline obs_websocket_request_response *obs_websocket_call_request(const char *request_type, obs_data_t *request_data = NULL)
|
static inline struct obs_websocket_request_response *
|
||||||
|
obs_websocket_call_request(const char *request_type, obs_data_t *request_data
|
||||||
|
#ifdef __cplusplus
|
||||||
|
= NULL
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (!obs_websocket_ensure_ph())
|
if (!obs_websocket_ensure_ph())
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -113,14 +122,16 @@ static inline obs_websocket_request_response *obs_websocket_call_request(const c
|
|||||||
if (request_data)
|
if (request_data)
|
||||||
request_data_string = obs_data_get_json(request_data);
|
request_data_string = obs_data_get_json(request_data);
|
||||||
|
|
||||||
calldata_t cd = {0};
|
calldata_t cd = {0, 0, 0, 0};
|
||||||
|
|
||||||
calldata_set_string(&cd, "request_type", request_type);
|
calldata_set_string(&cd, "request_type", request_type);
|
||||||
calldata_set_string(&cd, "request_data", request_data_string);
|
calldata_set_string(&cd, "request_data", request_data_string);
|
||||||
|
|
||||||
proc_handler_call(_ph, "call_request", &cd);
|
proc_handler_call(_ph, "call_request", &cd);
|
||||||
|
|
||||||
auto ret = (struct obs_websocket_request_response *)calldata_ptr(&cd, "response");
|
struct obs_websocket_request_response *ret =
|
||||||
|
(struct obs_websocket_request_response *)calldata_ptr(
|
||||||
|
&cd, "response");
|
||||||
|
|
||||||
calldata_free(&cd);
|
calldata_free(&cd);
|
||||||
|
|
||||||
@@ -128,7 +139,8 @@ static inline obs_websocket_request_response *obs_websocket_call_request(const c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Free a request response object returned by `obs_websocket_call_request()`
|
// Free a request response object returned by `obs_websocket_call_request()`
|
||||||
static inline void obs_websocket_request_response_free(struct obs_websocket_request_response *response)
|
static inline void obs_websocket_request_response_free(
|
||||||
|
struct obs_websocket_request_response *response)
|
||||||
{
|
{
|
||||||
if (!response)
|
if (!response)
|
||||||
return;
|
return;
|
||||||
@@ -144,12 +156,13 @@ static inline void obs_websocket_request_response_free(struct obs_websocket_requ
|
|||||||
|
|
||||||
// ALWAYS CALL ONLY VIA `obs_module_post_load()` CALLBACK!
|
// ALWAYS CALL ONLY VIA `obs_module_post_load()` CALLBACK!
|
||||||
// Registers a new "vendor" (Example: obs-ndi)
|
// Registers a new "vendor" (Example: obs-ndi)
|
||||||
static inline obs_websocket_vendor obs_websocket_register_vendor(const char *vendor_name)
|
static inline obs_websocket_vendor
|
||||||
|
obs_websocket_register_vendor(const char *vendor_name)
|
||||||
{
|
{
|
||||||
if (!obs_websocket_ensure_ph())
|
if (!obs_websocket_ensure_ph())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
calldata_t cd = {0};
|
calldata_t cd = {0, 0, 0, 0};
|
||||||
|
|
||||||
calldata_set_string(&cd, "name", vendor_name);
|
calldata_set_string(&cd, "name", vendor_name);
|
||||||
|
|
||||||
@@ -161,32 +174,37 @@ static inline obs_websocket_vendor obs_websocket_register_vendor(const char *ven
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Registers a new request for a vendor
|
// Registers a new request for a vendor
|
||||||
static inline bool obs_websocket_vendor_register_request(obs_websocket_vendor vendor, const char *request_type,
|
static inline bool obs_websocket_vendor_register_request(
|
||||||
obs_websocket_request_callback_function request_callback, void *priv_data)
|
obs_websocket_vendor vendor, const char *request_type,
|
||||||
|
obs_websocket_request_callback_function request_callback,
|
||||||
|
void *priv_data)
|
||||||
{
|
{
|
||||||
calldata_t cd = {0};
|
calldata_t cd = {0, 0, 0, 0};
|
||||||
|
|
||||||
struct obs_websocket_request_callback cb = {};
|
struct obs_websocket_request_callback cb = {request_callback,
|
||||||
cb.callback = request_callback;
|
priv_data};
|
||||||
cb.priv_data = priv_data;
|
|
||||||
|
|
||||||
calldata_set_string(&cd, "type", request_type);
|
calldata_set_string(&cd, "type", request_type);
|
||||||
calldata_set_ptr(&cd, "callback", &cb);
|
calldata_set_ptr(&cd, "callback", &cb);
|
||||||
|
|
||||||
bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_register", &cd);
|
bool success = obs_websocket_vendor_run_simple_proc(
|
||||||
|
vendor, "vendor_request_register", &cd);
|
||||||
calldata_free(&cd);
|
calldata_free(&cd);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unregisters an existing vendor request
|
// Unregisters an existing vendor request
|
||||||
static inline bool obs_websocket_vendor_unregister_request(obs_websocket_vendor vendor, const char *request_type)
|
static inline bool
|
||||||
|
obs_websocket_vendor_unregister_request(obs_websocket_vendor vendor,
|
||||||
|
const char *request_type)
|
||||||
{
|
{
|
||||||
calldata_t cd = {0};
|
calldata_t cd = {0, 0, 0, 0};
|
||||||
|
|
||||||
calldata_set_string(&cd, "type", request_type);
|
calldata_set_string(&cd, "type", request_type);
|
||||||
|
|
||||||
bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_unregister", &cd);
|
bool success = obs_websocket_vendor_run_simple_proc(
|
||||||
|
vendor, "vendor_request_unregister", &cd);
|
||||||
calldata_free(&cd);
|
calldata_free(&cd);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
@@ -194,14 +212,17 @@ static inline bool obs_websocket_vendor_unregister_request(obs_websocket_vendor
|
|||||||
|
|
||||||
// Does not affect event_data refcount.
|
// Does not affect event_data refcount.
|
||||||
// Emits an event under the vendor's name
|
// Emits an event under the vendor's name
|
||||||
static inline bool obs_websocket_vendor_emit_event(obs_websocket_vendor vendor, const char *event_name, obs_data_t *event_data)
|
static inline bool obs_websocket_vendor_emit_event(obs_websocket_vendor vendor,
|
||||||
|
const char *event_name,
|
||||||
|
obs_data_t *event_data)
|
||||||
{
|
{
|
||||||
calldata_t cd = {0};
|
calldata_t cd = {0, 0, 0, 0};
|
||||||
|
|
||||||
calldata_set_string(&cd, "type", event_name);
|
calldata_set_string(&cd, "type", event_name);
|
||||||
calldata_set_ptr(&cd, "data", (void *)event_data);
|
calldata_set_ptr(&cd, "data", (void *)event_data);
|
||||||
|
|
||||||
bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_event_emit", &cd);
|
bool success = obs_websocket_vendor_run_simple_proc(
|
||||||
|
vendor, "vendor_event_emit", &cd);
|
||||||
calldata_free(&cd);
|
calldata_free(&cd);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -14,8 +14,8 @@
|
|||||||
#include "tab-helpers.hpp"
|
#include "tab-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "websocket-api.hpp"
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
@@ -85,8 +85,8 @@ static void DisplayMissingDataDirWarning()
|
|||||||
"Please check installation instructions!\n\n"
|
"Please check installation instructions!\n\n"
|
||||||
"Data most likely expected at:\n\n";
|
"Data most likely expected at:\n\n";
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
msg += QString::fromStdString(
|
|
||||||
(std::filesystem::current_path().string()));
|
msg += QDir::currentPath();
|
||||||
msg += "/";
|
msg += "/";
|
||||||
#endif
|
#endif
|
||||||
msg += obs_get_module_data_path(obs_current_module());
|
msg += obs_get_module_data_path(obs_current_module());
|
||||||
@@ -126,9 +126,7 @@ void AdvSceneSwitcher::LoadUI()
|
|||||||
SetupTimeTab();
|
SetupTimeTab();
|
||||||
SetupAudioTab();
|
SetupAudioTab();
|
||||||
SetupVideoTab();
|
SetupVideoTab();
|
||||||
SetupNetworkTab();
|
|
||||||
SetupSceneGroupTab();
|
SetupSceneGroupTab();
|
||||||
SetupTriggerTab();
|
|
||||||
SetupMacroTab();
|
SetupMacroTab();
|
||||||
SetupOtherTabs(ui->tabWidget);
|
SetupOtherTabs(ui->tabWidget);
|
||||||
|
|
||||||
@@ -457,15 +455,8 @@ void SwitcherData::Start()
|
|||||||
|
|
||||||
// Will be overwritten quickly but might be useful
|
// Will be overwritten quickly but might be useful
|
||||||
writeToStatusFile("Advanced Scene Switcher running");
|
writeToStatusFile("Advanced Scene Switcher running");
|
||||||
}
|
SendWebsocketVendorEvent("AdvancedSceneSwitcherStarted",
|
||||||
|
nullptr);
|
||||||
if (networkConfig.ServerEnabled) {
|
|
||||||
server.start(networkConfig.ServerPort,
|
|
||||||
networkConfig.LockToIPv4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkConfig.ClientEnabled) {
|
|
||||||
client.connect(networkConfig.GetClientUri());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showSystemTrayNotifications) {
|
if (showSystemTrayNotifications) {
|
||||||
@@ -493,11 +484,12 @@ void SwitcherData::Stop()
|
|||||||
delete th;
|
delete th;
|
||||||
th = nullptr;
|
th = nullptr;
|
||||||
writeToStatusFile("Advanced Scene Switcher stopped");
|
writeToStatusFile("Advanced Scene Switcher stopped");
|
||||||
|
if (!obsIsShuttingDown) {
|
||||||
|
SendWebsocketVendorEvent("AdvancedSceneSwitcherStopped",
|
||||||
|
nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server.stop();
|
|
||||||
client.disconnect();
|
|
||||||
|
|
||||||
if (showSystemTrayNotifications) {
|
if (showSystemTrayNotifications) {
|
||||||
DisplayTrayMessage(
|
DisplayTrayMessage(
|
||||||
obs_module_text("AdvSceneSwitcher.pluginName"),
|
obs_module_text("AdvSceneSwitcher.pluginName"),
|
||||||
@@ -565,12 +557,7 @@ static void handleSceneChange()
|
|||||||
GetWeakSourceName(switcher->previousScene).c_str());
|
GetWeakSourceName(switcher->previousScene).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
switcher->checkTriggers();
|
|
||||||
switcher->checkDefaultSceneTransitions();
|
switcher->checkDefaultSceneTransitions();
|
||||||
|
|
||||||
if (switcher->networkConfig.ShouldSendFrontendSceneChange()) {
|
|
||||||
switcher->server.sendMessage({ws.Get(), nullptr, 0});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setLiveTime()
|
static void setLiveTime()
|
||||||
@@ -599,17 +586,6 @@ static void checkAutoStartStreaming()
|
|||||||
switcher->Start();
|
switcher->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handlePeviewSceneChange()
|
|
||||||
{
|
|
||||||
if (switcher->networkConfig.ShouldSendPrviewSceneChange()) {
|
|
||||||
OBSSourceAutoRelease source =
|
|
||||||
obs_frontend_get_current_preview_scene();
|
|
||||||
OBSWeakSourceAutoRelease weak =
|
|
||||||
obs_source_get_weak_source(source);
|
|
||||||
switcher->server.sendMessage({weak.Get(), nullptr, 0}, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleTransitionEnd()
|
static void handleTransitionEnd()
|
||||||
{
|
{
|
||||||
GetMacroTransitionCV().notify_all();
|
GetMacroTransitionCV().notify_all();
|
||||||
@@ -687,9 +663,6 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
|||||||
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
|
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
|
||||||
handleSceneChange();
|
handleSceneChange();
|
||||||
break;
|
break;
|
||||||
case OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED:
|
|
||||||
handlePeviewSceneChange();
|
|
||||||
break;
|
|
||||||
case OBS_FRONTEND_EVENT_RECORDING_STARTED:
|
case OBS_FRONTEND_EVENT_RECORDING_STARTED:
|
||||||
setLiveTime();
|
setLiveTime();
|
||||||
checkAutoStartRecording();
|
checkAutoStartRecording();
|
||||||
@@ -762,11 +735,6 @@ void OpenSettingsWindow()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *GetSettingsWindow()
|
|
||||||
{
|
|
||||||
return SettingsWindowIsOpened() ? AdvSceneSwitcher::window : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::HighligthMacroSettingsButton(bool enable)
|
void AdvSceneSwitcher::HighligthMacroSettingsButton(bool enable)
|
||||||
{
|
{
|
||||||
static QObject *highlight = nullptr;
|
static QObject *highlight = nullptr;
|
||||||
|
|||||||
@@ -359,24 +359,6 @@ public slots:
|
|||||||
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_serverPort_valueChanged(int value);
|
|
||||||
void on_lockToIPv4_stateChanged(int state);
|
|
||||||
void on_serverRestart_clicked();
|
|
||||||
void UpdateServerStatus();
|
|
||||||
void on_clientSettings_toggled(bool on);
|
|
||||||
void on_clientHostname_textChanged(const QString &text);
|
|
||||||
void on_clientPort_valueChanged(int value);
|
|
||||||
void on_sendSceneChange_stateChanged(int state);
|
|
||||||
void on_restrictSend_stateChanged(int state);
|
|
||||||
void on_sendPreview_stateChanged(int state);
|
|
||||||
void on_clientReconnect_clicked();
|
|
||||||
void UpdateClientStatus();
|
|
||||||
|
|
||||||
// Scene group tab
|
// Scene group tab
|
||||||
public:
|
public:
|
||||||
void SetupSceneGroupTab();
|
void SetupSceneGroupTab();
|
||||||
@@ -398,20 +380,12 @@ signals:
|
|||||||
void SceneGroupRemoved(const QString &name);
|
void SceneGroupRemoved(const QString &name);
|
||||||
void SceneGroupRenamed(const QString &oldName, const QString newName);
|
void SceneGroupRenamed(const QString &oldName, const QString newName);
|
||||||
|
|
||||||
// Trigger tab
|
|
||||||
public:
|
|
||||||
void SetupTriggerTab();
|
|
||||||
public slots:
|
|
||||||
void on_triggerAdd_clicked();
|
|
||||||
void on_triggerRemove_clicked();
|
|
||||||
void on_triggerUp_clicked();
|
|
||||||
void on_triggerDown_clicked();
|
|
||||||
|
|
||||||
/* --- End of legacy tab section --- */
|
/* --- End of legacy tab section --- */
|
||||||
|
private:
|
||||||
|
void SetCheckIntervalTooLowVisibility() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
void OpenSettingsWindow();
|
void OpenSettingsWindow();
|
||||||
QWidget *GetSettingsWindow();
|
|
||||||
void HighligthMacroSettingsButton(bool enable);
|
void HighligthMacroSettingsButton(bool enable);
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -150,6 +150,8 @@ void AdvSceneSwitcher::on_checkInterval_valueChanged(int value)
|
|||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->interval = value;
|
switcher->interval = value;
|
||||||
|
|
||||||
|
SetCheckIntervalTooLowVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::closeEvent(QCloseEvent *)
|
void AdvSceneSwitcher::closeEvent(QCloseEvent *)
|
||||||
@@ -216,7 +218,6 @@ static bool isLegacyTab(const QString &name)
|
|||||||
{
|
{
|
||||||
return name == obs_module_text(
|
return name == obs_module_text(
|
||||||
"AdvSceneSwitcher.sceneGroupTab.title") ||
|
"AdvSceneSwitcher.sceneGroupTab.title") ||
|
||||||
name == obs_module_text("AdvSceneSwitcher.networkTab.title") ||
|
|
||||||
name == obs_module_text(
|
name == obs_module_text(
|
||||||
"AdvSceneSwitcher.transitionTab.title") ||
|
"AdvSceneSwitcher.transitionTab.title") ||
|
||||||
name == obs_module_text(
|
name == obs_module_text(
|
||||||
@@ -234,9 +235,7 @@ static bool isLegacyTab(const QString &name)
|
|||||||
"AdvSceneSwitcher.sceneSequenceTab.title") ||
|
"AdvSceneSwitcher.sceneSequenceTab.title") ||
|
||||||
name == obs_module_text("AdvSceneSwitcher.audioTab.title") ||
|
name == obs_module_text("AdvSceneSwitcher.audioTab.title") ||
|
||||||
name == obs_module_text("AdvSceneSwitcher.videoTab.title") ||
|
name == obs_module_text("AdvSceneSwitcher.videoTab.title") ||
|
||||||
name == obs_module_text("AdvSceneSwitcher.pauseTab.title") ||
|
name == obs_module_text("AdvSceneSwitcher.pauseTab.title");
|
||||||
name == obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.title");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_hideLegacyTabs_stateChanged(int state)
|
void AdvSceneSwitcher::on_hideLegacyTabs_stateChanged(int state)
|
||||||
@@ -248,6 +247,10 @@ void AdvSceneSwitcher::on_hideLegacyTabs_stateChanged(int state)
|
|||||||
ui->tabWidget->setTabVisible(idx, !state);
|
ui->tabWidget->setTabVisible(idx, !state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Changing priority of legacy tabs will very likely not be necessary if
|
||||||
|
// the legacy tabs are hidden
|
||||||
|
ui->priorityBox->setVisible(!switcher->hideLegacyTabs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::SetDeprecationWarnings()
|
void AdvSceneSwitcher::SetDeprecationWarnings()
|
||||||
@@ -456,8 +459,6 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
|
|||||||
loadTimeSwitches(obj);
|
loadTimeSwitches(obj);
|
||||||
loadAudioSwitches(obj);
|
loadAudioSwitches(obj);
|
||||||
loadVideoSwitches(obj);
|
loadVideoSwitches(obj);
|
||||||
loadNetworkSettings(obj);
|
|
||||||
loadSceneTriggers(obj);
|
|
||||||
LoadGeneralSettings(obj);
|
LoadGeneralSettings(obj);
|
||||||
LoadHotkeys(obj);
|
LoadHotkeys(obj);
|
||||||
LoadUISettings(obj);
|
LoadUISettings(obj);
|
||||||
@@ -492,8 +493,6 @@ void SwitcherData::SaveSettings(obs_data_t *obj)
|
|||||||
saveTimeSwitches(obj);
|
saveTimeSwitches(obj);
|
||||||
saveAudioSwitches(obj);
|
saveAudioSwitches(obj);
|
||||||
saveVideoSwitches(obj);
|
saveVideoSwitches(obj);
|
||||||
saveNetworkSwitches(obj);
|
|
||||||
saveSceneTriggers(obj);
|
|
||||||
SaveGeneralSettings(obj);
|
SaveGeneralSettings(obj);
|
||||||
SaveHotkeys(obj);
|
SaveHotkeys(obj);
|
||||||
SaveUISettings(obj);
|
SaveUISettings(obj);
|
||||||
@@ -527,6 +526,7 @@ void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
|
|||||||
static_cast<int>(autoStartEvent));
|
static_cast<int>(autoStartEvent));
|
||||||
|
|
||||||
obs_data_set_int(obj, "logLevel", static_cast<int>(logLevel));
|
obs_data_set_int(obj, "logLevel", static_cast<int>(logLevel));
|
||||||
|
obs_data_set_int(obj, "logLevelVersion", 1);
|
||||||
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);
|
||||||
@@ -583,6 +583,25 @@ void SwitcherData::LoadGeneralSettings(obs_data_t *obj)
|
|||||||
static_cast<AutoStart>(obs_data_get_int(obj, "autoStartEvent"));
|
static_cast<AutoStart>(obs_data_get_int(obj, "autoStartEvent"));
|
||||||
|
|
||||||
logLevel = static_cast<LogLevel>(obs_data_get_int(obj, "logLevel"));
|
logLevel = static_cast<LogLevel>(obs_data_get_int(obj, "logLevel"));
|
||||||
|
if (obs_data_get_int(obj, "logLevelVersion") < 1) {
|
||||||
|
enum OldLogLevel { DEFAULT, LOG_ACTION, VERBOSE };
|
||||||
|
OldLogLevel oldLogLevel = static_cast<OldLogLevel>(
|
||||||
|
obs_data_get_int(obj, "logLevel"));
|
||||||
|
switch (oldLogLevel) {
|
||||||
|
case DEFAULT:
|
||||||
|
logLevel = LogLevel::DEFAULT;
|
||||||
|
break;
|
||||||
|
case LOG_ACTION:
|
||||||
|
logLevel = LogLevel::LOG_ACTION;
|
||||||
|
break;
|
||||||
|
case VERBOSE:
|
||||||
|
logLevel = LogLevel::VERBOSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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");
|
||||||
@@ -810,6 +829,28 @@ static void setupGeneralTabInactiveWarning(QTabWidget *tabs)
|
|||||||
inactiveTimer->start();
|
inactiveTimer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void advss::AdvSceneSwitcher::SetCheckIntervalTooLowVisibility() const
|
||||||
|
{
|
||||||
|
auto macro = GetMacroWithInvalidConditionInterval();
|
||||||
|
if (!macro) {
|
||||||
|
ui->checkIntervalTooLowWarning->hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString labelTextFormat(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.generalTab.status.checkIntervalTooLow"));
|
||||||
|
const QString labelTooltipFormat(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.generalTab.status.checkIntervalTooLow.tooltip"));
|
||||||
|
const QString name = QString::fromStdString(macro->Name());
|
||||||
|
const QString duration = QString::fromStdString(
|
||||||
|
macro->GetCustomConditionCheckInterval().ToString());
|
||||||
|
|
||||||
|
ui->checkIntervalTooLowWarning->setText(labelTextFormat.arg(name));
|
||||||
|
ui->checkIntervalTooLowWarning->setToolTip(
|
||||||
|
labelTooltipFormat.arg(name).arg(duration).arg(name));
|
||||||
|
ui->checkIntervalTooLowWarning->show();
|
||||||
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::SetupGeneralTab()
|
void AdvSceneSwitcher::SetupGeneralTab()
|
||||||
{
|
{
|
||||||
PopulateSceneSelection(ui->noMatchSwitchScene, false);
|
PopulateSceneSelection(ui->noMatchSwitchScene, false);
|
||||||
@@ -831,13 +872,14 @@ void AdvSceneSwitcher::SetupGeneralTab()
|
|||||||
DurationSelection *noMatchDelay = new DurationSelection();
|
DurationSelection *noMatchDelay = new DurationSelection();
|
||||||
noMatchDelay->SetDuration(switcher->noMatchDelay);
|
noMatchDelay->SetDuration(switcher->noMatchDelay);
|
||||||
noMatchDelay->setToolTip(obs_module_text(
|
noMatchDelay->setToolTip(obs_module_text(
|
||||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip"));
|
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMatchDelay.tooltip"));
|
||||||
ui->noMatchLayout->addWidget(noMatchDelay);
|
ui->noMatchLayout->addWidget(noMatchDelay);
|
||||||
QWidget::connect(noMatchDelay,
|
QWidget::connect(noMatchDelay,
|
||||||
SIGNAL(DurationChanged(const Duration &)), this,
|
SIGNAL(DurationChanged(const Duration &)), this,
|
||||||
SLOT(NoMatchDelayDurationChanged(const Duration &)));
|
SLOT(NoMatchDelayDurationChanged(const Duration &)));
|
||||||
|
|
||||||
ui->checkInterval->setValue(switcher->interval);
|
ui->checkInterval->setValue(switcher->interval);
|
||||||
|
SetCheckIntervalTooLowVisibility();
|
||||||
|
|
||||||
ui->enableCooldown->setChecked(switcher->enableCooldown);
|
ui->enableCooldown->setChecked(switcher->enableCooldown);
|
||||||
ui->cooldownTime->setEnabled(switcher->enableCooldown);
|
ui->cooldownTime->setEnabled(switcher->enableCooldown);
|
||||||
|
|||||||
@@ -1,581 +0,0 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
|
||||||
#include "layout-helpers.hpp"
|
|
||||||
#include "selection-helpers.hpp"
|
|
||||||
#include "source-helpers.hpp"
|
|
||||||
#include "switcher-data.hpp"
|
|
||||||
#include "ui-helpers.hpp"
|
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
#include <obs-frontend-api.h>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
namespace advss {
|
|
||||||
|
|
||||||
bool SceneTrigger::pause = false;
|
|
||||||
static QObject *addPulse = nullptr;
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_triggerAdd_clicked()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->sceneTriggers.emplace_back();
|
|
||||||
|
|
||||||
listAddClicked(ui->sceneTriggers,
|
|
||||||
new SceneTriggerWidget(this,
|
|
||||||
&switcher->sceneTriggers.back()),
|
|
||||||
addPulse);
|
|
||||||
|
|
||||||
ui->triggerHelp->setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_triggerRemove_clicked()
|
|
||||||
{
|
|
||||||
QListWidgetItem *item = ui->sceneTriggers->currentItem();
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
int idx = ui->sceneTriggers->currentRow();
|
|
||||||
auto &switches = switcher->sceneTriggers;
|
|
||||||
switches.erase(switches.begin() + idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_triggerUp_clicked()
|
|
||||||
{
|
|
||||||
int index = ui->sceneTriggers->currentRow();
|
|
||||||
if (!listMoveUp(ui->sceneTriggers)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SceneTriggerWidget *s1 =
|
|
||||||
(SceneTriggerWidget *)ui->sceneTriggers->itemWidget(
|
|
||||||
ui->sceneTriggers->item(index));
|
|
||||||
SceneTriggerWidget *s2 =
|
|
||||||
(SceneTriggerWidget *)ui->sceneTriggers->itemWidget(
|
|
||||||
ui->sceneTriggers->item(index - 1));
|
|
||||||
SceneTriggerWidget::swapSwitchData(s1, s2);
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
|
|
||||||
std::swap(switcher->sceneTriggers[index],
|
|
||||||
switcher->sceneTriggers[index - 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_triggerDown_clicked()
|
|
||||||
{
|
|
||||||
int index = ui->sceneTriggers->currentRow();
|
|
||||||
|
|
||||||
if (!listMoveDown(ui->sceneTriggers)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SceneTriggerWidget *s1 =
|
|
||||||
(SceneTriggerWidget *)ui->sceneTriggers->itemWidget(
|
|
||||||
ui->sceneTriggers->item(index));
|
|
||||||
SceneTriggerWidget *s2 =
|
|
||||||
(SceneTriggerWidget *)ui->sceneTriggers->itemWidget(
|
|
||||||
ui->sceneTriggers->item(index + 1));
|
|
||||||
SceneTriggerWidget::swapSwitchData(s1, s2);
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
|
|
||||||
std::swap(switcher->sceneTriggers[index],
|
|
||||||
switcher->sceneTriggers[index + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneTrigger::logMatch()
|
|
||||||
{
|
|
||||||
std::string sceneName = "";
|
|
||||||
std::string statusName = "";
|
|
||||||
std::string actionName = "";
|
|
||||||
|
|
||||||
switch (triggerType) {
|
|
||||||
case sceneTriggerType::NONE:
|
|
||||||
statusName = "NONE";
|
|
||||||
break;
|
|
||||||
case sceneTriggerType::SCENE_ACTIVE:
|
|
||||||
statusName = "SCENE ACTIVE";
|
|
||||||
break;
|
|
||||||
case sceneTriggerType::SCENE_INACTIVE:
|
|
||||||
statusName = "SCENE INACTIVE";
|
|
||||||
break;
|
|
||||||
case sceneTriggerType::SCENE_LEAVE:
|
|
||||||
statusName = "SCENE LEAVE";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (triggerAction) {
|
|
||||||
case sceneTriggerAction::NONE:
|
|
||||||
actionName = "NONE";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::START_RECORDING:
|
|
||||||
actionName = "START RECORDING";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::PAUSE_RECORDING:
|
|
||||||
actionName = "PAUSE RECORDING";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::UNPAUSE_RECORDING:
|
|
||||||
actionName = "UNPAUSE RECORDING";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::STOP_RECORDING:
|
|
||||||
actionName = "STOP RECORDING";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::START_STREAMING:
|
|
||||||
actionName = "START STREAMING";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::STOP_STREAMING:
|
|
||||||
actionName = "STOP STREAMING";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::START_REPLAY_BUFFER:
|
|
||||||
actionName = "START REPLAY BUFFER";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::STOP_REPLAY_BUFFER:
|
|
||||||
actionName = "STOP REPLAY BUFFER";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::MUTE_SOURCE:
|
|
||||||
actionName = "MUTE (" + GetWeakSourceName(audioSource) + ")";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::UNMUTE_SOURCE:
|
|
||||||
actionName = "UNMUTE (" + GetWeakSourceName(audioSource) + ")";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::START_SWITCHER:
|
|
||||||
actionName = "START SCENE SWITCHER";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::STOP_SWITCHER:
|
|
||||||
actionName = "STOP SCENE SWITCHER";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::START_VCAM:
|
|
||||||
actionName = "START VIRTUAL CAMERA";
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::STOP_VCAM:
|
|
||||||
actionName = "STOP VIRTUAL CAMERA";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
actionName = "UNKNOWN";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
blog(LOG_INFO,
|
|
||||||
"scene '%s' in status '%s' triggering action '%s' after %f seconds",
|
|
||||||
GetWeakSourceName(scene).c_str(), statusName.c_str(),
|
|
||||||
actionName.c_str(), duration.Seconds());
|
|
||||||
}
|
|
||||||
|
|
||||||
void frontEndActionThread(sceneTriggerAction action, double delay)
|
|
||||||
{
|
|
||||||
long long mil = delay * 1000;
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(mil));
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case sceneTriggerAction::NONE:
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::START_RECORDING:
|
|
||||||
obs_frontend_recording_start();
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::PAUSE_RECORDING:
|
|
||||||
obs_frontend_recording_pause(true);
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::UNPAUSE_RECORDING:
|
|
||||||
obs_frontend_recording_pause(false);
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::STOP_RECORDING:
|
|
||||||
obs_frontend_recording_stop();
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::START_STREAMING:
|
|
||||||
obs_frontend_streaming_start();
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::STOP_STREAMING:
|
|
||||||
obs_frontend_streaming_stop();
|
|
||||||
break;
|
|
||||||
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(26, 0, 0)
|
|
||||||
case sceneTriggerAction::START_REPLAY_BUFFER:
|
|
||||||
obs_frontend_replay_buffer_start();
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::STOP_REPLAY_BUFFER:
|
|
||||||
obs_frontend_replay_buffer_stop();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(27, 0, 0)
|
|
||||||
case sceneTriggerAction::START_VCAM:
|
|
||||||
obs_frontend_start_virtualcam();
|
|
||||||
break;
|
|
||||||
case sceneTriggerAction::STOP_VCAM:
|
|
||||||
obs_frontend_stop_virtualcam();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
blog(LOG_WARNING, "ignoring unexpected frontend action '%d'",
|
|
||||||
static_cast<int>(action));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void muteThread(OBSWeakSource source, double delay, bool mute)
|
|
||||||
{
|
|
||||||
long long mil = delay * 1000;
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(mil));
|
|
||||||
|
|
||||||
auto s = obs_weak_source_get_source(source);
|
|
||||||
obs_source_set_muted(s, mute);
|
|
||||||
obs_source_release(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void statusThread(double delay, bool stop)
|
|
||||||
{
|
|
||||||
long long mil = delay * 1000;
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(mil));
|
|
||||||
|
|
||||||
if (stop) {
|
|
||||||
switcher->Stop();
|
|
||||||
} else {
|
|
||||||
switcher->Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isFrontendAction(sceneTriggerAction triggerAction)
|
|
||||||
{
|
|
||||||
return triggerAction == sceneTriggerAction::START_RECORDING ||
|
|
||||||
triggerAction == sceneTriggerAction::PAUSE_RECORDING ||
|
|
||||||
triggerAction == sceneTriggerAction::UNPAUSE_RECORDING ||
|
|
||||||
triggerAction == sceneTriggerAction::STOP_RECORDING ||
|
|
||||||
triggerAction == sceneTriggerAction::START_STREAMING ||
|
|
||||||
triggerAction == sceneTriggerAction::STOP_STREAMING ||
|
|
||||||
triggerAction == sceneTriggerAction::START_REPLAY_BUFFER ||
|
|
||||||
triggerAction == sceneTriggerAction::STOP_REPLAY_BUFFER ||
|
|
||||||
triggerAction == sceneTriggerAction::START_VCAM ||
|
|
||||||
triggerAction == sceneTriggerAction::STOP_VCAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isAudioAction(sceneTriggerAction t)
|
|
||||||
{
|
|
||||||
return t == sceneTriggerAction::MUTE_SOURCE ||
|
|
||||||
t == sceneTriggerAction::UNMUTE_SOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isSwitcherStatusAction(sceneTriggerAction t)
|
|
||||||
{
|
|
||||||
return t == sceneTriggerAction::START_SWITCHER ||
|
|
||||||
t == sceneTriggerAction::STOP_SWITCHER;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneTrigger::performAction()
|
|
||||||
{
|
|
||||||
if (triggerAction == sceneTriggerAction::NONE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::thread t;
|
|
||||||
|
|
||||||
if (isFrontendAction(triggerAction)) {
|
|
||||||
t = std::thread(frontEndActionThread, triggerAction,
|
|
||||||
duration.Seconds());
|
|
||||||
} else if (isAudioAction(triggerAction)) {
|
|
||||||
bool mute = triggerAction == sceneTriggerAction::MUTE_SOURCE;
|
|
||||||
t = std::thread(muteThread, audioSource, duration.Seconds(),
|
|
||||||
mute);
|
|
||||||
} else if (isSwitcherStatusAction(triggerAction)) {
|
|
||||||
bool stop = triggerAction == sceneTriggerAction::STOP_SWITCHER;
|
|
||||||
t = std::thread(statusThread, duration.Seconds(), stop);
|
|
||||||
} else {
|
|
||||||
blog(LOG_WARNING, "ignoring unknown action '%d'",
|
|
||||||
static_cast<int>(triggerAction));
|
|
||||||
}
|
|
||||||
|
|
||||||
t.detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SceneTrigger::checkMatch(OBSWeakSource currentScene,
|
|
||||||
OBSWeakSource previousScene)
|
|
||||||
{
|
|
||||||
switch (triggerType) {
|
|
||||||
case sceneTriggerType::NONE:
|
|
||||||
return false;
|
|
||||||
case sceneTriggerType::SCENE_ACTIVE:
|
|
||||||
return currentScene == scene;
|
|
||||||
case sceneTriggerType::SCENE_INACTIVE:
|
|
||||||
return currentScene != scene;
|
|
||||||
case sceneTriggerType::SCENE_LEAVE:
|
|
||||||
return previousScene == scene;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitcherData::checkTriggers()
|
|
||||||
{
|
|
||||||
if (SceneTrigger::pause) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &t : sceneTriggers) {
|
|
||||||
if (stop && !isSwitcherStatusAction(t.triggerAction)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t.checkMatch(currentScene, previousScene)) {
|
|
||||||
t.logMatch();
|
|
||||||
t.performAction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitcherData::saveSceneTriggers(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
obs_data_array_t *triggerArray = obs_data_array_create();
|
|
||||||
for (auto &s : sceneTriggers) {
|
|
||||||
obs_data_t *array_obj = obs_data_create();
|
|
||||||
|
|
||||||
s.save(array_obj);
|
|
||||||
obs_data_array_push_back(triggerArray, array_obj);
|
|
||||||
|
|
||||||
obs_data_release(array_obj);
|
|
||||||
}
|
|
||||||
obs_data_set_array(obj, "triggers", triggerArray);
|
|
||||||
obs_data_array_release(triggerArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitcherData::loadSceneTriggers(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
sceneTriggers.clear();
|
|
||||||
|
|
||||||
obs_data_array_t *triggerArray = obs_data_get_array(obj, "triggers");
|
|
||||||
size_t count = obs_data_array_count(triggerArray);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
obs_data_t *array_obj = obs_data_array_item(triggerArray, i);
|
|
||||||
|
|
||||||
sceneTriggers.emplace_back();
|
|
||||||
sceneTriggers.back().load(array_obj);
|
|
||||||
|
|
||||||
obs_data_release(array_obj);
|
|
||||||
}
|
|
||||||
obs_data_array_release(triggerArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::SetupTriggerTab()
|
|
||||||
{
|
|
||||||
for (auto &s : switcher->sceneTriggers) {
|
|
||||||
QListWidgetItem *item;
|
|
||||||
item = new QListWidgetItem(ui->sceneTriggers);
|
|
||||||
ui->sceneTriggers->addItem(item);
|
|
||||||
SceneTriggerWidget *sw = new SceneTriggerWidget(this, &s);
|
|
||||||
item->setSizeHint(sw->minimumSizeHint());
|
|
||||||
ui->sceneTriggers->setItemWidget(item, sw);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switcher->sceneTriggers.size() == 0) {
|
|
||||||
if (!switcher->disableHints) {
|
|
||||||
addPulse = HighlightWidget(ui->triggerAdd,
|
|
||||||
QColor(Qt::green));
|
|
||||||
}
|
|
||||||
ui->triggerHelp->setVisible(true);
|
|
||||||
} else {
|
|
||||||
ui->triggerHelp->setVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneTrigger::save(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
obs_data_set_string(obj, "scene", GetWeakSourceName(scene).c_str());
|
|
||||||
obs_data_set_int(obj, "triggerType", static_cast<int>(triggerType));
|
|
||||||
obs_data_set_int(obj, "triggerAction", static_cast<int>(triggerAction));
|
|
||||||
duration.Save(obj, "duration");
|
|
||||||
obs_data_set_string(obj, "audioSource",
|
|
||||||
GetWeakSourceName(audioSource).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneTrigger::load(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
const char *sceneName = obs_data_get_string(obj, "scene");
|
|
||||||
scene = GetWeakSourceByName(sceneName);
|
|
||||||
|
|
||||||
triggerType = static_cast<sceneTriggerType>(
|
|
||||||
obs_data_get_int(obj, "triggerType"));
|
|
||||||
triggerAction = static_cast<sceneTriggerAction>(
|
|
||||||
obs_data_get_int(obj, "triggerAction"));
|
|
||||||
duration.Load(obj, "duration");
|
|
||||||
|
|
||||||
const char *audioSourceName = obs_data_get_string(obj, "audioSource");
|
|
||||||
audioSource = GetWeakSourceByName(audioSourceName);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void populateTriggers(QComboBox *list)
|
|
||||||
{
|
|
||||||
AddSelectionEntry(
|
|
||||||
list,
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none"));
|
|
||||||
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave"));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void populateActions(QComboBox *list)
|
|
||||||
{
|
|
||||||
AddSelectionEntry(
|
|
||||||
list,
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none"));
|
|
||||||
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera"));
|
|
||||||
list->addItem(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera"));
|
|
||||||
}
|
|
||||||
|
|
||||||
SceneTriggerWidget::SceneTriggerWidget(QWidget *parent, SceneTrigger *s)
|
|
||||||
: SwitchWidget(parent, s, false, false)
|
|
||||||
{
|
|
||||||
triggers = new QComboBox();
|
|
||||||
actions = new QComboBox();
|
|
||||||
duration = new DurationSelection();
|
|
||||||
audioSources = new QComboBox();
|
|
||||||
|
|
||||||
QWidget::connect(triggers, SIGNAL(currentIndexChanged(int)), this,
|
|
||||||
SLOT(TriggerTypeChanged(int)));
|
|
||||||
QWidget::connect(actions, SIGNAL(currentIndexChanged(int)), this,
|
|
||||||
SLOT(TriggerActionChanged(int)));
|
|
||||||
QWidget::connect(duration, SIGNAL(DurationChanged(const Duration &)),
|
|
||||||
this, SLOT(DurationChanged(const Duration &)));
|
|
||||||
QWidget::connect(audioSources,
|
|
||||||
SIGNAL(currentTextChanged(const QString &)), this,
|
|
||||||
SLOT(AudioSourceChanged(const QString &)));
|
|
||||||
|
|
||||||
populateTriggers(triggers);
|
|
||||||
populateActions(actions);
|
|
||||||
PopulateAudioSelection(audioSources);
|
|
||||||
|
|
||||||
if (s) {
|
|
||||||
triggers->setCurrentIndex(static_cast<int>(s->triggerType));
|
|
||||||
actions->setCurrentIndex(static_cast<int>(s->triggerAction));
|
|
||||||
duration->SetDuration(s->duration);
|
|
||||||
|
|
||||||
audioSources->setCurrentText(
|
|
||||||
GetWeakSourceName(s->audioSource).c_str());
|
|
||||||
|
|
||||||
if (isAudioAction(s->triggerAction)) {
|
|
||||||
audioSources->show();
|
|
||||||
} else {
|
|
||||||
audioSources->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
|
||||||
{"{{triggers}}", triggers},
|
|
||||||
{"{{actions}}", actions},
|
|
||||||
{"{{audioSources}}", audioSources},
|
|
||||||
{"{{duration}}", duration},
|
|
||||||
{"{{scenes}}", scenes}};
|
|
||||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.sceneTriggerTab.entry"),
|
|
||||||
mainLayout, widgetPlaceholders);
|
|
||||||
setLayout(mainLayout);
|
|
||||||
|
|
||||||
switchData = s;
|
|
||||||
|
|
||||||
loading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SceneTrigger *SceneTriggerWidget::getSwitchData()
|
|
||||||
{
|
|
||||||
return switchData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneTriggerWidget::setSwitchData(SceneTrigger *s)
|
|
||||||
{
|
|
||||||
switchData = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneTriggerWidget::swapSwitchData(SceneTriggerWidget *s1,
|
|
||||||
SceneTriggerWidget *s2)
|
|
||||||
{
|
|
||||||
SwitchWidget::swapSwitchData(s1, s2);
|
|
||||||
|
|
||||||
SceneTrigger *t = s1->getSwitchData();
|
|
||||||
s1->setSwitchData(s2->getSwitchData());
|
|
||||||
s2->setSwitchData(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneTriggerWidget::TriggerTypeChanged(int index)
|
|
||||||
{
|
|
||||||
if (loading || !switchData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switchData->triggerType = static_cast<sceneTriggerType>(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneTriggerWidget::TriggerActionChanged(int index)
|
|
||||||
{
|
|
||||||
if (loading || !switchData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switchData->triggerAction =
|
|
||||||
static_cast<sceneTriggerAction>(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isAudioAction(switchData->triggerAction)) {
|
|
||||||
audioSources->show();
|
|
||||||
} else {
|
|
||||||
audioSources->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneTriggerWidget::DurationChanged(const Duration &duration)
|
|
||||||
{
|
|
||||||
if (loading || !switchData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switchData->duration = duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneTriggerWidget::AudioSourceChanged(const QString &text)
|
|
||||||
{
|
|
||||||
if (loading || !switchData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switchData->audioSource = GetWeakSourceByQString(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace advss
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
Note: Long-term goal is to remove this tab / file.
|
|
||||||
Most functionality shall be moved to the Macro tab instead.
|
|
||||||
|
|
||||||
So if you plan to make changes here, please consider applying them to the
|
|
||||||
corresponding macro tab functionality instead.
|
|
||||||
******************************************************************************/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "switch-generic.hpp"
|
|
||||||
#include "duration-control.hpp"
|
|
||||||
|
|
||||||
namespace advss {
|
|
||||||
|
|
||||||
enum class sceneTriggerType {
|
|
||||||
NONE = 0,
|
|
||||||
SCENE_ACTIVE = 1,
|
|
||||||
SCENE_INACTIVE = 2,
|
|
||||||
SCENE_LEAVE = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class sceneTriggerAction {
|
|
||||||
NONE = 0,
|
|
||||||
START_RECORDING,
|
|
||||||
PAUSE_RECORDING,
|
|
||||||
UNPAUSE_RECORDING,
|
|
||||||
STOP_RECORDING,
|
|
||||||
|
|
||||||
START_STREAMING,
|
|
||||||
STOP_STREAMING,
|
|
||||||
|
|
||||||
START_REPLAY_BUFFER,
|
|
||||||
STOP_REPLAY_BUFFER,
|
|
||||||
|
|
||||||
MUTE_SOURCE,
|
|
||||||
UNMUTE_SOURCE,
|
|
||||||
|
|
||||||
START_SWITCHER,
|
|
||||||
STOP_SWITCHER,
|
|
||||||
|
|
||||||
START_VCAM,
|
|
||||||
STOP_VCAM,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SceneTrigger : SceneSwitcherEntry {
|
|
||||||
static bool pause;
|
|
||||||
sceneTriggerType triggerType = sceneTriggerType::NONE;
|
|
||||||
sceneTriggerAction triggerAction = sceneTriggerAction::NONE;
|
|
||||||
Duration duration;
|
|
||||||
OBSWeakSource audioSource = nullptr;
|
|
||||||
|
|
||||||
const char *getType() { return "trigger"; }
|
|
||||||
void save(obs_data_t *obj);
|
|
||||||
void load(obs_data_t *obj);
|
|
||||||
|
|
||||||
bool checkMatch(OBSWeakSource currentScene,
|
|
||||||
OBSWeakSource previousScene);
|
|
||||||
void performAction();
|
|
||||||
void logMatch();
|
|
||||||
};
|
|
||||||
|
|
||||||
class SceneTriggerWidget : public SwitchWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
SceneTriggerWidget(QWidget *parent, SceneTrigger *s);
|
|
||||||
SceneTrigger *getSwitchData();
|
|
||||||
void setSwitchData(SceneTrigger *s);
|
|
||||||
|
|
||||||
static void swapSwitchData(SceneTriggerWidget *s1,
|
|
||||||
SceneTriggerWidget *s2);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void TriggerTypeChanged(int index);
|
|
||||||
void TriggerActionChanged(int index);
|
|
||||||
void DurationChanged(const Duration &);
|
|
||||||
void AudioSourceChanged(const QString &text);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QComboBox *triggers;
|
|
||||||
QComboBox *actions;
|
|
||||||
DurationSelection *duration;
|
|
||||||
QComboBox *audioSources;
|
|
||||||
|
|
||||||
SceneTrigger *switchData;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace advss
|
|
||||||
@@ -22,7 +22,7 @@ void AdvSceneSwitcher::on_audioAdd_clicked()
|
|||||||
AudioSwitchWidget *sw =
|
AudioSwitchWidget *sw =
|
||||||
new AudioSwitchWidget(this, &switcher->audioSwitches.back());
|
new AudioSwitchWidget(this, &switcher->audioSwitches.back());
|
||||||
|
|
||||||
listAddClicked(ui->audioSwitches, sw, addPulse);
|
listAddClicked(ui->audioSwitches, sw, &addPulse);
|
||||||
|
|
||||||
ui->audioHelp->setVisible(false);
|
ui->audioHelp->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ void AdvSceneSwitcher::on_executableAdd_clicked()
|
|||||||
listAddClicked(ui->executables,
|
listAddClicked(ui->executables,
|
||||||
new ExecutableSwitchWidget(
|
new ExecutableSwitchWidget(
|
||||||
this, &switcher->executableSwitches.back()),
|
this, &switcher->executableSwitches.back()),
|
||||||
addPulse);
|
&addPulse);
|
||||||
|
|
||||||
ui->exeHelp->setVisible(false);
|
ui->exeHelp->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ void AdvSceneSwitcher::on_fileAdd_clicked()
|
|||||||
listAddClicked(ui->fileSwitches,
|
listAddClicked(ui->fileSwitches,
|
||||||
new FileSwitchWidget(this,
|
new FileSwitchWidget(this,
|
||||||
&switcher->fileSwitches.back()),
|
&switcher->fileSwitches.back()),
|
||||||
addPulse);
|
&addPulse);
|
||||||
|
|
||||||
ui->fileHelp->setVisible(false);
|
ui->fileHelp->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ void AdvSceneSwitcher::on_mediaAdd_clicked()
|
|||||||
listAddClicked(ui->mediaSwitches,
|
listAddClicked(ui->mediaSwitches,
|
||||||
new MediaSwitchWidget(this,
|
new MediaSwitchWidget(this,
|
||||||
&switcher->mediaSwitches.back()),
|
&switcher->mediaSwitches.back()),
|
||||||
addPulse);
|
&addPulse);
|
||||||
|
|
||||||
ui->mediaHelp->setVisible(false);
|
ui->mediaHelp->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,717 +0,0 @@
|
|||||||
/*
|
|
||||||
Most of this code is based on https://github.com/Palakis/obs-websocket
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
|
||||||
#include "obs-module-helper.hpp"
|
|
||||||
#include "scene-switch-helpers.hpp"
|
|
||||||
#include "source-helpers.hpp"
|
|
||||||
#include "switcher-data.hpp"
|
|
||||||
|
|
||||||
#include <obs-frontend-api.h>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QTime>
|
|
||||||
#include <QMainWindow>
|
|
||||||
|
|
||||||
namespace advss {
|
|
||||||
|
|
||||||
#define PARAM_SERVER_ENABLE "ServerEnabled"
|
|
||||||
#define PARAM_SERVER_PORT "ServerPort"
|
|
||||||
#define PARAM_LOCKTOIPV4 "LockToIPv4"
|
|
||||||
|
|
||||||
#define PARAM_CLIENT_ENABLE "ClientEnabled"
|
|
||||||
#define PARAM_CLIENT_PORT "ClientPort"
|
|
||||||
#define PARAM_ADDRESS "Address"
|
|
||||||
#define PARAM_CLIENT_SEND_SCENE_CHANGE "SendSceneChange"
|
|
||||||
#define PARAM_CLIENT_SEND_SCENE_CHANGE_ALL "SendSceneChangeAll"
|
|
||||||
#define PARAM_CLIENT_SENDPREVIEW "SendPreview"
|
|
||||||
|
|
||||||
#define RECONNECT_DELAY 10
|
|
||||||
|
|
||||||
#define SCENE_ENTRY "scene"
|
|
||||||
#define TRANSITION_ENTRY "transition"
|
|
||||||
#define TRANSITION_DURATION "duration"
|
|
||||||
#define SET_PREVIEW "preview"
|
|
||||||
|
|
||||||
using websocketpp::lib::placeholders::_1;
|
|
||||||
using websocketpp::lib::placeholders::_2;
|
|
||||||
using websocketpp::lib::bind;
|
|
||||||
|
|
||||||
NetworkConfig::NetworkConfig()
|
|
||||||
: ServerEnabled(false),
|
|
||||||
ServerPort(55555),
|
|
||||||
LockToIPv4(false),
|
|
||||||
ClientEnabled(false),
|
|
||||||
Address(""),
|
|
||||||
ClientPort(55555),
|
|
||||||
SendSceneChange(true),
|
|
||||||
SendSceneChangeAll(true),
|
|
||||||
SendPreview(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void NetworkConfig::Load(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
SetDefaults(obj);
|
|
||||||
|
|
||||||
ServerEnabled = obs_data_get_bool(obj, PARAM_SERVER_ENABLE);
|
|
||||||
ServerPort = obs_data_get_int(obj, PARAM_SERVER_PORT);
|
|
||||||
LockToIPv4 = obs_data_get_bool(obj, PARAM_LOCKTOIPV4);
|
|
||||||
|
|
||||||
ClientEnabled = obs_data_get_bool(obj, PARAM_CLIENT_ENABLE);
|
|
||||||
Address = obs_data_get_string(obj, PARAM_ADDRESS);
|
|
||||||
ClientPort = obs_data_get_int(obj, PARAM_CLIENT_PORT);
|
|
||||||
SendSceneChange =
|
|
||||||
obs_data_get_bool(obj, PARAM_CLIENT_SEND_SCENE_CHANGE);
|
|
||||||
SendSceneChangeAll =
|
|
||||||
obs_data_get_bool(obj, PARAM_CLIENT_SEND_SCENE_CHANGE_ALL);
|
|
||||||
SendPreview = obs_data_get_bool(obj, PARAM_CLIENT_SENDPREVIEW);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NetworkConfig::Save(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
obs_data_set_bool(obj, PARAM_SERVER_ENABLE, ServerEnabled);
|
|
||||||
obs_data_set_int(obj, PARAM_SERVER_PORT, ServerPort);
|
|
||||||
obs_data_set_bool(obj, PARAM_LOCKTOIPV4, LockToIPv4);
|
|
||||||
|
|
||||||
obs_data_set_bool(obj, PARAM_CLIENT_ENABLE, ClientEnabled);
|
|
||||||
obs_data_set_string(obj, PARAM_ADDRESS, Address.c_str());
|
|
||||||
obs_data_set_int(obj, PARAM_CLIENT_PORT, ClientPort);
|
|
||||||
obs_data_set_bool(obj, PARAM_CLIENT_SEND_SCENE_CHANGE, SendSceneChange);
|
|
||||||
obs_data_set_bool(obj, PARAM_CLIENT_SEND_SCENE_CHANGE_ALL,
|
|
||||||
SendSceneChangeAll);
|
|
||||||
obs_data_set_bool(obj, PARAM_CLIENT_SENDPREVIEW, SendPreview);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NetworkConfig::SetDefaults(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
obs_data_set_default_bool(obj, PARAM_SERVER_ENABLE, false);
|
|
||||||
obs_data_set_default_int(obj, PARAM_SERVER_PORT, ServerPort);
|
|
||||||
obs_data_set_default_bool(obj, PARAM_LOCKTOIPV4, LockToIPv4);
|
|
||||||
|
|
||||||
obs_data_set_default_bool(obj, PARAM_CLIENT_ENABLE, false);
|
|
||||||
obs_data_set_default_string(obj, PARAM_ADDRESS, Address.c_str());
|
|
||||||
obs_data_set_default_int(obj, PARAM_CLIENT_PORT, ClientPort);
|
|
||||||
obs_data_set_default_bool(obj, PARAM_CLIENT_SEND_SCENE_CHANGE,
|
|
||||||
SendSceneChange);
|
|
||||||
obs_data_set_default_bool(obj, PARAM_CLIENT_SEND_SCENE_CHANGE_ALL,
|
|
||||||
SendSceneChangeAll);
|
|
||||||
obs_data_set_default_bool(obj, PARAM_CLIENT_SENDPREVIEW, SendPreview);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NetworkConfig::GetClientUri()
|
|
||||||
{
|
|
||||||
return "ws://" + Address + ":" + std::to_string(ClientPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NetworkConfig::ShouldSendSceneChange()
|
|
||||||
{
|
|
||||||
return ServerEnabled && SendSceneChange;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NetworkConfig::ShouldSendFrontendSceneChange()
|
|
||||||
{
|
|
||||||
return ShouldSendSceneChange() && SendSceneChangeAll;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NetworkConfig::ShouldSendPrviewSceneChange()
|
|
||||||
{
|
|
||||||
return ServerEnabled && SendPreview;
|
|
||||||
}
|
|
||||||
|
|
||||||
WSServer::WSServer() : QObject(nullptr), _connections(), _clMutex()
|
|
||||||
{
|
|
||||||
_server.get_alog().clear_channels(
|
|
||||||
websocketpp::log::alevel::frame_header |
|
|
||||||
websocketpp::log::alevel::frame_payload |
|
|
||||||
websocketpp::log::alevel::control);
|
|
||||||
_server.init_asio();
|
|
||||||
#ifndef _WIN32
|
|
||||||
_server.set_reuse_addr(true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_server.set_open_handler(bind(&WSServer::onOpen, this, _1));
|
|
||||||
_server.set_close_handler(bind(&WSServer::onClose, this, _1));
|
|
||||||
_server.set_message_handler(bind(&WSServer::onMessage, this, _1, _2));
|
|
||||||
}
|
|
||||||
|
|
||||||
WSServer::~WSServer()
|
|
||||||
{
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSServer::start(quint16 port, bool lockToIPv4)
|
|
||||||
{
|
|
||||||
if (_server.is_listening() &&
|
|
||||||
(port == _serverPort && _lockToIPv4 == lockToIPv4)) {
|
|
||||||
blog(LOG_INFO,
|
|
||||||
"WSServer::start: server already on this port and protocol mode. no restart needed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_server.is_listening()) {
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
_server.reset();
|
|
||||||
|
|
||||||
_serverPort = port;
|
|
||||||
_lockToIPv4 = lockToIPv4;
|
|
||||||
|
|
||||||
websocketpp::lib::error_code errorCode;
|
|
||||||
if (lockToIPv4) {
|
|
||||||
blog(LOG_INFO, "WSServer::start: Locked to IPv4 bindings");
|
|
||||||
_server.listen(websocketpp::lib::asio::ip::tcp::v4(),
|
|
||||||
_serverPort, errorCode);
|
|
||||||
} else {
|
|
||||||
blog(LOG_INFO, "WSServer::start: Not locked to IPv4 bindings");
|
|
||||||
_server.listen(_serverPort, errorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorCode) {
|
|
||||||
std::string errorCodeMessage = errorCode.message();
|
|
||||||
blog(LOG_INFO, "server: listen failed: %s",
|
|
||||||
errorCodeMessage.c_str());
|
|
||||||
|
|
||||||
QString errorTitle =
|
|
||||||
obs_module_text("AdvSceneSwitcher.windowTitle");
|
|
||||||
QString errorMessage =
|
|
||||||
QString(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.networkTab.startFailed.message"))
|
|
||||||
.arg(_serverPort)
|
|
||||||
.arg(errorCodeMessage.c_str());
|
|
||||||
|
|
||||||
QMainWindow *mainWindow = reinterpret_cast<QMainWindow *>(
|
|
||||||
obs_frontend_get_main_window());
|
|
||||||
QMessageBox::warning(mainWindow, errorTitle, errorMessage);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switcher->serverStatus = ServerStatus::STARTING;
|
|
||||||
|
|
||||||
_server.start_accept();
|
|
||||||
|
|
||||||
_threadPool.start(Compatability::CreateFunctionRunnable([=]() {
|
|
||||||
blog(LOG_INFO, "WSServer::start: io thread started");
|
|
||||||
_server.run();
|
|
||||||
blog(LOG_INFO, "WSServer::start: io thread exited");
|
|
||||||
}));
|
|
||||||
|
|
||||||
switcher->serverStatus = ServerStatus::RUNNING;
|
|
||||||
blog(LOG_INFO,
|
|
||||||
"WSServer::start: server started successfully on port %d",
|
|
||||||
_serverPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSServer::stop()
|
|
||||||
{
|
|
||||||
if (!_server.is_listening()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_server.stop_listening();
|
|
||||||
for (connection_hdl hdl : _connections) {
|
|
||||||
websocketpp::lib::error_code ec;
|
|
||||||
_server.close(hdl, websocketpp::close::status::going_away,
|
|
||||||
"Server stopping", ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
_threadPool.waitForDone();
|
|
||||||
|
|
||||||
while (_connections.size() > 0) {
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
switcher->serverStatus = ServerStatus::NOT_RUNNING;
|
|
||||||
blog(LOG_INFO, "server stopped successfully");
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSServer::sendMessage(SceneSwitchInfo sceneSwitch, bool preview)
|
|
||||||
{
|
|
||||||
if (!sceneSwitch.scene) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OBSData data = obs_data_create();
|
|
||||||
obs_data_set_string(data, SCENE_ENTRY,
|
|
||||||
GetWeakSourceName(sceneSwitch.scene).c_str());
|
|
||||||
obs_data_set_string(data, TRANSITION_ENTRY,
|
|
||||||
GetWeakSourceName(sceneSwitch.transition).c_str());
|
|
||||||
obs_data_set_int(data, TRANSITION_DURATION, sceneSwitch.duration);
|
|
||||||
obs_data_set_bool(data, SET_PREVIEW, preview);
|
|
||||||
std::string message = obs_data_get_json(data);
|
|
||||||
obs_data_release(data);
|
|
||||||
|
|
||||||
for (connection_hdl hdl : _connections) {
|
|
||||||
websocketpp::lib::error_code ec;
|
|
||||||
_server.send(hdl, message, websocketpp::frame::opcode::text,
|
|
||||||
ec);
|
|
||||||
if (ec) {
|
|
||||||
std::string errorCodeMessage = ec.message();
|
|
||||||
blog(LOG_INFO, "server: send failed: %s",
|
|
||||||
errorCodeMessage.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VerboseLoggingEnabled()) {
|
|
||||||
blog(LOG_INFO, "server sent message:\n%s", message.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSServer::onOpen(connection_hdl hdl)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(_clMutex);
|
|
||||||
_connections.insert(hdl);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString clientIp = getRemoteEndpoint(hdl);
|
|
||||||
blog(LOG_INFO, "new client connection from %s",
|
|
||||||
clientIp.toUtf8().constData());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string processMessage(std::string payload)
|
|
||||||
{
|
|
||||||
auto config = switcher->networkConfig;
|
|
||||||
std::string msgContainer(payload);
|
|
||||||
const char *msg = msgContainer.c_str();
|
|
||||||
|
|
||||||
OBSData data = obs_data_create_from_json(msg);
|
|
||||||
if (!data) {
|
|
||||||
blog(LOG_ERROR, "invalid JSON payload received for '%s'", msg);
|
|
||||||
return "invalid JSON payload";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!obs_data_has_user_value(data, SCENE_ENTRY) ||
|
|
||||||
!obs_data_has_user_value(data, TRANSITION_ENTRY) ||
|
|
||||||
!obs_data_has_user_value(data, TRANSITION_DURATION) ||
|
|
||||||
!obs_data_has_user_value(data, SET_PREVIEW)) {
|
|
||||||
return "missing request parameters";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string sceneName = obs_data_get_string(data, SCENE_ENTRY);
|
|
||||||
std::string transitionName =
|
|
||||||
obs_data_get_string(data, TRANSITION_ENTRY);
|
|
||||||
int duration = obs_data_get_int(data, TRANSITION_DURATION);
|
|
||||||
bool preview = obs_data_get_bool(data, SET_PREVIEW);
|
|
||||||
|
|
||||||
obs_data_release(data);
|
|
||||||
|
|
||||||
auto scene = GetWeakSourceByName(sceneName.c_str());
|
|
||||||
if (!scene) {
|
|
||||||
return "ignoring request - unknown scene '" + sceneName + "'";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ret = "message ok";
|
|
||||||
|
|
||||||
auto transition = GetWeakTransitionByName(transitionName.c_str());
|
|
||||||
if (VerboseLoggingEnabled() && !transition) {
|
|
||||||
ret += " - ignoring invalid transition: '" + transitionName +
|
|
||||||
"'";
|
|
||||||
}
|
|
||||||
if (preview) {
|
|
||||||
SwitchPreviewScene(scene);
|
|
||||||
} else {
|
|
||||||
SwitchScene({scene, transition, duration});
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSServer::onMessage(connection_hdl, server::message_ptr message)
|
|
||||||
{
|
|
||||||
auto opcode = message->get_opcode();
|
|
||||||
if (opcode != websocketpp::frame::opcode::text) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_threadPool.start(Compatability::CreateFunctionRunnable([=]() {
|
|
||||||
if (message->get_payload() != "message ok") {
|
|
||||||
blog(LOG_WARNING, "received response: %s",
|
|
||||||
message->get_payload().c_str());
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSServer::onClose(connection_hdl hdl)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(_clMutex);
|
|
||||||
_connections.erase(hdl);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto conn = _server.get_con_from_hdl(hdl);
|
|
||||||
auto localCloseCode = conn->get_local_close_code();
|
|
||||||
|
|
||||||
if (localCloseCode != websocketpp::close::status::going_away) {
|
|
||||||
QString clientIp = getRemoteEndpoint(hdl);
|
|
||||||
blog(LOG_INFO, "client %s disconnected",
|
|
||||||
clientIp.toUtf8().constData());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString WSServer::getRemoteEndpoint(connection_hdl hdl)
|
|
||||||
{
|
|
||||||
auto conn = _server.get_con_from_hdl(hdl);
|
|
||||||
return QString::fromStdString(conn->get_remote_endpoint());
|
|
||||||
}
|
|
||||||
|
|
||||||
WSClient::WSClient() : QObject(nullptr)
|
|
||||||
{
|
|
||||||
_client.get_alog().clear_channels(
|
|
||||||
websocketpp::log::alevel::frame_header |
|
|
||||||
websocketpp::log::alevel::frame_payload |
|
|
||||||
websocketpp::log::alevel::control);
|
|
||||||
_client.init_asio();
|
|
||||||
#ifndef _WIN32
|
|
||||||
_client.set_reuse_addr(true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_client.set_open_handler(bind(&WSClient::onOpen, this, _1));
|
|
||||||
_client.set_fail_handler(bind(&WSClient::onFail, this, _1));
|
|
||||||
_client.set_message_handler(bind(&WSClient::onMessage, this, _1, _2));
|
|
||||||
_client.set_close_handler(bind(&WSClient::onClose, this, _1));
|
|
||||||
}
|
|
||||||
|
|
||||||
WSClient::~WSClient()
|
|
||||||
{
|
|
||||||
disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSClient::connectThread()
|
|
||||||
{
|
|
||||||
while (_retry) {
|
|
||||||
_client.reset();
|
|
||||||
switcher->clientStatus = ClientStatus::CONNECTING;
|
|
||||||
// Create a connection to the given URI and queue it for connection once
|
|
||||||
// the event loop starts
|
|
||||||
websocketpp::lib::error_code ec;
|
|
||||||
client::connection_ptr con = _client.get_connection(_uri, ec);
|
|
||||||
if (ec) {
|
|
||||||
_failMsg = ec.message();
|
|
||||||
blog(LOG_INFO, "client: connect failed: %s",
|
|
||||||
_failMsg.c_str());
|
|
||||||
switcher->clientStatus = ClientStatus::FAIL;
|
|
||||||
} else {
|
|
||||||
_client.connect(con);
|
|
||||||
_connection = connection_hdl(con);
|
|
||||||
|
|
||||||
// Start the ASIO io_service run loop
|
|
||||||
blog(LOG_INFO, "WSClient::connect: io thread started");
|
|
||||||
_connected = true;
|
|
||||||
_client.run();
|
|
||||||
_connected = false;
|
|
||||||
blog(LOG_INFO, "WSClient::connect: io thread exited");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_retry) {
|
|
||||||
std::unique_lock<std::mutex> lck(_waitMtx);
|
|
||||||
blog(LOG_INFO,
|
|
||||||
"trying to reconnect to %s in %d seconds.",
|
|
||||||
_uri.c_str(), RECONNECT_DELAY);
|
|
||||||
_cv.wait_for(lck,
|
|
||||||
std::chrono::seconds(RECONNECT_DELAY));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSClient::connect(std::string uri)
|
|
||||||
{
|
|
||||||
disconnect();
|
|
||||||
_uri = uri;
|
|
||||||
_retry = true;
|
|
||||||
|
|
||||||
_thread = std::thread(&WSClient::connectThread, this);
|
|
||||||
|
|
||||||
switcher->clientStatus = ClientStatus::DISCONNECTED;
|
|
||||||
blog(LOG_INFO, "WSClient::connect: exited");
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSClient::disconnect()
|
|
||||||
{
|
|
||||||
_retry = false;
|
|
||||||
websocketpp::lib::error_code ec;
|
|
||||||
_client.close(_connection, websocketpp::close::status::normal,
|
|
||||||
"Client stopping", ec);
|
|
||||||
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> waitLck(_waitMtx);
|
|
||||||
blog(LOG_INFO, "trying to reconnect to %s in %d seconds.",
|
|
||||||
_uri.c_str(), RECONNECT_DELAY);
|
|
||||||
_cv.notify_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (_connected) {
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
||||||
_client.close(_connection, websocketpp::close::status::normal,
|
|
||||||
"Client stopping", ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_thread.joinable()) {
|
|
||||||
_thread.join();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSClient::onOpen(connection_hdl)
|
|
||||||
{
|
|
||||||
blog(LOG_INFO, "connection to %s opened", _uri.c_str());
|
|
||||||
switcher->clientStatus = ClientStatus::CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSClient::onFail(connection_hdl)
|
|
||||||
{
|
|
||||||
blog(LOG_INFO, "connection to %s failed", _uri.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSClient::onMessage(connection_hdl hdl, client::message_ptr message)
|
|
||||||
{
|
|
||||||
auto opcode = message->get_opcode();
|
|
||||||
if (opcode != websocketpp::frame::opcode::text) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string payload = message->get_payload();
|
|
||||||
std::string response = processMessage(payload);
|
|
||||||
websocketpp::lib::error_code errorCode;
|
|
||||||
_client.send(hdl, response, websocketpp::frame::opcode::text,
|
|
||||||
errorCode);
|
|
||||||
|
|
||||||
if (errorCode) {
|
|
||||||
std::string errorCodeMessage = errorCode.message();
|
|
||||||
blog(LOG_INFO, "client(response): send failed: %s",
|
|
||||||
errorCodeMessage.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VerboseLoggingEnabled()) {
|
|
||||||
blog(LOG_INFO, "client sent message:\n%s", response.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSClient::onClose(connection_hdl)
|
|
||||||
{
|
|
||||||
blog(LOG_INFO, "client-connection to %s closed.", _uri.c_str());
|
|
||||||
switcher->clientStatus = ClientStatus::DISCONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitcherData::loadNetworkSettings(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
networkConfig.Load(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitcherData::saveNetworkSwitches(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
networkConfig.Save(obj);
|
|
||||||
if (!networkConfig.ServerEnabled) {
|
|
||||||
server.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::SetupNetworkTab()
|
|
||||||
{
|
|
||||||
ui->serverSettings->setChecked(switcher->networkConfig.ServerEnabled);
|
|
||||||
ui->serverPort->setValue(switcher->networkConfig.ServerPort);
|
|
||||||
ui->lockToIPv4->setChecked(switcher->networkConfig.LockToIPv4);
|
|
||||||
|
|
||||||
ui->clientSettings->setChecked(switcher->networkConfig.ClientEnabled);
|
|
||||||
ui->clientHostname->setText(switcher->networkConfig.Address.c_str());
|
|
||||||
ui->clientPort->setValue(switcher->networkConfig.ClientPort);
|
|
||||||
ui->sendSceneChange->setChecked(
|
|
||||||
switcher->networkConfig.SendSceneChange);
|
|
||||||
ui->restrictSend->setChecked(
|
|
||||||
!switcher->networkConfig.SendSceneChangeAll);
|
|
||||||
ui->sendPreview->setChecked(switcher->networkConfig.SendPreview);
|
|
||||||
ui->restrictSend->setDisabled(!switcher->networkConfig.SendSceneChange);
|
|
||||||
|
|
||||||
QTimer *statusTimer = new QTimer(this);
|
|
||||||
connect(statusTimer, SIGNAL(timeout()), this,
|
|
||||||
SLOT(UpdateClientStatus()));
|
|
||||||
connect(statusTimer, SIGNAL(timeout()), this,
|
|
||||||
SLOT(UpdateServerStatus()));
|
|
||||||
statusTimer->start(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_serverSettings_toggled(bool on)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->networkConfig.ServerEnabled = on;
|
|
||||||
if (on) {
|
|
||||||
switcher->server.start(switcher->networkConfig.ServerPort,
|
|
||||||
switcher->networkConfig.LockToIPv4);
|
|
||||||
} else {
|
|
||||||
switcher->server.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_serverPort_valueChanged(int value)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->networkConfig.ServerPort = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_lockToIPv4_stateChanged(int state)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->networkConfig.LockToIPv4 = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_serverRestart_clicked()
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->server.start(switcher->networkConfig.ServerPort,
|
|
||||||
switcher->networkConfig.LockToIPv4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::UpdateServerStatus()
|
|
||||||
{
|
|
||||||
switch (switcher->serverStatus) {
|
|
||||||
case ServerStatus::NOT_RUNNING:
|
|
||||||
ui->serverStatus->setText(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.networkTab.server.status.notRunning"));
|
|
||||||
break;
|
|
||||||
case ServerStatus::STARTING:
|
|
||||||
ui->serverStatus->setText(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.networkTab.server.status.starting"));
|
|
||||||
break;
|
|
||||||
case ServerStatus::RUNNING:
|
|
||||||
ui->serverStatus->setText(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.networkTab.server.status.running"));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_clientSettings_toggled(bool on)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->networkConfig.ClientEnabled = on;
|
|
||||||
|
|
||||||
if (on) {
|
|
||||||
switcher->client.connect(
|
|
||||||
switcher->networkConfig.GetClientUri());
|
|
||||||
} else {
|
|
||||||
switcher->client.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_clientHostname_textChanged(const QString &text)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->networkConfig.Address = text.toUtf8().constData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_clientPort_valueChanged(int value)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->networkConfig.ClientPort = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_sendSceneChange_stateChanged(int state)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->networkConfig.SendSceneChange = state;
|
|
||||||
ui->restrictSend->setDisabled(!state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_restrictSend_stateChanged(int state)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->networkConfig.SendSceneChangeAll = !state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_sendPreview_stateChanged(int state)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->networkConfig.SendPreview = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_clientReconnect_clicked()
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
switcher->client.connect(switcher->networkConfig.GetClientUri());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::UpdateClientStatus()
|
|
||||||
{
|
|
||||||
switch (switcher->clientStatus) {
|
|
||||||
case ClientStatus::DISCONNECTED:
|
|
||||||
ui->clientStatus->setText(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.networkTab.client.status.disconnected"));
|
|
||||||
break;
|
|
||||||
case ClientStatus::CONNECTING:
|
|
||||||
ui->clientStatus->setText(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.networkTab.client.status.connecting"));
|
|
||||||
break;
|
|
||||||
case ClientStatus::CONNECTED:
|
|
||||||
ui->clientStatus->setText(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.networkTab.client.status.connected"));
|
|
||||||
break;
|
|
||||||
case ClientStatus::FAIL:
|
|
||||||
ui->clientStatus->setText(QString("Error: ") +
|
|
||||||
switcher->client.getFail().c_str());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Compatability::StdFunctionRunnable::run()
|
|
||||||
{
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
|
|
||||||
QRunnable *Compatability::CreateFunctionRunnable(std::function<void()> func)
|
|
||||||
{
|
|
||||||
return new Compatability::StdFunctionRunnable(std::move(func));
|
|
||||||
}
|
|
||||||
|
|
||||||
Compatability::StdFunctionRunnable::StdFunctionRunnable(
|
|
||||||
std::function<void()> func)
|
|
||||||
: cb(std::move(func))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace advss
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
Most of this code is based on https://github.com/Palakis/obs-websocket
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <QtCore/QObject>
|
|
||||||
#include <QtCore/QSharedPointer>
|
|
||||||
#include <QtCore/QVariantHash>
|
|
||||||
#include <QtCore/QThreadPool>
|
|
||||||
#include <mutex>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <functional>
|
|
||||||
#include <QRunnable>
|
|
||||||
|
|
||||||
#include <websocketpp/config/asio_no_tls_client.hpp>
|
|
||||||
#include <websocketpp/config/asio_no_tls.hpp>
|
|
||||||
#include <websocketpp/server.hpp>
|
|
||||||
#include <websocketpp/client.hpp>
|
|
||||||
|
|
||||||
namespace advss {
|
|
||||||
|
|
||||||
using websocketpp::connection_hdl;
|
|
||||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
|
||||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
|
||||||
|
|
||||||
struct SceneSwitchInfo;
|
|
||||||
|
|
||||||
class NetworkConfig {
|
|
||||||
public:
|
|
||||||
NetworkConfig();
|
|
||||||
void Load(obs_data_t *obj);
|
|
||||||
void Save(obs_data_t *obj);
|
|
||||||
void SetDefaults(obs_data_t *obj);
|
|
||||||
|
|
||||||
std::string GetClientUri();
|
|
||||||
|
|
||||||
bool ShouldSendSceneChange();
|
|
||||||
bool ShouldSendFrontendSceneChange();
|
|
||||||
bool ShouldSendPrviewSceneChange();
|
|
||||||
|
|
||||||
// Server
|
|
||||||
bool ServerEnabled;
|
|
||||||
uint64_t ServerPort;
|
|
||||||
bool LockToIPv4;
|
|
||||||
|
|
||||||
// Client
|
|
||||||
bool ClientEnabled;
|
|
||||||
std::string Address;
|
|
||||||
uint64_t ClientPort;
|
|
||||||
bool SendSceneChange;
|
|
||||||
bool SendSceneChangeAll;
|
|
||||||
bool SendPreview;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WSServer : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit WSServer();
|
|
||||||
virtual ~WSServer();
|
|
||||||
void start(quint16 port, bool lockToIPv4);
|
|
||||||
void stop();
|
|
||||||
void sendMessage(SceneSwitchInfo sceneSwitch, bool preview = false);
|
|
||||||
QThreadPool *threadPool() { return &_threadPool; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void onOpen(connection_hdl hdl);
|
|
||||||
void onMessage(connection_hdl hdl, server::message_ptr message);
|
|
||||||
void onClose(connection_hdl hdl);
|
|
||||||
|
|
||||||
QString getRemoteEndpoint(connection_hdl hdl);
|
|
||||||
|
|
||||||
server _server;
|
|
||||||
quint16 _serverPort = 55555;
|
|
||||||
bool _lockToIPv4 = false;
|
|
||||||
std::set<connection_hdl, std::owner_less<connection_hdl>> _connections;
|
|
||||||
std::recursive_mutex _clMutex;
|
|
||||||
QThreadPool _threadPool;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ServerStatus {
|
|
||||||
NOT_RUNNING,
|
|
||||||
STARTING,
|
|
||||||
RUNNING,
|
|
||||||
};
|
|
||||||
|
|
||||||
class WSClient : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit WSClient();
|
|
||||||
virtual ~WSClient();
|
|
||||||
void connect(std::string uri);
|
|
||||||
void disconnect();
|
|
||||||
std::string getFail() { return _failMsg; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void onOpen(connection_hdl hdl);
|
|
||||||
void onFail(connection_hdl hdl);
|
|
||||||
void onMessage(connection_hdl hdl, client::message_ptr message);
|
|
||||||
void onClose(connection_hdl hdl);
|
|
||||||
void connectThread();
|
|
||||||
|
|
||||||
client _client;
|
|
||||||
std::string _uri;
|
|
||||||
connection_hdl _connection;
|
|
||||||
std::thread _thread;
|
|
||||||
bool _retry = false;
|
|
||||||
std::atomic_bool _connected = {false};
|
|
||||||
std::mutex _waitMtx;
|
|
||||||
std::condition_variable _cv;
|
|
||||||
std::string _failMsg;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ClientStatus {
|
|
||||||
DISCONNECTED,
|
|
||||||
CONNECTING,
|
|
||||||
CONNECTED,
|
|
||||||
FAIL,
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Compatability {
|
|
||||||
// Reimplement QRunnable for std::function. Retrocompatability for Qt < 5.15
|
|
||||||
class StdFunctionRunnable : public QRunnable {
|
|
||||||
std::function<void()> cb;
|
|
||||||
|
|
||||||
public:
|
|
||||||
StdFunctionRunnable(std::function<void()> func);
|
|
||||||
void run() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
QRunnable *CreateFunctionRunnable(std::function<void()> func);
|
|
||||||
} // namespace Compatability
|
|
||||||
|
|
||||||
} // namespace advss
|
|
||||||
@@ -20,7 +20,7 @@ void AdvSceneSwitcher::on_pauseAdd_clicked()
|
|||||||
listAddClicked(ui->pauseEntries,
|
listAddClicked(ui->pauseEntries,
|
||||||
new PauseEntryWidget(this,
|
new PauseEntryWidget(this,
|
||||||
&switcher->pauseEntries.back()),
|
&switcher->pauseEntries.back()),
|
||||||
addPulse);
|
&addPulse);
|
||||||
|
|
||||||
ui->pauseHelp->setVisible(false);
|
ui->pauseHelp->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ void AdvSceneSwitcher::on_randomAdd_clicked()
|
|||||||
listAddClicked(ui->randomSwitches,
|
listAddClicked(ui->randomSwitches,
|
||||||
new RandomSwitchWidget(this,
|
new RandomSwitchWidget(this,
|
||||||
&switcher->randomSwitches.back()),
|
&switcher->randomSwitches.back()),
|
||||||
addPulse);
|
&addPulse);
|
||||||
|
|
||||||
ui->randomHelp->setVisible(false);
|
ui->randomHelp->setVisible(false);
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ void AdvSceneSwitcher::SetupRandomTab()
|
|||||||
border-style: outset; \
|
border-style: outset; \
|
||||||
border-width: 2px; \
|
border-width: 2px; \
|
||||||
border-radius: 7px; \
|
border-radius: 7px; \
|
||||||
border-color: rgb(0,0,0,0) \
|
border-color: rgb(0,0,0) \
|
||||||
}");
|
}");
|
||||||
if (switcher->switchIfNotMatching != NoMatchBehavior::RANDOM_SWITCH) {
|
if (switcher->switchIfNotMatching != NoMatchBehavior::RANDOM_SWITCH) {
|
||||||
if (!switcher->disableHints) {
|
if (!switcher->disableHints) {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ void AdvSceneSwitcher::on_screenRegionAdd_clicked()
|
|||||||
listAddClicked(ui->screenRegionSwitches,
|
listAddClicked(ui->screenRegionSwitches,
|
||||||
new ScreenRegionWidget(
|
new ScreenRegionWidget(
|
||||||
this, &switcher->screenRegionSwitches.back()),
|
this, &switcher->screenRegionSwitches.back()),
|
||||||
addPulse);
|
&addPulse);
|
||||||
|
|
||||||
ui->regionHelp->setVisible(false);
|
ui->regionHelp->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ void AdvSceneSwitcher::on_sceneSequenceAdd_clicked()
|
|||||||
listAddClicked(ui->sceneSequenceSwitches,
|
listAddClicked(ui->sceneSequenceSwitches,
|
||||||
new SequenceWidget(
|
new SequenceWidget(
|
||||||
this, &switcher->sceneSequenceSwitches.back()),
|
this, &switcher->sceneSequenceSwitches.back()),
|
||||||
addPulse);
|
&addPulse);
|
||||||
|
|
||||||
ui->sequenceHelp->setVisible(false);
|
ui->sequenceHelp->setVisible(false);
|
||||||
}
|
}
|
||||||
@@ -585,6 +585,8 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s,
|
|||||||
QVariant(QStringLiteral("addIconSmall")));
|
QVariant(QStringLiteral("addIconSmall")));
|
||||||
reduce->setProperty("themeID",
|
reduce->setProperty("themeID",
|
||||||
QVariant(QStringLiteral("removeIconSmall")));
|
QVariant(QStringLiteral("removeIconSmall")));
|
||||||
|
extend->setProperty("class", QVariant(QStringLiteral("icon-plus")));
|
||||||
|
reduce->setProperty("class", QVariant(QStringLiteral("icon-trash")));
|
||||||
|
|
||||||
extend->setMaximumSize(22, 22);
|
extend->setMaximumSize(22, 22);
|
||||||
reduce->setMaximumSize(22, 22);
|
reduce->setMaximumSize(22, 22);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ void AdvSceneSwitcher::on_timeAdd_clicked()
|
|||||||
listAddClicked(ui->timeSwitches,
|
listAddClicked(ui->timeSwitches,
|
||||||
new TimeSwitchWidget(this,
|
new TimeSwitchWidget(this,
|
||||||
&switcher->timeSwitches.back()),
|
&switcher->timeSwitches.back()),
|
||||||
addPulse);
|
&addPulse);
|
||||||
|
|
||||||
ui->timeHelp->setVisible(false);
|
ui->timeHelp->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ void AdvSceneSwitcher::on_videoAdd_clicked()
|
|||||||
VideoSwitchWidget *sw =
|
VideoSwitchWidget *sw =
|
||||||
new VideoSwitchWidget(this, &switcher->videoSwitches.back());
|
new VideoSwitchWidget(this, &switcher->videoSwitches.back());
|
||||||
|
|
||||||
listAddClicked(ui->videoSwitches, sw, addPulse);
|
listAddClicked(ui->videoSwitches, sw, &addPulse);
|
||||||
|
|
||||||
ui->videoHelp->setVisible(false);
|
ui->videoHelp->setVisible(false);
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ void AdvSceneSwitcher::on_getScreenshot_clicked()
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto source = obs_weak_source_get_source(s->videoSource);
|
auto source = obs_weak_source_get_source(s->videoSource);
|
||||||
auto screenshotData = std::make_unique<ScreenshotHelper>(source);
|
auto screenshotData = std::make_unique<Screenshot>(source);
|
||||||
obs_source_release(source);
|
obs_source_release(source);
|
||||||
|
|
||||||
QString filePath = QFileDialog::getSaveFileName(this);
|
QString filePath = QFileDialog::getSaveFileName(this);
|
||||||
@@ -121,16 +121,16 @@ void AdvSceneSwitcher::on_getScreenshot_clicked()
|
|||||||
// During selection of the save path enough time should usually have
|
// During selection of the save path enough time should usually have
|
||||||
// passed already
|
// passed already
|
||||||
// Add this just in case ...
|
// Add this just in case ...
|
||||||
if (!screenshotData->done) {
|
if (!screenshotData->IsDone()) {
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!screenshotData->done) {
|
if (!screenshotData->IsDone()) {
|
||||||
DisplayMessage("Failed to get screenshot of source!");
|
DisplayMessage("Failed to get screenshot of source!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
screenshotData->image.save(file.fileName());
|
screenshotData->GetImage().save(file.fileName());
|
||||||
sw->SetFilePath(file.fileName());
|
sw->SetFilePath(file.fileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ void VideoSwitch::load(obs_data_t *obj)
|
|||||||
void VideoSwitch::getScreenshot()
|
void VideoSwitch::getScreenshot()
|
||||||
{
|
{
|
||||||
auto source = obs_weak_source_get_source(videoSource);
|
auto source = obs_weak_source_get_source(videoSource);
|
||||||
screenshotData = std::make_unique<ScreenshotHelper>(source);
|
screenshotData = std::make_unique<Screenshot>(source);
|
||||||
obs_source_release(source);
|
obs_source_release(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,56 +293,55 @@ bool VideoSwitch::checkMatch()
|
|||||||
|
|
||||||
bool match = false;
|
bool match = false;
|
||||||
|
|
||||||
if (screenshotData) {
|
if (!screenshotData) {
|
||||||
if (screenshotData->done) {
|
getScreenshot();
|
||||||
bool conditionMatch = false;
|
return match;
|
||||||
|
|
||||||
switch (condition) {
|
|
||||||
case videoSwitchType::MATCH:
|
|
||||||
conditionMatch = screenshotData->image ==
|
|
||||||
matchImage;
|
|
||||||
break;
|
|
||||||
case videoSwitchType::DIFFER:
|
|
||||||
conditionMatch = screenshotData->image !=
|
|
||||||
matchImage;
|
|
||||||
break;
|
|
||||||
case videoSwitchType::HAS_NOT_CHANGED:
|
|
||||||
conditionMatch = screenshotData->image ==
|
|
||||||
matchImage;
|
|
||||||
break;
|
|
||||||
case videoSwitchType::HAS_CHANGED:
|
|
||||||
conditionMatch = screenshotData->image !=
|
|
||||||
matchImage;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conditionMatch) {
|
|
||||||
currentMatchDuration +=
|
|
||||||
std::chrono::duration_cast<
|
|
||||||
std::chrono::milliseconds>(
|
|
||||||
screenshotData->time -
|
|
||||||
previousTime);
|
|
||||||
} else {
|
|
||||||
currentMatchDuration = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool durationMatch = currentMatchDuration.count() >=
|
|
||||||
duration * 1000;
|
|
||||||
|
|
||||||
if (conditionMatch && durationMatch) {
|
|
||||||
match = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!requiresFileInput(condition)) {
|
|
||||||
matchImage = std::move(screenshotData->image);
|
|
||||||
}
|
|
||||||
previousTime = std::move(screenshotData->time);
|
|
||||||
|
|
||||||
screenshotData.reset(nullptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!screenshotData->IsDone()) {
|
||||||
|
getScreenshot();
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool conditionMatch = false;
|
||||||
|
|
||||||
|
switch (condition) {
|
||||||
|
case videoSwitchType::MATCH:
|
||||||
|
conditionMatch = screenshotData->GetImage() == matchImage;
|
||||||
|
break;
|
||||||
|
case videoSwitchType::DIFFER:
|
||||||
|
conditionMatch = screenshotData->GetImage() != matchImage;
|
||||||
|
break;
|
||||||
|
case videoSwitchType::HAS_NOT_CHANGED:
|
||||||
|
conditionMatch = screenshotData->GetImage() == matchImage;
|
||||||
|
break;
|
||||||
|
case videoSwitchType::HAS_CHANGED:
|
||||||
|
conditionMatch = screenshotData->GetImage() != matchImage;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conditionMatch) {
|
||||||
|
currentMatchDuration +=
|
||||||
|
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
screenshotData->GetScreenshotTime() -
|
||||||
|
previousTime);
|
||||||
|
} else {
|
||||||
|
currentMatchDuration = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool durationMatch = currentMatchDuration.count() >= duration * 1000;
|
||||||
|
|
||||||
|
if (conditionMatch && durationMatch) {
|
||||||
|
match = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!requiresFileInput(condition)) {
|
||||||
|
matchImage = screenshotData->GetImage();
|
||||||
|
}
|
||||||
|
previousTime = screenshotData->GetScreenshotTime();
|
||||||
|
|
||||||
|
screenshotData.reset(nullptr);
|
||||||
|
|
||||||
getScreenshot();
|
getScreenshot();
|
||||||
return match;
|
return match;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ struct VideoSwitch : virtual SceneSwitcherEntry {
|
|||||||
double duration = 0;
|
double duration = 0;
|
||||||
bool ignoreInactiveSource = false;
|
bool ignoreInactiveSource = false;
|
||||||
|
|
||||||
std::unique_ptr<ScreenshotHelper> screenshotData = nullptr;
|
std::unique_ptr<Screenshot> screenshotData = nullptr;
|
||||||
std::chrono::high_resolution_clock::time_point previousTime{};
|
std::chrono::high_resolution_clock::time_point previousTime{};
|
||||||
QImage matchImage;
|
QImage matchImage;
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ void AdvSceneSwitcher::on_windowAdd_clicked()
|
|||||||
listAddClicked(ui->windowSwitches,
|
listAddClicked(ui->windowSwitches,
|
||||||
new WindowSwitchWidget(this,
|
new WindowSwitchWidget(this,
|
||||||
&switcher->windowSwitches.back()),
|
&switcher->windowSwitches.back()),
|
||||||
addPulse);
|
&addPulse);
|
||||||
|
|
||||||
ui->windowHelp->setVisible(false);
|
ui->windowHelp->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,13 +196,13 @@ void MacroActionMacro::RunActions(Macro *actionMacro) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_runOptions.reevaluateConditionState) {
|
if (_runOptions.reevaluateConditionState) {
|
||||||
conditionMacro->CeckMatch(true);
|
conditionMacro->CheckConditions(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((_runOptions.logic == RunOptions::Logic::CONDITIONS &&
|
if ((_runOptions.logic == RunOptions::Logic::CONDITIONS &&
|
||||||
conditionMacro->Matched()) ||
|
conditionMacro->ConditionsMatched()) ||
|
||||||
(_runOptions.logic == RunOptions::Logic::INVERT_CONDITIONS &&
|
(_runOptions.logic == RunOptions::Logic::INVERT_CONDITIONS &&
|
||||||
!conditionMacro->Matched())) {
|
!conditionMacro->ConditionsMatched())) {
|
||||||
runActionsHelper(actionMacro, _runOptions.runElseActions,
|
runActionsHelper(actionMacro, _runOptions.runElseActions,
|
||||||
_runOptions.setInputs, _runOptions.inputs);
|
_runOptions.setInputs, _runOptions.inputs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,21 @@ const static std::map<MacroActionVariable::Type, std::string> actionTypes = {
|
|||||||
"AdvSceneSwitcher.action.variable.type.truncateValue"},
|
"AdvSceneSwitcher.action.variable.type.truncateValue"},
|
||||||
{MacroActionVariable::Type::SWAP_VALUES,
|
{MacroActionVariable::Type::SWAP_VALUES,
|
||||||
"AdvSceneSwitcher.action.variable.type.swapValues"},
|
"AdvSceneSwitcher.action.variable.type.swapValues"},
|
||||||
|
{MacroActionVariable::Type::TRIM,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.trim"},
|
||||||
|
{MacroActionVariable::Type::CHANGE_CASE,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.changeCase"},
|
||||||
|
};
|
||||||
|
|
||||||
|
const static std::map<MacroActionVariable::CaseType, std::string> caseTypes = {
|
||||||
|
{MacroActionVariable::CaseType::LOWER_CASE,
|
||||||
|
"AdvSceneSwitcher.action.variable.case.type.lowerCase"},
|
||||||
|
{MacroActionVariable::CaseType::UPPER_CASE,
|
||||||
|
"AdvSceneSwitcher.action.variable.case.type.upperCase"},
|
||||||
|
{MacroActionVariable::CaseType::CAPITALIZED,
|
||||||
|
"AdvSceneSwitcher.action.variable.case.type.capitalized"},
|
||||||
|
{MacroActionVariable::CaseType::START_CASE,
|
||||||
|
"AdvSceneSwitcher.action.variable.case.type.startCase"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void apppend(Variable &var, const std::string &value)
|
static void apppend(Variable &var, const std::string &value)
|
||||||
@@ -90,16 +105,20 @@ MacroActionVariable::~MacroActionVariable()
|
|||||||
void MacroActionVariable::HandleIndexSubString(Variable *var)
|
void MacroActionVariable::HandleIndexSubString(Variable *var)
|
||||||
{
|
{
|
||||||
const auto curValue = var->Value();
|
const auto curValue = var->Value();
|
||||||
|
const auto subStringSize = _subStringSize.GetValue();
|
||||||
|
const auto subStringStart = _subStringStart.GetValue() - 1;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (_subStringSize == 0) {
|
if (subStringSize == 0) {
|
||||||
var->SetValue(curValue.substr(_subStringStart));
|
var->SetValue(curValue.substr(subStringStart));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var->SetValue(curValue.substr(_subStringStart, _subStringSize));
|
|
||||||
|
var->SetValue(curValue.substr(subStringStart, subStringSize));
|
||||||
} catch (const std::out_of_range &) {
|
} catch (const std::out_of_range &) {
|
||||||
vblog(LOG_WARNING,
|
vblog(LOG_WARNING,
|
||||||
"invalid start index \"%d\" selected for substring of \"%s\" of variable \"%s\"",
|
"invalid start index \"%d\" selected for substring of \"%s\" of variable \"%s\"",
|
||||||
_subStringStart, curValue.c_str(), var->Name().c_str());
|
subStringStart, curValue.c_str(), var->Name().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +131,8 @@ void MacroActionVariable::HandleRegexSubString(Variable *var)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto it = regex.globalMatch(QString::fromStdString(curValue));
|
auto it = regex.globalMatch(QString::fromStdString(curValue));
|
||||||
for (int idx = 0; idx < _regexMatchIdx; idx++) {
|
const auto regexMatchIndex = _regexMatchIdx.GetValue() - 1;
|
||||||
|
for (int idx = 0; idx < regexMatchIndex; idx++) {
|
||||||
if (!it.hasNext()) {
|
if (!it.hasNext()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -135,18 +155,12 @@ void MacroActionVariable::HandleFindAndReplace(Variable *var)
|
|||||||
var->SetValue(value);
|
var->SetValue(value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QString resultString = QString::fromStdString(value);
|
|
||||||
QString replacement = QString::fromStdString(_replaceStr);
|
QString replacement = QString::fromStdString(_replaceStr);
|
||||||
auto regex = _findRegex.GetRegularExpression(_findStr);
|
auto regex = _findRegex.GetRegularExpression(_findStr);
|
||||||
auto matchIterator = regex.globalMatch(QString::fromStdString(value));
|
auto result = QString::fromStdString(value);
|
||||||
int offset = 0;
|
result = result.replace(regex, replacement);
|
||||||
while (matchIterator.hasNext()) {
|
var->SetValue(result.toStdString());
|
||||||
QRegularExpressionMatch match = matchIterator.next();
|
|
||||||
resultString.replace(match.capturedStart() + offset,
|
|
||||||
match.capturedLength(), replacement);
|
|
||||||
offset += replacement.length() - match.capturedLength();
|
|
||||||
}
|
|
||||||
var->SetValue(resultString.toStdString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariable::HandleMathExpression(Variable *var)
|
void MacroActionVariable::HandleMathExpression(Variable *var)
|
||||||
@@ -159,6 +173,43 @@ void MacroActionVariable::HandleMathExpression(Variable *var)
|
|||||||
var->SetValue(std::get<double>(result));
|
var->SetValue(std::get<double>(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionVariable::HandleCaseChange(Variable *var)
|
||||||
|
{
|
||||||
|
auto value = QString::fromStdString(var->Value());
|
||||||
|
|
||||||
|
switch (_caseType) {
|
||||||
|
case CaseType::LOWER_CASE:
|
||||||
|
var->SetValue(value.toLower().toStdString());
|
||||||
|
break;
|
||||||
|
case CaseType::UPPER_CASE:
|
||||||
|
var->SetValue(value.toUpper().toStdString());
|
||||||
|
break;
|
||||||
|
case CaseType::CAPITALIZED: {
|
||||||
|
if (value.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
value[0] = value[0].toUpper();
|
||||||
|
var->SetValue(value.toStdString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CaseType::START_CASE: {
|
||||||
|
auto partList = value.split(QRegularExpression("\\b"));
|
||||||
|
|
||||||
|
for (auto &part : partList) {
|
||||||
|
if (part.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
part[0] = part[0].toUpper();
|
||||||
|
}
|
||||||
|
|
||||||
|
var->SetValue(partList.join("").toStdString());
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
struct GetSceneItemNameHelper {
|
struct GetSceneItemNameHelper {
|
||||||
int curIdx = 0;
|
int curIdx = 0;
|
||||||
int targetIdx = 0;
|
int targetIdx = 0;
|
||||||
@@ -278,10 +329,10 @@ bool MacroActionVariable::PerformAction()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Type::INCREMENT:
|
case Type::INCREMENT:
|
||||||
modifyNumValue(*var, _numValue, true);
|
modifyNumValue(*var, _numValue.GetValue(), true);
|
||||||
break;
|
break;
|
||||||
case Type::DECREMENT:
|
case Type::DECREMENT:
|
||||||
modifyNumValue(*var, _numValue, false);
|
modifyNumValue(*var, _numValue.GetValue(), false);
|
||||||
break;
|
break;
|
||||||
case Type::SET_CONDITION_VALUE:
|
case Type::SET_CONDITION_VALUE:
|
||||||
case Type::SET_ACTION_VALUE: {
|
case Type::SET_ACTION_VALUE: {
|
||||||
@@ -405,6 +456,15 @@ bool MacroActionVariable::PerformAction()
|
|||||||
var2->SetValue(tempValue);
|
var2->SetValue(tempValue);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case Type::TRIM: {
|
||||||
|
var->SetValue(QString::fromStdString(var->Value())
|
||||||
|
.trimmed()
|
||||||
|
.toStdString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case Type::CHANGE_CASE:
|
||||||
|
HandleCaseChange(var.get());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -418,13 +478,13 @@ bool MacroActionVariable::Save(obs_data_t *obj) const
|
|||||||
obs_data_set_string(obj, "variable2Name",
|
obs_data_set_string(obj, "variable2Name",
|
||||||
GetWeakVariableName(_variable2).c_str());
|
GetWeakVariableName(_variable2).c_str());
|
||||||
_strValue.Save(obj, "strValue");
|
_strValue.Save(obj, "strValue");
|
||||||
obs_data_set_double(obj, "numValue", _numValue);
|
_numValue.Save(obj, "numValue");
|
||||||
obs_data_set_int(obj, "condition", static_cast<int>(_type));
|
obs_data_set_int(obj, "condition", static_cast<int>(_type));
|
||||||
obs_data_set_int(obj, "segmentIdx", GetSegmentIndexValue());
|
obs_data_set_int(obj, "segmentIdx", GetSegmentIndexValue());
|
||||||
obs_data_set_int(obj, "subStringStart", _subStringStart);
|
_subStringStart.Save(obj, "subStringStart");
|
||||||
obs_data_set_int(obj, "subStringSize", _subStringSize);
|
_subStringSize.Save(obj, "subStringSize");
|
||||||
obs_data_set_string(obj, "regexPattern", _regexPattern.c_str());
|
obs_data_set_string(obj, "regexPattern", _regexPattern.c_str());
|
||||||
obs_data_set_int(obj, "regexMatchIdx", _regexMatchIdx);
|
_regexMatchIdx.Save(obj, "regexMatchIdx");
|
||||||
_findRegex.Save(obj, "findRegex");
|
_findRegex.Save(obj, "findRegex");
|
||||||
_findStr.Save(obj, "findStr");
|
_findStr.Save(obj, "findStr");
|
||||||
_replaceStr.Save(obj, "replaceStr");
|
_replaceStr.Save(obj, "replaceStr");
|
||||||
@@ -441,6 +501,10 @@ bool MacroActionVariable::Save(obs_data_t *obj) const
|
|||||||
obs_data_set_int(obj, "direction", static_cast<int>(_direction));
|
obs_data_set_int(obj, "direction", static_cast<int>(_direction));
|
||||||
_stringLength.Save(obj, "stringLength");
|
_stringLength.Save(obj, "stringLength");
|
||||||
obs_data_set_int(obj, "paddingChar", _paddingChar);
|
obs_data_set_int(obj, "paddingChar", _paddingChar);
|
||||||
|
obs_data_set_int(obj, "caseType", static_cast<int>(_caseType));
|
||||||
|
|
||||||
|
obs_data_set_int(obj, "version", 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,14 +516,10 @@ bool MacroActionVariable::Load(obs_data_t *obj)
|
|||||||
_variable2 = GetWeakVariableByName(
|
_variable2 = GetWeakVariableByName(
|
||||||
obs_data_get_string(obj, "variable2Name"));
|
obs_data_get_string(obj, "variable2Name"));
|
||||||
_strValue.Load(obj, "strValue");
|
_strValue.Load(obj, "strValue");
|
||||||
_numValue = obs_data_get_double(obj, "numValue");
|
|
||||||
_type = static_cast<Type>(obs_data_get_int(obj, "condition"));
|
_type = static_cast<Type>(obs_data_get_int(obj, "condition"));
|
||||||
_segmentIdxLoadValue = obs_data_get_int(obj, "segmentIdx");
|
_segmentIdxLoadValue = obs_data_get_int(obj, "segmentIdx");
|
||||||
_subStringStart = obs_data_get_int(obj, "subStringStart");
|
|
||||||
_subStringSize = obs_data_get_int(obj, "subStringSize");
|
|
||||||
_subStringRegex.Load(obj);
|
_subStringRegex.Load(obj);
|
||||||
_regexPattern = obs_data_get_string(obj, "regexPattern");
|
_regexPattern = obs_data_get_string(obj, "regexPattern");
|
||||||
_regexMatchIdx = obs_data_get_int(obj, "regexMatchIdx");
|
|
||||||
_findRegex.Load(obj, "findRegex");
|
_findRegex.Load(obj, "findRegex");
|
||||||
_findStr.Load(obj, "findStr");
|
_findStr.Load(obj, "findStr");
|
||||||
_replaceStr.Load(obj, "replaceStr");
|
_replaceStr.Load(obj, "replaceStr");
|
||||||
@@ -479,6 +539,22 @@ bool MacroActionVariable::Load(obs_data_t *obj)
|
|||||||
} else {
|
} else {
|
||||||
_paddingChar = ' ';
|
_paddingChar = ' ';
|
||||||
}
|
}
|
||||||
|
_caseType = static_cast<CaseType>(obs_data_get_int(obj, "caseType"));
|
||||||
|
|
||||||
|
// Convert old data format
|
||||||
|
// TODO: Remove in future version
|
||||||
|
if (!obs_data_has_user_value(obj, "version")) {
|
||||||
|
_numValue = obs_data_get_double(obj, "numValue");
|
||||||
|
_subStringStart = obs_data_get_int(obj, "subStringStart") + 1;
|
||||||
|
_subStringSize = obs_data_get_int(obj, "subStringSize");
|
||||||
|
_regexMatchIdx = obs_data_get_int(obj, "regexMatchIdx") + 1;
|
||||||
|
} else {
|
||||||
|
_numValue.Load(obj, "numValue");
|
||||||
|
_subStringStart.Load(obj, "subStringStart");
|
||||||
|
_subStringSize.Load(obj, "subStringSize");
|
||||||
|
_regexMatchIdx.Load(obj, "regexMatchIdx");
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,6 +673,14 @@ static inline void populateTypeSelection(QComboBox *list)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void populateCaseTypeSelection(QComboBox *list)
|
||||||
|
{
|
||||||
|
for (const auto &[type, name] : caseTypes) {
|
||||||
|
list->addItem(obs_module_text(name.c_str()),
|
||||||
|
static_cast<int>(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void populateDirectionSelection(QComboBox *list)
|
static inline void populateDirectionSelection(QComboBox *list)
|
||||||
{
|
{
|
||||||
list->addItems(
|
list->addItems(
|
||||||
@@ -614,7 +698,7 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_variables2(new VariableSelection(this)),
|
_variables2(new VariableSelection(this)),
|
||||||
_actions(new FilterComboBox(this)),
|
_actions(new FilterComboBox(this)),
|
||||||
_strValue(new VariableTextEdit(this, 5, 1, 1)),
|
_strValue(new VariableTextEdit(this, 5, 1, 1)),
|
||||||
_numValue(new QDoubleSpinBox()),
|
_numValue(new VariableDoubleSpinBox(this)),
|
||||||
_segmentIdx(new MacroSegmentSelection(
|
_segmentIdx(new MacroSegmentSelection(
|
||||||
this, MacroSegmentSelection::Type::CONDITION, false)),
|
this, MacroSegmentSelection::Type::CONDITION, false)),
|
||||||
_segmentValueStatus(new QLabel()),
|
_segmentValueStatus(new QLabel()),
|
||||||
@@ -622,11 +706,11 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_substringLayout(new QVBoxLayout()),
|
_substringLayout(new QVBoxLayout()),
|
||||||
_subStringIndexEntryLayout(new QHBoxLayout()),
|
_subStringIndexEntryLayout(new QHBoxLayout()),
|
||||||
_subStringRegexEntryLayout(new QHBoxLayout()),
|
_subStringRegexEntryLayout(new QHBoxLayout()),
|
||||||
_subStringStart(new QSpinBox()),
|
_subStringStart(new VariableSpinBox(this)),
|
||||||
_subStringSize(new QSpinBox()),
|
_subStringSize(new VariableSpinBox(this)),
|
||||||
_substringRegex(new RegexConfigWidget(parent)),
|
_substringRegex(new RegexConfigWidget(parent)),
|
||||||
_regexPattern(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
_regexPattern(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||||
_regexMatchIdx(new QSpinBox()),
|
_regexMatchIdx(new VariableSpinBox(this)),
|
||||||
_findReplaceLayout(new QHBoxLayout()),
|
_findReplaceLayout(new QHBoxLayout()),
|
||||||
_findRegex(new RegexConfigWidget()),
|
_findRegex(new RegexConfigWidget()),
|
||||||
_findStr(new VariableTextEdit(this, 10, 1, 1)),
|
_findStr(new VariableTextEdit(this, 10, 1, 1)),
|
||||||
@@ -645,10 +729,11 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_tempVars(new TempVariableSelection(this)),
|
_tempVars(new TempVariableSelection(this)),
|
||||||
_tempVarsHelp(new HelpIcon(obs_module_text(
|
_tempVarsHelp(new HelpIcon(obs_module_text(
|
||||||
"AdvSceneSwitcher.action.variable.type.setToTempvar.help"))),
|
"AdvSceneSwitcher.action.variable.type.setToTempvar.help"))),
|
||||||
_sceneItemIndex(new VariableSpinBox()),
|
_sceneItemIndex(new VariableSpinBox(this)),
|
||||||
_direction(new QComboBox()),
|
_direction(new QComboBox()),
|
||||||
_stringLength(new VariableSpinBox()),
|
_stringLength(new VariableSpinBox(this)),
|
||||||
_paddingCharSelection(new SingleCharSelection()),
|
_paddingCharSelection(new SingleCharSelection()),
|
||||||
|
_caseType(new FilterComboBox(this)),
|
||||||
_entryLayout(new QHBoxLayout())
|
_entryLayout(new QHBoxLayout())
|
||||||
{
|
{
|
||||||
_numValue->setMinimum(-9999999999);
|
_numValue->setMinimum(-9999999999);
|
||||||
@@ -665,12 +750,15 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_regexMatchIdx->setMinimum(1);
|
_regexMatchIdx->setMinimum(1);
|
||||||
_regexMatchIdx->setMaximum(999);
|
_regexMatchIdx->setMaximum(999);
|
||||||
_regexMatchIdx->setSuffix(".");
|
_regexMatchIdx->setSuffix(".");
|
||||||
|
_replaceStr->setToolTip(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.findAndReplace.replace.tooltip"));
|
||||||
_inputPrompt->setSizePolicy(QSizePolicy::MinimumExpanding,
|
_inputPrompt->setSizePolicy(QSizePolicy::MinimumExpanding,
|
||||||
QSizePolicy::Preferred);
|
QSizePolicy::Preferred);
|
||||||
_sceneItemIndex->setMinimum(1);
|
_sceneItemIndex->setMinimum(1);
|
||||||
_stringLength->setMaximum(999);
|
_stringLength->setMaximum(999);
|
||||||
populateTypeSelection(_actions);
|
populateTypeSelection(_actions);
|
||||||
populateDirectionSelection(_direction);
|
populateDirectionSelection(_direction);
|
||||||
|
populateCaseTypeSelection(_caseType);
|
||||||
|
|
||||||
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
||||||
this, SLOT(VariableChanged(const QString &)));
|
this, SLOT(VariableChanged(const QString &)));
|
||||||
@@ -680,24 +768,32 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
SLOT(ActionChanged(int)));
|
SLOT(ActionChanged(int)));
|
||||||
QWidget::connect(_strValue, SIGNAL(textChanged()), this,
|
QWidget::connect(_strValue, SIGNAL(textChanged()), this,
|
||||||
SLOT(StrValueChanged()));
|
SLOT(StrValueChanged()));
|
||||||
QWidget::connect(_numValue, SIGNAL(valueChanged(double)), this,
|
QWidget::connect(
|
||||||
SLOT(NumValueChanged(double)));
|
_numValue,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
|
||||||
|
this, SLOT(NumValueChanged(const NumberVariable<double> &)));
|
||||||
QWidget::connect(_segmentIdx,
|
QWidget::connect(_segmentIdx,
|
||||||
SIGNAL(SelectionChanged(const IntVariable &)), this,
|
SIGNAL(SelectionChanged(const IntVariable &)), this,
|
||||||
SLOT(SegmentIndexChanged(const IntVariable &)));
|
SLOT(SegmentIndexChanged(const IntVariable &)));
|
||||||
QWidget::connect(window(), SIGNAL(MacroSegmentOrderChanged()), this,
|
QWidget::connect(window(), SIGNAL(MacroSegmentOrderChanged()), this,
|
||||||
SLOT(MacroSegmentOrderChanged()));
|
SLOT(MacroSegmentOrderChanged()));
|
||||||
QWidget::connect(_subStringStart, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(
|
||||||
SLOT(SubStringStartChanged(int)));
|
_subStringStart,
|
||||||
QWidget::connect(_subStringSize, SIGNAL(valueChanged(int)), this,
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
SLOT(SubStringSizeChanged(int)));
|
this, SLOT(SubStringStartChanged(const NumberVariable<int> &)));
|
||||||
|
QWidget::connect(
|
||||||
|
_subStringSize,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
|
this, SLOT(SubStringSizeChanged(const NumberVariable<int> &)));
|
||||||
QWidget::connect(_substringRegex,
|
QWidget::connect(_substringRegex,
|
||||||
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
||||||
SLOT(SubStringRegexChanged(const RegexConfig &)));
|
SLOT(SubStringRegexChanged(const RegexConfig &)));
|
||||||
QWidget::connect(_regexPattern, SIGNAL(textChanged()), this,
|
QWidget::connect(_regexPattern, SIGNAL(textChanged()), this,
|
||||||
SLOT(RegexPatternChanged()));
|
SLOT(RegexPatternChanged()));
|
||||||
QWidget::connect(_regexMatchIdx, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(
|
||||||
SLOT(RegexMatchIdxChanged(int)));
|
_regexMatchIdx,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
|
this, SLOT(RegexMatchIdxChanged(const NumberVariable<int> &)));
|
||||||
QWidget::connect(_findRegex,
|
QWidget::connect(_findRegex,
|
||||||
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
||||||
SLOT(FindRegexChanged(const RegexConfig &)));
|
SLOT(FindRegexChanged(const RegexConfig &)));
|
||||||
@@ -735,6 +831,8 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
QWidget::connect(_paddingCharSelection,
|
QWidget::connect(_paddingCharSelection,
|
||||||
SIGNAL(CharChanged(const QString &)), this,
|
SIGNAL(CharChanged(const QString &)), this,
|
||||||
SLOT(CharSelectionChanged(const QString &)));
|
SLOT(CharSelectionChanged(const QString &)));
|
||||||
|
QWidget::connect(_caseType, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(CaseTypeChanged(int)));
|
||||||
|
|
||||||
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{variables}}", _variables},
|
{"{{variables}}", _variables},
|
||||||
@@ -762,6 +860,7 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
{"{{direction}}", _direction},
|
{"{{direction}}", _direction},
|
||||||
{"{{stringLength}}", _stringLength},
|
{"{{stringLength}}", _stringLength},
|
||||||
{"{{paddingCharSelection}}", _paddingCharSelection},
|
{"{{paddingCharSelection}}", _paddingCharSelection},
|
||||||
|
{"{{caseType}}", _caseType},
|
||||||
};
|
};
|
||||||
PlaceWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.action.variable.entry.other"),
|
obs_module_text("AdvSceneSwitcher.action.variable.entry.other"),
|
||||||
@@ -832,7 +931,7 @@ void MacroActionVariableEdit::UpdateEntryData()
|
|||||||
_actions->setCurrentIndex(
|
_actions->setCurrentIndex(
|
||||||
_actions->findData(static_cast<int>(_entryData->_type)));
|
_actions->findData(static_cast<int>(_entryData->_type)));
|
||||||
_strValue->setPlainText(_entryData->_strValue);
|
_strValue->setPlainText(_entryData->_strValue);
|
||||||
_numValue->setValue(_entryData->_numValue);
|
_numValue->SetValue(_entryData->_numValue);
|
||||||
_segmentIdx->SetValue(_entryData->GetSegmentIndexValue() + 1);
|
_segmentIdx->SetValue(_entryData->GetSegmentIndexValue() + 1);
|
||||||
_segmentIdx->SetMacro(_entryData->GetMacro());
|
_segmentIdx->SetMacro(_entryData->GetMacro());
|
||||||
_segmentIdx->SetType(
|
_segmentIdx->SetType(
|
||||||
@@ -840,13 +939,13 @@ void MacroActionVariableEdit::UpdateEntryData()
|
|||||||
MacroActionVariable::Type::SET_CONDITION_VALUE
|
MacroActionVariable::Type::SET_CONDITION_VALUE
|
||||||
? MacroSegmentSelection::Type::CONDITION
|
? MacroSegmentSelection::Type::CONDITION
|
||||||
: MacroSegmentSelection::Type::ACTION);
|
: MacroSegmentSelection::Type::ACTION);
|
||||||
_subStringStart->setValue(_entryData->_subStringStart + 1);
|
_subStringStart->SetValue(_entryData->_subStringStart);
|
||||||
_subStringSize->setValue(_entryData->_subStringSize);
|
_subStringSize->SetValue(_entryData->_subStringSize);
|
||||||
_substringRegex->SetRegexConfig(_entryData->_subStringRegex);
|
_substringRegex->SetRegexConfig(_entryData->_subStringRegex);
|
||||||
_findRegex->SetRegexConfig(_entryData->_findRegex);
|
_findRegex->SetRegexConfig(_entryData->_findRegex);
|
||||||
_regexPattern->setPlainText(
|
_regexPattern->setPlainText(
|
||||||
QString::fromStdString(_entryData->_regexPattern));
|
QString::fromStdString(_entryData->_regexPattern));
|
||||||
_regexMatchIdx->setValue(_entryData->_regexMatchIdx + 1);
|
_regexMatchIdx->SetValue(_entryData->_regexMatchIdx);
|
||||||
_findStr->setPlainText(_entryData->_findStr);
|
_findStr->setPlainText(_entryData->_findStr);
|
||||||
_replaceStr->setPlainText(_entryData->_replaceStr);
|
_replaceStr->setPlainText(_entryData->_replaceStr);
|
||||||
_mathExpression->setText(_entryData->_mathExpression);
|
_mathExpression->setText(_entryData->_mathExpression);
|
||||||
@@ -862,6 +961,9 @@ void MacroActionVariableEdit::UpdateEntryData()
|
|||||||
_stringLength->SetValue(_entryData->_stringLength);
|
_stringLength->SetValue(_entryData->_stringLength);
|
||||||
_paddingCharSelection->setText(
|
_paddingCharSelection->setText(
|
||||||
QChar::fromLatin1(_entryData->_paddingChar));
|
QChar::fromLatin1(_entryData->_paddingChar));
|
||||||
|
_caseType->setCurrentIndex(
|
||||||
|
_caseType->findData(static_cast<int>(_entryData->_caseType)));
|
||||||
|
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -918,14 +1020,15 @@ void MacroActionVariableEdit::StrValueChanged()
|
|||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::NumValueChanged(double val)
|
void MacroActionVariableEdit::NumValueChanged(
|
||||||
|
const NumberVariable<double> &value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_numValue = val;
|
_entryData->_numValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::SegmentIndexChanged(const IntVariable &val)
|
void MacroActionVariableEdit::SegmentIndexChanged(const IntVariable &val)
|
||||||
@@ -1036,24 +1139,26 @@ void MacroActionVariableEdit::MacroSegmentOrderChanged()
|
|||||||
_segmentIdx->SetValue(_entryData->GetSegmentIndexValue() + 1);
|
_segmentIdx->SetValue(_entryData->GetSegmentIndexValue() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::SubStringStartChanged(int val)
|
void MacroActionVariableEdit::SubStringStartChanged(
|
||||||
|
const NumberVariable<int> &start)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_subStringStart = val - 1;
|
_entryData->_subStringStart = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::SubStringSizeChanged(int val)
|
void MacroActionVariableEdit::SubStringSizeChanged(
|
||||||
|
const NumberVariable<int> &size)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_subStringSize = val;
|
_entryData->_subStringSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::SubStringRegexChanged(const RegexConfig &conf)
|
void MacroActionVariableEdit::SubStringRegexChanged(const RegexConfig &conf)
|
||||||
@@ -1080,14 +1185,15 @@ void MacroActionVariableEdit::RegexPatternChanged()
|
|||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::RegexMatchIdxChanged(int val)
|
void MacroActionVariableEdit::RegexMatchIdxChanged(
|
||||||
|
const NumberVariable<int> &index)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_regexMatchIdx = val - 1;
|
_entryData->_regexMatchIdx = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::FindStrValueChanged()
|
void MacroActionVariableEdit::FindStrValueChanged()
|
||||||
@@ -1268,6 +1374,17 @@ void MacroActionVariableEdit::CharSelectionChanged(const QString &character)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::CaseTypeChanged(int index)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_caseType = static_cast<MacroActionVariable::CaseType>(
|
||||||
|
_caseType->itemData(index).toInt());
|
||||||
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::SetWidgetVisibility()
|
void MacroActionVariableEdit::SetWidgetVisibility()
|
||||||
{
|
{
|
||||||
if (!_entryData) {
|
if (!_entryData) {
|
||||||
@@ -1290,6 +1407,7 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
{"{{direction}}", _direction},
|
{"{{direction}}", _direction},
|
||||||
{"{{stringLength}}", _stringLength},
|
{"{{stringLength}}", _stringLength},
|
||||||
{"{{paddingCharSelection}}", _paddingCharSelection},
|
{"{{paddingCharSelection}}", _paddingCharSelection},
|
||||||
|
{"{{caseType}}", _caseType},
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *layoutString = "";
|
const char *layoutString = "";
|
||||||
@@ -1414,6 +1532,9 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
_entryData->_type == MacroActionVariable::Type::TRUNCATE);
|
_entryData->_type == MacroActionVariable::Type::TRUNCATE);
|
||||||
_paddingCharSelection->setVisible(_entryData->_type ==
|
_paddingCharSelection->setVisible(_entryData->_type ==
|
||||||
MacroActionVariable::Type::PAD);
|
MacroActionVariable::Type::PAD);
|
||||||
|
_caseType->setVisible(_entryData->_type ==
|
||||||
|
MacroActionVariable::Type::CHANGE_CASE);
|
||||||
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,18 +50,20 @@ public:
|
|||||||
PAD,
|
PAD,
|
||||||
TRUNCATE,
|
TRUNCATE,
|
||||||
SWAP_VALUES,
|
SWAP_VALUES,
|
||||||
|
TRIM,
|
||||||
|
CHANGE_CASE,
|
||||||
};
|
};
|
||||||
|
|
||||||
Type _type = Type::SET_FIXED_VALUE;
|
Type _type = Type::SET_FIXED_VALUE;
|
||||||
std::weak_ptr<Variable> _variable;
|
std::weak_ptr<Variable> _variable;
|
||||||
std::weak_ptr<Variable> _variable2;
|
std::weak_ptr<Variable> _variable2;
|
||||||
StringVariable _strValue = "";
|
StringVariable _strValue = "";
|
||||||
double _numValue = 0;
|
DoubleVariable _numValue = 0;
|
||||||
int _subStringStart = 0;
|
IntVariable _subStringStart = 0;
|
||||||
int _subStringSize = 0;
|
IntVariable _subStringSize = 0;
|
||||||
RegexConfig _subStringRegex = RegexConfig::PartialMatchRegexConfig();
|
RegexConfig _subStringRegex = RegexConfig::PartialMatchRegexConfig();
|
||||||
std::string _regexPattern = ".*";
|
std::string _regexPattern = ".*";
|
||||||
int _regexMatchIdx = 0;
|
IntVariable _regexMatchIdx = 0;
|
||||||
RegexConfig _findRegex;
|
RegexConfig _findRegex;
|
||||||
StringVariable _findStr = obs_module_text(
|
StringVariable _findStr = obs_module_text(
|
||||||
"AdvSceneSwitcher.action.variable.findAndReplace.find");
|
"AdvSceneSwitcher.action.variable.findAndReplace.find");
|
||||||
@@ -89,12 +91,22 @@ public:
|
|||||||
IntVariable _stringLength = 1;
|
IntVariable _stringLength = 1;
|
||||||
char _paddingChar = '0';
|
char _paddingChar = '0';
|
||||||
|
|
||||||
|
enum class CaseType {
|
||||||
|
LOWER_CASE,
|
||||||
|
UPPER_CASE,
|
||||||
|
CAPITALIZED,
|
||||||
|
START_CASE,
|
||||||
|
};
|
||||||
|
|
||||||
|
CaseType _caseType = CaseType::LOWER_CASE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DecrementCurrentSegmentVariableRef();
|
void DecrementCurrentSegmentVariableRef();
|
||||||
void HandleIndexSubString(Variable *);
|
void HandleIndexSubString(Variable *);
|
||||||
void HandleRegexSubString(Variable *);
|
void HandleRegexSubString(Variable *);
|
||||||
void HandleFindAndReplace(Variable *);
|
void HandleFindAndReplace(Variable *);
|
||||||
void HandleMathExpression(Variable *);
|
void HandleMathExpression(Variable *);
|
||||||
|
void HandleCaseChange(Variable *);
|
||||||
void SetToSceneItemName(Variable *);
|
void SetToSceneItemName(Variable *);
|
||||||
|
|
||||||
std::weak_ptr<MacroSegment> _macroSegment;
|
std::weak_ptr<MacroSegment> _macroSegment;
|
||||||
@@ -124,15 +136,15 @@ private slots:
|
|||||||
void Variable2Changed(const QString &);
|
void Variable2Changed(const QString &);
|
||||||
void ActionChanged(int);
|
void ActionChanged(int);
|
||||||
void StrValueChanged();
|
void StrValueChanged();
|
||||||
void NumValueChanged(double);
|
void NumValueChanged(const NumberVariable<double> &value);
|
||||||
void SegmentIndexChanged(const IntVariable &);
|
void SegmentIndexChanged(const IntVariable &);
|
||||||
void UpdateSegmentVariableValue();
|
void UpdateSegmentVariableValue();
|
||||||
void MacroSegmentOrderChanged();
|
void MacroSegmentOrderChanged();
|
||||||
void SubStringStartChanged(int val);
|
void SubStringStartChanged(const NumberVariable<int> &start);
|
||||||
void SubStringSizeChanged(int val);
|
void SubStringSizeChanged(const NumberVariable<int> &size);
|
||||||
void SubStringRegexChanged(const RegexConfig &conf);
|
void SubStringRegexChanged(const RegexConfig &conf);
|
||||||
void RegexPatternChanged();
|
void RegexPatternChanged();
|
||||||
void RegexMatchIdxChanged(int val);
|
void RegexMatchIdxChanged(const NumberVariable<int> &index);
|
||||||
void FindStrValueChanged();
|
void FindStrValueChanged();
|
||||||
void FindRegexChanged(const RegexConfig &conf);
|
void FindRegexChanged(const RegexConfig &conf);
|
||||||
void ReplaceStrValueChanged();
|
void ReplaceStrValueChanged();
|
||||||
@@ -148,6 +160,7 @@ private slots:
|
|||||||
void DirectionChanged(int);
|
void DirectionChanged(int);
|
||||||
void StringLengthChanged(const NumberVariable<int> &);
|
void StringLengthChanged(const NumberVariable<int> &);
|
||||||
void CharSelectionChanged(const QString &);
|
void CharSelectionChanged(const QString &);
|
||||||
|
void CaseTypeChanged(int index);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
@@ -160,18 +173,18 @@ private:
|
|||||||
VariableSelection *_variables2;
|
VariableSelection *_variables2;
|
||||||
FilterComboBox *_actions;
|
FilterComboBox *_actions;
|
||||||
VariableTextEdit *_strValue;
|
VariableTextEdit *_strValue;
|
||||||
QDoubleSpinBox *_numValue;
|
VariableDoubleSpinBox *_numValue;
|
||||||
MacroSegmentSelection *_segmentIdx;
|
MacroSegmentSelection *_segmentIdx;
|
||||||
QLabel *_segmentValueStatus;
|
QLabel *_segmentValueStatus;
|
||||||
ResizingPlainTextEdit *_segmentValue;
|
ResizingPlainTextEdit *_segmentValue;
|
||||||
QVBoxLayout *_substringLayout;
|
QVBoxLayout *_substringLayout;
|
||||||
QHBoxLayout *_subStringIndexEntryLayout;
|
QHBoxLayout *_subStringIndexEntryLayout;
|
||||||
QHBoxLayout *_subStringRegexEntryLayout;
|
QHBoxLayout *_subStringRegexEntryLayout;
|
||||||
QSpinBox *_subStringStart;
|
VariableSpinBox *_subStringStart;
|
||||||
QSpinBox *_subStringSize;
|
VariableSpinBox *_subStringSize;
|
||||||
RegexConfigWidget *_substringRegex;
|
RegexConfigWidget *_substringRegex;
|
||||||
ResizingPlainTextEdit *_regexPattern;
|
ResizingPlainTextEdit *_regexPattern;
|
||||||
QSpinBox *_regexMatchIdx;
|
VariableSpinBox *_regexMatchIdx;
|
||||||
QHBoxLayout *_findReplaceLayout;
|
QHBoxLayout *_findReplaceLayout;
|
||||||
RegexConfigWidget *_findRegex;
|
RegexConfigWidget *_findRegex;
|
||||||
VariableTextEdit *_findStr;
|
VariableTextEdit *_findStr;
|
||||||
@@ -192,6 +205,7 @@ private:
|
|||||||
QComboBox *_direction;
|
QComboBox *_direction;
|
||||||
VariableSpinBox *_stringLength;
|
VariableSpinBox *_stringLength;
|
||||||
SingleCharSelection *_paddingCharSelection;
|
SingleCharSelection *_paddingCharSelection;
|
||||||
|
FilterComboBox *_caseType;
|
||||||
QHBoxLayout *_entryLayout;
|
QHBoxLayout *_entryLayout;
|
||||||
|
|
||||||
std::shared_ptr<MacroActionVariable> _entryData;
|
std::shared_ptr<MacroActionVariable> _entryData;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ bool MacroConditionMacro::CheckStateCondition()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return macro->Matched();
|
return macro->ConditionsMatched();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionMacro::CheckMultiStateCondition()
|
bool MacroConditionMacro::CheckMultiStateCondition()
|
||||||
@@ -72,7 +72,7 @@ bool MacroConditionMacro::CheckMultiStateCondition()
|
|||||||
if (!macro) {
|
if (!macro) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (macro->Matched()) {
|
if (macro->ConditionsMatched()) {
|
||||||
matchedCount++;
|
matchedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ bool MacroConditionQueue::CheckCondition()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetTempVarValue("size", std::to_string(queue->Size()));
|
||||||
|
SetTempVarValue("running", queue->IsRunning());
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case Condition::STARTED:
|
case Condition::STARTED:
|
||||||
return queue->IsRunning();
|
return queue->IsRunning();
|
||||||
@@ -63,6 +66,18 @@ std::string MacroConditionQueue::GetShortDesc() const
|
|||||||
return GetActionQueueName(_queue);
|
return GetActionQueueName(_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroConditionQueue::SetupTempVars()
|
||||||
|
{
|
||||||
|
MacroCondition::SetupTempVars();
|
||||||
|
AddTempvar("size",
|
||||||
|
obs_module_text("AdvSceneSwitcher.tempVar.queue.size"));
|
||||||
|
AddTempvar(
|
||||||
|
"running",
|
||||||
|
obs_module_text("AdvSceneSwitcher.tempVar.queue.running"),
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.tempVar.queue.running.description"));
|
||||||
|
}
|
||||||
|
|
||||||
static inline void populateQueueTypeSelection(QComboBox *list)
|
static inline void populateQueueTypeSelection(QComboBox *list)
|
||||||
{
|
{
|
||||||
for (const auto &[_, name] : conditionTypes) {
|
for (const auto &[_, name] : conditionTypes) {
|
||||||
@@ -141,6 +156,7 @@ void MacroConditionQueueEdit::UpdateEntryData()
|
|||||||
}
|
}
|
||||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||||
_queues->SetActionQueue(_entryData->_queue);
|
_queues->SetActionQueue(_entryData->_queue);
|
||||||
|
_size->SetValue(_entryData->_size);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ public:
|
|||||||
IntVariable _size = 1;
|
IntVariable _size = 1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void SetupTempVars();
|
||||||
|
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
static const std::string id;
|
static const std::string id;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -138,8 +138,9 @@ void MacroDock::UpdateText()
|
|||||||
|
|
||||||
_pauseToggle->setText(macro->Paused() ? _unpauseButtonText.c_str()
|
_pauseToggle->setText(macro->Paused() ? _unpauseButtonText.c_str()
|
||||||
: _pauseButtonText.c_str());
|
: _pauseButtonText.c_str());
|
||||||
_statusText->setText(macro->Matched() ? _conditionsTrueText.c_str()
|
_statusText->setText(macro->ConditionsMatched()
|
||||||
: _conditionsFalseText.c_str());
|
? _conditionsTrueText.c_str()
|
||||||
|
: _conditionsFalseText.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroDock::Highlight()
|
void MacroDock::Highlight()
|
||||||
|
|||||||
@@ -85,9 +85,11 @@ std::string GetMacroName(Macro *macro)
|
|||||||
return macro ? macro->Name() : "";
|
return macro ? macro->Name() : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t MillisecondsSinceMacroConditionCheck(Macro *macro)
|
std::chrono::high_resolution_clock::time_point
|
||||||
|
LastMacroConditionCheckTime(Macro *macro)
|
||||||
{
|
{
|
||||||
return macro ? macro->MsSinceLastCheck() : 0;
|
return macro ? macro->LastConditionCheckTime()
|
||||||
|
: std::chrono::high_resolution_clock::time_point{};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroIsStopped(Macro *macro)
|
bool MacroIsStopped(Macro *macro)
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ EXPORT bool MacroSwitchedScene();
|
|||||||
|
|
||||||
EXPORT std::string GetMacroName(Macro *);
|
EXPORT std::string GetMacroName(Macro *);
|
||||||
|
|
||||||
EXPORT int64_t MillisecondsSinceMacroConditionCheck(Macro *);
|
EXPORT std::chrono::high_resolution_clock::time_point
|
||||||
|
LastMacroConditionCheckTime(Macro *);
|
||||||
|
|
||||||
EXPORT bool MacroIsStopped(Macro *);
|
EXPORT bool MacroIsStopped(Macro *);
|
||||||
EXPORT bool MacroIsPaused(Macro *);
|
EXPORT bool MacroIsPaused(Macro *);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "macro-segment-copy-paste.hpp"
|
#include "macro-segment-copy-paste.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "ui-helpers.hpp"
|
|
||||||
|
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
|
|
||||||
@@ -76,22 +75,10 @@ void AdvSceneSwitcher::PasteMacroSegment()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MacroSegmentCopyInfo::Type::ACTION:
|
case MacroSegmentCopyInfo::Type::ACTION:
|
||||||
if (IsCursorInWidgetArea(ui->macroElseActions)) {
|
|
||||||
AddMacroElseAction(macro.get(),
|
|
||||||
macro->ElseActions().size(),
|
|
||||||
copyInfo.segment->GetId(),
|
|
||||||
data.Get());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
AddMacroAction(macro.get(), macro->Actions().size(),
|
AddMacroAction(macro.get(), macro->Actions().size(),
|
||||||
copyInfo.segment->GetId(), data.Get());
|
copyInfo.segment->GetId(), data.Get());
|
||||||
break;
|
break;
|
||||||
case MacroSegmentCopyInfo::Type::ELSE:
|
case MacroSegmentCopyInfo::Type::ELSE:
|
||||||
if (IsCursorInWidgetArea(ui->macroActions)) {
|
|
||||||
AddMacroAction(macro.get(), macro->Actions().size(),
|
|
||||||
copyInfo.segment->GetId(), data.Get());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
AddMacroElseAction(macro.get(), macro->ElseActions().size(),
|
AddMacroElseAction(macro.get(), macro->ElseActions().size(),
|
||||||
copyInfo.segment->GetId(), data.Get());
|
copyInfo.segment->GetId(), data.Get());
|
||||||
break;
|
break;
|
||||||
@@ -111,6 +98,21 @@ bool MacroActionIsInClipboard()
|
|||||||
copyInfo.type == MacroSegmentCopyInfo::Type::ELSE;
|
copyInfo.type == MacroSegmentCopyInfo::Type::ELSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetCopySegmentTargetActionType(bool setToElseAction)
|
||||||
|
{
|
||||||
|
if (copyInfo.type == MacroSegmentCopyInfo::Type::ACTION &&
|
||||||
|
setToElseAction) {
|
||||||
|
copyInfo.type = MacroSegmentCopyInfo::Type::ELSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copyInfo.type == MacroSegmentCopyInfo::Type::ELSE &&
|
||||||
|
!setToElseAction) {
|
||||||
|
copyInfo.type = MacroSegmentCopyInfo::Type::ACTION;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetupSegmentCopyPasteShortcutHandlers(AdvSceneSwitcher *window)
|
void SetupSegmentCopyPasteShortcutHandlers(AdvSceneSwitcher *window)
|
||||||
{
|
{
|
||||||
auto copyShortcut = new QShortcut(QKeySequence("Ctrl+C"), window);
|
auto copyShortcut = new QShortcut(QKeySequence("Ctrl+C"), window);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ class AdvSceneSwitcher;
|
|||||||
|
|
||||||
bool MacroSegmentIsInClipboard();
|
bool MacroSegmentIsInClipboard();
|
||||||
bool MacroActionIsInClipboard();
|
bool MacroActionIsInClipboard();
|
||||||
|
void SetCopySegmentTargetActionType(bool setToElseAction);
|
||||||
void SetupSegmentCopyPasteShortcutHandlers(AdvSceneSwitcher *window);
|
void SetupSegmentCopyPasteShortcutHandlers(AdvSceneSwitcher *window);
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ static bool posIsInScrollbar(const QScrollBar *scrollbar, const QPoint &pos)
|
|||||||
return globalGeo.contains(pos);
|
return globalGeo.contains(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
int MacroSegmentList::GetDragIndex(const QPoint &pos)
|
int MacroSegmentList::GetDragIndex(const QPoint &pos) const
|
||||||
{
|
{
|
||||||
// Don't drag widget when interacting with the scrollbars
|
// Don't drag widget when interacting with the scrollbars
|
||||||
if (posIsInScrollbar(horizontalScrollBar(), mapTo(this, pos)) ||
|
if (posIsInScrollbar(horizontalScrollBar(), mapTo(this, pos)) ||
|
||||||
@@ -88,12 +88,12 @@ int MacroSegmentList::GetDragIndex(const QPoint &pos)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::SetHelpMsg(const QString &msg)
|
void MacroSegmentList::SetHelpMsg(const QString &msg) const
|
||||||
{
|
{
|
||||||
_helpMsg->setText(msg);
|
_helpMsg->setText(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::SetHelpMsgVisible(bool visible)
|
void MacroSegmentList::SetHelpMsgVisible(bool visible) const
|
||||||
{
|
{
|
||||||
_helpMsg->setVisible(visible);
|
_helpMsg->setVisible(visible);
|
||||||
}
|
}
|
||||||
@@ -110,12 +110,12 @@ void MacroSegmentList::Add(QWidget *widget)
|
|||||||
_contentLayout->addWidget(widget);
|
_contentLayout->addWidget(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::Remove(int idx)
|
void MacroSegmentList::Remove(int idx) const
|
||||||
{
|
{
|
||||||
DeleteLayoutItemWidget(_contentLayout->takeAt(idx));
|
DeleteLayoutItemWidget(_contentLayout->takeAt(idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::Clear(int idx)
|
void MacroSegmentList::Clear(int idx) const
|
||||||
{
|
{
|
||||||
ClearLayout(_contentLayout, idx);
|
ClearLayout(_contentLayout, idx);
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ void MacroSegmentList::Highlight(int idx, QColor color)
|
|||||||
HighlightWidget(widget, color, QColor(0, 0, 0, 0), true);
|
HighlightWidget(widget, color, QColor(0, 0, 0, 0), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::SetCollapsed(bool collapse)
|
void MacroSegmentList::SetCollapsed(bool collapse) const
|
||||||
{
|
{
|
||||||
QLayoutItem *item = nullptr;
|
QLayoutItem *item = nullptr;
|
||||||
for (int i = 0; i < _contentLayout->count(); i++) {
|
for (int i = 0; i < _contentLayout->count(); i++) {
|
||||||
@@ -145,7 +145,7 @@ void MacroSegmentList::SetCollapsed(bool collapse)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::SetSelection(int idx)
|
void MacroSegmentList::SetSelection(int idx) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _contentLayout->count(); ++i) {
|
for (int i = 0; i < _contentLayout->count(); ++i) {
|
||||||
auto widget = static_cast<MacroSegmentEdit *>(
|
auto widget = static_cast<MacroSegmentEdit *>(
|
||||||
@@ -235,7 +235,7 @@ void MacroSegmentList::dragEnterEvent(QDragEnterEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroSegmentEdit *MacroSegmentList::WidgetAt(int idx)
|
MacroSegmentEdit *MacroSegmentList::WidgetAt(int idx) const
|
||||||
{
|
{
|
||||||
if (idx < 0 || idx >= _contentLayout->count()) {
|
if (idx < 0 || idx >= _contentLayout->count()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -247,11 +247,16 @@ MacroSegmentEdit *MacroSegmentList::WidgetAt(int idx)
|
|||||||
return static_cast<MacroSegmentEdit *>(item->widget());
|
return static_cast<MacroSegmentEdit *>(item->widget());
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroSegmentEdit *MacroSegmentList::WidgetAt(const QPoint &pos)
|
MacroSegmentEdit *MacroSegmentList::WidgetAt(const QPoint &pos) const
|
||||||
{
|
{
|
||||||
return WidgetAt(GetSegmentIndexFromPos(mapToGlobal(pos)));
|
return WidgetAt(GetSegmentIndexFromPos(mapToGlobal(pos)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MacroSegmentList::IndexAt(const QPoint &pos) const
|
||||||
|
{
|
||||||
|
return GetSegmentIndexFromPos(mapToGlobal(pos));
|
||||||
|
}
|
||||||
|
|
||||||
void MacroSegmentList::HideLastDropLine()
|
void MacroSegmentList::HideLastDropLine()
|
||||||
{
|
{
|
||||||
if (_dropLineIdx >= 0 && _dropLineIdx < _contentLayout->count()) {
|
if (_dropLineIdx >= 0 && _dropLineIdx < _contentLayout->count()) {
|
||||||
@@ -303,7 +308,7 @@ void MacroSegmentList::dragMoveEvent(QDragMoveEvent *event)
|
|||||||
CheckDropLine(_dragCursorPos);
|
CheckDropLine(_dragCursorPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect MacroSegmentList::GetContentItemRectWithPadding(int idx)
|
QRect MacroSegmentList::GetContentItemRectWithPadding(int idx) const
|
||||||
{
|
{
|
||||||
auto item = _contentLayout->itemAt(idx);
|
auto item = _contentLayout->itemAt(idx);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
@@ -325,7 +330,7 @@ QRect MacroSegmentList::GetContentItemRectWithPadding(int idx)
|
|||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MacroSegmentList::GetSegmentIndexFromPos(const QPoint &pos)
|
int MacroSegmentList::GetSegmentIndexFromPos(const QPoint &pos) const
|
||||||
{
|
{
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
for (int i = 0; i < _contentLayout->count(); ++i) {
|
for (int i = 0; i < _contentLayout->count(); ++i) {
|
||||||
@@ -337,7 +342,7 @@ int MacroSegmentList::GetSegmentIndexFromPos(const QPoint &pos)
|
|||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::CheckScroll()
|
void MacroSegmentList::CheckScroll() const
|
||||||
{
|
{
|
||||||
while (_autoScroll) {
|
while (_autoScroll) {
|
||||||
const int scrollTrigger = 15;
|
const int scrollTrigger = 15;
|
||||||
@@ -407,14 +412,14 @@ void MacroSegmentList::CheckDropLine(const QPoint &pos)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroSegmentList::IsInListArea(const QPoint &pos)
|
bool MacroSegmentList::IsInListArea(const QPoint &pos) const
|
||||||
{
|
{
|
||||||
const QRect layoutRect(mapToGlobal(_layout->contentsRect().topLeft()),
|
const QRect layoutRect(mapToGlobal(_layout->contentsRect().topLeft()),
|
||||||
_layout->contentsRect().size());
|
_layout->contentsRect().size());
|
||||||
return layoutRect.contains(pos);
|
return layoutRect.contains(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
int MacroSegmentList::GetDropIndex(const QPoint &pos)
|
int MacroSegmentList::GetDropIndex(const QPoint &pos) const
|
||||||
{
|
{
|
||||||
int idx = GetSegmentIndexFromPos(pos);
|
int idx = GetSegmentIndexFromPos(pos);
|
||||||
if (idx == _dragPosition) {
|
if (idx == _dragPosition) {
|
||||||
|
|||||||
@@ -15,18 +15,19 @@ class MacroSegmentList : public QScrollArea {
|
|||||||
public:
|
public:
|
||||||
MacroSegmentList(QWidget *parent = nullptr);
|
MacroSegmentList(QWidget *parent = nullptr);
|
||||||
virtual ~MacroSegmentList();
|
virtual ~MacroSegmentList();
|
||||||
void SetHelpMsg(const QString &msg);
|
void SetHelpMsg(const QString &msg) const;
|
||||||
void SetHelpMsgVisible(bool visible);
|
void SetHelpMsgVisible(bool visible) const;
|
||||||
MacroSegmentEdit *WidgetAt(int idx);
|
MacroSegmentEdit *WidgetAt(int idx) const;
|
||||||
MacroSegmentEdit *WidgetAt(const QPoint &);
|
MacroSegmentEdit *WidgetAt(const QPoint &) const;
|
||||||
|
int IndexAt(const QPoint &) const;
|
||||||
void Insert(int idx, MacroSegmentEdit *widget);
|
void Insert(int idx, MacroSegmentEdit *widget);
|
||||||
void Add(QWidget *widget);
|
void Add(QWidget *widget);
|
||||||
void Remove(int idx);
|
void Remove(int idx) const;
|
||||||
void Clear(int idx = 0); // Clear all elements >= idx
|
void Clear(int idx = 0) const; // Clear all elements >= idx
|
||||||
void Highlight(int idx, QColor color = QColor(Qt::green));
|
void Highlight(int idx, QColor color = QColor(Qt::green));
|
||||||
void SetCollapsed(bool);
|
void SetCollapsed(bool) const;
|
||||||
void SetSelection(int idx);
|
void SetSelection(int idx) const;
|
||||||
QVBoxLayout *ContentLayout() { return _contentLayout; }
|
QVBoxLayout *ContentLayout() const { return _contentLayout; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void SelectionChanged(int idx);
|
void SelectionChanged(int idx);
|
||||||
@@ -43,13 +44,13 @@ protected:
|
|||||||
void dropEvent(QDropEvent *event);
|
void dropEvent(QDropEvent *event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int GetDragIndex(const QPoint &);
|
int GetSegmentIndexFromPos(const QPoint &) const;
|
||||||
int GetDropIndex(const QPoint &);
|
int GetDragIndex(const QPoint &) const;
|
||||||
int GetSegmentIndexFromPos(const QPoint &);
|
int GetDropIndex(const QPoint &) const;
|
||||||
void CheckScroll();
|
void CheckScroll() const;
|
||||||
void CheckDropLine(const QPoint &);
|
void CheckDropLine(const QPoint &);
|
||||||
bool IsInListArea(const QPoint &);
|
bool IsInListArea(const QPoint &) const;
|
||||||
QRect GetContentItemRectWithPadding(int idx);
|
QRect GetContentItemRectWithPadding(int idx) const;
|
||||||
void HideLastDropLine();
|
void HideLastDropLine();
|
||||||
|
|
||||||
int _dragPosition = -1;
|
int _dragPosition = -1;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ MacroSegmentSelection::MacroSegmentSelection(QWidget *parent, Type type,
|
|||||||
{
|
{
|
||||||
_index->setMinimum(0);
|
_index->setMinimum(0);
|
||||||
_index->setMaximum(99);
|
_index->setMaximum(99);
|
||||||
_index->specialValueText("-");
|
_index->setSpecialValueText("-");
|
||||||
if (!allowVariables) {
|
if (!allowVariables) {
|
||||||
_index->DisableVariableSelection();
|
_index->DisableVariableSelection();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,17 @@ protected:
|
|||||||
virtual void SetupTempVars();
|
virtual void SetupTempVars();
|
||||||
void AddTempvar(const std::string &id, const std::string &name,
|
void AddTempvar(const std::string &id, const std::string &name,
|
||||||
const std::string &description = "");
|
const std::string &description = "");
|
||||||
|
|
||||||
void SetTempVarValue(const std::string &id, const std::string &value);
|
void SetTempVarValue(const std::string &id, const std::string &value);
|
||||||
|
|
||||||
|
template<typename T, typename = std::enable_if_t<
|
||||||
|
std::is_same<std::decay_t<T>, bool>::value>>
|
||||||
|
void SetTempVarValue(const std::string &id, T value)
|
||||||
|
{
|
||||||
|
SetTempVarValue(id, value ? std::string("true")
|
||||||
|
: std::string("false"));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ClearAvailableTempvars();
|
void ClearAvailableTempvars();
|
||||||
std::optional<const TempVariable>
|
std::optional<const TempVariable>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "layout-helpers.hpp"
|
#include "layout-helpers.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
|
#include "ui-helpers.hpp"
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#include "macro-settings.hpp"
|
#include "macro-settings.hpp"
|
||||||
#include "layout-helpers.hpp"
|
#include "layout-helpers.hpp"
|
||||||
#include "obs-module-helper.hpp"
|
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
|
#include "obs-module-helper.hpp"
|
||||||
|
#include "plugin-state-helpers.hpp"
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
@@ -20,6 +21,10 @@ void GlobalMacroSettings::Save(obs_data_t *obj) const
|
|||||||
obs_data_set_bool(data, "highlightActions", _highlightActions);
|
obs_data_set_bool(data, "highlightActions", _highlightActions);
|
||||||
obs_data_set_bool(data, "newMacroRegisterHotkey",
|
obs_data_set_bool(data, "newMacroRegisterHotkey",
|
||||||
_newMacroRegisterHotkeys);
|
_newMacroRegisterHotkeys);
|
||||||
|
obs_data_set_bool(data, "newMacroUseShortCircuitEvaluation",
|
||||||
|
_newMacroUseShortCircuitEvaluation);
|
||||||
|
obs_data_set_bool(data, "saveSettingsOnMacroChange",
|
||||||
|
_saveSettingsOnMacroChange);
|
||||||
obs_data_set_obj(obj, "macroSettings", data);
|
obs_data_set_obj(obj, "macroSettings", data);
|
||||||
obs_data_release(data);
|
obs_data_release(data);
|
||||||
}
|
}
|
||||||
@@ -38,6 +43,12 @@ void GlobalMacroSettings::Load(obs_data_t *obj)
|
|||||||
_highlightActions = obs_data_get_bool(data, "highlightActions");
|
_highlightActions = obs_data_get_bool(data, "highlightActions");
|
||||||
_newMacroRegisterHotkeys =
|
_newMacroRegisterHotkeys =
|
||||||
obs_data_get_bool(data, "newMacroRegisterHotkey");
|
obs_data_get_bool(data, "newMacroRegisterHotkey");
|
||||||
|
_newMacroUseShortCircuitEvaluation =
|
||||||
|
obs_data_get_bool(data, "newMacroUseShortCircuitEvaluation");
|
||||||
|
_saveSettingsOnMacroChange =
|
||||||
|
obs_data_has_user_value(data, "saveSettingsOnMacroChange")
|
||||||
|
? obs_data_get_bool(data, "saveSettingsOnMacroChange")
|
||||||
|
: true;
|
||||||
obs_data_release(data);
|
obs_data_release(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,16 +56,29 @@ MacroSettingsDialog::MacroSettingsDialog(QWidget *parent,
|
|||||||
const GlobalMacroSettings &settings,
|
const GlobalMacroSettings &settings,
|
||||||
Macro *macro)
|
Macro *macro)
|
||||||
: QDialog(parent),
|
: QDialog(parent),
|
||||||
_executed(new QCheckBox(obs_module_text(
|
_highlightExecutedMacros(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.macroTab.highlightExecutedMacros"))),
|
"AdvSceneSwitcher.macroTab.highlightExecutedMacros"))),
|
||||||
_conditions(new QCheckBox(obs_module_text(
|
_highlightConditions(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.macroTab.highlightTrueConditions"))),
|
"AdvSceneSwitcher.macroTab.highlightTrueConditions"))),
|
||||||
_actions(new QCheckBox(obs_module_text(
|
_highlightActions(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.macroTab.highlightPerformedActions"))),
|
"AdvSceneSwitcher.macroTab.highlightPerformedActions"))),
|
||||||
_newMacroRegisterHotkeys(new QCheckBox(obs_module_text(
|
_newMacroRegisterHotkeys(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.macroTab.newMacroRegisterHotkey"))),
|
"AdvSceneSwitcher.macroTab.newMacroRegisterHotkey"))),
|
||||||
|
_newMacroUseShortCircuitEvaluation(new QCheckBox(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.newMacroUseShortCircuitEvaluation"))),
|
||||||
|
_saveSettingsOnMacroChange(new QCheckBox(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.saveSettingsOnMacroChange"))),
|
||||||
_currentMacroRegisterHotkeys(new QCheckBox(obs_module_text(
|
_currentMacroRegisterHotkeys(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.macroTab.currentDisableHotkeys"))),
|
"AdvSceneSwitcher.macroTab.currentRegisterHotkeys"))),
|
||||||
|
_currentUseShortCircuitEvaluation(new QCheckBox(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.currentUseShortCircuitEvaluation"))),
|
||||||
|
_currentUseCustomConditionCheckInterval(new QCheckBox(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.currentUseCustomConditionCheckInterval"))),
|
||||||
|
_currentCustomConditionCheckInterval(
|
||||||
|
new DurationSelection(this, true, 0.01)),
|
||||||
|
_currentCustomConditionCheckIntervalWarning(new QLabel(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.currentUseCustomConditionCheckIntervalWarning"))),
|
||||||
|
_currentPauseSaveBehavior(new QComboBox(this)),
|
||||||
_currentSkipOnStartup(new QCheckBox(obs_module_text(
|
_currentSkipOnStartup(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup"))),
|
"AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup"))),
|
||||||
_currentStopActionsIfNotDone(new QCheckBox(obs_module_text(
|
_currentStopActionsIfNotDone(new QCheckBox(obs_module_text(
|
||||||
@@ -83,12 +107,32 @@ MacroSettingsDialog::MacroSettingsDialog(QWidget *parent,
|
|||||||
setWindowModality(Qt::WindowModality::WindowModal);
|
setWindowModality(Qt::WindowModality::WindowModal);
|
||||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
|
||||||
|
_newMacroUseShortCircuitEvaluation->setToolTip(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.shortCircuit.tooltip"));
|
||||||
|
_saveSettingsOnMacroChange->setToolTip(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.saveSettingsOnMacroChange.tooltip"));
|
||||||
|
_currentUseShortCircuitEvaluation->setToolTip(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.shortCircuit.tooltip"));
|
||||||
|
|
||||||
|
_currentPauseSaveBehavior->addItem(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.pauseStateSaveBehavior.persist"),
|
||||||
|
static_cast<int>(Macro::PauseStateSaveBehavior::PERSIST));
|
||||||
|
_currentPauseSaveBehavior->addItem(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.pauseStateSaveBehavior.pause"),
|
||||||
|
static_cast<int>(Macro::PauseStateSaveBehavior::PAUSE));
|
||||||
|
_currentPauseSaveBehavior->addItem(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.pauseStateSaveBehavior.unpause"),
|
||||||
|
static_cast<int>(Macro::PauseStateSaveBehavior::UNPAUSE));
|
||||||
|
|
||||||
auto highlightOptions = new QGroupBox(
|
auto highlightOptions = new QGroupBox(
|
||||||
obs_module_text("AdvSceneSwitcher.macroTab.highlightSettings"));
|
obs_module_text("AdvSceneSwitcher.macroTab.highlightSettings"));
|
||||||
auto highlightLayout = new QVBoxLayout;
|
auto highlightLayout = new QVBoxLayout;
|
||||||
highlightLayout->addWidget(_executed);
|
highlightLayout->addWidget(_highlightExecutedMacros);
|
||||||
highlightLayout->addWidget(_conditions);
|
highlightLayout->addWidget(_highlightConditions);
|
||||||
highlightLayout->addWidget(_actions);
|
highlightLayout->addWidget(_highlightActions);
|
||||||
highlightOptions->setLayout(highlightLayout);
|
highlightOptions->setLayout(highlightLayout);
|
||||||
|
|
||||||
auto hotkeyOptions = new QGroupBox(
|
auto hotkeyOptions = new QGroupBox(
|
||||||
@@ -101,8 +145,29 @@ MacroSettingsDialog::MacroSettingsDialog(QWidget *parent,
|
|||||||
auto generalOptions = new QGroupBox(
|
auto generalOptions = new QGroupBox(
|
||||||
obs_module_text("AdvSceneSwitcher.macroTab.generalSettings"));
|
obs_module_text("AdvSceneSwitcher.macroTab.generalSettings"));
|
||||||
auto generalLayout = new QVBoxLayout;
|
auto generalLayout = new QVBoxLayout;
|
||||||
|
generalLayout->addWidget(_saveSettingsOnMacroChange);
|
||||||
generalLayout->addWidget(_currentSkipOnStartup);
|
generalLayout->addWidget(_currentSkipOnStartup);
|
||||||
generalLayout->addWidget(_currentStopActionsIfNotDone);
|
generalLayout->addWidget(_currentStopActionsIfNotDone);
|
||||||
|
generalLayout->addWidget(_currentUseShortCircuitEvaluation);
|
||||||
|
generalLayout->addWidget(_newMacroUseShortCircuitEvaluation);
|
||||||
|
|
||||||
|
auto durationLayout = new QHBoxLayout();
|
||||||
|
durationLayout->addWidget(_currentUseCustomConditionCheckInterval);
|
||||||
|
durationLayout->addWidget(_currentCustomConditionCheckInterval);
|
||||||
|
durationLayout->addStretch();
|
||||||
|
auto customConditionIntervalLayout = new QVBoxLayout();
|
||||||
|
customConditionIntervalLayout->addLayout(durationLayout);
|
||||||
|
customConditionIntervalLayout->addWidget(
|
||||||
|
_currentCustomConditionCheckIntervalWarning);
|
||||||
|
generalLayout->addLayout(customConditionIntervalLayout);
|
||||||
|
|
||||||
|
auto pauseStateSaveBehavorLayout = new QHBoxLayout();
|
||||||
|
pauseStateSaveBehavorLayout->addWidget(new QLabel(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.pauseStateSaveBehavior")));
|
||||||
|
pauseStateSaveBehavorLayout->addWidget(_currentPauseSaveBehavior);
|
||||||
|
pauseStateSaveBehavorLayout->addStretch();
|
||||||
|
generalLayout->addLayout(pauseStateSaveBehavorLayout);
|
||||||
|
|
||||||
generalOptions->setLayout(generalLayout);
|
generalOptions->setLayout(generalLayout);
|
||||||
|
|
||||||
auto inputOptions = new QGroupBox(
|
auto inputOptions = new QGroupBox(
|
||||||
@@ -178,6 +243,13 @@ MacroSettingsDialog::MacroSettingsDialog(QWidget *parent,
|
|||||||
&MacroSettingsDialog::PauseButtonEnableChanged);
|
&MacroSettingsDialog::PauseButtonEnableChanged);
|
||||||
connect(_currentMacroDockAddStatusLabel, &QCheckBox::stateChanged, this,
|
connect(_currentMacroDockAddStatusLabel, &QCheckBox::stateChanged, this,
|
||||||
&MacroSettingsDialog::StatusLabelEnableChanged);
|
&MacroSettingsDialog::StatusLabelEnableChanged);
|
||||||
|
connect(_currentUseCustomConditionCheckInterval,
|
||||||
|
&QCheckBox::stateChanged, this, [this](int state) {
|
||||||
|
_currentCustomConditionCheckInterval->setEnabled(state);
|
||||||
|
});
|
||||||
|
connect(_currentCustomConditionCheckInterval,
|
||||||
|
&DurationSelection::DurationChanged, this,
|
||||||
|
[this]() { SetCustomConditionIntervalWarningVisibility(); });
|
||||||
|
|
||||||
auto scrollArea = new QScrollArea(this);
|
auto scrollArea = new QScrollArea(this);
|
||||||
scrollArea->setWidgetResizable(true);
|
scrollArea->setWidgetResizable(true);
|
||||||
@@ -198,20 +270,43 @@ MacroSettingsDialog::MacroSettingsDialog(QWidget *parent,
|
|||||||
dialogLayout->addWidget(buttonbox);
|
dialogLayout->addWidget(buttonbox);
|
||||||
setLayout(dialogLayout);
|
setLayout(dialogLayout);
|
||||||
|
|
||||||
_executed->setChecked(settings._highlightExecuted);
|
_highlightExecutedMacros->setChecked(settings._highlightExecuted);
|
||||||
_conditions->setChecked(settings._highlightConditions);
|
_highlightConditions->setChecked(settings._highlightConditions);
|
||||||
_actions->setChecked(settings._highlightActions);
|
_highlightActions->setChecked(settings._highlightActions);
|
||||||
_newMacroRegisterHotkeys->setChecked(settings._newMacroRegisterHotkeys);
|
_newMacroRegisterHotkeys->setChecked(settings._newMacroRegisterHotkeys);
|
||||||
|
_newMacroUseShortCircuitEvaluation->setChecked(
|
||||||
|
settings._newMacroUseShortCircuitEvaluation);
|
||||||
|
_saveSettingsOnMacroChange->setChecked(
|
||||||
|
settings._saveSettingsOnMacroChange);
|
||||||
|
|
||||||
if (!macro || macro->IsGroup()) {
|
if (!macro || macro->IsGroup()) {
|
||||||
hotkeyOptions->hide();
|
hotkeyOptions->hide();
|
||||||
generalOptions->hide();
|
|
||||||
|
// General group
|
||||||
|
_currentSkipOnStartup->hide();
|
||||||
|
_currentStopActionsIfNotDone->hide();
|
||||||
|
_currentUseShortCircuitEvaluation->hide();
|
||||||
|
SetLayoutVisible(customConditionIntervalLayout, false);
|
||||||
|
SetLayoutVisible(pauseStateSaveBehavorLayout, false);
|
||||||
|
|
||||||
inputOptions->hide();
|
inputOptions->hide();
|
||||||
_dockOptions->hide();
|
_dockOptions->hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentMacroRegisterHotkeys->setChecked(macro->PauseHotkeysEnabled());
|
_currentMacroRegisterHotkeys->setChecked(macro->PauseHotkeysEnabled());
|
||||||
|
_currentUseShortCircuitEvaluation->setChecked(
|
||||||
|
macro->ShortCircuitEvaluationEnabled());
|
||||||
|
_currentUseCustomConditionCheckInterval->setChecked(
|
||||||
|
macro->CustomConditionCheckIntervalEnabled());
|
||||||
|
_currentCustomConditionCheckInterval->SetDuration(
|
||||||
|
macro->GetCustomConditionCheckInterval());
|
||||||
|
_currentCustomConditionCheckInterval->setEnabled(
|
||||||
|
macro->CustomConditionCheckIntervalEnabled());
|
||||||
|
SetCustomConditionIntervalWarningVisibility();
|
||||||
|
_currentPauseSaveBehavior->setCurrentIndex(
|
||||||
|
_currentPauseSaveBehavior->findData(
|
||||||
|
static_cast<int>(macro->GetPauseStateSaveBehavior())));
|
||||||
_currentSkipOnStartup->setChecked(macro->SkipExecOnStart());
|
_currentSkipOnStartup->setChecked(macro->SkipExecOnStart());
|
||||||
_currentStopActionsIfNotDone->setChecked(macro->StopActionsIfNotDone());
|
_currentStopActionsIfNotDone->setChecked(macro->StopActionsIfNotDone());
|
||||||
_currentInputs->SetInputs(macro->GetInputVariables());
|
_currentInputs->SetInputs(macro->GetInputVariables());
|
||||||
@@ -313,6 +408,15 @@ void MacroSettingsDialog::Resize()
|
|||||||
_dockOptions->updateGeometry();
|
_dockOptions->updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroSettingsDialog::SetCustomConditionIntervalWarningVisibility() const
|
||||||
|
{
|
||||||
|
_currentCustomConditionCheckIntervalWarning->setVisible(
|
||||||
|
_currentUseCustomConditionCheckInterval->isChecked() &&
|
||||||
|
GetIntervalValue() >
|
||||||
|
_currentCustomConditionCheckInterval->GetDuration()
|
||||||
|
.Milliseconds());
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroSettingsDialog::AskForSettings(QWidget *parent,
|
bool MacroSettingsDialog::AskForSettings(QWidget *parent,
|
||||||
GlobalMacroSettings &userInput,
|
GlobalMacroSettings &userInput,
|
||||||
Macro *macro)
|
Macro *macro)
|
||||||
@@ -322,17 +426,33 @@ bool MacroSettingsDialog::AskForSettings(QWidget *parent,
|
|||||||
if (dialog.exec() != DialogCode::Accepted) {
|
if (dialog.exec() != DialogCode::Accepted) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
userInput._highlightExecuted = dialog._executed->isChecked();
|
userInput._highlightExecuted =
|
||||||
userInput._highlightConditions = dialog._conditions->isChecked();
|
dialog._highlightExecutedMacros->isChecked();
|
||||||
userInput._highlightActions = dialog._actions->isChecked();
|
userInput._highlightConditions =
|
||||||
|
dialog._highlightConditions->isChecked();
|
||||||
|
userInput._highlightActions = dialog._highlightActions->isChecked();
|
||||||
userInput._newMacroRegisterHotkeys =
|
userInput._newMacroRegisterHotkeys =
|
||||||
dialog._newMacroRegisterHotkeys->isChecked();
|
dialog._newMacroRegisterHotkeys->isChecked();
|
||||||
|
userInput._newMacroUseShortCircuitEvaluation =
|
||||||
|
dialog._newMacroUseShortCircuitEvaluation->isChecked();
|
||||||
|
userInput._saveSettingsOnMacroChange =
|
||||||
|
dialog._saveSettingsOnMacroChange->isChecked();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro->EnablePauseHotkeys(
|
macro->EnablePauseHotkeys(
|
||||||
dialog._currentMacroRegisterHotkeys->isChecked());
|
dialog._currentMacroRegisterHotkeys->isChecked());
|
||||||
|
macro->SetShortCircuitEvaluation(
|
||||||
|
dialog._currentUseShortCircuitEvaluation->isChecked());
|
||||||
|
macro->SetCustomConditionCheckIntervalEnabled(
|
||||||
|
dialog._currentUseCustomConditionCheckInterval->isChecked());
|
||||||
|
macro->SetCustomConditionCheckInterval(
|
||||||
|
dialog._currentCustomConditionCheckInterval->GetDuration());
|
||||||
|
macro->SetPauseStateSaveBehavior(
|
||||||
|
static_cast<Macro::PauseStateSaveBehavior>(
|
||||||
|
dialog._currentPauseSaveBehavior->currentData()
|
||||||
|
.toInt()));
|
||||||
macro->SetSkipExecOnStart(dialog._currentSkipOnStartup->isChecked());
|
macro->SetSkipExecOnStart(dialog._currentSkipOnStartup->isChecked());
|
||||||
macro->SetStopActionsIfNotDone(
|
macro->SetStopActionsIfNotDone(
|
||||||
dialog._currentStopActionsIfNotDone->isChecked());
|
dialog._currentStopActionsIfNotDone->isChecked());
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "variable-line-edit.hpp"
|
#include "variable-line-edit.hpp"
|
||||||
|
#include "duration-control.hpp"
|
||||||
#include "macro-input.hpp"
|
#include "macro-input.hpp"
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
@@ -23,6 +24,8 @@ public:
|
|||||||
bool _highlightConditions = false;
|
bool _highlightConditions = false;
|
||||||
bool _highlightActions = false;
|
bool _highlightActions = false;
|
||||||
bool _newMacroRegisterHotkeys = true;
|
bool _newMacroRegisterHotkeys = true;
|
||||||
|
bool _newMacroUseShortCircuitEvaluation = false;
|
||||||
|
bool _saveSettingsOnMacroChange = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dialog for configuring global and individual macro specific settings
|
// Dialog for configuring global and individual macro specific settings
|
||||||
@@ -43,13 +46,22 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void Resize();
|
void Resize();
|
||||||
|
void SetCustomConditionIntervalWarningVisibility() const;
|
||||||
|
|
||||||
QCheckBox *_executed;
|
// Global macro settings
|
||||||
QCheckBox *_conditions;
|
QCheckBox *_highlightExecutedMacros;
|
||||||
QCheckBox *_actions;
|
QCheckBox *_highlightConditions;
|
||||||
|
QCheckBox *_highlightActions;
|
||||||
QCheckBox *_newMacroRegisterHotkeys;
|
QCheckBox *_newMacroRegisterHotkeys;
|
||||||
|
QCheckBox *_newMacroUseShortCircuitEvaluation;
|
||||||
|
QCheckBox *_saveSettingsOnMacroChange;
|
||||||
// Current macro specific settings
|
// Current macro specific settings
|
||||||
QCheckBox *_currentMacroRegisterHotkeys;
|
QCheckBox *_currentMacroRegisterHotkeys;
|
||||||
|
QCheckBox *_currentUseShortCircuitEvaluation;
|
||||||
|
QCheckBox *_currentUseCustomConditionCheckInterval;
|
||||||
|
DurationSelection *_currentCustomConditionCheckInterval;
|
||||||
|
QLabel *_currentCustomConditionCheckIntervalWarning;
|
||||||
|
QComboBox *_currentPauseSaveBehavior;
|
||||||
QCheckBox *_currentSkipOnStartup;
|
QCheckBox *_currentSkipOnStartup;
|
||||||
QCheckBox *_currentStopActionsIfNotDone;
|
QCheckBox *_currentStopActionsIfNotDone;
|
||||||
MacroInputSelection *_currentInputs;
|
MacroInputSelection *_currentInputs;
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ bool AdvSceneSwitcher::AddNewMacro(std::shared_ptr<Macro> &res,
|
|||||||
}
|
}
|
||||||
|
|
||||||
res = std::make_shared<Macro>(
|
res = std::make_shared<Macro>(
|
||||||
name, GetGlobalMacroSettings()._newMacroRegisterHotkeys);
|
name, GetGlobalMacroSettings()._newMacroRegisterHotkeys,
|
||||||
|
GetGlobalMacroSettings()._newMacroUseShortCircuitEvaluation);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,11 +100,33 @@ void AdvSceneSwitcher::on_macroAdd_clicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->macros->Add(newMacro);
|
|
||||||
if (addPulse) {
|
if (addPulse) {
|
||||||
addPulse->deleteLater();
|
addPulse->deleteLater();
|
||||||
addPulse = nullptr;
|
addPulse = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto selectedMacro = GetSelectedMacro();
|
||||||
|
if (!selectedMacro) {
|
||||||
|
ui->macros->Add(newMacro);
|
||||||
|
emit MacroAdded(QString::fromStdString(name));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedMacro->IsGroup()) {
|
||||||
|
ui->macros->Add(newMacro, selectedMacro);
|
||||||
|
emit MacroAdded(QString::fromStdString(name));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto selectedMacroGroup = selectedMacro->Parent();
|
||||||
|
if (!selectedMacroGroup) {
|
||||||
|
ui->macros->Add(newMacro, selectedMacro);
|
||||||
|
emit MacroAdded(QString::fromStdString(name));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Macro::PrepareMoveToGroup(selectedMacroGroup, newMacro);
|
||||||
|
ui->macros->Add(newMacro, selectedMacro);
|
||||||
emit MacroAdded(QString::fromStdString(name));
|
emit MacroAdded(QString::fromStdString(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,7 +764,10 @@ void AdvSceneSwitcher::MacroSelectionChanged()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SetEditMacro(*macro);
|
SetEditMacro(*macro);
|
||||||
obs_frontend_save();
|
|
||||||
|
if (GetGlobalMacroSettings()._saveSettingsOnMacroChange) {
|
||||||
|
obs_frontend_save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::HighlightOnChange()
|
void AdvSceneSwitcher::HighlightOnChange()
|
||||||
@@ -762,6 +788,16 @@ void AdvSceneSwitcher::HighlightOnChange()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void resetSegmentHighlights(MacroSegmentList *list)
|
||||||
|
{
|
||||||
|
MacroSegmentEdit *widget = nullptr;
|
||||||
|
for (int i = 0; (widget = list->WidgetAt(i)); i++) {
|
||||||
|
if (widget && widget->Data()) {
|
||||||
|
(void)widget->Data()->GetHighlightAndReset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_macroSettings_clicked()
|
void AdvSceneSwitcher::on_macroSettings_clicked()
|
||||||
{
|
{
|
||||||
GlobalMacroSettings prop = GetGlobalMacroSettings();
|
GlobalMacroSettings prop = GetGlobalMacroSettings();
|
||||||
@@ -770,8 +806,22 @@ void AdvSceneSwitcher::on_macroSettings_clicked()
|
|||||||
if (!accepted) {
|
if (!accepted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetGlobalMacroSettings() = prop;
|
GetGlobalMacroSettings() = prop;
|
||||||
emit HighlightMacrosChanged(prop._highlightExecuted);
|
emit HighlightMacrosChanged(prop._highlightExecuted);
|
||||||
|
|
||||||
|
// Reset highlights to avoid all macro segments being highlighted, which
|
||||||
|
// would have been highlighted at least once since the moment the
|
||||||
|
// highlighting was disabled
|
||||||
|
if (prop._highlightConditions) {
|
||||||
|
resetSegmentHighlights(ui->conditionsList);
|
||||||
|
}
|
||||||
|
if (prop._highlightActions) {
|
||||||
|
resetSegmentHighlights(ui->actionsList);
|
||||||
|
resetSegmentHighlights(ui->elseActionsList);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetCheckIntervalTooLowVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moveControlsToSplitter(QSplitter *splitter, int idx,
|
static void moveControlsToSplitter(QSplitter *splitter, int idx,
|
||||||
@@ -1130,22 +1180,46 @@ static void setupCopyPasteContextMenuEnry(AdvSceneSwitcher *ss,
|
|||||||
[ss]() { ss->CopyMacroSegment(); });
|
[ss]() { ss->CopyMacroSegment(); });
|
||||||
copy->setEnabled(!!segmentEdit);
|
copy->setEnabled(!!segmentEdit);
|
||||||
|
|
||||||
|
bool pasteAsElseAction = true;
|
||||||
const char *pasteText = "AdvSceneSwitcher.macroTab.segment.paste";
|
const char *pasteText = "AdvSceneSwitcher.macroTab.segment.paste";
|
||||||
if (MacroActionIsInClipboard()) {
|
if (MacroActionIsInClipboard()) {
|
||||||
if (IsCursorInWidgetArea(ss->ui->macroActions)) {
|
if (IsCursorInWidgetArea(ss->ui->macroActions)) {
|
||||||
|
pasteAsElseAction = false;
|
||||||
pasteText =
|
pasteText =
|
||||||
"AdvSceneSwitcher.macroTab.segment.pasteAction";
|
"AdvSceneSwitcher.macroTab.segment.pasteAction";
|
||||||
} else if (IsCursorInWidgetArea(ss->ui->macroElseActions)) {
|
} else if (IsCursorInWidgetArea(ss->ui->macroElseActions)) {
|
||||||
|
pasteAsElseAction = true;
|
||||||
pasteText =
|
pasteText =
|
||||||
"AdvSceneSwitcher.macroTab.segment.pasteElseAction";
|
"AdvSceneSwitcher.macroTab.segment.pasteElseAction";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto paste = menu.addAction(obs_module_text(pasteText), ss,
|
auto paste = menu.addAction(
|
||||||
[ss]() { ss->PasteMacroSegment(); });
|
obs_module_text(pasteText), ss, [ss, pasteAsElseAction]() {
|
||||||
|
SetCopySegmentTargetActionType(pasteAsElseAction);
|
||||||
|
ss->PasteMacroSegment();
|
||||||
|
});
|
||||||
paste->setEnabled(MacroSegmentIsInClipboard());
|
paste->setEnabled(MacroSegmentIsInClipboard());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setupRemoveContextMenuEnry(
|
||||||
|
AdvSceneSwitcher *ss,
|
||||||
|
const std::function<void(AdvSceneSwitcher *, int)> &remove,
|
||||||
|
const QPoint &pos, MacroSegmentList *list, QMenu &menu)
|
||||||
|
{
|
||||||
|
const auto segmentEditIndex = list->IndexAt(pos);
|
||||||
|
if (segmentEditIndex == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.addAction(
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroTab.segment.remove"), ss,
|
||||||
|
[ss, remove, segmentEditIndex]() {
|
||||||
|
remove(ss, segmentEditIndex);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static void setupConextMenu(AdvSceneSwitcher *ss, const QPoint &pos,
|
static void setupConextMenu(AdvSceneSwitcher *ss, const QPoint &pos,
|
||||||
|
std::function<void(AdvSceneSwitcher *, int)> remove,
|
||||||
std::function<void(AdvSceneSwitcher *)> expand,
|
std::function<void(AdvSceneSwitcher *)> expand,
|
||||||
std::function<void(AdvSceneSwitcher *)> collapse,
|
std::function<void(AdvSceneSwitcher *)> collapse,
|
||||||
std::function<void(AdvSceneSwitcher *)> maximize,
|
std::function<void(AdvSceneSwitcher *)> maximize,
|
||||||
@@ -1157,6 +1231,8 @@ static void setupConextMenu(AdvSceneSwitcher *ss, const QPoint &pos,
|
|||||||
|
|
||||||
setupCopyPasteContextMenuEnry(ss, segmentEdit, menu);
|
setupCopyPasteContextMenuEnry(ss, segmentEdit, menu);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
setupRemoveContextMenuEnry(ss, remove, pos, list, menu);
|
||||||
|
menu.addSeparator();
|
||||||
setupSegmentLabelContextMenuEntries(segmentEdit, menu);
|
setupSegmentLabelContextMenuEntries(segmentEdit, menu);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.expandAll"),
|
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.expandAll"),
|
||||||
@@ -1173,7 +1249,8 @@ static void setupConextMenu(AdvSceneSwitcher *ss, const QPoint &pos,
|
|||||||
|
|
||||||
void AdvSceneSwitcher::ShowMacroActionsContextMenu(const QPoint &pos)
|
void AdvSceneSwitcher::ShowMacroActionsContextMenu(const QPoint &pos)
|
||||||
{
|
{
|
||||||
setupConextMenu(this, pos, &AdvSceneSwitcher::ExpandAllActions,
|
setupConextMenu(this, pos, &AdvSceneSwitcher::RemoveMacroAction,
|
||||||
|
&AdvSceneSwitcher::ExpandAllActions,
|
||||||
&AdvSceneSwitcher::CollapseAllActions,
|
&AdvSceneSwitcher::CollapseAllActions,
|
||||||
&AdvSceneSwitcher::MaximizeActions,
|
&AdvSceneSwitcher::MaximizeActions,
|
||||||
&AdvSceneSwitcher::MinimizeActions, ui->actionsList);
|
&AdvSceneSwitcher::MinimizeActions, ui->actionsList);
|
||||||
@@ -1181,7 +1258,8 @@ void AdvSceneSwitcher::ShowMacroActionsContextMenu(const QPoint &pos)
|
|||||||
|
|
||||||
void AdvSceneSwitcher::ShowMacroElseActionsContextMenu(const QPoint &pos)
|
void AdvSceneSwitcher::ShowMacroElseActionsContextMenu(const QPoint &pos)
|
||||||
{
|
{
|
||||||
setupConextMenu(this, pos, &AdvSceneSwitcher::ExpandAllElseActions,
|
setupConextMenu(this, pos, &AdvSceneSwitcher::RemoveMacroElseAction,
|
||||||
|
&AdvSceneSwitcher::ExpandAllElseActions,
|
||||||
&AdvSceneSwitcher::CollapseAllElseActions,
|
&AdvSceneSwitcher::CollapseAllElseActions,
|
||||||
&AdvSceneSwitcher::MaximizeElseActions,
|
&AdvSceneSwitcher::MaximizeElseActions,
|
||||||
&AdvSceneSwitcher::MinimizeElseActions,
|
&AdvSceneSwitcher::MinimizeElseActions,
|
||||||
@@ -1190,7 +1268,8 @@ void AdvSceneSwitcher::ShowMacroElseActionsContextMenu(const QPoint &pos)
|
|||||||
|
|
||||||
void AdvSceneSwitcher::ShowMacroConditionsContextMenu(const QPoint &pos)
|
void AdvSceneSwitcher::ShowMacroConditionsContextMenu(const QPoint &pos)
|
||||||
{
|
{
|
||||||
setupConextMenu(this, pos, &AdvSceneSwitcher::ExpandAllConditions,
|
setupConextMenu(this, pos, &AdvSceneSwitcher::RemoveMacroCondition,
|
||||||
|
&AdvSceneSwitcher::ExpandAllConditions,
|
||||||
&AdvSceneSwitcher::CollapseAllConditions,
|
&AdvSceneSwitcher::CollapseAllConditions,
|
||||||
&AdvSceneSwitcher::MaximizeConditions,
|
&AdvSceneSwitcher::MaximizeConditions,
|
||||||
&AdvSceneSwitcher::MinimizeConditions,
|
&AdvSceneSwitcher::MinimizeConditions,
|
||||||
|
|||||||
@@ -76,13 +76,15 @@ namespace advss {
|
|||||||
|
|
||||||
static std::deque<std::shared_ptr<Macro>> macros;
|
static std::deque<std::shared_ptr<Macro>> macros;
|
||||||
|
|
||||||
Macro::Macro(const std::string &name, const bool addHotkey)
|
Macro::Macro(const std::string &name, const bool addHotkey,
|
||||||
|
const bool shortCircuitEvaluation)
|
||||||
{
|
{
|
||||||
SetName(name);
|
SetName(name);
|
||||||
if (addHotkey) {
|
if (addHotkey) {
|
||||||
SetupHotkeys();
|
SetupHotkeys();
|
||||||
}
|
}
|
||||||
_registerHotkeys = addHotkey;
|
_registerHotkeys = addHotkey;
|
||||||
|
_useShortCircuitEvaluation = shortCircuitEvaluation;
|
||||||
}
|
}
|
||||||
|
|
||||||
Macro::~Macro()
|
Macro::~Macro()
|
||||||
@@ -181,7 +183,62 @@ static bool checkCondition(const std::shared_ptr<MacroCondition> &condition)
|
|||||||
return conditionMatched;
|
return conditionMatched;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Macro::CeckMatch(bool ignorePause)
|
bool Macro::CheckConditionHelper(
|
||||||
|
const std::shared_ptr<MacroCondition> &condition) const
|
||||||
|
{
|
||||||
|
bool conditionMatched = false;
|
||||||
|
bool wasEvaluated = false;
|
||||||
|
|
||||||
|
const auto evaluateCondition = [&condition, &conditionMatched,
|
||||||
|
&wasEvaluated]() -> bool {
|
||||||
|
conditionMatched = checkCondition(condition);
|
||||||
|
conditionMatched =
|
||||||
|
condition->CheckDurationModifier(conditionMatched);
|
||||||
|
wasEvaluated = true;
|
||||||
|
return conditionMatched;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto logicType = condition->GetLogicType();
|
||||||
|
if (logicType == Logic::Type::NONE) {
|
||||||
|
vblog(LOG_INFO, "ignoring condition '%s' for '%s'",
|
||||||
|
condition->GetId().c_str(), _name.c_str());
|
||||||
|
if (!_useShortCircuitEvaluation) {
|
||||||
|
(void)evaluateCondition();
|
||||||
|
}
|
||||||
|
return _matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = _useShortCircuitEvaluation
|
||||||
|
// Evaluate the condition result if needed
|
||||||
|
? Logic::ApplyConditionLogic(logicType, _matched,
|
||||||
|
evaluateCondition,
|
||||||
|
_name.c_str())
|
||||||
|
// Evaluate the condition result right away
|
||||||
|
: Logic::ApplyConditionLogic(logicType, _matched,
|
||||||
|
evaluateCondition(),
|
||||||
|
_name.c_str());
|
||||||
|
|
||||||
|
const bool isNegativeLogicType = Logic::IsNegationType(logicType);
|
||||||
|
if (wasEvaluated && ((conditionMatched && !isNegativeLogicType) ||
|
||||||
|
(!conditionMatched && isNegativeLogicType))) {
|
||||||
|
condition->EnableHighlight();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VerboseLoggingEnabled()) {
|
||||||
|
if (wasEvaluated) {
|
||||||
|
blog(LOG_INFO, "condition %s returned %d",
|
||||||
|
condition->GetId().c_str(), conditionMatched);
|
||||||
|
} else {
|
||||||
|
blog(LOG_INFO,
|
||||||
|
"condition %s evaluation skipped (short circuit)",
|
||||||
|
condition->GetId().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Macro::CheckConditions(bool ignorePause)
|
||||||
{
|
{
|
||||||
if (_isGroup) {
|
if (_isGroup) {
|
||||||
return false;
|
return false;
|
||||||
@@ -194,28 +251,7 @@ bool Macro::CeckMatch(bool ignorePause)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool conditionMatched = checkCondition(condition);
|
_matched = CheckConditionHelper(condition);
|
||||||
conditionMatched =
|
|
||||||
condition->CheckDurationModifier(conditionMatched);
|
|
||||||
|
|
||||||
const auto logicType = condition->GetLogicType();
|
|
||||||
if (logicType == Logic::Type::NONE) {
|
|
||||||
vblog(LOG_INFO, "ignoring condition '%s' for '%s'",
|
|
||||||
condition->GetId().c_str(), _name.c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
vblog(LOG_INFO, "condition %s returned %d",
|
|
||||||
condition->GetId().c_str(), conditionMatched);
|
|
||||||
|
|
||||||
const bool isNegativeLogicType =
|
|
||||||
Logic::IsNegationType(logicType);
|
|
||||||
if ((conditionMatched && !isNegativeLogicType) ||
|
|
||||||
(!conditionMatched && isNegativeLogicType)) {
|
|
||||||
condition->EnableHighlight();
|
|
||||||
}
|
|
||||||
|
|
||||||
_matched = Logic::ApplyConditionLogic(
|
|
||||||
logicType, _matched, conditionMatched, _name.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vblog(LOG_INFO, "Macro %s returned %d", _name.c_str(), _matched);
|
vblog(LOG_INFO, "Macro %s returned %d", _name.c_str(), _matched);
|
||||||
@@ -273,12 +309,26 @@ bool Macro::PerformActions(bool match, bool forceParallel, bool ignorePause)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Macro::WasExecutedSince(
|
bool Macro::WasExecutedSince(const TimePoint &time) const
|
||||||
const std::chrono::high_resolution_clock::time_point &time) const
|
|
||||||
{
|
{
|
||||||
return _lastExecutionTime > time;
|
return _lastExecutionTime > time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Macro::ConditionsShouldBeChecked() const
|
||||||
|
{
|
||||||
|
if (!_useCustomConditionCheckInterval) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto timePassed = std::chrono::high_resolution_clock::now() -
|
||||||
|
LastConditionCheckTime();
|
||||||
|
const auto timePassedMs =
|
||||||
|
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
timePassed);
|
||||||
|
return timePassedMs.count() >=
|
||||||
|
_customConditionCheckInterval.Milliseconds();
|
||||||
|
}
|
||||||
|
|
||||||
bool Macro::ShouldRunActions() const
|
bool Macro::ShouldRunActions() const
|
||||||
{
|
{
|
||||||
const bool hasActionsToExecute =
|
const bool hasActionsToExecute =
|
||||||
@@ -301,18 +351,6 @@ bool Macro::ShouldRunActions() const
|
|||||||
return hasActionsToExecute;
|
return hasActionsToExecute;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t Macro::MsSinceLastCheck() const
|
|
||||||
{
|
|
||||||
if (_lastCheckTime.time_since_epoch().count() == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const auto timePassed =
|
|
||||||
std::chrono::high_resolution_clock::now() - _lastCheckTime;
|
|
||||||
return std::chrono::duration_cast<std::chrono::milliseconds>(timePassed)
|
|
||||||
.count() +
|
|
||||||
1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::SetName(const std::string &name)
|
void Macro::SetName(const std::string &name)
|
||||||
{
|
{
|
||||||
const bool nameChanged = _name == name;
|
const bool nameChanged = _name == name;
|
||||||
@@ -368,18 +406,17 @@ bool Macro::RunActionsHelper(
|
|||||||
|
|
||||||
bool Macro::RunActions(bool ignorePause)
|
bool Macro::RunActions(bool ignorePause)
|
||||||
{
|
{
|
||||||
vblog(LOG_INFO, "running actions of %s", _name.c_str());
|
mblog(LOG_INFO, "running actions of %s", _name.c_str());
|
||||||
return RunActionsHelper(_actions, ignorePause);
|
return RunActionsHelper(_actions, ignorePause);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Macro::RunElseActions(bool ignorePause)
|
bool Macro::RunElseActions(bool ignorePause)
|
||||||
{
|
{
|
||||||
vblog(LOG_INFO, "running else actions of %s", _name.c_str());
|
mblog(LOG_INFO, "running else actions of %s", _name.c_str());
|
||||||
return RunActionsHelper(_elseActions, ignorePause);
|
return RunActionsHelper(_elseActions, ignorePause);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Macro::WasPausedSince(
|
bool Macro::WasPausedSince(const TimePoint &time) const
|
||||||
const std::chrono::high_resolution_clock::time_point &time) const
|
|
||||||
{
|
{
|
||||||
return _lastUnpauseTime > time;
|
return _lastUnpauseTime > time;
|
||||||
}
|
}
|
||||||
@@ -394,6 +431,36 @@ void Macro::SetStopActionsIfNotDone(bool stopActionsIfNotDone)
|
|||||||
_stopActionsIfNotDone = stopActionsIfNotDone;
|
_stopActionsIfNotDone = stopActionsIfNotDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Macro::SetShortCircuitEvaluation(bool useShortCircuitEvaluation)
|
||||||
|
{
|
||||||
|
_useShortCircuitEvaluation = useShortCircuitEvaluation;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Macro::ShortCircuitEvaluationEnabled() const
|
||||||
|
{
|
||||||
|
return _useShortCircuitEvaluation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Macro::SetCustomConditionCheckIntervalEnabled(bool enable)
|
||||||
|
{
|
||||||
|
_useCustomConditionCheckInterval = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Macro::CustomConditionCheckIntervalEnabled() const
|
||||||
|
{
|
||||||
|
return _useCustomConditionCheckInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Macro::SetCustomConditionCheckInterval(const Duration &duration)
|
||||||
|
{
|
||||||
|
_customConditionCheckInterval = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
Duration Macro::GetCustomConditionCheckInterval() const
|
||||||
|
{
|
||||||
|
return _customConditionCheckInterval;
|
||||||
|
}
|
||||||
|
|
||||||
void Macro::SetPaused(bool pause)
|
void Macro::SetPaused(bool pause)
|
||||||
{
|
{
|
||||||
if (_paused && !pause) {
|
if (_paused && !pause) {
|
||||||
@@ -414,6 +481,16 @@ void Macro::AddHelperThread(std::thread &&newThread)
|
|||||||
_helperThreads.push_back(std::move(newThread));
|
_helperThreads.push_back(std::move(newThread));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Macro::SetPauseStateSaveBehavior(PauseStateSaveBehavior behavior)
|
||||||
|
{
|
||||||
|
_pauseSaveBehavior = behavior;
|
||||||
|
}
|
||||||
|
|
||||||
|
Macro::PauseStateSaveBehavior Macro::GetPauseStateSaveBehavior() const
|
||||||
|
{
|
||||||
|
return _pauseSaveBehavior;
|
||||||
|
}
|
||||||
|
|
||||||
void Macro::Stop()
|
void Macro::Stop()
|
||||||
{
|
{
|
||||||
_stop = true;
|
_stop = true;
|
||||||
@@ -613,11 +690,6 @@ bool Macro::Save(obs_data_t *obj, bool saveForCopy) const
|
|||||||
if (!saveForCopy) {
|
if (!saveForCopy) {
|
||||||
obs_data_set_string(obj, "name", _name.c_str());
|
obs_data_set_string(obj, "name", _name.c_str());
|
||||||
}
|
}
|
||||||
obs_data_set_bool(obj, "pause", _paused);
|
|
||||||
obs_data_set_bool(obj, "parallel", _runInParallel);
|
|
||||||
obs_data_set_bool(obj, "onChange", _performActionsOnChange);
|
|
||||||
obs_data_set_bool(obj, "skipExecOnStart", _skipExecOnStart);
|
|
||||||
obs_data_set_bool(obj, "stopActionsIfNotDone", _stopActionsIfNotDone);
|
|
||||||
|
|
||||||
obs_data_set_bool(obj, "group", _isGroup);
|
obs_data_set_bool(obj, "group", _isGroup);
|
||||||
if (_isGroup) {
|
if (_isGroup) {
|
||||||
@@ -628,6 +700,19 @@ bool Macro::Save(obs_data_t *obj, bool saveForCopy) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obs_data_set_int(obj, "pauseSaveBehavior",
|
||||||
|
static_cast<int>(_pauseSaveBehavior));
|
||||||
|
obs_data_set_bool(obj, "pause", _paused);
|
||||||
|
obs_data_set_bool(obj, "parallel", _runInParallel);
|
||||||
|
obs_data_set_bool(obj, "onChange", _performActionsOnChange);
|
||||||
|
obs_data_set_bool(obj, "skipExecOnStart", _skipExecOnStart);
|
||||||
|
obs_data_set_bool(obj, "stopActionsIfNotDone", _stopActionsIfNotDone);
|
||||||
|
obs_data_set_bool(obj, "useShortCircuitEvaluation",
|
||||||
|
_useShortCircuitEvaluation);
|
||||||
|
obs_data_set_bool(obj, "useCustomConditionCheckInterval",
|
||||||
|
_useCustomConditionCheckInterval);
|
||||||
|
_customConditionCheckInterval.Save(obj, "customConditionCheckInterval");
|
||||||
|
|
||||||
SaveDockSettings(obj, saveForCopy);
|
SaveDockSettings(obj, saveForCopy);
|
||||||
|
|
||||||
SaveSplitterPos(_actionConditionSplitterPosition, obj,
|
SaveSplitterPos(_actionConditionSplitterPosition, obj,
|
||||||
@@ -676,11 +761,6 @@ bool Macro::Save(obs_data_t *obj, bool saveForCopy) const
|
|||||||
bool Macro::Load(obs_data_t *obj)
|
bool Macro::Load(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
_name = obs_data_get_string(obj, "name");
|
_name = obs_data_get_string(obj, "name");
|
||||||
_paused = obs_data_get_bool(obj, "pause");
|
|
||||||
_runInParallel = obs_data_get_bool(obj, "parallel");
|
|
||||||
_performActionsOnChange = obs_data_get_bool(obj, "onChange");
|
|
||||||
_skipExecOnStart = obs_data_get_bool(obj, "skipExecOnStart");
|
|
||||||
_stopActionsIfNotDone = obs_data_get_bool(obj, "stopActionsIfNotDone");
|
|
||||||
|
|
||||||
_isGroup = obs_data_get_bool(obj, "group");
|
_isGroup = obs_data_get_bool(obj, "group");
|
||||||
if (_isGroup) {
|
if (_isGroup) {
|
||||||
@@ -692,6 +772,32 @@ bool Macro::Load(obs_data_t *obj)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_pauseSaveBehavior = static_cast<PauseStateSaveBehavior>(
|
||||||
|
obs_data_get_int(obj, "pauseSaveBehavior"));
|
||||||
|
switch (_pauseSaveBehavior) {
|
||||||
|
case PauseStateSaveBehavior::PERSIST:
|
||||||
|
_paused = obs_data_get_bool(obj, "pause");
|
||||||
|
break;
|
||||||
|
case PauseStateSaveBehavior::PAUSE:
|
||||||
|
_paused = true;
|
||||||
|
break;
|
||||||
|
case PauseStateSaveBehavior::UNPAUSE:
|
||||||
|
_paused = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_paused = obs_data_get_bool(obj, "pause");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_runInParallel = obs_data_get_bool(obj, "parallel");
|
||||||
|
_performActionsOnChange = obs_data_get_bool(obj, "onChange");
|
||||||
|
_skipExecOnStart = obs_data_get_bool(obj, "skipExecOnStart");
|
||||||
|
_stopActionsIfNotDone = obs_data_get_bool(obj, "stopActionsIfNotDone");
|
||||||
|
_useShortCircuitEvaluation =
|
||||||
|
obs_data_get_bool(obj, "useShortCircuitEvaluation");
|
||||||
|
_useCustomConditionCheckInterval =
|
||||||
|
obs_data_get_bool(obj, "useCustomConditionCheckInterval");
|
||||||
|
_customConditionCheckInterval.Load(obj, "customConditionCheckInterval");
|
||||||
|
|
||||||
LoadDockSettings(obj);
|
LoadDockSettings(obj);
|
||||||
|
|
||||||
LoadSplitterPos(_actionConditionSplitterPosition, obj,
|
LoadSplitterPos(_actionConditionSplitterPosition, obj,
|
||||||
@@ -1253,7 +1359,15 @@ bool CheckMacros()
|
|||||||
{
|
{
|
||||||
bool matchFound = false;
|
bool matchFound = false;
|
||||||
for (const auto &m : macros) {
|
for (const auto &m : macros) {
|
||||||
if (m->CeckMatch() || m->ElseActions().size() > 0) {
|
if (!m->ConditionsShouldBeChecked()) {
|
||||||
|
vblog(LOG_INFO,
|
||||||
|
"skipping condition check for macro \"%s\" "
|
||||||
|
"(custom check interval)",
|
||||||
|
m->Name().c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m->CheckConditions() || m->ElseActions().size() > 0) {
|
||||||
matchFound = true;
|
matchFound = true;
|
||||||
// This has to be performed here for now as actions are
|
// This has to be performed here for now as actions are
|
||||||
// not performed immediately after checking conditions.
|
// not performed immediately after checking conditions.
|
||||||
@@ -1299,7 +1413,7 @@ bool RunMacros()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
vblog(LOG_INFO, "running macro: %s", m->Name().c_str());
|
vblog(LOG_INFO, "running macro: %s", m->Name().c_str());
|
||||||
if (!m->PerformActions(m->Matched())) {
|
if (!m->PerformActions(m->ConditionsMatched())) {
|
||||||
blog(LOG_WARNING, "abort macro: %s", m->Name().c_str());
|
blog(LOG_WARNING, "abort macro: %s", m->Name().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1350,4 +1464,27 @@ void InvalidateMacroTempVarValues()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Macro> GetMacroWithInvalidConditionInterval()
|
||||||
|
{
|
||||||
|
if (macros.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto ¯o : macros) {
|
||||||
|
if (!macro) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!macro->CustomConditionCheckIntervalEnabled()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (macro->GetCustomConditionCheckInterval().Milliseconds() <
|
||||||
|
GetIntervalValue()) {
|
||||||
|
return macro;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -22,24 +22,33 @@ namespace advss {
|
|||||||
class MacroDock;
|
class MacroDock;
|
||||||
|
|
||||||
class Macro {
|
class Macro {
|
||||||
|
using TimePoint = std::chrono::high_resolution_clock::time_point;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Macro(const std::string &name = "", const bool addHotkey = false);
|
enum class PauseStateSaveBehavior { PERSIST, PAUSE, UNPAUSE };
|
||||||
virtual ~Macro();
|
|
||||||
|
Macro(const std::string &name = "", const bool addHotkey = false,
|
||||||
|
const bool shortCircuitEvaluation = false);
|
||||||
|
~Macro();
|
||||||
|
|
||||||
std::string Name() const { return _name; }
|
std::string Name() const { return _name; }
|
||||||
void SetName(const std::string &name);
|
void SetName(const std::string &name);
|
||||||
|
|
||||||
bool CeckMatch(bool ignorePause = false);
|
bool CheckConditions(bool ignorePause = false);
|
||||||
bool Matched() const { return _matched; }
|
bool ConditionsMatched() const { return _matched; }
|
||||||
int64_t MsSinceLastCheck() const;
|
TimePoint LastConditionCheckTime() const { return _lastCheckTime; }
|
||||||
|
bool ConditionsShouldBeChecked() const;
|
||||||
|
|
||||||
bool ShouldRunActions() const;
|
bool ShouldRunActions() const;
|
||||||
bool PerformActions(bool match, bool forceParallel = false,
|
bool PerformActions(bool match, bool forceParallel = false,
|
||||||
bool ignorePause = false);
|
bool ignorePause = false);
|
||||||
|
|
||||||
void SetPaused(bool pause = true);
|
void SetPaused(bool pause = true);
|
||||||
bool Paused() const { return _paused; }
|
bool Paused() const { return _paused; }
|
||||||
bool WasPausedSince(
|
bool WasPausedSince(const TimePoint &) const;
|
||||||
const std::chrono::high_resolution_clock::time_point &) const;
|
|
||||||
|
void SetPauseStateSaveBehavior(PauseStateSaveBehavior);
|
||||||
|
PauseStateSaveBehavior GetPauseStateSaveBehavior() const;
|
||||||
|
|
||||||
void Stop();
|
void Stop();
|
||||||
bool GetStop() const { return _stop; }
|
bool GetStop() const { return _stop; }
|
||||||
@@ -54,6 +63,14 @@ public:
|
|||||||
void SetStopActionsIfNotDone(bool stopActionsIfNotDone);
|
void SetStopActionsIfNotDone(bool stopActionsIfNotDone);
|
||||||
bool StopActionsIfNotDone() const { return _stopActionsIfNotDone; }
|
bool StopActionsIfNotDone() const { return _stopActionsIfNotDone; }
|
||||||
|
|
||||||
|
void SetShortCircuitEvaluation(bool useShortCircuitEvaluation);
|
||||||
|
bool ShortCircuitEvaluationEnabled() const;
|
||||||
|
|
||||||
|
void SetCustomConditionCheckIntervalEnabled(bool enable);
|
||||||
|
bool CustomConditionCheckIntervalEnabled() const;
|
||||||
|
void SetCustomConditionCheckInterval(const Duration &);
|
||||||
|
Duration GetCustomConditionCheckInterval() const;
|
||||||
|
|
||||||
int RunCount() const { return _runCount; };
|
int RunCount() const { return _runCount; };
|
||||||
void ResetRunCount() { _runCount = 0; };
|
void ResetRunCount() { _runCount = 0; };
|
||||||
|
|
||||||
@@ -113,8 +130,7 @@ public:
|
|||||||
void SetElseActionSplitterPosition(const QList<int>);
|
void SetElseActionSplitterPosition(const QList<int>);
|
||||||
const QList<int> &GetElseActionSplitterPosition() const;
|
const QList<int> &GetElseActionSplitterPosition() const;
|
||||||
bool HasValidSplitterPositions() const;
|
bool HasValidSplitterPositions() const;
|
||||||
bool WasExecutedSince(
|
bool WasExecutedSince(const TimePoint &) const;
|
||||||
const std::chrono::high_resolution_clock::time_point &) const;
|
|
||||||
bool OnChangePreventedActionsRecently();
|
bool OnChangePreventedActionsRecently();
|
||||||
void ResetUIHelpers();
|
void ResetUIHelpers();
|
||||||
|
|
||||||
@@ -149,6 +165,9 @@ private:
|
|||||||
void ClearHotkeys() const;
|
void ClearHotkeys() const;
|
||||||
void SetHotkeysDesc() const;
|
void SetHotkeysDesc() const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
CheckConditionHelper(const std::shared_ptr<MacroCondition> &) const;
|
||||||
|
|
||||||
bool RunActionsHelper(
|
bool RunActionsHelper(
|
||||||
const std::deque<std::shared_ptr<MacroAction>> &actions,
|
const std::deque<std::shared_ptr<MacroAction>> &actions,
|
||||||
bool ignorePause);
|
bool ignorePause);
|
||||||
@@ -164,9 +183,9 @@ private:
|
|||||||
bool _die = false;
|
bool _die = false;
|
||||||
bool _stop = false;
|
bool _stop = false;
|
||||||
bool _done = true;
|
bool _done = true;
|
||||||
std::chrono::high_resolution_clock::time_point _lastCheckTime{};
|
TimePoint _lastCheckTime{};
|
||||||
std::chrono::high_resolution_clock::time_point _lastUnpauseTime{};
|
TimePoint _lastUnpauseTime{};
|
||||||
std::chrono::high_resolution_clock::time_point _lastExecutionTime{};
|
TimePoint _lastExecutionTime{};
|
||||||
std::thread _backgroundThread;
|
std::thread _backgroundThread;
|
||||||
std::vector<std::thread> _helperThreads;
|
std::vector<std::thread> _helperThreads;
|
||||||
|
|
||||||
@@ -179,10 +198,14 @@ private:
|
|||||||
bool _isGroup = false;
|
bool _isGroup = false;
|
||||||
bool _isCollapsed = false;
|
bool _isCollapsed = false;
|
||||||
|
|
||||||
|
bool _useShortCircuitEvaluation = false;
|
||||||
|
bool _useCustomConditionCheckInterval = false;
|
||||||
|
Duration _customConditionCheckInterval = 0.3;
|
||||||
|
bool _conditionSateChanged = false;
|
||||||
|
|
||||||
bool _runInParallel = false;
|
bool _runInParallel = false;
|
||||||
bool _matched = false;
|
bool _matched = false;
|
||||||
bool _lastMatched = false;
|
bool _lastMatched = false;
|
||||||
bool _conditionSateChanged = false;
|
|
||||||
bool _performActionsOnChange = true;
|
bool _performActionsOnChange = true;
|
||||||
bool _skipExecOnStart = false;
|
bool _skipExecOnStart = false;
|
||||||
bool _stopActionsIfNotDone = false;
|
bool _stopActionsIfNotDone = false;
|
||||||
@@ -193,6 +216,9 @@ private:
|
|||||||
obs_hotkey_id _unpauseHotkey = OBS_INVALID_HOTKEY_ID;
|
obs_hotkey_id _unpauseHotkey = OBS_INVALID_HOTKEY_ID;
|
||||||
obs_hotkey_id _togglePauseHotkey = OBS_INVALID_HOTKEY_ID;
|
obs_hotkey_id _togglePauseHotkey = OBS_INVALID_HOTKEY_ID;
|
||||||
|
|
||||||
|
PauseStateSaveBehavior _pauseSaveBehavior =
|
||||||
|
PauseStateSaveBehavior::PERSIST;
|
||||||
|
|
||||||
MacroInputVariables _inputVariables;
|
MacroInputVariables _inputVariables;
|
||||||
|
|
||||||
// UI helpers
|
// UI helpers
|
||||||
@@ -230,5 +256,6 @@ Macro *GetMacroByName(const char *name);
|
|||||||
Macro *GetMacroByQString(const QString &name);
|
Macro *GetMacroByQString(const QString &name);
|
||||||
std::weak_ptr<Macro> GetWeakMacroByName(const char *name);
|
std::weak_ptr<Macro> GetWeakMacroByName(const char *name);
|
||||||
void InvalidateMacroTempVarValues();
|
void InvalidateMacroTempVarValues();
|
||||||
|
std::shared_ptr<Macro> GetMacroWithInvalidConditionInterval();
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "plugin-state-helpers.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "sync-helpers.hpp"
|
#include "sync-helpers.hpp"
|
||||||
#include "tab-helpers.hpp"
|
#include "tab-helpers.hpp"
|
||||||
|
#include "time-helpers.hpp"
|
||||||
#include "ui-helpers.hpp"
|
#include "ui-helpers.hpp"
|
||||||
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
@@ -55,6 +56,13 @@ void ActionQueueTable::Add()
|
|||||||
QString::fromStdString(newQueue->Name()));
|
QString::fromStdString(newQueue->Name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double getSecondsSinceLastEmpty(ActionQueue *queue)
|
||||||
|
{
|
||||||
|
const auto time = std::chrono::high_resolution_clock::now() -
|
||||||
|
queue->GetLastEmptyTime();
|
||||||
|
return std::chrono::duration_cast<std::chrono::seconds>(time).count();
|
||||||
|
}
|
||||||
|
|
||||||
static QStringList getCellLabels(ActionQueue *queue, bool addName = true)
|
static QStringList getCellLabels(ActionQueue *queue, bool addName = true)
|
||||||
{
|
{
|
||||||
assert(queue);
|
assert(queue);
|
||||||
@@ -64,6 +72,7 @@ static QStringList getCellLabels(ActionQueue *queue, bool addName = true)
|
|||||||
result << QString::fromStdString(queue->Name());
|
result << QString::fromStdString(queue->Name());
|
||||||
}
|
}
|
||||||
result << QString::number(queue->Size())
|
result << QString::number(queue->Size())
|
||||||
|
<< FormatRelativeTime(getSecondsSinceLastEmpty(queue))
|
||||||
<< QString::fromStdString(obs_module_text(
|
<< QString::fromStdString(obs_module_text(
|
||||||
queue->IsRunning()
|
queue->IsRunning()
|
||||||
? "AdvSceneSwitcher.actionQueueTab.yes"
|
? "AdvSceneSwitcher.actionQueueTab.yes"
|
||||||
@@ -199,6 +208,8 @@ ActionQueueTable::ActionQueueTable(QTabWidget *parent)
|
|||||||
"AdvSceneSwitcher.actionQueueTab.name.header")
|
"AdvSceneSwitcher.actionQueueTab.name.header")
|
||||||
<< obs_module_text(
|
<< obs_module_text(
|
||||||
"AdvSceneSwitcher.actionQueueTab.size.header")
|
"AdvSceneSwitcher.actionQueueTab.size.header")
|
||||||
|
<< obs_module_text(
|
||||||
|
"AdvSceneSwitcher.actionQueueTab.lastEmpty.header")
|
||||||
<< obs_module_text(
|
<< obs_module_text(
|
||||||
"AdvSceneSwitcher.actionQueueTab.isRunning.header")
|
"AdvSceneSwitcher.actionQueueTab.isRunning.header")
|
||||||
<< obs_module_text(
|
<< obs_module_text(
|
||||||
|
|||||||
@@ -26,7 +26,10 @@ void SetupActionQueues()
|
|||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionQueue::ActionQueue() : Item() {}
|
ActionQueue::ActionQueue() : Item()
|
||||||
|
{
|
||||||
|
_lastEmpty = std::chrono::high_resolution_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
ActionQueue::~ActionQueue()
|
ActionQueue::~ActionQueue()
|
||||||
{
|
{
|
||||||
@@ -124,6 +127,14 @@ bool ActionQueue::IsEmpty()
|
|||||||
return _actions.empty();
|
return _actions.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ActionQueue::TimePoint ActionQueue::GetLastEmptyTime()
|
||||||
|
{
|
||||||
|
if (IsEmpty()) {
|
||||||
|
_lastEmpty = std::chrono::high_resolution_clock::now();
|
||||||
|
}
|
||||||
|
return _lastEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ActionQueue::Size()
|
size_t ActionQueue::Size()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
@@ -137,6 +148,8 @@ void ActionQueue::RunActions()
|
|||||||
{ // Grab next action to run
|
{ // Grab next action to run
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
while (_actions.empty() && !_stop) {
|
while (_actions.empty() && !_stop) {
|
||||||
|
_lastEmpty =
|
||||||
|
std::chrono::high_resolution_clock::now();
|
||||||
_cv.wait(lock);
|
_cv.wait(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
#include "item-selection-helpers.hpp"
|
#include "item-selection-helpers.hpp"
|
||||||
#include "macro-action.hpp"
|
#include "macro-action.hpp"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <condition_variable>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <obs-data.h>
|
#include <obs-data.h>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <condition_variable>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -14,6 +15,8 @@ class ActionQueueSelection;
|
|||||||
class ActionQueueSettingsDialog;
|
class ActionQueueSettingsDialog;
|
||||||
|
|
||||||
class ActionQueue : public Item {
|
class ActionQueue : public Item {
|
||||||
|
using TimePoint = std::chrono::high_resolution_clock::time_point;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ActionQueue();
|
ActionQueue();
|
||||||
~ActionQueue();
|
~ActionQueue();
|
||||||
@@ -30,6 +33,7 @@ public:
|
|||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
bool IsEmpty();
|
bool IsEmpty();
|
||||||
|
TimePoint GetLastEmptyTime();
|
||||||
|
|
||||||
void Add(const std::shared_ptr<MacroAction> &);
|
void Add(const std::shared_ptr<MacroAction> &);
|
||||||
size_t Size();
|
size_t Size();
|
||||||
@@ -44,6 +48,7 @@ private:
|
|||||||
std::condition_variable _cv;
|
std::condition_variable _cv;
|
||||||
std::thread _thread;
|
std::thread _thread;
|
||||||
std::deque<std::shared_ptr<MacroAction>> _actions;
|
std::deque<std::shared_ptr<MacroAction>> _actions;
|
||||||
|
TimePoint _lastEmpty;
|
||||||
|
|
||||||
friend ActionQueueSelection;
|
friend ActionQueueSelection;
|
||||||
friend ActionQueueSettingsDialog;
|
friend ActionQueueSettingsDialog;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "scene-group.hpp"
|
#include "scene-group.hpp"
|
||||||
#include "scene-trigger.hpp"
|
|
||||||
#include "switch-audio.hpp"
|
#include "switch-audio.hpp"
|
||||||
#include "switch-executable.hpp"
|
#include "switch-executable.hpp"
|
||||||
#include "switch-file.hpp"
|
#include "switch-file.hpp"
|
||||||
@@ -14,7 +13,6 @@
|
|||||||
#include "switch-window.hpp"
|
#include "switch-window.hpp"
|
||||||
#include "switch-sequence.hpp"
|
#include "switch-sequence.hpp"
|
||||||
#include "switch-video.hpp"
|
#include "switch-video.hpp"
|
||||||
#include "switch-network.hpp"
|
|
||||||
|
|
||||||
#include "macro-settings.hpp"
|
#include "macro-settings.hpp"
|
||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
@@ -137,7 +135,7 @@ public:
|
|||||||
bool transitionOverrideOverride = false;
|
bool transitionOverrideOverride = false;
|
||||||
bool adjustActiveTransitionType = true;
|
bool adjustActiveTransitionType = true;
|
||||||
|
|
||||||
enum class LogLevel { DEFAULT, PRINT_ACTION, VERBOSE };
|
enum class LogLevel { DEFAULT, LOG_MACRO, LOG_ACTION, VERBOSE };
|
||||||
LogLevel logLevel = LogLevel::DEFAULT;
|
LogLevel logLevel = LogLevel::DEFAULT;
|
||||||
|
|
||||||
/* --- End of General tab section --- */
|
/* --- End of General tab section --- */
|
||||||
@@ -194,9 +192,7 @@ public:
|
|||||||
void saveTimeSwitches(obs_data_t *obj);
|
void saveTimeSwitches(obs_data_t *obj);
|
||||||
void saveAudioSwitches(obs_data_t *obj);
|
void saveAudioSwitches(obs_data_t *obj);
|
||||||
void saveSceneGroups(obs_data_t *obj);
|
void saveSceneGroups(obs_data_t *obj);
|
||||||
void saveSceneTriggers(obs_data_t *obj);
|
|
||||||
void saveVideoSwitches(obs_data_t *obj);
|
void saveVideoSwitches(obs_data_t *obj);
|
||||||
void saveNetworkSwitches(obs_data_t *obj);
|
|
||||||
|
|
||||||
void loadWindowTitleSwitches(obs_data_t *obj);
|
void loadWindowTitleSwitches(obs_data_t *obj);
|
||||||
void loadScreenRegionSwitches(obs_data_t *obj);
|
void loadScreenRegionSwitches(obs_data_t *obj);
|
||||||
@@ -211,9 +207,7 @@ public:
|
|||||||
void loadTimeSwitches(obs_data_t *obj);
|
void loadTimeSwitches(obs_data_t *obj);
|
||||||
void loadAudioSwitches(obs_data_t *obj);
|
void loadAudioSwitches(obs_data_t *obj);
|
||||||
void loadSceneGroups(obs_data_t *obj);
|
void loadSceneGroups(obs_data_t *obj);
|
||||||
void loadSceneTriggers(obs_data_t *obj);
|
|
||||||
void loadVideoSwitches(obs_data_t *obj);
|
void loadVideoSwitches(obs_data_t *obj);
|
||||||
void loadNetworkSettings(obs_data_t *obj);
|
|
||||||
|
|
||||||
void Prune();
|
void Prune();
|
||||||
|
|
||||||
@@ -236,7 +230,6 @@ public:
|
|||||||
void checkAudioSwitchFallback(OBSWeakSource &scene,
|
void checkAudioSwitchFallback(OBSWeakSource &scene,
|
||||||
OBSWeakSource &transition);
|
OBSWeakSource &transition);
|
||||||
bool checkVideoSwitch(OBSWeakSource &scene, OBSWeakSource &transition);
|
bool checkVideoSwitch(OBSWeakSource &scene, OBSWeakSource &transition);
|
||||||
void checkTriggers();
|
|
||||||
bool checkPause();
|
bool checkPause();
|
||||||
void checkDefaultSceneTransitions();
|
void checkDefaultSceneTransitions();
|
||||||
void writeSceneInfoToFile();
|
void writeSceneInfoToFile();
|
||||||
@@ -256,7 +249,6 @@ public:
|
|||||||
FileIOData fileIO;
|
FileIOData fileIO;
|
||||||
std::deque<FileSwitch> fileSwitches;
|
std::deque<FileSwitch> fileSwitches;
|
||||||
std::deque<ExecutableSwitch> executableSwitches;
|
std::deque<ExecutableSwitch> executableSwitches;
|
||||||
std::deque<SceneTrigger> sceneTriggers;
|
|
||||||
std::deque<SceneTransition> sceneTransitions;
|
std::deque<SceneTransition> sceneTransitions;
|
||||||
std::deque<DefaultSceneTransition> defaultSceneTransitions;
|
std::deque<DefaultSceneTransition> defaultSceneTransitions;
|
||||||
std::deque<MediaSwitch> mediaSwitches;
|
std::deque<MediaSwitch> mediaSwitches;
|
||||||
@@ -265,11 +257,6 @@ public:
|
|||||||
QDateTime liveTime;
|
QDateTime liveTime;
|
||||||
std::deque<AudioSwitch> audioSwitches;
|
std::deque<AudioSwitch> audioSwitches;
|
||||||
AudioSwitchFallback audioFallback;
|
AudioSwitchFallback audioFallback;
|
||||||
WSServer server;
|
|
||||||
ServerStatus serverStatus = ServerStatus::NOT_RUNNING;
|
|
||||||
WSClient client;
|
|
||||||
ClientStatus clientStatus = ClientStatus::DISCONNECTED;
|
|
||||||
NetworkConfig networkConfig;
|
|
||||||
std::deque<VideoSwitch> videoSwitches;
|
std::deque<VideoSwitch> videoSwitches;
|
||||||
std::deque<SceneGroup> sceneGroups;
|
std::deque<SceneGroup> sceneGroups;
|
||||||
SceneGroup *lastRandomSceneGroup = nullptr;
|
SceneGroup *lastRandomSceneGroup = nullptr;
|
||||||
|
|||||||
38
lib/utils/auto-update-tooltip-label.cpp
Normal file
38
lib/utils/auto-update-tooltip-label.cpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#include "auto-update-tooltip-label.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
AutoUpdateTooltipLabel::AutoUpdateTooltipLabel(
|
||||||
|
QWidget *parent, const std::function<QString()> &updateTooltipCallback,
|
||||||
|
int updateIntervalMs)
|
||||||
|
: QLabel(parent),
|
||||||
|
_callback(updateTooltipCallback),
|
||||||
|
_timer(new QTimer(this)),
|
||||||
|
_updateIntervalMs(updateIntervalMs)
|
||||||
|
{
|
||||||
|
connect(_timer, &QTimer::timeout, this,
|
||||||
|
&AutoUpdateTooltipLabel::UpdateTooltip);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
void AutoUpdateTooltipLabel::enterEvent(QEnterEvent *event)
|
||||||
|
#else
|
||||||
|
void AutoUpdateTooltipLabel::enterEvent(QEvent *event)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
_timer->start(_updateIntervalMs);
|
||||||
|
QLabel::enterEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoUpdateTooltipLabel::leaveEvent(QEvent *event)
|
||||||
|
{
|
||||||
|
_timer->stop();
|
||||||
|
QLabel::leaveEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoUpdateTooltipLabel::UpdateTooltip()
|
||||||
|
{
|
||||||
|
setToolTip(_callback());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
36
lib/utils/auto-update-tooltip-label.hpp
Normal file
36
lib/utils/auto-update-tooltip-label.hpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "export-symbol-helper.hpp"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
class ADVSS_EXPORT AutoUpdateTooltipLabel : public QLabel {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
AutoUpdateTooltipLabel(
|
||||||
|
QWidget *parent,
|
||||||
|
const std::function<QString()> &updateTooltipCallback,
|
||||||
|
int updateIntervalMs = 300);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
void enterEvent(QEnterEvent *event) override;
|
||||||
|
#else
|
||||||
|
void enterEvent(QEvent *event) override;
|
||||||
|
#endif
|
||||||
|
void leaveEvent(QEvent *event) override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void UpdateTooltip();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::function<QString()> _callback;
|
||||||
|
QTimer *_timer;
|
||||||
|
const int _updateIntervalMs;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -19,6 +19,15 @@ const std::map<Logic::Type, const char *> Logic::localeMap = {
|
|||||||
|
|
||||||
bool Logic::ApplyConditionLogic(Type type, bool currentMatchResult,
|
bool Logic::ApplyConditionLogic(Type type, bool currentMatchResult,
|
||||||
bool conditionMatched, const char *context)
|
bool conditionMatched, const char *context)
|
||||||
|
{
|
||||||
|
return ApplyConditionLogic(
|
||||||
|
type, currentMatchResult,
|
||||||
|
[conditionMatched]() { return conditionMatched; }, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Logic::ApplyConditionLogic(Type type, bool currentMatchResult,
|
||||||
|
const std::function<bool()> &evaluateCondition,
|
||||||
|
const char *context)
|
||||||
{
|
{
|
||||||
if (!context) {
|
if (!context) {
|
||||||
context = "";
|
context = "";
|
||||||
@@ -26,22 +35,22 @@ bool Logic::ApplyConditionLogic(Type type, bool currentMatchResult,
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::ROOT_NONE:
|
case Type::ROOT_NONE:
|
||||||
return conditionMatched;
|
return evaluateCondition();
|
||||||
case Type::ROOT_NOT:
|
case Type::ROOT_NOT:
|
||||||
return !conditionMatched;
|
return !evaluateCondition();
|
||||||
case Type::ROOT_LAST:
|
case Type::ROOT_LAST:
|
||||||
break;
|
break;
|
||||||
case Type::NONE:
|
case Type::NONE:
|
||||||
vblog(LOG_INFO, "skipping condition check for '%s'", context);
|
vblog(LOG_INFO, "skipping condition check for '%s'", context);
|
||||||
return currentMatchResult;
|
return currentMatchResult;
|
||||||
case Type::AND:
|
case Type::AND:
|
||||||
return currentMatchResult && conditionMatched;
|
return currentMatchResult && evaluateCondition();
|
||||||
case Type::OR:
|
case Type::OR:
|
||||||
return currentMatchResult || conditionMatched;
|
return currentMatchResult || evaluateCondition();
|
||||||
case Type::AND_NOT:
|
case Type::AND_NOT:
|
||||||
return currentMatchResult && !conditionMatched;
|
return currentMatchResult && !evaluateCondition();
|
||||||
case Type::OR_NOT:
|
case Type::OR_NOT:
|
||||||
return currentMatchResult || !conditionMatched;
|
return currentMatchResult || !evaluateCondition();
|
||||||
case Type::LAST:
|
case Type::LAST:
|
||||||
default:
|
default:
|
||||||
blog(LOG_WARNING, "ignoring invalid logic check (%s)", context);
|
blog(LOG_WARNING, "ignoring invalid logic check (%s)", context);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <obs-data.h>
|
#include <obs-data.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -39,6 +40,10 @@ public:
|
|||||||
static bool ApplyConditionLogic(Type, bool currentMatchResult,
|
static bool ApplyConditionLogic(Type, bool currentMatchResult,
|
||||||
bool conditionMatched,
|
bool conditionMatched,
|
||||||
const char *context);
|
const char *context);
|
||||||
|
static bool
|
||||||
|
ApplyConditionLogic(Type, bool currentMatchResult,
|
||||||
|
const std::function<bool()> &evaluateCondition,
|
||||||
|
const char *context);
|
||||||
|
|
||||||
static void PopulateLogicTypeSelection(QComboBox *list,
|
static void PopulateLogicTypeSelection(QComboBox *list,
|
||||||
bool isRootCondition);
|
bool isRootCondition);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace advss {
|
|||||||
|
|
||||||
static void populateUnits(QComboBox *list)
|
static void populateUnits(QComboBox *list)
|
||||||
{
|
{
|
||||||
list->addItem(obs_module_text("AdvSceneSwitcher.unit.secends"));
|
list->addItem(obs_module_text("AdvSceneSwitcher.unit.seconds"));
|
||||||
list->addItem(obs_module_text("AdvSceneSwitcher.unit.minutes"));
|
list->addItem(obs_module_text("AdvSceneSwitcher.unit.minutes"));
|
||||||
list->addItem(obs_module_text("AdvSceneSwitcher.unit.hours"));
|
list->addItem(obs_module_text("AdvSceneSwitcher.unit.hours"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ public:
|
|||||||
bool showUnitSelection = true,
|
bool showUnitSelection = true,
|
||||||
double minValue = 0.0);
|
double minValue = 0.0);
|
||||||
EXPORT void SetDuration(const Duration &);
|
EXPORT void SetDuration(const Duration &);
|
||||||
|
Duration GetDuration() const { return _current; }
|
||||||
EXPORT QDoubleSpinBox *SpinBox() { return _duration->SpinBox(); }
|
EXPORT QDoubleSpinBox *SpinBox() { return _duration->SpinBox(); }
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ static std::string durationUnitToString(Duration::Unit u)
|
|||||||
{
|
{
|
||||||
switch (u) {
|
switch (u) {
|
||||||
case Duration::Unit::SECONDS:
|
case Duration::Unit::SECONDS:
|
||||||
return obs_module_text("AdvSceneSwitcher.unit.secends");
|
return obs_module_text("AdvSceneSwitcher.unit.seconds");
|
||||||
case Duration::Unit::MINUTES:
|
case Duration::Unit::MINUTES:
|
||||||
return obs_module_text("AdvSceneSwitcher.unit.minutes");
|
return obs_module_text("AdvSceneSwitcher.unit.minutes");
|
||||||
case Duration::Unit::HOURS:
|
case Duration::Unit::HOURS:
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -38,8 +37,8 @@ void FileSelection::SetPath(const QString &path)
|
|||||||
|
|
||||||
QString FileSelection::ValidPathOrDesktop(const QString &path)
|
QString FileSelection::ValidPathOrDesktop(const QString &path)
|
||||||
{
|
{
|
||||||
if (std::filesystem::exists(
|
QFileInfo fileInfo(path);
|
||||||
std::filesystem::path(path.toStdString()))) {
|
if (fileInfo.isFile()) {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
return QStandardPaths::writableLocation(
|
return QStandardPaths::writableLocation(
|
||||||
|
|||||||
@@ -14,29 +14,32 @@ ListControls::ListControls(QWidget *parent, bool reorder) : QToolBar(parent)
|
|||||||
|
|
||||||
setIconSize({16, 16});
|
setIconSize({16, 16});
|
||||||
|
|
||||||
AddActionHelper("addIconSmall", "AdvSceneSwitcher.listControls.add",
|
AddActionHelper("addIconSmall", "icon-plus",
|
||||||
|
"AdvSceneSwitcher.listControls.add",
|
||||||
[this]() { Add(); });
|
[this]() { Add(); });
|
||||||
AddActionHelper("removeIconSmall",
|
AddActionHelper("removeIconSmall", "icon-trash",
|
||||||
"AdvSceneSwitcher.listControls.remove",
|
"AdvSceneSwitcher.listControls.remove",
|
||||||
[this]() { Remove(); });
|
[this]() { Remove(); });
|
||||||
|
|
||||||
if (reorder) {
|
if (reorder) {
|
||||||
addSeparator();
|
addSeparator();
|
||||||
AddActionHelper("upArrowIconSmall",
|
AddActionHelper("upArrowIconSmall", "icon-up",
|
||||||
"AdvSceneSwitcher.listControls.up",
|
"AdvSceneSwitcher.listControls.up",
|
||||||
[this]() { Up(); });
|
[this]() { Up(); });
|
||||||
AddActionHelper("downArrowIconSmall",
|
AddActionHelper("downArrowIconSmall", "icon-down",
|
||||||
"AdvSceneSwitcher.listControls.down",
|
"AdvSceneSwitcher.listControls.down",
|
||||||
[this]() { Down(); });
|
[this]() { Down(); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListControls::AddActionHelper(const char *theme, const char *tooltip,
|
void ListControls::AddActionHelper(const char *theme, const char *className,
|
||||||
|
const char *tooltip,
|
||||||
const std::function<void()> &signal)
|
const std::function<void()> &signal)
|
||||||
{
|
{
|
||||||
auto button = new QToolButton(this);
|
auto button = new QToolButton(this);
|
||||||
button->setToolTip(obs_module_text(tooltip));
|
button->setToolTip(obs_module_text(tooltip));
|
||||||
button->setProperty("themeID", QVariant(QString(theme)));
|
button->setProperty("themeID", QVariant(QString(theme)));
|
||||||
|
button->setProperty("class", QVariant(QString(className)));
|
||||||
(void)addWidget(button);
|
(void)addWidget(button);
|
||||||
button->connect(button, &QToolButton::clicked, this, signal);
|
button->connect(button, &QToolButton::clicked, this, signal);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ signals:
|
|||||||
void Down();
|
void Down();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddActionHelper(const char *theme, const char *tooltip,
|
void AddActionHelper(const char *theme, const char *className,
|
||||||
|
const char *tooltip,
|
||||||
const std::function<void()> &signal);
|
const std::function<void()> &signal);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,34 @@ void ListEditor::showEvent(QShowEvent *e)
|
|||||||
UpdateListSize();
|
UpdateListSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QListWidgetItem *getItemFromWidget(QListWidget *list, QWidget *widget)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < list->count(); i++) {
|
||||||
|
auto item = list->item(i);
|
||||||
|
if (!item) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto itemWidget = list->itemWidget(item);
|
||||||
|
if (itemWidget == widget) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ListEditor::GetIndexOfSignal() const
|
||||||
|
{
|
||||||
|
auto sender = this->sender();
|
||||||
|
if (!sender) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
auto widget = qobject_cast<QWidget *>(sender);
|
||||||
|
if (!widget) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return _list->row(getItemFromWidget(_list, widget));
|
||||||
|
}
|
||||||
|
|
||||||
void ListEditor::UpdateListSize()
|
void ListEditor::UpdateListSize()
|
||||||
{
|
{
|
||||||
SetHeightToContentHeight(_list);
|
SetHeightToContentHeight(_list);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ private slots:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UpdateListSize();
|
void UpdateListSize();
|
||||||
|
int GetIndexOfSignal() const;
|
||||||
|
|
||||||
QListWidget *_list;
|
QListWidget *_list;
|
||||||
ListControls *_controls;
|
ListControls *_controls;
|
||||||
|
|||||||
@@ -12,9 +12,15 @@ bool VerboseLoggingEnabled()
|
|||||||
bool ActionLoggingEnabled()
|
bool ActionLoggingEnabled()
|
||||||
{
|
{
|
||||||
return GetSwitcher() &&
|
return GetSwitcher() &&
|
||||||
(GetSwitcher()->logLevel ==
|
(GetSwitcher()->logLevel == SwitcherData::LogLevel::LOG_ACTION ||
|
||||||
SwitcherData::LogLevel::PRINT_ACTION ||
|
VerboseLoggingEnabled());
|
||||||
GetSwitcher()->logLevel == SwitcherData::LogLevel::VERBOSE);
|
}
|
||||||
|
|
||||||
|
bool MacroLoggingEnabled()
|
||||||
|
{
|
||||||
|
return GetSwitcher() &&
|
||||||
|
(GetSwitcher()->logLevel == SwitcherData::LogLevel::LOG_MACRO ||
|
||||||
|
ActionLoggingEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -27,6 +27,13 @@ namespace advss {
|
|||||||
blog(level, msg, ##__VA_ARGS__); \
|
blog(level, msg, ##__VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
// Print log with "[adv-ss] " if log level is set to "macro", "action" or "verbose"
|
||||||
|
#define mblog(level, msg, ...) \
|
||||||
|
do { \
|
||||||
|
if (MacroLoggingEnabled()) { \
|
||||||
|
blog(level, msg, ##__VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -34,5 +41,7 @@ namespace advss {
|
|||||||
EXPORT bool VerboseLoggingEnabled();
|
EXPORT bool VerboseLoggingEnabled();
|
||||||
// Returns true if log level is set to "action" or "verbose"
|
// Returns true if log level is set to "action" or "verbose"
|
||||||
EXPORT bool ActionLoggingEnabled();
|
EXPORT bool ActionLoggingEnabled();
|
||||||
|
// Returns true if log level is set to "macro", "action" or "verbose"
|
||||||
|
EXPORT bool MacroLoggingEnabled();
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -23,13 +23,16 @@ bool MouseWheelWidgetAdjustmentGuard::eventFilter(QObject *o, QEvent *e)
|
|||||||
|
|
||||||
void PreventMouseWheelAdjustWithoutFocus(QWidget *w)
|
void PreventMouseWheelAdjustWithoutFocus(QWidget *w)
|
||||||
{
|
{
|
||||||
// Ignore QScrollBar as there is no danger of accidentally modifying anything
|
// Ignore QScrollBar as there is no danger of accidentally modifying
|
||||||
// and long expanded QComboBox would be difficult to interact with otherwise.
|
// anything and long expanded QComboBox would be difficult to interact
|
||||||
// Ignore OSCMessageElementEdit to allow OSCMessageEdit list to up update
|
// with otherwise.
|
||||||
// current index correctly.
|
// Ignore OSCMessageElementEdit and ChatMessagePropertyEdit to allow
|
||||||
|
// lists to up update the current index correctly.
|
||||||
if (qobject_cast<QScrollBar *>(w) ||
|
if (qobject_cast<QScrollBar *>(w) ||
|
||||||
QString(w->metaObject()->className()) ==
|
QString(w->metaObject()->className()) ==
|
||||||
"advss::OSCMessageElementEdit") {
|
"advss::OSCMessageElementEdit" ||
|
||||||
|
QString(w->metaObject()->className()) ==
|
||||||
|
"advss::ChatMessagePropertyEdit") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
w->setFocusPolicy(Qt::StrongFocus);
|
w->setFocusPolicy(Qt::StrongFocus);
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#include "switcher-data.hpp"
|
#include "switcher-data.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "scene-group.hpp"
|
#include "scene-group.hpp"
|
||||||
#include "scene-trigger.hpp"
|
|
||||||
#include "switch-audio.hpp"
|
#include "switch-audio.hpp"
|
||||||
#include "switch-executable.hpp"
|
#include "switch-executable.hpp"
|
||||||
#include "switch-file.hpp"
|
#include "switch-file.hpp"
|
||||||
@@ -16,7 +15,6 @@
|
|||||||
#include "switch-window.hpp"
|
#include "switch-window.hpp"
|
||||||
#include "switch-sequence.hpp"
|
#include "switch-sequence.hpp"
|
||||||
#include "switch-video.hpp"
|
#include "switch-video.hpp"
|
||||||
#include "switch-network.hpp"
|
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|||||||
@@ -79,11 +79,12 @@ bool RegexConfig::Matches(const std::string &text,
|
|||||||
QString::fromStdString(expression));
|
QString::fromStdString(expression));
|
||||||
}
|
}
|
||||||
|
|
||||||
RegexConfig RegexConfig::PartialMatchRegexConfig()
|
RegexConfig RegexConfig::PartialMatchRegexConfig(bool enabled)
|
||||||
{
|
{
|
||||||
RegexConfig conf;
|
RegexConfig regex;
|
||||||
conf._partialMatch = true;
|
regex._partialMatch = true;
|
||||||
return conf;
|
regex._enable = enabled;
|
||||||
|
return regex;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegexConfigWidget::RegexConfigWidget(QWidget *parent, bool showEnable)
|
RegexConfigWidget::RegexConfigWidget(QWidget *parent, bool showEnable)
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
EXPORT bool Matches(const std::string &text,
|
EXPORT bool Matches(const std::string &text,
|
||||||
const std::string &expression) const;
|
const std::string &expression) const;
|
||||||
|
|
||||||
EXPORT static RegexConfig PartialMatchRegexConfig();
|
EXPORT static RegexConfig PartialMatchRegexConfig(bool enabled = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _enable = false;
|
bool _enable = false;
|
||||||
@@ -48,16 +48,15 @@ private:
|
|||||||
friend RegexConfigDialog;
|
friend RegexConfigDialog;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RegexConfigWidget : public QWidget {
|
class ADVSS_EXPORT RegexConfigWidget : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
EXPORT RegexConfigWidget(QWidget *parent = nullptr,
|
RegexConfigWidget(QWidget *parent = nullptr, bool showEnable = true);
|
||||||
bool showEnable = true);
|
void SetRegexConfig(const RegexConfig &);
|
||||||
EXPORT void SetRegexConfig(const RegexConfig &);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
EXPORT void EnableChanged(bool);
|
void EnableChanged(bool);
|
||||||
EXPORT void OpenSettingsClicked();
|
void OpenSettingsClicked();
|
||||||
signals:
|
signals:
|
||||||
void RegexConfigChanged(const RegexConfig &);
|
void RegexConfigChanged(const RegexConfig &);
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,13 @@ ResourceTable::ResourceTable(QTabWidget *parent, const QString &help,
|
|||||||
{
|
{
|
||||||
_add->setProperty("themeID",
|
_add->setProperty("themeID",
|
||||||
QVariant(QString::fromUtf8("addIconSmall")));
|
QVariant(QString::fromUtf8("addIconSmall")));
|
||||||
|
_add->setProperty("class", QVariant(QString::fromUtf8("icon-plus")));
|
||||||
_add->setToolTip(addToolTip);
|
_add->setToolTip(addToolTip);
|
||||||
|
|
||||||
_remove->setProperty("themeID",
|
_remove->setProperty("themeID",
|
||||||
QVariant(QString::fromUtf8("removeIconSmall")));
|
QVariant(QString::fromUtf8("removeIconSmall")));
|
||||||
|
_remove->setProperty("class",
|
||||||
|
QVariant(QString::fromUtf8("icon-trash")));
|
||||||
_remove->setToolTip(removeToolTip);
|
_remove->setToolTip(removeToolTip);
|
||||||
|
|
||||||
_help->setWordWrap(true);
|
_help->setWordWrap(true);
|
||||||
|
|||||||
@@ -145,10 +145,6 @@ void SwitchScene(const SceneSwitchInfo &sceneSwitch, bool force)
|
|||||||
}
|
}
|
||||||
|
|
||||||
vblog(LOG_INFO, "switched scene");
|
vblog(LOG_INFO, "switched scene");
|
||||||
|
|
||||||
if (switcher->networkConfig.ShouldSendSceneChange()) {
|
|
||||||
switcher->server.sendMessage(sceneSwitch);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,10 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
static void ScreenshotTick(void *param, float);
|
Screenshot::Screenshot(obs_source_t *source, const QRect &subarea,
|
||||||
|
bool blocking, int timeout, bool saveToFile,
|
||||||
ScreenshotHelper::ScreenshotHelper(obs_source_t *source, const QRect &subarea,
|
std::string path)
|
||||||
bool blocking, int timeout, bool saveToFile,
|
: _weakSource(OBSGetWeakRef(source)),
|
||||||
std::string path)
|
|
||||||
: weakSource(OBSGetWeakRef(source)),
|
|
||||||
_subarea(subarea),
|
_subarea(subarea),
|
||||||
_blocking(blocking),
|
_blocking(blocking),
|
||||||
_saveToFile(saveToFile),
|
_saveToFile(saveToFile),
|
||||||
@@ -35,12 +33,12 @@ ScreenshotHelper::ScreenshotHelper(obs_source_t *source, const QRect &subarea,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenshotHelper::~ScreenshotHelper()
|
Screenshot::~Screenshot()
|
||||||
{
|
{
|
||||||
if (_initDone) {
|
if (_initDone) {
|
||||||
obs_enter_graphics();
|
obs_enter_graphics();
|
||||||
gs_stagesurface_destroy(stagesurf);
|
gs_stagesurface_destroy(_stagesurf);
|
||||||
gs_texrender_destroy(texrender);
|
gs_texrender_destroy(_texrender);
|
||||||
obs_leave_graphics();
|
obs_leave_graphics();
|
||||||
}
|
}
|
||||||
obs_remove_tick_callback(ScreenshotTick, this);
|
obs_remove_tick_callback(ScreenshotTick, this);
|
||||||
@@ -49,21 +47,21 @@ ScreenshotHelper::~ScreenshotHelper()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenshotHelper::Screenshot()
|
void Screenshot::CreateScreenshot()
|
||||||
{
|
{
|
||||||
OBSSource source = OBSGetStrongRef(weakSource);
|
OBSSource source = OBSGetStrongRef(_weakSource);
|
||||||
|
|
||||||
if (source) {
|
if (source) {
|
||||||
cx = obs_source_get_base_width(source);
|
_cx = obs_source_get_base_width(source);
|
||||||
cy = obs_source_get_base_height(source);
|
_cy = obs_source_get_base_height(source);
|
||||||
} else {
|
} else {
|
||||||
obs_video_info ovi;
|
obs_video_info ovi;
|
||||||
obs_get_video_info(&ovi);
|
obs_get_video_info(&ovi);
|
||||||
cx = ovi.base_width;
|
_cx = ovi.base_width;
|
||||||
cy = ovi.base_height;
|
_cy = ovi.base_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect renderArea(0, 0, cx, cy);
|
QRect renderArea(0, 0, _cx, _cy);
|
||||||
if (!_subarea.isEmpty()) {
|
if (!_subarea.isEmpty()) {
|
||||||
renderArea &= _subarea;
|
renderArea &= _subarea;
|
||||||
}
|
}
|
||||||
@@ -73,19 +71,19 @@ void ScreenshotHelper::Screenshot()
|
|||||||
"Cannot screenshot \"%s\", invalid target size",
|
"Cannot screenshot \"%s\", invalid target size",
|
||||||
obs_source_get_name(source));
|
obs_source_get_name(source));
|
||||||
obs_remove_tick_callback(ScreenshotTick, this);
|
obs_remove_tick_callback(ScreenshotTick, this);
|
||||||
done = true;
|
_done = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx = renderArea.width();
|
_cx = renderArea.width();
|
||||||
cy = renderArea.height();
|
_cy = renderArea.height();
|
||||||
|
|
||||||
texrender = gs_texrender_create(GS_RGBA, GS_ZS_NONE);
|
_texrender = gs_texrender_create(GS_RGBA, GS_ZS_NONE);
|
||||||
stagesurf = gs_stagesurface_create(renderArea.width(),
|
_stagesurf = gs_stagesurface_create(renderArea.width(),
|
||||||
renderArea.height(), GS_RGBA);
|
renderArea.height(), GS_RGBA);
|
||||||
|
|
||||||
gs_texrender_reset(texrender);
|
gs_texrender_reset(_texrender);
|
||||||
if (gs_texrender_begin(texrender, renderArea.width(),
|
if (gs_texrender_begin(_texrender, renderArea.width(),
|
||||||
renderArea.height())) {
|
renderArea.height())) {
|
||||||
vec4 zero;
|
vec4 zero;
|
||||||
vec4_zero(&zero);
|
vec4_zero(&zero);
|
||||||
@@ -108,48 +106,48 @@ void ScreenshotHelper::Screenshot()
|
|||||||
}
|
}
|
||||||
|
|
||||||
gs_blend_state_pop();
|
gs_blend_state_pop();
|
||||||
gs_texrender_end(texrender);
|
gs_texrender_end(_texrender);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenshotHelper::Download()
|
void Screenshot::Download()
|
||||||
{
|
{
|
||||||
gs_stage_texture(stagesurf, gs_texrender_get_texture(texrender));
|
gs_stage_texture(_stagesurf, gs_texrender_get_texture(_texrender));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenshotHelper::Copy()
|
void Screenshot::Copy()
|
||||||
{
|
{
|
||||||
uint8_t *videoData = nullptr;
|
uint8_t *videoData = nullptr;
|
||||||
uint32_t videoLinesize = 0;
|
uint32_t videoLinesize = 0;
|
||||||
|
|
||||||
image = QImage(cx, cy, QImage::Format::Format_RGBA8888);
|
_image = QImage(_cx, _cy, QImage::Format::Format_RGBA8888);
|
||||||
|
|
||||||
if (gs_stagesurface_map(stagesurf, &videoData, &videoLinesize)) {
|
if (gs_stagesurface_map(_stagesurf, &videoData, &videoLinesize)) {
|
||||||
int linesize = image.bytesPerLine();
|
int linesize = _image.bytesPerLine();
|
||||||
for (int y = 0; y < (int)cy; y++)
|
for (int y = 0; y < (int)_cy; y++)
|
||||||
memcpy(image.scanLine(y),
|
memcpy(_image.scanLine(y),
|
||||||
videoData + (y * videoLinesize), linesize);
|
videoData + (y * videoLinesize), linesize);
|
||||||
|
|
||||||
gs_stagesurface_unmap(stagesurf);
|
gs_stagesurface_unmap(_stagesurf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenshotHelper::MarkDone()
|
void Screenshot::MarkDone()
|
||||||
{
|
{
|
||||||
time = std::chrono::high_resolution_clock::now();
|
_time = std::chrono::high_resolution_clock::now();
|
||||||
done = true;
|
_done = true;
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
_cv.notify_all();
|
_cv.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenshotHelper::WriteToFile()
|
void Screenshot::WriteToFile()
|
||||||
{
|
{
|
||||||
if (!_saveToFile) {
|
if (!_saveToFile) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_saveThread = std::thread([this]() {
|
_saveThread = std::thread([this]() {
|
||||||
if (image.save(QString::fromStdString(_path))) {
|
if (_image.save(QString::fromStdString(_path))) {
|
||||||
vblog(LOG_INFO, "Wrote screenshot to \"%s\"",
|
vblog(LOG_INFO, "Wrote screenshot to \"%s\"",
|
||||||
_path.c_str());
|
_path.c_str());
|
||||||
} else {
|
} else {
|
||||||
@@ -165,19 +163,19 @@ void ScreenshotHelper::WriteToFile()
|
|||||||
#define STAGE_COPY_AND_SAVE 2
|
#define STAGE_COPY_AND_SAVE 2
|
||||||
#define STAGE_FINISH 3
|
#define STAGE_FINISH 3
|
||||||
|
|
||||||
static void ScreenshotTick(void *param, float)
|
void Screenshot::ScreenshotTick(void *param, float)
|
||||||
{
|
{
|
||||||
ScreenshotHelper *data = reinterpret_cast<ScreenshotHelper *>(param);
|
Screenshot *data = reinterpret_cast<Screenshot *>(param);
|
||||||
|
|
||||||
if (data->stage == STAGE_FINISH) {
|
if (data->_stage == STAGE_FINISH) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_enter_graphics();
|
obs_enter_graphics();
|
||||||
|
|
||||||
switch (data->stage) {
|
switch (data->_stage) {
|
||||||
case STAGE_SCREENSHOT:
|
case STAGE_SCREENSHOT:
|
||||||
data->Screenshot();
|
data->CreateScreenshot();
|
||||||
break;
|
break;
|
||||||
case STAGE_DOWNLOAD:
|
case STAGE_DOWNLOAD:
|
||||||
data->Download();
|
data->Download();
|
||||||
@@ -193,7 +191,7 @@ static void ScreenshotTick(void *param, float)
|
|||||||
|
|
||||||
obs_leave_graphics();
|
obs_leave_graphics();
|
||||||
|
|
||||||
data->stage++;
|
data->_stage++;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -9,36 +9,42 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
class ScreenshotHelper {
|
class Screenshot {
|
||||||
public:
|
using TimePoint = std::chrono::high_resolution_clock::time_point;
|
||||||
EXPORT ScreenshotHelper() = default;
|
|
||||||
EXPORT ScreenshotHelper(obs_source_t *source,
|
|
||||||
const QRect &subarea = QRect(),
|
|
||||||
bool blocking = false, int timeout = 1000,
|
|
||||||
bool saveToFile = false, std::string path = "");
|
|
||||||
EXPORT ScreenshotHelper &operator=(const ScreenshotHelper &) = delete;
|
|
||||||
EXPORT ScreenshotHelper(const ScreenshotHelper &) = delete;
|
|
||||||
EXPORT ~ScreenshotHelper();
|
|
||||||
|
|
||||||
void Screenshot();
|
public:
|
||||||
|
EXPORT Screenshot() = default;
|
||||||
|
EXPORT Screenshot(obs_source_t *source, const QRect &subarea = QRect(),
|
||||||
|
bool blocking = false, int timeout = 1000,
|
||||||
|
bool saveToFile = false, std::string path = "");
|
||||||
|
EXPORT Screenshot &operator=(const Screenshot &) = delete;
|
||||||
|
EXPORT Screenshot(const Screenshot &) = delete;
|
||||||
|
EXPORT ~Screenshot();
|
||||||
|
|
||||||
|
EXPORT bool IsDone() const { return _done; }
|
||||||
|
EXPORT QImage &GetImage() { return _image; }
|
||||||
|
EXPORT TimePoint GetScreenshotTime() const { return _time; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void ScreenshotTick(void *param, float);
|
||||||
|
void CreateScreenshot();
|
||||||
void Download();
|
void Download();
|
||||||
void Copy();
|
void Copy();
|
||||||
void MarkDone();
|
void MarkDone();
|
||||||
void WriteToFile();
|
void WriteToFile();
|
||||||
|
|
||||||
gs_texrender_t *texrender = nullptr;
|
gs_texrender_t *_texrender = nullptr;
|
||||||
gs_stagesurf_t *stagesurf = nullptr;
|
gs_stagesurf_t *_stagesurf = nullptr;
|
||||||
OBSWeakSource weakSource;
|
OBSWeakSource _weakSource;
|
||||||
QImage image;
|
QImage _image;
|
||||||
uint32_t cx = 0;
|
uint32_t _cx = 0;
|
||||||
uint32_t cy = 0;
|
uint32_t _cy = 0;
|
||||||
|
|
||||||
int stage = 0;
|
int _stage = 0;
|
||||||
|
|
||||||
bool done = false;
|
bool _done = false;
|
||||||
std::chrono::high_resolution_clock::time_point time;
|
TimePoint _time;
|
||||||
|
|
||||||
private:
|
|
||||||
std::atomic_bool _initDone = false;
|
std::atomic_bool _initDone = false;
|
||||||
QRect _subarea = QRect();
|
QRect _subarea = QRect();
|
||||||
bool _blocking = false;
|
bool _blocking = false;
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ StatusDockWidget::StatusDockWidget(QWidget *parent) : QFrame(parent)
|
|||||||
|
|
||||||
auto action = new QAction;
|
auto action = new QAction;
|
||||||
action->setProperty("themeID", QVariant(QString::fromUtf8("cogsIcon")));
|
action->setProperty("themeID", QVariant(QString::fromUtf8("cogsIcon")));
|
||||||
|
action->setProperty("class", QVariant(QString::fromUtf8("icon-cogs")));
|
||||||
action->connect(action, &QAction::triggered, OpenSettingsWindow);
|
action->connect(action, &QAction::triggered, OpenSettingsWindow);
|
||||||
const auto path = QString::fromStdString(GetDataFilePath(
|
const auto path = QString::fromStdString(GetDataFilePath(
|
||||||
"res/images/" + GetThemeTypeName() + "Advanced.svg"));
|
"res/images/" + GetThemeTypeName() + "Advanced.svg"));
|
||||||
|
|||||||
@@ -11,12 +11,11 @@
|
|||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
static std::vector<std::string> tabNames = {
|
static std::vector<std::string> tabNames = {
|
||||||
"generalTab", "macroTab", "windowTitleTab",
|
"generalTab", "macroTab", "windowTitleTab", "executableTab",
|
||||||
"executableTab", "screenRegionTab", "mediaTab",
|
"screenRegionTab", "mediaTab", "fileTab", "randomTab",
|
||||||
"fileTab", "randomTab", "timeTab",
|
"timeTab", "idleTab", "sceneSequenceTab", "audioTab",
|
||||||
"idleTab", "sceneSequenceTab", "audioTab",
|
"videoTab", "sceneGroupTab", "transitionsTab", "pauseTab",
|
||||||
"videoTab", "networkTab", "sceneGroupTab",
|
};
|
||||||
"transitionsTab", "pauseTab", "sceneTriggerTab"};
|
|
||||||
|
|
||||||
static std::vector<int> tabOrder = std::vector<int>(tabNames.size());
|
static std::vector<int> tabOrder = std::vector<int>(tabNames.size());
|
||||||
|
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ void TempVariableRef::Save(obs_data_t *obj, const char *name) const
|
|||||||
obs_data_set_int(data, "type", static_cast<int>(type));
|
obs_data_set_int(data, "type", static_cast<int>(type));
|
||||||
obs_data_set_int(data, "idx", GetIdx());
|
obs_data_set_int(data, "idx", GetIdx());
|
||||||
obs_data_set_string(data, "id", _id.c_str());
|
obs_data_set_string(data, "id", _id.c_str());
|
||||||
|
obs_data_set_int(data, "version", 1);
|
||||||
obs_data_set_obj(obj, name, data);
|
obs_data_set_obj(obj, name, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,6 +176,14 @@ void TempVariableRef::Load(obs_data_t *obj, Macro *macro, const char *name)
|
|||||||
_id = obs_data_get_string(data, "id");
|
_id = obs_data_get_string(data, "id");
|
||||||
const auto type =
|
const auto type =
|
||||||
static_cast<SegmentType>(obs_data_get_int(data, "type"));
|
static_cast<SegmentType>(obs_data_get_int(data, "type"));
|
||||||
|
|
||||||
|
// Backwards compatibility checks
|
||||||
|
if (obs_data_get_int(data, "version") < 1) {
|
||||||
|
if (_id == "chatter") {
|
||||||
|
_id = "user_login";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AddPostLoadStep([this, idx, type, macro]() {
|
AddPostLoadStep([this, idx, type, macro]() {
|
||||||
this->PostLoad(idx, type, macro);
|
this->PostLoad(idx, type, macro);
|
||||||
});
|
});
|
||||||
@@ -446,35 +455,4 @@ void NotifyUIAboutTempVarChange()
|
|||||||
nullptr, false);
|
nullptr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoUpdateTooltipLabel::AutoUpdateTooltipLabel(
|
|
||||||
QWidget *parent, std::function<QString()> updateFunc)
|
|
||||||
: QLabel(parent),
|
|
||||||
_updateFunc(updateFunc),
|
|
||||||
_timer(new QTimer(this))
|
|
||||||
{
|
|
||||||
connect(_timer, &QTimer::timeout, this,
|
|
||||||
&AutoUpdateTooltipLabel::UpdateTooltip);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
void AutoUpdateTooltipLabel::enterEvent(QEnterEvent *event)
|
|
||||||
#else
|
|
||||||
void AutoUpdateTooltipLabel::enterEvent(QEvent *event)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
_timer->start(300);
|
|
||||||
QLabel::enterEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AutoUpdateTooltipLabel::leaveEvent(QEvent *event)
|
|
||||||
{
|
|
||||||
_timer->stop();
|
|
||||||
QLabel::leaveEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AutoUpdateTooltipLabel::UpdateTooltip()
|
|
||||||
{
|
|
||||||
setToolTip(_updateFunc());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "auto-update-tooltip-label.hpp"
|
||||||
#include "filter-combo-box.hpp"
|
#include "filter-combo-box.hpp"
|
||||||
|
|
||||||
#include <obs-data.h>
|
#include <obs-data.h>
|
||||||
@@ -6,8 +7,6 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <QEnterEvent>
|
#include <QEnterEvent>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QLabel>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -79,29 +78,6 @@ private:
|
|||||||
friend TempVariableSelection;
|
friend TempVariableSelection;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AutoUpdateTooltipLabel : public QLabel {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
AutoUpdateTooltipLabel(QWidget *parent,
|
|
||||||
std::function<QString()> updateFunc);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
void enterEvent(QEnterEvent *event) override;
|
|
||||||
#else
|
|
||||||
void enterEvent(QEvent *event) override;
|
|
||||||
#endif
|
|
||||||
void leaveEvent(QEvent *event) override;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void UpdateTooltip();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::function<QString()> _updateFunc;
|
|
||||||
QTimer *_timer;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ADVSS_EXPORT TempVariableSelection : public QWidget {
|
class ADVSS_EXPORT TempVariableSelection : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|||||||
63
lib/utils/time-helpers.cpp
Normal file
63
lib/utils/time-helpers.cpp
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#include "time-helpers.hpp"
|
||||||
|
#include "obs-module-helper.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
static QString combineRelativeTimeParts(const double unitCount,
|
||||||
|
const char *unitName)
|
||||||
|
{
|
||||||
|
QString combined = obs_module_text("AdvSceneSwitcher.time.relative");
|
||||||
|
|
||||||
|
return combined.arg(QString::number(unitCount, 'g', 2)).arg(unitName);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FormatRelativeTime(const double seconds)
|
||||||
|
{
|
||||||
|
// 365.2425 days
|
||||||
|
double divided = seconds / 31556952;
|
||||||
|
if (divided >= 1) {
|
||||||
|
return combineRelativeTimeParts(
|
||||||
|
divided,
|
||||||
|
obs_module_text("AdvSceneSwitcher.unit.years"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 30.436875 days
|
||||||
|
divided = seconds / 2629746;
|
||||||
|
if (divided >= 1) {
|
||||||
|
return combineRelativeTimeParts(
|
||||||
|
divided,
|
||||||
|
obs_module_text("AdvSceneSwitcher.unit.months"));
|
||||||
|
}
|
||||||
|
|
||||||
|
divided = seconds / 604800;
|
||||||
|
if (divided >= 1) {
|
||||||
|
return combineRelativeTimeParts(
|
||||||
|
divided,
|
||||||
|
obs_module_text("AdvSceneSwitcher.unit.weeks"));
|
||||||
|
}
|
||||||
|
|
||||||
|
divided = seconds / 86400;
|
||||||
|
if (divided >= 1) {
|
||||||
|
return combineRelativeTimeParts(
|
||||||
|
divided, obs_module_text("AdvSceneSwitcher.unit.days"));
|
||||||
|
}
|
||||||
|
|
||||||
|
divided = seconds / 3600;
|
||||||
|
if (divided >= 1) {
|
||||||
|
return combineRelativeTimeParts(
|
||||||
|
divided,
|
||||||
|
obs_module_text("AdvSceneSwitcher.unit.hours"));
|
||||||
|
}
|
||||||
|
|
||||||
|
divided = seconds / 60;
|
||||||
|
if (divided >= 1) {
|
||||||
|
return combineRelativeTimeParts(
|
||||||
|
divided,
|
||||||
|
obs_module_text("AdvSceneSwitcher.unit.minutes"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return combineRelativeTimeParts(
|
||||||
|
seconds, obs_module_text("AdvSceneSwitcher.unit.seconds"));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
8
lib/utils/time-helpers.hpp
Normal file
8
lib/utils/time-helpers.hpp
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
QString FormatRelativeTime(const double seconds);
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "ui-helpers.hpp"
|
#include "ui-helpers.hpp"
|
||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "non-modal-dialog.hpp"
|
#include "non-modal-dialog.hpp"
|
||||||
#include "obs-module-helper.hpp"
|
#include "obs-module-helper.hpp"
|
||||||
|
#include "plugin-state-helpers.hpp"
|
||||||
|
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
#include <QGraphicsColorizeEffect>
|
#include <QGraphicsColorizeEffect>
|
||||||
@@ -64,8 +66,12 @@ void SetHeightToContentHeight(QListWidget *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int scrollBarHeight = getHorizontalScrollBarHeight(list);
|
int scrollBarHeight = getHorizontalScrollBarHeight(list);
|
||||||
int height = (list->sizeHintForRow(0) + list->spacing()) * nrItems +
|
int height = 2 * list->frameWidth() + scrollBarHeight;
|
||||||
2 * list->frameWidth() + scrollBarHeight;
|
|
||||||
|
for (int i = 0; i < nrItems; i++) {
|
||||||
|
height += (list->sizeHintForRow(i) + list->spacing());
|
||||||
|
}
|
||||||
|
|
||||||
list->setMinimumHeight(height);
|
list->setMinimumHeight(height);
|
||||||
list->setMaximumHeight(height);
|
list->setMaximumHeight(height);
|
||||||
}
|
}
|
||||||
@@ -98,7 +104,10 @@ int FindIdxInRagne(QComboBox *list, int start, int stop,
|
|||||||
return foundIdx;
|
return foundIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *GetSettingsWindow();
|
QWidget *GetSettingsWindow()
|
||||||
|
{
|
||||||
|
return SettingsWindowIsOpened() ? AdvSceneSwitcher::window : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool DisplayMessage(const QString &msg, bool question, bool modal)
|
bool DisplayMessage(const QString &msg, bool question, bool modal)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ EXPORT void DisplayTrayMessage(const QString &title, const QString &msg,
|
|||||||
const QIcon &icon = QIcon());
|
const QIcon &icon = QIcon());
|
||||||
|
|
||||||
EXPORT std::string GetThemeTypeName();
|
EXPORT std::string GetThemeTypeName();
|
||||||
|
EXPORT QWidget *GetSettingsWindow();
|
||||||
|
|
||||||
void QeueUITask(void (*task)(void *param), void *param);
|
void QeueUITask(void (*task)(void *param), void *param);
|
||||||
|
|
||||||
|
|||||||
@@ -76,15 +76,15 @@ std::string ToString(double value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void listAddClicked(QListWidget *list, QWidget *newWidget,
|
void listAddClicked(QListWidget *list, QWidget *newWidget,
|
||||||
QObject *addHighlight)
|
QObject **addHighlight)
|
||||||
{
|
{
|
||||||
if (!list || !newWidget) {
|
if (!list || !newWidget) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addHighlight) {
|
if (addHighlight && *addHighlight) {
|
||||||
addHighlight->deleteLater();
|
(*addHighlight)->deleteLater();
|
||||||
addHighlight = nullptr;
|
*addHighlight = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ std::string ToString(double value);
|
|||||||
/* Legacy helpers */
|
/* Legacy helpers */
|
||||||
|
|
||||||
void listAddClicked(QListWidget *list, QWidget *newWidget,
|
void listAddClicked(QListWidget *list, QWidget *newWidget,
|
||||||
QObject *addHighlight = nullptr);
|
QObject **addHighlight = nullptr);
|
||||||
bool listMoveUp(QListWidget *list);
|
bool listMoveUp(QListWidget *list);
|
||||||
bool listMoveDown(QListWidget *list);
|
bool listMoveDown(QListWidget *list);
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical)
|
|||||||
if (showConfig) {
|
if (showConfig) {
|
||||||
config = new QPushButton(this);
|
config = new QPushButton(this);
|
||||||
config->setProperty("themeID", "menuIconSmall");
|
config->setProperty("themeID", "menuIconSmall");
|
||||||
|
config->setProperty("class", "icon-dots-vert");
|
||||||
config->setSizePolicy(QSizePolicy::Maximum,
|
config->setSizePolicy(QSizePolicy::Maximum,
|
||||||
QSizePolicy::Maximum);
|
QSizePolicy::Maximum);
|
||||||
config->setMaximumSize(22, 22);
|
config->setMaximumSize(22, 22);
|
||||||
@@ -619,7 +620,7 @@ VolumeMeter::VolumeMeter(QWidget *parent, obs_volmeter_t *obs_volmeter,
|
|||||||
magnitudeColor.setRgb(0x00, 0x00, 0x00); // Black
|
magnitudeColor.setRgb(0x00, 0x00, 0x00); // Black
|
||||||
majorTickColor.setRgb(0xff, 0xff, 0xff); // Black
|
majorTickColor.setRgb(0xff, 0xff, 0xff); // Black
|
||||||
minorTickColor.setRgb(0xcc, 0xcc, 0xcc); // Black
|
minorTickColor.setRgb(0xcc, 0xcc, 0xcc); // Black
|
||||||
minimumLevel = -60.0; // -60 dB
|
minimumLevel = -100.0; // -100 dB
|
||||||
warningLevel = -20.0; // -20 dB
|
warningLevel = -20.0; // -20 dB
|
||||||
errorLevel = -9.0; // -9 dB
|
errorLevel = -9.0; // -9 dB
|
||||||
clipLevel = -0.5; // -0.5 dB
|
clipLevel = -0.5; // -0.5 dB
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user