Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b74e9d2e2a |
37
.github/actions/run-tests/action.yml
vendored
@@ -1,37 +0,0 @@
|
||||
name: 'Package plugin'
|
||||
description: 'Packages the plugin for specified architecture and build config.'
|
||||
inputs:
|
||||
target:
|
||||
description: 'Build target'
|
||||
required: true
|
||||
workingDirectory:
|
||||
description: 'Working directory'
|
||||
required: false
|
||||
default: ${{ github.workspace }}
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Run macOS tests
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
shell: zsh {0}
|
||||
run: |
|
||||
if [[ '${{ inputs.target }}' != 'x86_64' ]]; then
|
||||
echo tests skipped!
|
||||
exit 0
|
||||
fi
|
||||
${{ inputs.workingDirectory }}/build_x86_64/tests/advanced-scene-switcher-tests
|
||||
|
||||
- name: Run Linux packaging
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ '${{ inputs.target }}' != 'x86_64' ]]; then
|
||||
exit 0
|
||||
fi
|
||||
${{ inputs.workingDirectory }}/build_x86_64/tests/advanced-scene-switcher-tests
|
||||
|
||||
- name: Run Windows packaging
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
shell: pwsh
|
||||
run: |
|
||||
${{ inputs.workingDirectory }}/build_x64/tests/RelWithDebInfo/advanced-scene-switcher-tests.exe
|
||||
10
.github/scripts/.build.zsh
vendored
@@ -170,17 +170,11 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
||||
|
||||
local product_name
|
||||
local product_version
|
||||
local git_tag="$(git describe --tags)"
|
||||
|
||||
read -r product_name product_version <<< \
|
||||
"$(jq -r '. | {name, version} | join(" ")' ${buildspec_file})"
|
||||
|
||||
if [[ "${git_tag}" =~ '^([0-9]+\.){0,2}(\*|[0-9]+)$' ]] {
|
||||
log_info "Using git tag as version identifier '${git_tag}'"
|
||||
product_version="${git_tag}"
|
||||
} else {
|
||||
log_info "Using buildspec.json version identifier '${product_version}'"
|
||||
}
|
||||
|
||||
|
||||
|
||||
case ${host_os} {
|
||||
macos)
|
||||
|
||||
9
.github/scripts/.package.zsh
vendored
@@ -128,18 +128,9 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
||||
|
||||
local product_name
|
||||
local product_version
|
||||
local git_tag="$(git describe --tags)"
|
||||
|
||||
read -r product_name product_version <<< \
|
||||
"$(jq -r '. | {name, version} | join(" ")' ${project_root}/buildspec.json)"
|
||||
|
||||
if [[ "${git_tag}" =~ '^([0-9]+\.){0,2}(\*|[0-9]+)$' ]] {
|
||||
log_info "Using git tag as version identifier '${git_tag}'"
|
||||
product_version="${git_tag}"
|
||||
} else {
|
||||
log_info "Using buildspec.json version identifier '${product_version}'"
|
||||
}
|
||||
|
||||
if [[ ${host_os} == 'macos' ]] {
|
||||
autoload -Uz check_packages read_codesign read_codesign_installer read_codesign_pass
|
||||
|
||||
|
||||
21
.github/workflows/main.yml
vendored
@@ -155,12 +155,6 @@ jobs:
|
||||
codesign: 'true'
|
||||
codesignIdent: ${{ env.CODESIGN_IDENT }}
|
||||
|
||||
- name: Run tests
|
||||
uses: ./plugin/.github/actions/run-tests
|
||||
with:
|
||||
workingDirectory: ${{ github.workspace }}/plugin
|
||||
target: ${{ matrix.arch }}
|
||||
|
||||
- name: Package Plugin
|
||||
uses: ./plugin/.github/actions/package-plugin
|
||||
with:
|
||||
@@ -256,12 +250,6 @@ jobs:
|
||||
config: RelWithDebInfo
|
||||
portable: ${{ matrix.portable }}
|
||||
|
||||
- name: Run tests
|
||||
uses: ./plugin/.github/actions/run-tests
|
||||
with:
|
||||
workingDirectory: ${{ github.workspace }}/plugin
|
||||
target: ${{ matrix.arch }}
|
||||
|
||||
- name: Package Plugin
|
||||
uses: ./plugin/.github/actions/package-plugin
|
||||
with:
|
||||
@@ -365,12 +353,6 @@ jobs:
|
||||
config: RelWithDebInfo
|
||||
visualStudio: 'Visual Studio 17 2022'
|
||||
|
||||
- name: Run tests
|
||||
uses: ./plugin/.github/actions/run-tests
|
||||
with:
|
||||
workingDirectory: ${{ github.workspace }}/plugin
|
||||
target: ${{ matrix.arch }}
|
||||
|
||||
- name: Package Plugin
|
||||
uses: ./plugin/.github/actions/package-plugin
|
||||
with:
|
||||
@@ -425,11 +407,10 @@ jobs:
|
||||
for file in ${{ github.workspace }}/**/@(*.pkg|*.exe|*.deb|*.zip); do
|
||||
echo " ${file##*/}: $(sha256sum "${file}" | cut -d " " -f 1)" >> ${{ github.workspace }}/CHECKSUMS.txt
|
||||
done
|
||||
cat ${{ github.workspace }}/CHECKSUMS.txt
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5
|
||||
with:
|
||||
draft: true
|
||||
prerelease: true
|
||||
|
||||
3
.gitmodules
vendored
@@ -16,6 +16,3 @@
|
||||
[submodule "deps/tesseract"]
|
||||
path = deps/tesseract
|
||||
url = https://github.com/tesseract-ocr/tesseract.git
|
||||
[submodule "deps/libremidi"]
|
||||
path = deps/libremidi
|
||||
url = https://github.com/jcelerier/libremidi.git
|
||||
|
||||
@@ -42,20 +42,21 @@ target_sources(
|
||||
src/general.cpp
|
||||
src/hotkey.cpp
|
||||
src/hotkey.hpp
|
||||
src/hotkey.hpp
|
||||
src/platform-funcs.hpp
|
||||
src/scene-group.cpp
|
||||
src/scene-group.hpp
|
||||
src/status-control.cpp
|
||||
src/status-control.hpp
|
||||
src/switcher-data.cpp
|
||||
src/switcher-data.hpp
|
||||
src/switcher-data-structs.cpp
|
||||
src/switcher-data-structs.hpp
|
||||
src/version.cpp
|
||||
src/version.h)
|
||||
|
||||
# Legacy function sources
|
||||
target_sources(
|
||||
${LIB_NAME}
|
||||
PRIVATE src/legacy/scene-group.cpp
|
||||
src/legacy/scene-group.hpp
|
||||
src/legacy/scene-trigger.cpp
|
||||
PRIVATE src/legacy/scene-trigger.cpp
|
||||
src/legacy/scene-trigger.hpp
|
||||
src/legacy/switch-audio.cpp
|
||||
src/legacy/switch-audio.hpp
|
||||
@@ -73,6 +74,7 @@ target_sources(
|
||||
src/legacy/switch-network.hpp
|
||||
src/legacy/switch-pause.cpp
|
||||
src/legacy/switch-pause.hpp
|
||||
src/legacy/switch-priority.cpp
|
||||
src/legacy/switch-random.cpp
|
||||
src/legacy/switch-random.hpp
|
||||
src/legacy/switch-screen-region.cpp
|
||||
@@ -107,8 +109,6 @@ target_sources(
|
||||
src/macro-core/macro-action-macro.hpp
|
||||
src/macro-core/macro-action-media.cpp
|
||||
src/macro-core/macro-action-media.hpp
|
||||
src/macro-core/macro-action-osc.cpp
|
||||
src/macro-core/macro-action-osc.hpp
|
||||
src/macro-core/macro-action-plugin-state.cpp
|
||||
src/macro-core/macro-action-plugin-state.hpp
|
||||
src/macro-core/macro-action-profile.cpp
|
||||
@@ -165,8 +165,6 @@ target_sources(
|
||||
src/macro-core/macro-condition-cursor.hpp
|
||||
src/macro-core/macro-condition-date.cpp
|
||||
src/macro-core/macro-condition-date.hpp
|
||||
src/macro-core/macro-condition-display.cpp
|
||||
src/macro-core/macro-condition-display.hpp
|
||||
src/macro-core/macro-condition-edit.cpp
|
||||
src/macro-core/macro-condition-edit.hpp
|
||||
src/macro-core/macro-condition-file.cpp
|
||||
@@ -193,8 +191,6 @@ target_sources(
|
||||
src/macro-core/macro-condition-recording.hpp
|
||||
src/macro-core/macro-condition-replay-buffer.cpp
|
||||
src/macro-core/macro-condition-replay-buffer.hpp
|
||||
src/macro-core/macro-condition-run.cpp
|
||||
src/macro-core/macro-condition-run.hpp
|
||||
src/macro-core/macro-condition-scene-order.cpp
|
||||
src/macro-core/macro-condition-scene-order.hpp
|
||||
src/macro-core/macro-condition-scene-transform.cpp
|
||||
@@ -223,8 +219,6 @@ target_sources(
|
||||
src/macro-core/macro-condition-window.hpp
|
||||
src/macro-core/macro-condition.cpp
|
||||
src/macro-core/macro-condition.hpp
|
||||
src/macro-core/macro-dock.cpp
|
||||
src/macro-core/macro-dock.hpp
|
||||
src/macro-core/macro-properties.cpp
|
||||
src/macro-core/macro-properties.hpp
|
||||
src/macro-core/macro-ref.cpp
|
||||
@@ -252,28 +246,12 @@ target_sources(
|
||||
src/utils/duration-control.hpp
|
||||
src/utils/item-selection-helpers.cpp
|
||||
src/utils/item-selection-helpers.hpp
|
||||
src/utils/log-helper.hpp
|
||||
src/utils/file-selection.cpp
|
||||
src/utils/file-selection.hpp
|
||||
src/utils/filter-selection.cpp
|
||||
src/utils/filter-selection.hpp
|
||||
src/utils/macro-list.cpp
|
||||
src/utils/macro-list.hpp
|
||||
src/utils/math-helpers.cpp
|
||||
src/utils/math-helpers.hpp
|
||||
src/utils/mouse-wheel-guard.cpp
|
||||
src/utils/mouse-wheel-guard.hpp
|
||||
src/utils/name-dialog.cpp
|
||||
src/utils/name-dialog.hpp
|
||||
src/utils/obs-dock.hpp
|
||||
src/utils/obs-module-helper.cpp
|
||||
src/utils/obs-module-helper.hpp
|
||||
src/utils/osc-helpers.cpp
|
||||
src/utils/osc-helpers.hpp
|
||||
src/utils/priority-helper.cpp
|
||||
src/utils/priority-helper.hpp
|
||||
src/utils/process-config.cpp
|
||||
src/utils/process-config.hpp
|
||||
src/utils/regex-config.cpp
|
||||
src/utils/regex-config.hpp
|
||||
src/utils/resizing-text-edit.cpp
|
||||
@@ -282,8 +260,6 @@ target_sources(
|
||||
src/utils/scene-item-selection.hpp
|
||||
src/utils/scene-selection.cpp
|
||||
src/utils/scene-selection.hpp
|
||||
src/utils/scene-switch-helpers.cpp
|
||||
src/utils/scene-switch-helpers.hpp
|
||||
src/utils/screenshot-helper.cpp
|
||||
src/utils/screenshot-helper.hpp
|
||||
src/utils/section.cpp
|
||||
@@ -292,26 +268,12 @@ target_sources(
|
||||
src/utils/slider-spinbox.hpp
|
||||
src/utils/source-selection.cpp
|
||||
src/utils/source-selection.hpp
|
||||
src/utils/string-list.cpp
|
||||
src/utils/string-list.hpp
|
||||
src/utils/striped-frame.cpp
|
||||
src/utils/striped-frame.hpp
|
||||
src/utils/sync-helper.cpp
|
||||
src/utils/sync-helper.hpp
|
||||
src/utils/transition-selection.cpp
|
||||
src/utils/transition-selection.hpp
|
||||
src/utils/utility.cpp
|
||||
src/utils/utility.hpp
|
||||
src/utils/variable.cpp
|
||||
src/utils/variable.hpp
|
||||
src/utils/variable-line-edit.cpp
|
||||
src/utils/variable-line-edit.hpp
|
||||
src/utils/variable-number.tpp
|
||||
src/utils/variable-number.hpp
|
||||
src/utils/variable-spinbox.cpp
|
||||
src/utils/variable-spinbox.hpp
|
||||
src/utils/variable-string.cpp
|
||||
src/utils/variable-string.hpp
|
||||
src/utils/variable-text-edit.cpp
|
||||
src/utils/variable-text-edit.hpp
|
||||
src/utils/volume-control.cpp
|
||||
@@ -358,8 +320,7 @@ target_include_directories(
|
||||
${LIB_NAME}
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/websocketpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/obs-websocket/lib"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/exprtk")
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/obs-websocket/lib")
|
||||
|
||||
# --- End of section ---
|
||||
|
||||
@@ -370,8 +331,7 @@ if(OS_WINDOWS)
|
||||
|
||||
target_compile_definitions(${LIB_NAME} PRIVATE UNICODE _UNICODE)
|
||||
if(MSVC)
|
||||
target_compile_options(${LIB_NAME} PUBLIC /MP /d2FH4- /wd4267 /wd4267
|
||||
/bigobj)
|
||||
target_compile_options(${LIB_NAME} PUBLIC /MP /d2FH4- /wd4267 /wd4267)
|
||||
endif()
|
||||
target_sources(${LIB_NAME} PRIVATE src/win/advanced-scene-switcher-win.cpp)
|
||||
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
||||
@@ -488,4 +448,3 @@ endif()
|
||||
# --- End of section ---
|
||||
|
||||
add_subdirectory(src/macro-external)
|
||||
add_subdirectory(tests)
|
||||
|
||||
@@ -22,5 +22,9 @@
|
||||
</array>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.13</string>
|
||||
<key>com.apple.security.automation.apple-events</key>
|
||||
<true/>
|
||||
<key>NSAppleEventsUsageDescription</key>
|
||||
<string>Advanced scene switcher needs additional permissions to be able to run AppleScript applications</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -25,7 +25,7 @@ DirExistsWarning=no
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Files]
|
||||
Source: "..\release\*"; Excludes: "*.zip"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "..\release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "..\LICENSE"; Flags: dontcopy
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ AdvSceneSwitcher.condition.stream.state.start="Stream läuft"
|
||||
AdvSceneSwitcher.condition.stream.state.stop="Stream gestoppt"
|
||||
AdvSceneSwitcher.condition.stream.state.starting="Stream wird gestartet"
|
||||
AdvSceneSwitcher.condition.stream.state.stopping="Stream wird gestoppt"
|
||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
|
||||
AdvSceneSwitcher.condition.record="Aufnahme"
|
||||
AdvSceneSwitcher.condition.record.state.start="Aufnahme läuft"
|
||||
AdvSceneSwitcher.condition.record.state.pause="Aufnahme pausiert"
|
||||
@@ -428,7 +428,7 @@ AdvSceneSwitcher.action.recording.type.unpause="Aufnahme nicht mehr pausieren"
|
||||
AdvSceneSwitcher.action.recording.type.split="Aufnahme-Datei teilen"
|
||||
AdvSceneSwitcher.action.recording.pause.hint="Bitte beachten, dass je nach Aufnahmeeinstellung die Aufnahme möglicherweise nicht unterbrochen werden kann"
|
||||
AdvSceneSwitcher.action.recording.split.hint="Vergewissern, dass die automatische Dateiaufteilung in den OBS-Einstellungen aktiviert ist!"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
|
||||
AdvSceneSwitcher.action.replay="Replay Buffer"
|
||||
AdvSceneSwitcher.action.replay.saveWarn="Warnung: Ein zu häufiges Speichern kann dazu führen, dass der Replay Buffer nicht gespeichert wird!"
|
||||
AdvSceneSwitcher.action.replay.type.stop="Replay Buffer stoppen"
|
||||
@@ -438,7 +438,7 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.streaming="Stream"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="Stream stoppen"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Stream starten"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.run="Ausführen"
|
||||
AdvSceneSwitcher.action.run.arguments="Argumente:"
|
||||
AdvSceneSwitcher.action.run.addArgument="Argument hinzufügen"
|
||||
@@ -506,7 +506,7 @@ AdvSceneSwitcher.action.hotkey.leftMeta="Linke Meta-Taste"
|
||||
AdvSceneSwitcher.action.hotkey.rightMeta="Rechte Meta-Taste"
|
||||
AdvSceneSwitcher.action.hotkey.onlyOBS="Tastendruck nur an OBS senden"
|
||||
AdvSceneSwitcher.action.hotkey.disabled="Globale Tastendrücke können nicht simuliert werden - die Funktionalität beschränkt sich auf das Senden von Tastendrücken an OBS!"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Drücke {{keys}} für {{duration}}"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Drücke {{keys}} für {{duration}} Millisekunden"
|
||||
AdvSceneSwitcher.action.sceneOrder="Reihenfolge der Szenenelemente"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Nach oben verschieben"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Nach unten verschieben"
|
||||
@@ -545,6 +545,7 @@ AdvSceneSwitcher.action.random="Zufall"
|
||||
AdvSceneSwitcher.action.random.allowRepeat="Aufeinanderfolgende Ausführung desselben Makros zulassen"
|
||||
AdvSceneSwitcher.action.random.entry="Zufällige Ausführung eines der folgenden Makros (pausierte Makros werden ignoriert)"
|
||||
AdvSceneSwitcher.action.systray="Benachrichtigung im System-Tray"
|
||||
AdvSceneSwitcher.action.systray.entry="Benachrichtigung anzeigen: {{message}}"
|
||||
AdvSceneSwitcher.action.screenshot="Screenshot"
|
||||
AdvSceneSwitcher.action.screenshot.save.default="Standard"
|
||||
AdvSceneSwitcher.action.screenshot.save.custom="Benutzerdefiniert"
|
||||
@@ -586,7 +587,7 @@ AdvSceneSwitcher.action.variable.invalidSelection="Ungültige Auswahl!"
|
||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Aktionen wird nicht unterstützt!"
|
||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Bedingungen wird nicht unterstützt!"
|
||||
AdvSceneSwitcher.action.variable.currentSegmentValue="Aktueller Wert:"
|
||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}"
|
||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}"
|
||||
|
||||
|
||||
; Transition Tab
|
||||
|
||||
@@ -30,8 +30,6 @@ AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Enable verbose loggi
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Save window position and size"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Show system tray notifications"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Disable UI hints"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailure="Display warning if plugins cannot be loaded"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage="<html><body>Loading of the following plugin libraries was unsuccessful, which could result in some Advanced Scene Switcher functions not being available:%1Check the OBS logs for details.<br>This message can be disabled on the General tab.</body></html>"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="Hide tabs which can be represented via macros"
|
||||
AdvSceneSwitcher.generalTab.matchBehavior="Match behavior"
|
||||
AdvSceneSwitcher.generalTab.priority="Priority"
|
||||
@@ -85,7 +83,6 @@ AdvSceneSwitcher.macroTab.defaultGroupName="Group %1"
|
||||
AdvSceneSwitcher.macroTab.exists="Macro name exists already"
|
||||
AdvSceneSwitcher.macroTab.groupDeleteConfirm="Are you sure you want to delete \"%1\" and all its elements?"
|
||||
AdvSceneSwitcher.macroTab.deleteMultipleMacrosConfirmation="Are you sure you want to delete %1 macros?"
|
||||
AdvSceneSwitcher.macroTab.deleteSingleMacroConfirmation="Are you sure you want to delete \"%1\"?"
|
||||
AdvSceneSwitcher.macroTab.contextMenuAdd="Add"
|
||||
AdvSceneSwitcher.macroTab.copy="Duplicate Macro"
|
||||
AdvSceneSwitcher.macroTab.group="Group Selected Macros"
|
||||
@@ -98,22 +95,11 @@ AdvSceneSwitcher.macroTab.maximize="Maximize"
|
||||
AdvSceneSwitcher.macroTab.minimize="Minimize"
|
||||
AdvSceneSwitcher.macroTab.highlightSettings="Visual settings"
|
||||
AdvSceneSwitcher.macroTab.hotkeySettings="Hotkey settings"
|
||||
AdvSceneSwitcher.macroTab.dockSettings="Dock settings"
|
||||
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Highlight recently executed macros"
|
||||
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.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.currentRegisterDock="Register dock widget to control the pause state of selected macro or run it manually"
|
||||
AdvSceneSwitcher.macroTab.currentDockAddRunButton="Add button to run the macro"
|
||||
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="Add button to pause or unpause the macro"
|
||||
AdvSceneSwitcher.macroTab.currentDockButtonText.run="Run button text:"
|
||||
AdvSceneSwitcher.macroTab.currentDockButtonText.pause="Pause button text:"
|
||||
AdvSceneSwitcher.macroTab.currentDockButtonText.unpause="Unpause button text:"
|
||||
|
||||
AdvSceneSwitcher.macroDock.pause="Pause"
|
||||
AdvSceneSwitcher.macroDock.unpause="Unpause"
|
||||
AdvSceneSwitcher.macroDock.run="Run"
|
||||
|
||||
; Macro List
|
||||
AdvSceneSwitcher.macroList.deleted="deleted"
|
||||
@@ -164,14 +150,9 @@ AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="During transi
|
||||
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
||||
AdvSceneSwitcher.condition.window="Window"
|
||||
AdvSceneSwitcher.condition.window.entry.window="{{checkTitle}}Window title matches{{windowRegex}}{{windows}}"
|
||||
AdvSceneSwitcher.condition.window.entry.fullscreen="{{fullscreen}}Window is fullscreen"
|
||||
AdvSceneSwitcher.condition.window.entry.maximized="{{maximized}}Window is maximized"
|
||||
AdvSceneSwitcher.condition.window.entry.focused="{{focused}}Window is focused"
|
||||
AdvSceneSwitcher.condition.window.entry.focusedChange="{{windowFocusChanged}}Focus window changed"
|
||||
AdvSceneSwitcher.condition.window.entry.text="{{checkText}}Window contains text{{textRegex}}{{windowText}}"
|
||||
AdvSceneSwitcher.condition.window.entry.text.note="This option might not work on every text being displayed in a window.\nIf that is the case, you can consider using the Video conditions OCR check instead."
|
||||
AdvSceneSwitcher.condition.window.entry.currentFocus="Current focus window:{{focusWindow}}"
|
||||
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} exist and ..."
|
||||
AdvSceneSwitcher.condition.window.entry.line2="... is {{fullscreen}} fullscreen {{maximized}} maximized {{focused}} focused {{windowFocusChanged}} foreground window changed"
|
||||
AdvSceneSwitcher.condition.window.entry.line3="Current foreground window: {{focusWindow}}"
|
||||
AdvSceneSwitcher.condition.file="File"
|
||||
AdvSceneSwitcher.condition.file.type.match="matches"
|
||||
AdvSceneSwitcher.condition.file.type.contentChange="content changed"
|
||||
@@ -261,8 +242,7 @@ AdvSceneSwitcher.condition.stream.state.start="Stream running"
|
||||
AdvSceneSwitcher.condition.stream.state.stop="Stream stopped"
|
||||
AdvSceneSwitcher.condition.stream.state.starting="Stream starting"
|
||||
AdvSceneSwitcher.condition.stream.state.stopping="Stream stopping"
|
||||
AdvSceneSwitcher.condition.stream.state.keyFrameInterval="Keyframe interval equals"
|
||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
|
||||
AdvSceneSwitcher.condition.record="Recording"
|
||||
AdvSceneSwitcher.condition.record.state.start="Recording running"
|
||||
AdvSceneSwitcher.condition.record.state.pause="Recording paused"
|
||||
@@ -327,7 +307,7 @@ AdvSceneSwitcher.condition.filter.type.settings="Settings match"
|
||||
AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.condition.filter.entry.line1="On {{sources}} {{filters}} {{conditions}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}}{{getSettings}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.sceneOrder="Scene item order"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.above="Is above"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.below="Is below"
|
||||
@@ -436,16 +416,6 @@ AdvSceneSwitcher.condition.variable.type.equalsVariable="equals variable"
|
||||
AdvSceneSwitcher.condition.variable.type.lessThanVariable="is less than variable"
|
||||
AdvSceneSwitcher.condition.variable.type.greaterThanVariable="is greater than variable"
|
||||
AdvSceneSwitcher.condition.variable.entry="{{variables}}{{conditions}}{{strValue}}{{numValue}}{{variables2}}"
|
||||
AdvSceneSwitcher.condition.run="Run"
|
||||
AdvSceneSwitcher.condition.run.entry="Process exits before timeout of{{timeout}} seconds"
|
||||
AdvSceneSwitcher.condition.run.entry.exit="{{checkExitCode}}Check for exit code{{exitCode}}"
|
||||
AdvSceneSwitcher.condition.midi="MIDI"
|
||||
AdvSceneSwitcher.condition.midi.entry="Mesasge was received from {{device}} which matches:"
|
||||
AdvSceneSwitcher.condition.midi.entry.listen="Set MIDI message selection to messages incoming on selected device: {{listenButton}}"
|
||||
AdvSceneSwitcher.condition.display="Display"
|
||||
AdvSceneSwitcher.condition.display.type.displayName="Name of connected displays matches"
|
||||
AdvSceneSwitcher.condition.display.type.displayCount="Number of connected displays is"
|
||||
AdvSceneSwitcher.condition.display.entry="{{conditions}}{{displays}}{{regex}}{{displayCount}}"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.switchScene="Switch scene"
|
||||
@@ -479,11 +449,9 @@ AdvSceneSwitcher.action.recording.type.start="Start recording"
|
||||
AdvSceneSwitcher.action.recording.type.pause="Pause recording"
|
||||
AdvSceneSwitcher.action.recording.type.unpause="Unpause recording"
|
||||
AdvSceneSwitcher.action.recording.type.split="Split recording file"
|
||||
AdvSceneSwitcher.action.recording.type.changeOutputFolder="Change output folder"
|
||||
AdvSceneSwitcher.action.recording.type.changeOutputFileFormat="Change filename formatting"
|
||||
AdvSceneSwitcher.action.recording.pause.hint="Note that depending on your recording settings you might not be able to pause recording"
|
||||
AdvSceneSwitcher.action.recording.split.hint="Make sure to enable automatic file splitting in the OBS settings first!"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
|
||||
AdvSceneSwitcher.action.replay="Replay buffer"
|
||||
AdvSceneSwitcher.action.replay.saveWarn="Warning: Saving too frequently might result in the replay buffer not actually being saved!"
|
||||
AdvSceneSwitcher.action.replay.type.stop="Stop replay buffer"
|
||||
@@ -493,9 +461,13 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.streaming="Streaming"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="Stop streaming"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Start streaming"
|
||||
AdvSceneSwitcher.action.streaming.type.keyFrameInterval="Set keyframe interval"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.run="Run"
|
||||
AdvSceneSwitcher.action.run.arguments="Arguments:"
|
||||
AdvSceneSwitcher.action.run.addArgument="Add argument"
|
||||
AdvSceneSwitcher.action.run.addArgumentDescription="Add new argument:"
|
||||
AdvSceneSwitcher.action.run.entry="Run {{filePath}}"
|
||||
AdvSceneSwitcher.action.run.entry.workingDirectory="Working directory:{{workingDirectory}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
|
||||
@@ -541,8 +513,6 @@ AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:"
|
||||
AdvSceneSwitcher.action.pluginState.type.import="Import settings from"
|
||||
AdvSceneSwitcher.action.pluginState.importWarning="Note: Action will be ignored while settings window is opened."
|
||||
AdvSceneSwitcher.action.pluginState.type.terminate="Shut down OBS"
|
||||
AdvSceneSwitcher.action.pluginState.terminateConfirm="OBS will be shut down automatically in 10 seconds!\nDo you want to continue shutting down OBS?"
|
||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
|
||||
AdvSceneSwitcher.action.virtualCamera="Virtual camera"
|
||||
AdvSceneSwitcher.action.virtualCamera.type.stop="Stop virtual camera"
|
||||
@@ -559,7 +529,7 @@ AdvSceneSwitcher.action.hotkey.leftMeta="Left Meta"
|
||||
AdvSceneSwitcher.action.hotkey.rightMeta="Right Meta"
|
||||
AdvSceneSwitcher.action.hotkey.onlyOBS="Send keypress only to OBS"
|
||||
AdvSceneSwitcher.action.hotkey.disabled="Cannot simulate global key presses - functionality limited to sending key press to OBS!"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Press {{keys}} for {{duration}}"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Press {{keys}} for {{duration}} milliseconds"
|
||||
AdvSceneSwitcher.action.sceneOrder="Scene item order"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Move up"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Move down"
|
||||
@@ -598,10 +568,7 @@ AdvSceneSwitcher.action.random="Random"
|
||||
AdvSceneSwitcher.action.random.allowRepeat="Allow consecutive execution of the same macro"
|
||||
AdvSceneSwitcher.action.random.entry="Randomly run any of the following macros (paused macros are ignored)"
|
||||
AdvSceneSwitcher.action.systray="System tray notification"
|
||||
AdvSceneSwitcher.action.systray.title="Title:"
|
||||
AdvSceneSwitcher.action.systray.message="Message:"
|
||||
AdvSceneSwitcher.action.systray.icon="Icon:"
|
||||
AdvSceneSwitcher.action.systray.iconHint="Leave blank to use the default icon"
|
||||
AdvSceneSwitcher.action.systray.entry="Show notification: {{message}}"
|
||||
AdvSceneSwitcher.action.screenshot="Screenshot"
|
||||
AdvSceneSwitcher.action.screenshot.save.default="Default"
|
||||
AdvSceneSwitcher.action.screenshot.save.custom="Custom"
|
||||
@@ -627,9 +594,6 @@ AdvSceneSwitcher.action.websocket.type.event="Event"
|
||||
AdvSceneSwitcher.action.websocket.entry.request="Send scene switcher {{type}} via {{connection}}"
|
||||
AdvSceneSwitcher.action.websocket.entry.event="Send scene switcher {{type}} to connected clients"
|
||||
AdvSceneSwitcher.action.http="Http"
|
||||
AdvSceneSwitcher.action.http.setHeaders="Set headers"
|
||||
AdvSceneSwitcher.action.http.headers="Headers:"
|
||||
AdvSceneSwitcher.action.http.addHeader="Add header"
|
||||
AdvSceneSwitcher.action.http.type.get="GET"
|
||||
AdvSceneSwitcher.action.http.type.post="POST"
|
||||
AdvSceneSwitcher.action.http.entry.line1="Send {{method}} to {{url}}"
|
||||
@@ -644,21 +608,15 @@ AdvSceneSwitcher.action.variable.type.setActionValue="Set to action value"
|
||||
AdvSceneSwitcher.action.variable.type.setConditionValue="Set to condition value"
|
||||
AdvSceneSwitcher.action.variable.type.roundToInt="Round to nearest integer"
|
||||
AdvSceneSwitcher.action.variable.type.subString="Set to substring of current value"
|
||||
AdvSceneSwitcher.action.variable.type.findAndReplace="Find and replace in current value"
|
||||
AdvSceneSwitcher.action.variable.type.mathExpression="Mathematical expression"
|
||||
AdvSceneSwitcher.action.variable.mathExpression.example="( 1 + 2 * 3 ) / 4"
|
||||
AdvSceneSwitcher.action.variable.findAndReplace.find="Text to find"
|
||||
AdvSceneSwitcher.action.variable.findAndReplace.replace="Text to replace with"
|
||||
AdvSceneSwitcher.action.variable.subString.begin="Beginning"
|
||||
AdvSceneSwitcher.action.variable.subString.all="All"
|
||||
AdvSceneSwitcher.action.variable.invalidSelection="Invalid selection!"
|
||||
AdvSceneSwitcher.action.variable.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.currentSegmentValue="Current value:"
|
||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}"
|
||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}"
|
||||
AdvSceneSwitcher.action.variable.entry.substringIndex="Substring start:{{subStringStart}} Substring size:{{subStringSize}}"
|
||||
AdvSceneSwitcher.action.variable.entry.substringRegex="Assign value of{{regexMatchIdx}}match using regular expression:"
|
||||
AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{replaceStr}}"
|
||||
AdvSceneSwitcher.action.projector="Projector"
|
||||
AdvSceneSwitcher.action.projector.type.source="Source"
|
||||
AdvSceneSwitcher.action.projector.type.scene="Scene"
|
||||
@@ -670,10 +628,7 @@ AdvSceneSwitcher.action.projector.windowed="Windowed"
|
||||
AdvSceneSwitcher.action.projector.fullscreen="Fullscreen"
|
||||
AdvSceneSwitcher.action.projector.entry="Open{{windowTypes}}projector of{{types}}{{scenes}}{{sources}}"
|
||||
AdvSceneSwitcher.action.projector.entry.monitor="on{{monitors}}"
|
||||
AdvSceneSwitcher.action.midi="MIDI"
|
||||
AdvSceneSwitcher.action.midi.entry="Send message to {{device}}:"
|
||||
AdvSceneSwitcher.action.midi.entry.listen="Set MIDI message selection to messages incoming on {{listenDevices}}: {{listenButton}}"
|
||||
AdvSceneSwitcher.action.osc="Open Sound Control"
|
||||
|
||||
|
||||
; Transition Tab
|
||||
AdvSceneSwitcher.transitionTab.title="Transition"
|
||||
@@ -953,7 +908,6 @@ AdvSceneSwitcher.connection.password="Password:"
|
||||
AdvSceneSwitcher.connection.reconnect="Reconnect automatically:"
|
||||
AdvSceneSwitcher.connection.reconnectDelay="Automatically reconnect after:"
|
||||
AdvSceneSwitcher.connection.connectOnStart="Connect on startup:"
|
||||
AdvSceneSwitcher.connection.useOBSWebsocketProtocol="<html><head/><body><p>Use the obs-websocket <a href=\"https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md\"><span style=\" text-decoration: underline; color:#268bd2;\">protocol</span></a></p></body></html>"
|
||||
AdvSceneSwitcher.connection.test="Test connection"
|
||||
AdvSceneSwitcher.connection.status.disconnected="Disconnected"
|
||||
AdvSceneSwitcher.connection.status.connecting="Connecting"
|
||||
@@ -967,68 +921,6 @@ AdvSceneSwitcher.regex.dotMatchNewline=". matches newlines"
|
||||
AdvSceneSwitcher.regex.multiLine="^ and $ match start/end of line"
|
||||
AdvSceneSwitcher.regex.extendedPattern="Enable Qt's ExtendedPatternSyntax"
|
||||
|
||||
AdvSceneSwitcher.process.showAdvanced="Show advanced settings"
|
||||
AdvSceneSwitcher.process.arguments="Arguments:"
|
||||
AdvSceneSwitcher.process.addArgument="Add argument"
|
||||
AdvSceneSwitcher.process.addArgumentDescription="Add new argument:"
|
||||
AdvSceneSwitcher.process.entry="Run{{filePath}}{{advancedSettings}}"
|
||||
AdvSceneSwitcher.process.entry.workingDirectory="Working directory:{{workingDirectory}}"
|
||||
|
||||
AdvSceneSwitcher.math.expressionFail="Failed evaluate expression"
|
||||
|
||||
AdvSceneSwitcher.midi.deviceNamePattern="[Port #%1] %2"
|
||||
AdvSceneSwitcher.midi.message.type="Type:"
|
||||
AdvSceneSwitcher.midi.message.type.optional="Any"
|
||||
AdvSceneSwitcher.midi.message.type.invalid="Invalid"
|
||||
AdvSceneSwitcher.midi.message.type.noteOff="Note Off"
|
||||
AdvSceneSwitcher.midi.message.type.noteOn="Note On"
|
||||
AdvSceneSwitcher.midi.message.type.polyphonicPressure="Polyphonic Pressure"
|
||||
AdvSceneSwitcher.midi.message.type.controlChange="Control Change"
|
||||
AdvSceneSwitcher.midi.message.type.programChange="Program Change"
|
||||
AdvSceneSwitcher.midi.message.type.channelAftertouch="Channel Aftertouch"
|
||||
AdvSceneSwitcher.midi.message.type.pitchBend="Pitch Bend"
|
||||
AdvSceneSwitcher.midi.message.type.systemExclusive="System Exclusive"
|
||||
AdvSceneSwitcher.midi.message.type.timeCode="Time Code"
|
||||
AdvSceneSwitcher.midi.message.type.songPositionPointer="Song Position Pointer"
|
||||
AdvSceneSwitcher.midi.message.type.songSelect="Song Select"
|
||||
AdvSceneSwitcher.midi.message.type.reserved1="Reserved (1)"
|
||||
AdvSceneSwitcher.midi.message.type.reserved2="Reserved (2)"
|
||||
AdvSceneSwitcher.midi.message.type.tuneRequest="Tune Request"
|
||||
AdvSceneSwitcher.midi.message.type.endOfSystemExclusive="End of System Exclusive"
|
||||
AdvSceneSwitcher.midi.message.type.timeClock="Time Clock"
|
||||
AdvSceneSwitcher.midi.message.type.reserved3="Reserved (3)"
|
||||
AdvSceneSwitcher.midi.message.type.startFile="Start File"
|
||||
AdvSceneSwitcher.midi.message.type.continueFile="Continue File"
|
||||
AdvSceneSwitcher.midi.message.type.stopFile="Stop File"
|
||||
AdvSceneSwitcher.midi.message.type.reserved4="Reserved (4)"
|
||||
AdvSceneSwitcher.midi.message.type.activeSensing="Active Sensing"
|
||||
AdvSceneSwitcher.midi.message.type.systemReset="System Reset"
|
||||
AdvSceneSwitcher.midi.message.type.unknown="Unknown"
|
||||
AdvSceneSwitcher.midi.message.channel="Channel:"
|
||||
AdvSceneSwitcher.midi.message.note="Note / Value(1):"
|
||||
AdvSceneSwitcher.midi.message.value="Value(2):"
|
||||
AdvSceneSwitcher.midi.message.placeholder="Any"
|
||||
AdvSceneSwitcher.midi.resetDevices="Reconnect all MIDI devices"
|
||||
AdvSceneSwitcher.midi.startListen="Start listening"
|
||||
AdvSceneSwitcher.midi.stopListen="Stop listening"
|
||||
AdvSceneSwitcher.midi.startListenFail="Device is busy!\nSomething else is already listening!"
|
||||
AdvSceneSwitcher.midi.deviceOpenFail="Failed to initialize MIDI device!"
|
||||
|
||||
AdvSceneSwitcher.osc.network="Network"
|
||||
AdvSceneSwitcher.osc.network.protocol="Protocol:"
|
||||
AdvSceneSwitcher.osc.network.address="Address:"
|
||||
AdvSceneSwitcher.osc.network.port="Port:"
|
||||
AdvSceneSwitcher.osc.message="Message"
|
||||
AdvSceneSwitcher.osc.message.type.none="None"
|
||||
AdvSceneSwitcher.osc.message.type.float="Float"
|
||||
AdvSceneSwitcher.osc.message.type.int="Integer"
|
||||
AdvSceneSwitcher.osc.message.type.string="String"
|
||||
AdvSceneSwitcher.osc.message.type.binaryBlob="Binary blob"
|
||||
AdvSceneSwitcher.osc.message.type.true="True"
|
||||
AdvSceneSwitcher.osc.message.type.false="False"
|
||||
AdvSceneSwitcher.osc.message.type.infinity="Infinitum"
|
||||
AdvSceneSwitcher.osc.message.type.null="Nil"
|
||||
|
||||
AdvSceneSwitcher.selectScene="--select scene--"
|
||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||
|
||||
@@ -179,7 +179,7 @@ AdvSceneSwitcher.condition.stream.state.start="Transmisión en ejecución"
|
||||
AdvSceneSwitcher.condition.stream.state.stop="Transmisión detenida"
|
||||
AdvSceneSwitcher.condition.stream.state.starting="Inicio de transmisión"
|
||||
AdvSceneSwitcher.condition.stream.state.stopping="Detener transmisión"
|
||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
|
||||
AdvSceneSwitcher.condition.record="Grabación"
|
||||
AdvSceneSwitcher.condition.record.state.start="Grabación en ejecución"
|
||||
AdvSceneSwitcher.condition.record.state.pause="Grabación en pausa"
|
||||
@@ -350,7 +350,7 @@ AdvSceneSwitcher.action.recording.type.start="Iniciar grabación"
|
||||
AdvSceneSwitcher.action.recording.type.pause="Pausar grabación"
|
||||
AdvSceneSwitcher.action.recording.type.unpause="Reanudar grabación"
|
||||
AdvSceneSwitcher.action.recording.pause.hint="Tenga en cuenta que, dependiendo de la configuración de grabación, es posible que no pueda pausar la grabación"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
|
||||
AdvSceneSwitcher.action.replay="Búfer de reproducción"
|
||||
AdvSceneSwitcher.action.replay.saveWarn="Advertencia: ¡Guardar con demasiada frecuencia puede hacer que el búfer de reproducción no se guarde realmente!"
|
||||
AdvSceneSwitcher.action.replay.type.stop="Detener el búfer de reproducción"
|
||||
@@ -360,7 +360,7 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.streaming="Transmisión"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="Detener transmisión"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Iniciar transmisión"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.run="Ejecutar"
|
||||
AdvSceneSwitcher.action.run.arguments="Argumentos:"
|
||||
AdvSceneSwitcher.action.run.addArgument="Agregar argumento"
|
||||
@@ -422,7 +422,7 @@ AdvSceneSwitcher.action.hotkey.leftMeta="Meta izquierda"
|
||||
AdvSceneSwitcher.action.hotkey.rightMeta="Meta derecho"
|
||||
AdvSceneSwitcher.action.hotkey.onlyOBS="Enviar pulsación de tecla solo a OBS"
|
||||
AdvSceneSwitcher.action.hotkey.disabled="No se puede simular la pulsación de teclas: ¡funcionalidad desactivada!"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Presione {{keys}} durante {{duration}}"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Presione {{keys}} durante {{duration}} milisegundos"
|
||||
AdvSceneSwitcher.action.sceneOrder="Orden de elementos de escena"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Mover hacia arriba"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Mover hacia abajo"
|
||||
@@ -460,6 +460,7 @@ AdvSceneSwitcher.action.timer.entry="{{timerAction}} temporizadores en {{macros}
|
||||
AdvSceneSwitcher.action.random="Aleatorio"
|
||||
AdvSceneSwitcher.action.random.entry="Ejecute aleatoriamente cualquiera de las siguientes macros (las macros en pausa se ignoran)"
|
||||
AdvSceneSwitcher.action.systray="Notificación de la bandeja del sistema"
|
||||
AdvSceneSwitcher.action.systray.entry="Mostrar notificación: {{message}}"
|
||||
AdvSceneSwitcher.action.screenshot="Captura de pantalla"
|
||||
AdvSceneSwitcher.action.screenshot.mainOutput="Salida principal de OBS"
|
||||
AdvSceneSwitcher.action.profile="Perfil"
|
||||
|
||||
@@ -135,7 +135,7 @@ AdvSceneSwitcher.action.recording.type.start="Начать запись"
|
||||
AdvSceneSwitcher.action.recording.type.pause="Пауза записи"
|
||||
AdvSceneSwitcher.action.recording.type.unpause="Снять запись с паузы"
|
||||
AdvSceneSwitcher.action.recording.pause.hint="Обратите внимание, что в зависимости от настроек записи вы можете не иметь возможности приостановить запись"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
|
||||
AdvSceneSwitcher.action.replay="Буфер воспроизведения"
|
||||
AdvSceneSwitcher.action.replay.type.stop="Остановить буфер воспроизведения"
|
||||
AdvSceneSwitcher.action.replay.type.start="Начать воспроизведение буфера"
|
||||
@@ -144,7 +144,7 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.streaming="Потоковое вещание"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="Остановить потоковое вещание"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Начать потоковое вещание"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.run="Запустить"
|
||||
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ AdvSceneSwitcher.condition.stream.state.start="Yayın çalışıyor"
|
||||
AdvSceneSwitcher.condition.stream.state.stop="Yayın durdu"
|
||||
AdvSceneSwitcher.condition.stream.state.starting="Yayın başlıyor"
|
||||
AdvSceneSwitcher.condition.stream.state.stopping="Yayın duruyor"
|
||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
|
||||
AdvSceneSwitcher.condition.record="Kayıt"
|
||||
AdvSceneSwitcher.condition.record.state.start="Kayıt Çalışıyor"
|
||||
AdvSceneSwitcher.condition.record.state.pause="Kayıt durakladı"
|
||||
@@ -281,7 +281,7 @@ AdvSceneSwitcher.action.recording.type.start="Kayıt Başlat"
|
||||
AdvSceneSwitcher.action.recording.type.pause="Kayıt Duraklat"
|
||||
AdvSceneSwitcher.action.recording.type.unpause="Kayıt Duraklatma"
|
||||
AdvSceneSwitcher.action.recording.pause.hint="Kayıt ayarlarınıza bağlı olarak kaydı duraklatamayabileceğinizi unutmayın."
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
|
||||
AdvSceneSwitcher.action.replay="Tekrar arabelleği"
|
||||
AdvSceneSwitcher.action.replay.type.stop="Tekrar arabelleğini durdur"
|
||||
AdvSceneSwitcher.action.replay.type.start="Tekrar arabelleğini başlat"
|
||||
@@ -290,7 +290,7 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.streaming="Yayın"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="Yayın durdur"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Yayın başlat"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.run="Çalıştır"
|
||||
AdvSceneSwitcher.action.run.arguments="Argümanlar:"
|
||||
AdvSceneSwitcher.action.run.addArgument="Argüman ekle"
|
||||
@@ -350,7 +350,7 @@ AdvSceneSwitcher.action.hotkey.leftMeta="Sol Meta"
|
||||
AdvSceneSwitcher.action.hotkey.rightMeta="Sağ Meta"
|
||||
AdvSceneSwitcher.action.hotkey.onlyOBS="Tuşa basımı yalnızca OBS'ye gönder"
|
||||
AdvSceneSwitcher.action.hotkey.disabled="Tuşa basma simülasyonu yapılamıyor - işlevsellik devre dışı!"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Bas {{keys}} uygun {{duration}}"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Bas {{keys}} uygun {{duration}} millisaniye"
|
||||
AdvSceneSwitcher.action.sceneOrder="Sahne öğesi sırası"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Yukarı taşı"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Aşağı indir"
|
||||
@@ -377,6 +377,7 @@ AdvSceneSwitcher.action.timer.entry="{{timerAction}} zamanlayıcılar açık {{m
|
||||
AdvSceneSwitcher.action.random="Rastgele"
|
||||
AdvSceneSwitcher.action.random.entry="Aşağıdaki makrolardan herhangi birini rastgele çalıştırın (duraklatılmış makrolar yoksayılır)"
|
||||
AdvSceneSwitcher.action.systray="Sistem tepsisi bildirimi"
|
||||
AdvSceneSwitcher.action.systray.entry="Bildirimleri göster: {{message}}"
|
||||
AdvSceneSwitcher.action.screenshot="Ekran görüntüsü"
|
||||
AdvSceneSwitcher.action.screenshot.mainOutput="OBS'nin ana çıkışı"
|
||||
AdvSceneSwitcher.action.profile="Profil"
|
||||
|
||||
@@ -4,7 +4,7 @@ AdvSceneSwitcher.windowTitle="高级场景切换器"
|
||||
; General Tab
|
||||
AdvSceneSwitcher.generalTab.title="通用"
|
||||
AdvSceneSwitcher.generalTab.status="状态"
|
||||
AdvSceneSwitcher.generalTab.status.hotkeytips="快捷键可在OBS设置中设置<br><br>汉化作者:[ 从不咕咕的阿坤 ] - 全平台统一名 - 如对你有所帮助,劳烦点个关注!"
|
||||
AdvSceneSwitcher.generalTab.status.hotkeytips="快捷键可在OBS设置中设置"
|
||||
AdvSceneSwitcher.generalTab.status.currentStatus="当前状态:"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup="在OBS启动时"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup.asLastRun="按照最后运行时的状态"
|
||||
@@ -24,14 +24,11 @@ AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="时间精度最
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="不切换"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="切换到随机场景列表中任意随机场景"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="切换到"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="执行完操作后,跳过执行操作,为"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="在此期间,可能的匹配项将被忽略!"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="详细日志输出"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="保存窗口位置和大小"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="显示系统托盘通知"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="禁用UI提示"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailure="如果无法加载插件显示警告"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage="<html><body>加载以下插件库失败,这可能导致某些高级场景切换器功能不可用:%1 查看 OBS 日志了解详细信息.<br>可以在“常规”选项卡上禁用此消息.</body></html>"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="隐藏可通过宏操作的分组栏"
|
||||
AdvSceneSwitcher.generalTab.matchBehavior="场景匹配设置"
|
||||
AdvSceneSwitcher.generalTab.priority="优先级"
|
||||
@@ -81,39 +78,17 @@ AdvSceneSwitcher.macroTab.runFail="运行 \"%1\" 失败!\n其中一个操作失
|
||||
AdvSceneSwitcher.macroTab.runInParallel="与其他宏同时运行宏"
|
||||
AdvSceneSwitcher.macroTab.onChange="仅在条件更改时执行操作"
|
||||
AdvSceneSwitcher.macroTab.defaultname="宏 %1"
|
||||
AdvSceneSwitcher.macroTab.defaultGroupName="组 %1"
|
||||
AdvSceneSwitcher.macroTab.exists="宏名称已存在"
|
||||
AdvSceneSwitcher.macroTab.groupDeleteConfirm="您确定要删除 \"%1\"及其所有元素吗?"
|
||||
AdvSceneSwitcher.macroTab.deleteMultipleMacrosConfirmation="您确定要删除 %1 宏吗?"
|
||||
AdvSceneSwitcher.macroTab.deleteSingleMacroConfirmation="你确定你要删除 \"%1\"?"
|
||||
AdvSceneSwitcher.macroTab.contextMenuAdd="增加"
|
||||
AdvSceneSwitcher.macroTab.copy="创建副本"
|
||||
AdvSceneSwitcher.macroTab.group="对选定的宏进行分组"
|
||||
AdvSceneSwitcher.macroTab.ungroup="解除选定的组的分组"
|
||||
AdvSceneSwitcher.macroTab.rename="重命名"
|
||||
AdvSceneSwitcher.macroTab.remove="删除"
|
||||
AdvSceneSwitcher.macroTab.expandAll="全部展开"
|
||||
AdvSceneSwitcher.macroTab.collapseAll="全部收回"
|
||||
AdvSceneSwitcher.macroTab.maximize="最大化"
|
||||
AdvSceneSwitcher.macroTab.minimize="最小化"
|
||||
AdvSceneSwitcher.macroTab.highlightSettings="显示 设置"
|
||||
AdvSceneSwitcher.macroTab.hotkeySettings="热键 设置"
|
||||
AdvSceneSwitcher.macroTab.dockSettings="停靠 设置"
|
||||
AdvSceneSwitcher.macroTab.highlightExecutedMacros="突出显示最近执行的宏"
|
||||
AdvSceneSwitcher.macroTab.highlightTrueConditions="突出显示最近运算为 真 的当前选定宏的条件"
|
||||
AdvSceneSwitcher.macroTab.highlightPerformedActions="突出显示当前选定宏的最近执行的操作"
|
||||
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="使用快捷键控制新增宏的暂停状态"
|
||||
AdvSceneSwitcher.macroTab.currentDisableHotkeys="使用快捷键控制所选宏的暂停状态"
|
||||
AdvSceneSwitcher.macroTab.currentRegisterDock="注册停靠小部件以控制所选宏的暂停状态或手动运行它"
|
||||
AdvSceneSwitcher.macroTab.currentDockAddRunButton="添加按钮以运行宏"
|
||||
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="添加按钮以暂停或取消暂停宏"
|
||||
AdvSceneSwitcher.macroTab.currentDockButtonText.run="运行按钮文本:"
|
||||
AdvSceneSwitcher.macroTab.currentDockButtonText.pause="暂停按钮文本:"
|
||||
AdvSceneSwitcher.macroTab.currentDockButtonText.unpause="取消暂停按钮文本:"
|
||||
|
||||
AdvSceneSwitcher.macroDock.pause="暂停"
|
||||
AdvSceneSwitcher.macroDock.unpause="取消暂停"
|
||||
AdvSceneSwitcher.macroDock.run="运行"
|
||||
|
||||
; Macro List
|
||||
AdvSceneSwitcher.macroList.deleted="删除"
|
||||
@@ -137,17 +112,10 @@ AdvSceneSwitcher.condition.audio.state.mute="静音"
|
||||
AdvSceneSwitcher.condition.audio.state.unmute="取消静音"
|
||||
AdvSceneSwitcher.condition.audio.type.output="输出音频"
|
||||
AdvSceneSwitcher.condition.audio.type.volume="配置音量级别"
|
||||
AdvSceneSwitcher.condition.audio.type.syncOffset="同步偏移"
|
||||
AdvSceneSwitcher.condition.audio.type.monitor="音频监控"
|
||||
AdvSceneSwitcher.condition.audio.type.balance="音频平衡"
|
||||
AdvSceneSwitcher.condition.audio.entry="{{checkType}} 的 {{audioSources}} 是 {{condition}}{{volume}}{{syncOffset}}{{monitorTypes}}"
|
||||
AdvSceneSwitcher.condition.cursor="屏幕区域"
|
||||
AdvSceneSwitcher.condition.cursor.type.region="当前位置"
|
||||
AdvSceneSwitcher.condition.cursor.type.moving="正在移动"
|
||||
AdvSceneSwitcher.condition.cursor.type.click="点击"
|
||||
AdvSceneSwitcher.condition.cursor.button.left="鼠标左键"
|
||||
AdvSceneSwitcher.condition.cursor.button.middle="鼠标中键"
|
||||
AdvSceneSwitcher.condition.cursor.button.right="鼠标右键"
|
||||
AdvSceneSwitcher.condition.cursor.showFrame="显示帧率"
|
||||
AdvSceneSwitcher.condition.cursor.hideFrame="隐藏帧率"
|
||||
AdvSceneSwitcher.condition.cursor.entry.line1="鼠标 处于{{conditions}}{{buttons}}{{minX}}{{minY}}{{maxX}}{{maxY}}{{toggleFrameButton}}"
|
||||
@@ -157,47 +125,36 @@ AdvSceneSwitcher.condition.scene.type.current="当前场景是"
|
||||
AdvSceneSwitcher.condition.scene.type.previous="上一个场景是"
|
||||
AdvSceneSwitcher.condition.scene.type.changed="场景改变了"
|
||||
AdvSceneSwitcher.condition.scene.type.notChanged="场景没有改变"
|
||||
AdvSceneSwitcher.condition.scene.type.currentPattern="当前场景匹配"
|
||||
AdvSceneSwitcher.condition.scene.type.previousPattern="上一个场景匹配"
|
||||
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="在转场过程中检查转场源场景"
|
||||
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="在转场过程中检查转场源场景"
|
||||
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
||||
AdvSceneSwitcher.condition.window="窗口"
|
||||
AdvSceneSwitcher.condition.window.entry.window="{{checkTitle}}窗口标题匹配{{windowRegex}}{{windows}}"
|
||||
AdvSceneSwitcher.condition.window.entry.fullscreen="{{fullscreen}}窗口为全屏"
|
||||
AdvSceneSwitcher.condition.window.entry.maximized="{{maximized}}窗口为最大化"
|
||||
AdvSceneSwitcher.condition.window.entry.focused="{{focused}}窗口为焦点"
|
||||
AdvSceneSwitcher.condition.window.entry.focusedChange="{{windowFocusChanged}}焦点窗口被改变"
|
||||
AdvSceneSwitcher.condition.window.entry.text="{{checkText}}窗口包含文本{{textRegex}}{{windowText}}"
|
||||
AdvSceneSwitcher.condition.window.entry.text.note="此选项可能不会对窗口中显示的每个文本起作用。\n如果是这种情况,您可以考虑使用视频条件OCR检查来代替。"
|
||||
AdvSceneSwitcher.condition.window.entry.currentFocus="当前焦点窗口:{{focusWindow}}"
|
||||
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} 存在..."
|
||||
AdvSceneSwitcher.condition.window.entry.line2="... 并且是 {{fullscreen}} 全屏 {{maximized}} 最大化 {{focused}} 获得焦点 {{windowFocusChanged}} 焦点窗口已更改"
|
||||
AdvSceneSwitcher.condition.window.entry.line3="当前焦点窗口: {{focusWindow}}"
|
||||
AdvSceneSwitcher.condition.file="文件"
|
||||
AdvSceneSwitcher.condition.file.type.match="内容完全匹配"
|
||||
AdvSceneSwitcher.condition.file.type.contentChange="内容已更改"
|
||||
AdvSceneSwitcher.condition.file.type.dateChange="修改日期已更改"
|
||||
AdvSceneSwitcher.condition.file.remote="远程文件"
|
||||
AdvSceneSwitcher.condition.file.local="本地文件"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="文件内容来自{{fileType}}{{filePath}}{{conditions}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.media="媒体"
|
||||
AdvSceneSwitcher.condition.media.source="源"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="任何媒体源"
|
||||
AdvSceneSwitcher.condition.media.allOnScene="所有媒体源"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="任何媒体来源"
|
||||
AdvSceneSwitcher.condition.media.allOnScene="所有媒体来源"
|
||||
AdvSceneSwitcher.condition.media.matchOnChange="仅在更改时匹配(注意:此选项将在未来版本中删除-请改用时间限制)"
|
||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="不幸的是,并非所有媒体源类型的行为都相同(例如,媒体源与VLC视频源“停止”状态)。\n所以,请尝试适合您的设置!"
|
||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}} 的状态是 {{states}} 和 {{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}的状态是{{states}}和{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.video="视频"
|
||||
AdvSceneSwitcher.condition.video.condition.match="完全匹配"
|
||||
AdvSceneSwitcher.condition.video.condition.differ="不匹配"
|
||||
AdvSceneSwitcher.condition.video.condition.hasChanged="已改变"
|
||||
AdvSceneSwitcher.condition.video.condition.hasNotChanged="未改变"
|
||||
AdvSceneSwitcher.condition.video.condition.hasChanged="改变了"
|
||||
AdvSceneSwitcher.condition.video.condition.hasNotChanged="没有改变"
|
||||
AdvSceneSwitcher.condition.video.condition.noImage="没有输出"
|
||||
AdvSceneSwitcher.condition.video.condition.pattern="匹配模式"
|
||||
AdvSceneSwitcher.condition.video.condition.object="包含对象"
|
||||
AdvSceneSwitcher.condition.video.condition.brightness="亮度"
|
||||
AdvSceneSwitcher.condition.video.condition.ocr="包含文本"
|
||||
AdvSceneSwitcher.condition.video.askFileAction="是否要使用现有文件或创建当前选定源的屏幕截图?"
|
||||
AdvSceneSwitcher.condition.video.askFileAction.file="使用现有文件"
|
||||
AdvSceneSwitcher.condition.video.askFileAction.screenshot="创建屏幕截图"
|
||||
@@ -207,49 +164,28 @@ AdvSceneSwitcher.condition.video.usePatternForChangedCheck="使用模式匹配"
|
||||
AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip="这将允许您控制图像必须更改多少才能使条件为真."
|
||||
AdvSceneSwitcher.condition.video.patternThreshold="阈值: "
|
||||
AdvSceneSwitcher.condition.video.patternThresholdDescription="较高的阈值意味着模式需要更紧密地匹配视频源."
|
||||
AdvSceneSwitcher.condition.video.patternThresholdUseAlphaAsMask="使用alpha通道作为模式的遮罩."
|
||||
AdvSceneSwitcher.condition.video.patternMatchMode="使用模式匹配方式 {{patternMatchingModes}}"
|
||||
AdvSceneSwitcher.condition.video.patternMatchMode.crossCorrelation="交叉相关"
|
||||
AdvSceneSwitcher.condition.video.patternMatchMode.correlationCoefficient="相关系数"
|
||||
AdvSceneSwitcher.condition.video.patternMatchMode.squaredDifference="平方差"
|
||||
AdvSceneSwitcher.condition.video.patternMatchMode.tip="使用的最佳方法取决于具体问题和所涉及图像的特性。\n在实践中,通常需要使用不同的方法和参数进行实验,以找到对特定用例的最佳匹配。"
|
||||
AdvSceneSwitcher.condition.video.patternThresholdUseAlphaAsMask="使用alpha通道作为图案的遮罩."
|
||||
AdvSceneSwitcher.condition.video.brightnessThreshold="平均亮度:"
|
||||
AdvSceneSwitcher.condition.video.brightnessThresholdDescription="高的值表示明亮的图像,低的值表示较暗的图像。"
|
||||
AdvSceneSwitcher.condition.video.brightnessThresholdDescription="较高的值表示图像较亮,较低的值表示图像较暗。"
|
||||
AdvSceneSwitcher.condition.video.currentBrightness="当前平均亮度: %1"
|
||||
AdvSceneSwitcher.condition.video.objectScaleThreshold="模型比例: "
|
||||
AdvSceneSwitcher.condition.video.objectScaleThresholdDescription="较低的模型比例会产生更多的匹配,但将导致CPU负载更高."
|
||||
AdvSceneSwitcher.condition.video.objectScaleThresholdDescription="较低的模比例将导致更多的匹配,但会导致更高的CPU负载."
|
||||
AdvSceneSwitcher.condition.video.minNeighborDescription="较高的“最小区域”值将导致较少但质量较高的匹配."
|
||||
AdvSceneSwitcher.condition.video.showMatch="显示模式"
|
||||
AdvSceneSwitcher.condition.video.showMatch.loading="检查是否匹配"
|
||||
AdvSceneSwitcher.condition.video.showMatch.loading="Checking for match"
|
||||
AdvSceneSwitcher.condition.video.screenshotFail="无法获取源的屏幕截图!"
|
||||
AdvSceneSwitcher.condition.video.screenshotEmpty="屏幕截图为空 - 源是否可见?"
|
||||
AdvSceneSwitcher.condition.video.screenshotEmpty="Screenshot is empty - Is the source visible?"
|
||||
AdvSceneSwitcher.condition.video.patternMatchFail="没有找到模式!"
|
||||
AdvSceneSwitcher.condition.video.patternMatchSuccess="模式以红色突出显示"
|
||||
AdvSceneSwitcher.condition.video.patternMatchSuccess="Pattern is highlighted in red"
|
||||
AdvSceneSwitcher.condition.video.objectMatchFail="找不到对象!"
|
||||
AdvSceneSwitcher.condition.video.objectMatchSuccess="对象以红色突出显示"
|
||||
AdvSceneSwitcher.condition.video.ocrMatchSuccess="检测到的文本:\n\n%1"
|
||||
AdvSceneSwitcher.condition.video.objectMatchSuccess="Object is highlighted in red"
|
||||
AdvSceneSwitcher.condition.video.modelLoadFail="无法加载模型数据!"
|
||||
AdvSceneSwitcher.condition.video.selectColor="选择颜色"
|
||||
AdvSceneSwitcher.condition.video.ocrMode.singleColumn="单列可变大小的文本"
|
||||
AdvSceneSwitcher.condition.video.ocrMode.singleBlockVertText="垂直对齐的单个统一文本块"
|
||||
AdvSceneSwitcher.condition.video.ocrMode.singleBlock="单个统一的文本块"
|
||||
AdvSceneSwitcher.condition.video.ocrMode.singleLine="单个文本行"
|
||||
AdvSceneSwitcher.condition.video.ocrMode.singleWord="单词"
|
||||
AdvSceneSwitcher.condition.video.ocrMode.circleWord="圆圈中的单个单词"
|
||||
AdvSceneSwitcher.condition.video.ocrMode.singleChar="单个字符"
|
||||
AdvSceneSwitcher.condition.video.ocrMode.sparseText="不按特定顺序查找文本"
|
||||
AdvSceneSwitcher.condition.video.ocrMode.sparseTextOSD="不按特定顺序查找文本(OSD)"
|
||||
AdvSceneSwitcher.condition.video.type.main="OBS的主输出"
|
||||
AdvSceneSwitcher.condition.video.type.source="源"
|
||||
AdvSceneSwitcher.condition.video.type.scene="场景"
|
||||
AdvSceneSwitcher.condition.video.entry="{{videoInputTypes}}{{sources}}{{scenes}}{{condition}}{{imagePath}}"
|
||||
AdvSceneSwitcher.condition.video.entry.modelPath="模型数据 (haar级联分类器): {{modelDataPath}}"
|
||||
AdvSceneSwitcher.condition.video.entry.minNeighbor="最小区域: {{minNeighbors}}"
|
||||
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}每隔一段时间检查一次,来减少CPU负载 {{throttleCount}} 毫秒"
|
||||
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}通过只执行每一次检查来减少CPU负载 {{throttleCount}} 毫秒"
|
||||
AdvSceneSwitcher.condition.video.entry.checkAreaEnable="仅在区域内执行检查"
|
||||
AdvSceneSwitcher.condition.video.entry.checkArea="{{checkAreaEnable}}{{checkArea}}{{selectArea}}"
|
||||
AdvSceneSwitcher.condition.video.entry.orcColorPick="检查文本颜色:{{textColor}}{{selectColor}}"
|
||||
AdvSceneSwitcher.condition.video.entry.orcTextType="检查文本类型:{{textType}}"
|
||||
AdvSceneSwitcher.condition.video.minSize="最小尺寸:"
|
||||
AdvSceneSwitcher.condition.video.maxSize="最大尺寸:"
|
||||
AdvSceneSwitcher.condition.video.selectArea="选择区域"
|
||||
@@ -261,25 +197,21 @@ AdvSceneSwitcher.condition.stream.state.start="推流启动"
|
||||
AdvSceneSwitcher.condition.stream.state.stop="推流停止"
|
||||
AdvSceneSwitcher.condition.stream.state.starting="推流启动中"
|
||||
AdvSceneSwitcher.condition.stream.state.stopping="推流停止中"
|
||||
AdvSceneSwitcher.condition.stream.state.keyFrameInterval="关键帧间隔等于"
|
||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
|
||||
AdvSceneSwitcher.condition.record="录制"
|
||||
AdvSceneSwitcher.condition.record.state.start="录制运行中"
|
||||
AdvSceneSwitcher.condition.record.state.pause="录制暂停"
|
||||
AdvSceneSwitcher.condition.record.state.stop="录制停止"
|
||||
AdvSceneSwitcher.condition.record.entry="{{recordState}}"
|
||||
AdvSceneSwitcher.condition.process="进程"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}} 是正在运行 {{focused}} 并且是获得焦点"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}} 是正在运行 {{focused}} 而且是获得焦点"
|
||||
AdvSceneSwitcher.condition.process.entry.focus="当前焦点进程: {{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.idle="闲置检测"
|
||||
AdvSceneSwitcher.condition.idle.entry="没有键盘或鼠标输入{{duration}}"
|
||||
AdvSceneSwitcher.condition.pluginState="插件状态"
|
||||
AdvSceneSwitcher.condition.pluginState.state.start="插件已启动"
|
||||
AdvSceneSwitcher.condition.pluginState.state.restart="插件已重新启动"
|
||||
AdvSceneSwitcher.condition.pluginState.state.running="插件正在运行"
|
||||
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="在此时间间隔内触发了自动场景更改"
|
||||
AdvSceneSwitcher.condition.pluginState.state.running="高级场景切换程序正在运行"
|
||||
AdvSceneSwitcher.condition.pluginState.state.shutdown="OBS正在关闭"
|
||||
AdvSceneSwitcher.condition.pluginState.state.sceneCollection="场景集合已加载"
|
||||
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="场景被上一个宏改变"
|
||||
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
|
||||
AdvSceneSwitcher.condition.timer="计时器"
|
||||
AdvSceneSwitcher.condition.timer.type.fixed="固定"
|
||||
@@ -304,11 +236,11 @@ AdvSceneSwitcher.condition.macro.state.type.above="大于"
|
||||
AdvSceneSwitcher.condition.macro.state.type.equal="等于"
|
||||
AdvSceneSwitcher.condition.macro.count.reset="重置"
|
||||
AdvSceneSwitcher.condition.macro.pausedWarning="所选宏当前已暂停!"
|
||||
AdvSceneSwitcher.condition.macro.state.entry="{{macros}} 的条件为真"
|
||||
AdvSceneSwitcher.condition.macro.multistate.entry=" 以下宏的 {{multiStateConditions}}{{multiStateCount}} 的条件为真:"
|
||||
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} 执行 {{conditions}} {{count}} 次(相对于下面计数匹配)"
|
||||
AdvSceneSwitcher.condition.macro.state.entry="条件 {{macros}} 运行结果为真"
|
||||
AdvSceneSwitcher.condition.macro.multistate.entry="条件 {{multiStateConditions}}{{multiStateCount}} 以下宏运行结果为真:"
|
||||
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} 运行 {{conditions}} {{count}} 次(相对于下面计数匹配)"
|
||||
AdvSceneSwitcher.condition.macro.count.entry.line2="当前计数: {{currentCount}} {{resetCount}}"
|
||||
AdvSceneSwitcher.condition.source="源"
|
||||
AdvSceneSwitcher.condition.source="来源"
|
||||
AdvSceneSwitcher.condition.source.type.active="是激活状态"
|
||||
AdvSceneSwitcher.condition.source.type.showing="是显示状态"
|
||||
AdvSceneSwitcher.condition.source.type.settings="设置完全匹配"
|
||||
@@ -325,7 +257,7 @@ AdvSceneSwitcher.condition.filter.type.active="已启用"
|
||||
AdvSceneSwitcher.condition.filter.type.showing="已关闭"
|
||||
AdvSceneSwitcher.condition.filter.type.settings="设置完全匹配"
|
||||
AdvSceneSwitcher.condition.filter.getSettings="获取当前设置"
|
||||
AdvSceneSwitcher.condition.filter.entry.line1="在 {{sources}} 的 {{filters}} 是 {{conditions}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line1="在 {{sources}} {{filters}} {{conditions}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.sceneOrder="场景项目顺序"
|
||||
@@ -357,8 +289,7 @@ AdvSceneSwitcher.condition.date.state.at="现在"
|
||||
AdvSceneSwitcher.condition.date.state.after="之后"
|
||||
AdvSceneSwitcher.condition.date.state.before="之前"
|
||||
AdvSceneSwitcher.condition.date.state.between="之间"
|
||||
AdvSceneSwitcher.condition.date.state.pattern="模式"
|
||||
AdvSceneSwitcher.condition.date.separator="到"
|
||||
AdvSceneSwitcher.condition.date.separator="和"
|
||||
AdvSceneSwitcher.condition.date.ignoreDate="如果未选中,日期组件将被忽略"
|
||||
AdvSceneSwitcher.condition.date.ignoreTime="如果未选中,时间组件将被忽略"
|
||||
AdvSceneSwitcher.condition.date.showAdvancedSettings="显示高级设置"
|
||||
@@ -366,9 +297,8 @@ AdvSceneSwitcher.condition.date.showSimpleSettings="显示简单设置"
|
||||
AdvSceneSwitcher.condition.date.entry.simple="在 {{dayOfWeek}} {{weekCondition}} {{ignoreWeekTime}}{{weekTime}}"
|
||||
AdvSceneSwitcher.condition.date.entry.advanced="{{condition}} {{ignoreDate}}{{date}} {{ignoreTime}}{{time}} {{separator}} {{date2}} {{time2}}"
|
||||
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}} 在匹配到日期时间后,每隔 {{duration}} 重复一次"
|
||||
AdvSceneSwitcher.condition.date.entry.pattern="当前日期 \"{{currentDate}}\" 匹配模式 {{pattern}}"
|
||||
AdvSceneSwitcher.condition.date.entry.nextMatchDate="下一次匹配 在: %1"
|
||||
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} 重复时,将选定的日期更新为重复日期"
|
||||
AdvSceneSwitcher.condition.date.entry.nextMatchDate="Next match at: %1"
|
||||
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} On repeat update selected date to repeat date"
|
||||
AdvSceneSwitcher.condition.sceneTransform="场景项目被改变"
|
||||
AdvSceneSwitcher.condition.sceneTransform.getTransform="内容或者设置被改变了"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line1="在 {{scenes}} {{sources}} 匹配变换"
|
||||
@@ -386,7 +316,6 @@ AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{scen
|
||||
AdvSceneSwitcher.condition.sceneVisibility="场景项目可见"
|
||||
AdvSceneSwitcher.condition.sceneVisibility.type.shown="显示的"
|
||||
AdvSceneSwitcher.condition.sceneVisibility.type.hidden="隐藏的"
|
||||
AdvSceneSwitcher.condition.sceneVisibility.type.changed="可见性已更改"
|
||||
AdvSceneSwitcher.condition.sceneVisibility.entry="在 {{scenes}} {{sources}} 是 {{conditions}} "
|
||||
AdvSceneSwitcher.condition.studioMode="工作室模式"
|
||||
AdvSceneSwitcher.condition.studioMode.state.active="工作室模式处于活动状态"
|
||||
@@ -416,7 +345,7 @@ AdvSceneSwitcher.condition.stats.condition.above="大于"
|
||||
AdvSceneSwitcher.condition.stats.condition.equals="等于"
|
||||
AdvSceneSwitcher.condition.stats.condition.below="少于"
|
||||
AdvSceneSwitcher.condition.stats.dockHint="你可以打开“统计”窗口查看当前状态"
|
||||
AdvSceneSwitcher.condition.stats.entry="{{stats}} 是 {{condition}} {{value}}"
|
||||
AdvSceneSwitcher.condition.stats.entry="{{stats}} is {{condition}} {{value}}"
|
||||
AdvSceneSwitcher.condition.profile="配置文件"
|
||||
AdvSceneSwitcher.condition.profile.entry="当前活动的配置文件为 {{profiles}}"
|
||||
AdvSceneSwitcher.condition.websocket="websocket"
|
||||
@@ -432,20 +361,7 @@ AdvSceneSwitcher.condition.variable.type.number="是一个数字"
|
||||
AdvSceneSwitcher.condition.variable.type.lessThan="小于"
|
||||
AdvSceneSwitcher.condition.variable.type.greaterThan="大于"
|
||||
AdvSceneSwitcher.condition.variable.type.valueChanged="值已更改"
|
||||
AdvSceneSwitcher.condition.variable.type.equalsVariable="等于变量"
|
||||
AdvSceneSwitcher.condition.variable.type.lessThanVariable="小于变量"
|
||||
AdvSceneSwitcher.condition.variable.type.greaterThanVariable="大于变量"
|
||||
AdvSceneSwitcher.condition.variable.entry="{{variables}}{{conditions}}{{strValue}}{{numValue}}{{variables2}}"
|
||||
AdvSceneSwitcher.condition.run="运行"
|
||||
AdvSceneSwitcher.condition.run.entry="进程在超时 {{timeout}} 秒之前退出"
|
||||
AdvSceneSwitcher.condition.run.entry.exit="{{checkExitCode}}检查退出代码{{exitCode}}"
|
||||
AdvSceneSwitcher.condition.midi="MIDI"
|
||||
AdvSceneSwitcher.condition.midi.entry="从{{device}} 收到的信息,符合:(从不咕咕的阿坤:这个好像是声卡工作是录音相关的功能,英文太抽象了,我就硬译过来了,如有相关设备,音乐好的,可以根据英文翻译好发给我!)"
|
||||
AdvSceneSwitcher.condition.midi.entry.listen="将MIDI信息选择设置为从选定设备上接收的信息: {{listenButton}}"
|
||||
AdvSceneSwitcher.condition.display="显示器"
|
||||
AdvSceneSwitcher.condition.display.type.displayName="连接的显示器的名称匹配"
|
||||
AdvSceneSwitcher.condition.display.type.displayCount="连接的显示器的数量为"
|
||||
AdvSceneSwitcher.condition.display.entry="{{conditions}}{{displays}}{{regex}}{{displayCount}}"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.switchScene="切换场景"
|
||||
@@ -462,10 +378,6 @@ AdvSceneSwitcher.action.audio.type.mute="静音"
|
||||
AdvSceneSwitcher.action.audio.type.unmute="取消静音"
|
||||
AdvSceneSwitcher.action.audio.type.sourceVolume="来源音量"
|
||||
AdvSceneSwitcher.action.audio.type.masterVolume="主音量"
|
||||
AdvSceneSwitcher.action.audio.type.syncOffset="设置同步偏移"
|
||||
AdvSceneSwitcher.action.audio.type.monitor="设置音频监听"
|
||||
AdvSceneSwitcher.action.audio.type.balance="设置平衡"
|
||||
AdvSceneSwitcher.action.audio.balance.description="选择的音频源将滑块方向移动(从不咕咕的阿坤的理解:左/右声道偏侧向)"
|
||||
AdvSceneSwitcher.action.audio.fade.type.duration="持续时间"
|
||||
AdvSceneSwitcher.action.audio.fade.type.rate="百分比"
|
||||
AdvSceneSwitcher.action.audio.fade.duration="{{fade}}淡出 {{fadeTypes}} {{duration}} 秒."
|
||||
@@ -479,44 +391,42 @@ AdvSceneSwitcher.action.recording.type.start="开始录制"
|
||||
AdvSceneSwitcher.action.recording.type.pause="暂停录制"
|
||||
AdvSceneSwitcher.action.recording.type.unpause="取消录制暂停"
|
||||
AdvSceneSwitcher.action.recording.type.split="分割录制文件"
|
||||
AdvSceneSwitcher.action.recording.type.changeOutputFolder="更改输出文件夹"
|
||||
AdvSceneSwitcher.action.recording.type.changeOutputFileFormat="改变文件名的格式"
|
||||
AdvSceneSwitcher.action.recording.pause.hint="请注意,根据您的录制设置,您可能无法暂停录制"
|
||||
AdvSceneSwitcher.action.recording.split.hint="确保先在OBS设置中启用自动分割文件!"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||
AdvSceneSwitcher.action.replay="回放缓存"
|
||||
AdvSceneSwitcher.action.replay.saveWarn="警告:保存过于频繁可能会导致回放缓存实际上未保存!"
|
||||
AdvSceneSwitcher.action.replay.type.stop="停止回放缓存"
|
||||
AdvSceneSwitcher.action.replay.type.start="启动回放缓存"
|
||||
AdvSceneSwitcher.action.replay.type.save="保存回放缓存"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
|
||||
AdvSceneSwitcher.action.replay="回放缓冲区"
|
||||
AdvSceneSwitcher.action.replay.saveWarn="警告:保存过于频繁可能会导致重播缓冲区实际上未保存!"
|
||||
AdvSceneSwitcher.action.replay.type.stop="停止回放缓冲区"
|
||||
AdvSceneSwitcher.action.replay.type.start="启动回放缓冲区"
|
||||
AdvSceneSwitcher.action.replay.type.save="保存回放缓冲区"
|
||||
AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.streaming="推流"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="停止推流"
|
||||
AdvSceneSwitcher.action.streaming.type.start="开始推流"
|
||||
AdvSceneSwitcher.action.streaming.type.keyFrameInterval="设置关键帧间隔"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.run="运行"
|
||||
AdvSceneSwitcher.action.run.arguments="参数:"
|
||||
AdvSceneSwitcher.action.run.addArgument="添加参数"
|
||||
AdvSceneSwitcher.action.run.addArgumentDescription="添加新参数:"
|
||||
AdvSceneSwitcher.action.run.entry="运行 {{filePath}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility="场景项目可见性"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.show="显示"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="隐藏"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="切换"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="来源"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="全部"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="置{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="设置{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
|
||||
AdvSceneSwitcher.action.filter="滤镜"
|
||||
AdvSceneSwitcher.action.filter.type.enable="开启"
|
||||
AdvSceneSwitcher.action.filter.type.disable="关闭"
|
||||
AdvSceneSwitcher.action.filter.type.settings="参数设置"
|
||||
AdvSceneSwitcher.action.filter.entry="置 {{sources}} {{actions}} {{filters}}"
|
||||
AdvSceneSwitcher.action.filter.entry="在 {{sources}} {{actions}} {{filters}}"
|
||||
AdvSceneSwitcher.action.filter.getSettings="获取当前设置"
|
||||
AdvSceneSwitcher.action.source="源"
|
||||
AdvSceneSwitcher.action.source="来源"
|
||||
AdvSceneSwitcher.action.source.type.enable="启用"
|
||||
AdvSceneSwitcher.action.source.type.disable="停用"
|
||||
AdvSceneSwitcher.action.source.type.settings="配置设置"
|
||||
AdvSceneSwitcher.action.source.type.refreshSettings="刷新源设置"
|
||||
AdvSceneSwitcher.action.source.type.pressSettingsButton="按下设置按钮"
|
||||
AdvSceneSwitcher.action.source.type.refreshSettings.tooltip="可用于刷新浏览器、媒体、源、etc"
|
||||
AdvSceneSwitcher.action.source.noSettingsButtons="未找到按钮!"
|
||||
AdvSceneSwitcher.action.source.type.refreshSettings.tooltip="可用于刷新浏览器、媒体等源"
|
||||
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
|
||||
AdvSceneSwitcher.action.source.warning="警告:OBS UI无法控制全局启用和禁用源,注意,通过这个设置禁用,我测试,你必须通过这个在启用才行,不然点击小眼睛你无法显示!"
|
||||
AdvSceneSwitcher.action.source.getSettings="获取当前设置"
|
||||
@@ -533,16 +443,14 @@ AdvSceneSwitcher.action.macro="宏"
|
||||
AdvSceneSwitcher.action.macro.type.pause="暂停"
|
||||
AdvSceneSwitcher.action.macro.type.unpause="取消暂停"
|
||||
AdvSceneSwitcher.action.macro.type.resetCounter="复位计数器"
|
||||
AdvSceneSwitcher.action.macro.type.run="运行操作"
|
||||
AdvSceneSwitcher.action.macro.type.stop="停止操作"
|
||||
AdvSceneSwitcher.action.macro.type.run="运行"
|
||||
AdvSceneSwitcher.action.macro.type.stop="停止"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="插件状态"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="停止高级场景切换插件"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项时:"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项:"
|
||||
AdvSceneSwitcher.action.pluginState.type.import="从设置导入"
|
||||
AdvSceneSwitcher.action.pluginState.importWarning="注意:当“设置”窗口打开时,操作将被忽略。"
|
||||
AdvSceneSwitcher.action.pluginState.type.terminate="关闭 OBS"
|
||||
AdvSceneSwitcher.action.pluginState.terminateConfirm="OBS将在10秒后自动关闭!/n你想继续关闭OBS吗?"
|
||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
|
||||
AdvSceneSwitcher.action.virtualCamera="虚拟摄像机"
|
||||
AdvSceneSwitcher.action.virtualCamera.type.stop="停止虚拟摄像机"
|
||||
@@ -559,7 +467,7 @@ AdvSceneSwitcher.action.hotkey.leftMeta="左 Meta"
|
||||
AdvSceneSwitcher.action.hotkey.rightMeta="右 Meta"
|
||||
AdvSceneSwitcher.action.hotkey.onlyOBS="仅向OBS发送按键"
|
||||
AdvSceneSwitcher.action.hotkey.disabled="无法模拟按键-功能已禁用!"
|
||||
AdvSceneSwitcher.action.hotkey.entry="按下 {{keys}} 在 {{duration}} 秒"
|
||||
AdvSceneSwitcher.action.hotkey.entry="按下 {{keys}} for {{duration}} 毫秒"
|
||||
AdvSceneSwitcher.action.sceneOrder="场景项目顺序"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="上移"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="下移"
|
||||
@@ -567,9 +475,9 @@ AdvSceneSwitcher.action.sceneOrder.type.moveTop="顶部"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="底部"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.movePosition="移动到数值位置"
|
||||
AdvSceneSwitcher.action.sceneOrder.entry="在 {{scenes}} {{actions}} {{sources}} {{position}}"
|
||||
AdvSceneSwitcher.action.sceneTransform="场景项目转换"
|
||||
AdvSceneSwitcher.action.sceneTransform.getTransform="获得转换"
|
||||
AdvSceneSwitcher.action.sceneTransform.entry="在 {{scenes}} 上转换 {{sources}}"
|
||||
AdvSceneSwitcher.action.sceneTransform="场景项目变换"
|
||||
AdvSceneSwitcher.action.sceneTransform.getTransform="得到变换"
|
||||
AdvSceneSwitcher.action.sceneTransform.entry="在 {{scenes}} 变换 {{sources}}"
|
||||
AdvSceneSwitcher.action.file="文件"
|
||||
AdvSceneSwitcher.action.file.type.write="写入"
|
||||
AdvSceneSwitcher.action.file.type.append="追加写入"
|
||||
@@ -595,13 +503,9 @@ AdvSceneSwitcher.action.timer.type.reset="重置"
|
||||
AdvSceneSwitcher.action.timer.type.setTimeRemaining="设置剩余时间"
|
||||
AdvSceneSwitcher.action.timer.entry="{{timerAction}} 定时在 {{macros}} {{duration}}"
|
||||
AdvSceneSwitcher.action.random="随机"
|
||||
AdvSceneSwitcher.action.random.allowRepeat="允许连续执行同一宏"
|
||||
AdvSceneSwitcher.action.random.entry="随机运行以下任何宏(忽略暂停的宏)"
|
||||
AdvSceneSwitcher.action.systray="系统托盘通知"
|
||||
AdvSceneSwitcher.action.systray.title="标题:"
|
||||
AdvSceneSwitcher.action.systray.message="信息:"
|
||||
AdvSceneSwitcher.action.systray.icon="图标:"
|
||||
AdvSceneSwitcher.action.systray.iconHint="留空以使用默认图标"
|
||||
AdvSceneSwitcher.action.systray.entry="显示通知: {{message}}"
|
||||
AdvSceneSwitcher.action.screenshot="截图"
|
||||
AdvSceneSwitcher.action.screenshot.save.default="默认"
|
||||
AdvSceneSwitcher.action.screenshot.save.custom="其他"
|
||||
@@ -624,56 +528,21 @@ AdvSceneSwitcher.action.sequence.continueFrom="继续所选项目"
|
||||
AdvSceneSwitcher.action.websocket="websocket"
|
||||
AdvSceneSwitcher.action.websocket.type.request="request"
|
||||
AdvSceneSwitcher.action.websocket.type.event="event"
|
||||
AdvSceneSwitcher.action.websocket.entry.request="通过{{connection}} 发送场景切换器 {{type}}"
|
||||
AdvSceneSwitcher.action.websocket.entry.request="发送场景切换器 {{type}}{{connection}}"
|
||||
AdvSceneSwitcher.action.websocket.entry.event="发送场景切换器 {{type}} 到连接的客户端"
|
||||
AdvSceneSwitcher.action.http="Http"
|
||||
AdvSceneSwitcher.action.http.setHeaders="设置头信息(SET headers)"
|
||||
AdvSceneSwitcher.action.http.headers="头信息(headers):"
|
||||
AdvSceneSwitcher.action.http.addHeader="增加头信息(ADD headers)"
|
||||
AdvSceneSwitcher.action.http.type.get="获取(GET)"
|
||||
AdvSceneSwitcher.action.http.type.post="发送(POST)"
|
||||
AdvSceneSwitcher.action.http.type.get="GET"
|
||||
AdvSceneSwitcher.action.http.type.post="POST"
|
||||
AdvSceneSwitcher.action.http.entry.line1="发送 {{method}} 到 {{url}}"
|
||||
AdvSceneSwitcher.action.http.entry.line2="超时: {{timeout}} 秒"
|
||||
AdvSceneSwitcher.action.variable="变量"
|
||||
AdvSceneSwitcher.action.variable.type.set="设置为固定值"
|
||||
AdvSceneSwitcher.action.variable.type.set="设置"
|
||||
AdvSceneSwitcher.action.variable.type.append="追加"
|
||||
AdvSceneSwitcher.action.variable.type.appendVar="追加变量"
|
||||
AdvSceneSwitcher.action.variable.type.increment="增加"
|
||||
AdvSceneSwitcher.action.variable.type.decrement="减少"
|
||||
AdvSceneSwitcher.action.variable.type.setActionValue="设置为操作值"
|
||||
AdvSceneSwitcher.action.variable.type.setConditionValue="设置为条件值"
|
||||
AdvSceneSwitcher.action.variable.type.roundToInt="取整到最近的整数"
|
||||
AdvSceneSwitcher.action.variable.type.subString="设置为当前值的子字符串"
|
||||
AdvSceneSwitcher.action.variable.type.findAndReplace="在当前值中查找并替换"
|
||||
AdvSceneSwitcher.action.variable.type.mathExpression="数学表达式"
|
||||
AdvSceneSwitcher.action.variable.mathExpression.example="( 1 + 2 * 3 ) / 4"
|
||||
AdvSceneSwitcher.action.variable.findAndReplace.find="要查找的文本"
|
||||
AdvSceneSwitcher.action.variable.findAndReplace.replace="要替换为的文本"
|
||||
AdvSceneSwitcher.action.variable.subString.begin="开始"
|
||||
AdvSceneSwitcher.action.variable.subString.all="全部"
|
||||
AdvSceneSwitcher.action.variable.invalidSelection="无效选择!"
|
||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="不支持从 %1 个操作获取变量值!"
|
||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="不支持从 %1 条件中获取变量值!"
|
||||
AdvSceneSwitcher.action.variable.currentSegmentValue="当前值:"
|
||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}"
|
||||
AdvSceneSwitcher.action.variable.entry.substringIndex="子字符串开始:{{subStringStart}} 子字符串大小:{{subStringSize}}"
|
||||
AdvSceneSwitcher.action.variable.entry.substringRegex="使用正则表达式为 {{regexMatchIdx}} 匹配的值:"
|
||||
AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{replaceStr}}"
|
||||
AdvSceneSwitcher.action.projector="投影仪"
|
||||
AdvSceneSwitcher.action.projector.type.source="源"
|
||||
AdvSceneSwitcher.action.projector.type.scene="场景"
|
||||
AdvSceneSwitcher.action.projector.type.preview="预览"
|
||||
AdvSceneSwitcher.action.projector.type.program="程序"
|
||||
AdvSceneSwitcher.action.projector.type.multiview="多视图"
|
||||
AdvSceneSwitcher.action.projector.display="显示"
|
||||
AdvSceneSwitcher.action.projector.windowed="窗口"
|
||||
AdvSceneSwitcher.action.projector.fullscreen="全屏"
|
||||
AdvSceneSwitcher.action.projector.entry="打开为{{windowTypes}} 的 {{types}}{{scenes}}{{sources}}投影"
|
||||
AdvSceneSwitcher.action.projector.entry.monitor="在 {{monitors}} 上 (从不咕咕的阿坤说:谨慎开启!)"
|
||||
AdvSceneSwitcher.action.midi="MIDI"
|
||||
AdvSceneSwitcher.action.midi.entry="发送消息到 {{device}}:"
|
||||
AdvSceneSwitcher.action.midi.entry.listen="将MIDI消息选择设置为 {{listenDevices}} 上传入的消息: {{listenButton}}"
|
||||
AdvSceneSwitcher.action.osc="打开声音控制"
|
||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}"
|
||||
|
||||
|
||||
; Transition Tab
|
||||
AdvSceneSwitcher.transitionTab.title="转场特效"
|
||||
@@ -953,7 +822,6 @@ AdvSceneSwitcher.connection.password="密码:"
|
||||
AdvSceneSwitcher.connection.reconnect="自动重新连接:"
|
||||
AdvSceneSwitcher.connection.reconnectDelay="自动重新连接延迟:"
|
||||
AdvSceneSwitcher.connection.connectOnStart="启动时自动连接:"
|
||||
AdvSceneSwitcher.connection.useOBSWebsocketProtocol="<html><head/><body><p>如何使用 obs-websocket <a href=\"https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md\"><span style=\" text-decoration: underline; color:#268bd2;\">protocol</span></a></p></body></html>"
|
||||
AdvSceneSwitcher.connection.test="测试连接"
|
||||
AdvSceneSwitcher.connection.status.disconnected="断开"
|
||||
AdvSceneSwitcher.connection.status.connecting="连接"
|
||||
@@ -967,68 +835,6 @@ AdvSceneSwitcher.regex.dotMatchNewline=". 匹配换行符"
|
||||
AdvSceneSwitcher.regex.multiLine="^ 和 $ 是匹配行的开始/结束"
|
||||
AdvSceneSwitcher.regex.extendedPattern="启用Qt的扩展模式语法"
|
||||
|
||||
AdvSceneSwitcher.process.showAdvanced="显示高级设置"
|
||||
AdvSceneSwitcher.process.arguments="参数:"
|
||||
AdvSceneSwitcher.process.addArgument="增加参数"
|
||||
AdvSceneSwitcher.process.addArgumentDescription="添加新参数:"
|
||||
AdvSceneSwitcher.process.entry="运行{{filePath}}{{advancedSettings}}"
|
||||
AdvSceneSwitcher.process.entry.workingDirectory="工作目录:{{workingDirectory}}"
|
||||
|
||||
AdvSceneSwitcher.math.expressionFail="计算表达式失败"
|
||||
|
||||
AdvSceneSwitcher.midi.deviceNamePattern="[端口 #%1] %2"
|
||||
AdvSceneSwitcher.midi.message.type="类型:"
|
||||
AdvSceneSwitcher.midi.message.type.optional="任意"
|
||||
AdvSceneSwitcher.midi.message.type.invalid="无效"
|
||||
AdvSceneSwitcher.midi.message.type.noteOff="关闭音符"
|
||||
AdvSceneSwitcher.midi.message.type.noteOn="打开音符"
|
||||
AdvSceneSwitcher.midi.message.type.polyphonicPressure="合成音压力"
|
||||
AdvSceneSwitcher.midi.message.type.controlChange="控制更改"
|
||||
AdvSceneSwitcher.midi.message.type.programChange="程序更改"
|
||||
AdvSceneSwitcher.midi.message.type.channelAftertouch="频道余音"
|
||||
AdvSceneSwitcher.midi.message.type.pitchBend="音高弯曲"
|
||||
AdvSceneSwitcher.midi.message.type.systemExclusive="系统独占"
|
||||
AdvSceneSwitcher.midi.message.type.timeCode="时间码"
|
||||
AdvSceneSwitcher.midi.message.type.songPositionPointer="歌曲位置指针"
|
||||
AdvSceneSwitcher.midi.message.type.songSelect="歌曲选择"
|
||||
AdvSceneSwitcher.midi.message.type.reserved1="保留 (1)"
|
||||
AdvSceneSwitcher.midi.message.type.reserved2="保留 (2)"
|
||||
AdvSceneSwitcher.midi.message.type.tuneRequest="调音请求"
|
||||
AdvSceneSwitcher.midi.message.type.endOfSystemExclusive="系统独占结束"
|
||||
AdvSceneSwitcher.midi.message.type.timeClock="时间时钟"
|
||||
AdvSceneSwitcher.midi.message.type.reserved3="保留 (3)"
|
||||
AdvSceneSwitcher.midi.message.type.startFile="开始文件"
|
||||
AdvSceneSwitcher.midi.message.type.continueFile="继续文件"
|
||||
AdvSceneSwitcher.midi.message.type.stopFile="停止文件"
|
||||
AdvSceneSwitcher.midi.message.type.reserved4="保留 (4)"
|
||||
AdvSceneSwitcher.midi.message.type.activeSensing="主动感应"
|
||||
AdvSceneSwitcher.midi.message.type.systemReset="系统充值"
|
||||
AdvSceneSwitcher.midi.message.type.unknown="未知"
|
||||
AdvSceneSwitcher.midi.message.channel="频道 :"
|
||||
AdvSceneSwitcher.midi.message.note="音符 / 值(1):"
|
||||
AdvSceneSwitcher.midi.message.value="值(2):"
|
||||
AdvSceneSwitcher.midi.message.placeholder="任意"
|
||||
AdvSceneSwitcher.midi.resetDevices="重新连接所有 MIDI 设备"
|
||||
AdvSceneSwitcher.midi.startListen="开始监听"
|
||||
AdvSceneSwitcher.midi.stopListen="停止监听"
|
||||
AdvSceneSwitcher.midi.startListenFail="设备正忙!\n其他设备已经在监听!"
|
||||
AdvSceneSwitcher.midi.deviceOpenFail="初始化 MIDI 设备失败!"
|
||||
|
||||
AdvSceneSwitcher.osc.network="网络"
|
||||
AdvSceneSwitcher.osc.network.protocol="协议:"
|
||||
AdvSceneSwitcher.osc.network.address="地址:"
|
||||
AdvSceneSwitcher.osc.network.port="端口:"
|
||||
AdvSceneSwitcher.osc.message="信息"
|
||||
AdvSceneSwitcher.osc.message.type.none="无"
|
||||
AdvSceneSwitcher.osc.message.type.float="浮点数哦"
|
||||
AdvSceneSwitcher.osc.message.type.int="整数"
|
||||
AdvSceneSwitcher.osc.message.type.string="字符串"
|
||||
AdvSceneSwitcher.osc.message.type.binaryBlob="二进制"
|
||||
AdvSceneSwitcher.osc.message.type.true="真"
|
||||
AdvSceneSwitcher.osc.message.type.false="假"
|
||||
AdvSceneSwitcher.osc.message.type.infinity="无限"
|
||||
AdvSceneSwitcher.osc.message.type.null="无"
|
||||
|
||||
AdvSceneSwitcher.selectScene="--选择场景--"
|
||||
AdvSceneSwitcher.selectPreviousScene="上个场景"
|
||||
AdvSceneSwitcher.selectCurrentScene="当前场景"
|
||||
@@ -1038,7 +844,7 @@ AdvSceneSwitcher.currentTransition="当前转场特效"
|
||||
AdvSceneSwitcher.anyTransition="任何转场特效"
|
||||
AdvSceneSwitcher.selectTransition="--选择转场特效--"
|
||||
AdvSceneSwitcher.selectWindow="--选择窗口--"
|
||||
AdvSceneSwitcher.selectSource="--选择源--"
|
||||
AdvSceneSwitcher.selectSource="--选择来源--"
|
||||
AdvSceneSwitcher.selectAudioSource="--选择音频源--"
|
||||
AdvSceneSwitcher.selectVideoSource="--选择视频源--"
|
||||
AdvSceneSwitcher.OBSVideoOutput="OBS的主要输出"
|
||||
@@ -1059,8 +865,8 @@ AdvSceneSwitcher.sceneItemSelection.any="任何"
|
||||
|
||||
AdvSceneSwitcher.status.active="运行中"
|
||||
AdvSceneSwitcher.status.inactive="已停止"
|
||||
AdvSceneSwitcher.running="插件正在运行"
|
||||
AdvSceneSwitcher.stopped="插件已停止"
|
||||
AdvSceneSwitcher.running="插件运行"
|
||||
AdvSceneSwitcher.stopped="插件停止"
|
||||
|
||||
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>这似乎是第一次启动高级场景切换程序.<br>请看一下 <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> 查看指南和示例列表.<br>如果有问题,在在OBS论坛插件帖子内提问 <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">thread</span></a></p></body></html>"
|
||||
|
||||
@@ -1074,8 +880,4 @@ AdvSceneSwitcher.duration.condition.none="没有时间限制"
|
||||
AdvSceneSwitcher.duration.condition.more="时间少于"
|
||||
AdvSceneSwitcher.duration.condition.equal="时间等于"
|
||||
AdvSceneSwitcher.duration.condition.less="时间大于"
|
||||
AdvSceneSwitcher.duration.condition.within="在最后"
|
||||
|
||||
AdvSceneSwitcher.audio.monitor.none="关闭监听"
|
||||
AdvSceneSwitcher.audio.monitor.monitorOnly="仅监听(输出静音)"
|
||||
AdvSceneSwitcher.audio.monitor.both="监听并输出"
|
||||
AdvSceneSwitcher.duration.condition.within="保留结果后余存"
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 13.855469 0 l -1.539063 1.4375 c -0.453125 0.421875 -0.53125 1.148438 -0.269531 1.707031 l -5.886719 5.996094 c -0.011718 0 -0.019531 0 -0.03125 0 c -0.257812 -0.128906 -0.550781 -0.183594 -0.839844 -0.148437 c -0.328124 0.046874 -0.632812 0.199218 -0.867187 0.441406 l -3.945313 3.996094 c -0.3906245 0.375 -0.5468745 0.933593 -0.4062495 1.457031 c 0.1406255 0.523437 0.5546875 0.929687 1.0820315 1.058593 c 0.527344 0.132813 1.082031 -0.03125 1.453125 -0.425781 l 3.945312 -3.996093 c 0.472657 -0.453126 0.59375 -1.15625 0.296875 -1.738282 l 5.890625 -5.964844 c 0.558594 0.25 1.273438 0.148438 1.707031 -0.289062 l 1.414063 -1.5625 z m -10.308594 0.0898438 c -0.398437 0 -0.785156 0.0937502 -1.140625 0.2187502 l 1.882812 1.878906 c 0.390626 0.382812 0.390626 1 0 1.386719 l -0.710937 0.707031 c -0.386719 0.386719 -1 0.386719 -1.390625 0 l -1.882812 -1.878906 c -0.125 0.355468 -0.2187505 0.742187 -0.2187505 1.140625 c 0 1.90625 1.5507815 3.453125 3.4609375 3.453125 c 0.402344 0 0.789063 -0.09375 1.144531 -0.21875 l 1.175782 1.171875 h 0.058593 l 2.070313 -2.0625 l -1.203125 -1.203125 c 0.125 -0.359375 0.214843 -0.742188 0.214843 -1.140625 c 0 -1.90625 -1.546874 -3.4531252 -3.460937 -3.4531252 z m 6.550781 7.8906252 l -2.070312 2.066406 c 0.011718 0.027344 0.023437 0.058594 0.03125 0.089844 l 1.144531 1.140625 c -0.125 0.355468 -0.21875 0.742187 -0.21875 1.140625 c 0 1.902343 1.550781 3.449219 3.460937 3.449219 c 0.433594 0 0.855469 -0.101563 1.238282 -0.246094 l -2.007813 -2 c -0.386719 -0.386719 -0.386719 -1.035156 0 -1.417969 l 0.679688 -0.679687 c 0.195312 -0.191407 0.457031 -0.308594 0.710937 -0.308594 s 0.515625 0.117187 0.710938 0.308594 l 1.945312 1.941406 c 0.105469 -0.328125 0.183594 -0.683594 0.183594 -1.046875 c 0 -1.90625 -1.546875 -3.453125 -3.460938 -3.453125 c -0.398437 0 -0.785156 0.09375 -1.140624 0.21875 z m 0 0" fill="#fefefe"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="#fefefe">
|
||||
<path d="m 3 1 c -1.644531 0 -3 1.355469 -3 3 v 8 c 0 1.644531 1.355469 3 3 3 h 8.882812 c 0.832032 0 1.578126 -0.402344 2.054688 -0.9375 c 0.472656 -0.53125 0.738281 -1.167969 0.910156 -1.800781 l 0.972656 -2.609375 c 0.390626 -1.449219 -0.09375 -2.652344 -0.820312 -3.167969 c -0.484375 -0.34375 -0.714844 -0.292969 -1 -0.324219 v -1.160156 c 0 -0.855469 -0.558594 -1.589844 -1.09375 -1.828125 c -0.53125 -0.238281 -1.011719 -0.167969 -1.011719 -0.167969 l 0.105469 -0.003906 h -3.585938 l -1.707031 -1.707031 c -0.1875 -0.1875 -0.441406 -0.292969 -0.707031 -0.292969 z m 0 2 h 2.585938 l 1.707031 1.707031 c 0.1875 0.1875 0.441406 0.292969 0.707031 0.292969 h 4 c 0.035156 0 0.070312 -0.003906 0.105469 -0.007812 c 0 0 0.019531 0.019531 -0.011719 0.003906 c -0.035156 -0.011719 -0.09375 -0.25 -0.09375 0.003906 v 2 c 0 0.550781 0.449219 1 1 1 c 1 0 1.046875 0.703125 0.886719 1.128906 l -0.972657 2.609375 c -0.117187 0.4375 -0.296874 0.800781 -0.472656 0.996094 c -0.175781 0.199219 -0.285156 0.265625 -0.558594 0.265625 h -8.882812 c -0.570312 0 -1 -0.429688 -1 -1 v -8 c 0 -0.570312 0.46875 -0.792969 1 -1 z m 0 0"/>
|
||||
<path d="m 7 6 l 0.042969 0.003906 c -0.914063 -0.042968 -1.75 0.390625 -2.195313 0.96875 c -0.710937 1.222656 -1.15625 2.277344 -1.800781 3.71875 c -0.171875 0.523438 0.117187 1.089844 0.640625 1.261719 c 0.527344 0.171875 1.09375 -0.117187 1.261719 -0.640625 c 0.488281 -1.011719 0.921875 -1.816406 1.339843 -2.808594 c 0.210938 -0.503906 0.703126 -0.492187 0.898438 -0.503906 h 5.8125 c 0.550781 0 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m 0 0"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg width="640" height="640" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" version="1.1">
|
||||
<defs>
|
||||
<path d="m599.62,325.49c0,151.77 -123.21,274.98 -274.98,274.98c-151.76,0 -274.97,-123.21 -274.97,-274.98c0,-151.76 123.21,-274.97 274.97,-274.97c151.77,0 274.98,123.21 274.98,274.97z" id="c3Wyq0kfYS"/>
|
||||
<mask height="689.95" id="maskanTyyngos" maskUnits="userSpaceOnUse" width="689.95" x="-20.33" y="-19.48">
|
||||
<rect fill="white" height="689.95" id="svg_1" width="689.95" x="-20.33" y="-19.48"/>
|
||||
<use fill="black" id="svg_2" xlink:href="#c3Wyq0kfYS"/>
|
||||
</mask>
|
||||
<path d="m334.97,96.07c4.54,0 8.23,3.68 8.23,8.23c0,46.94 0,179.54 0,226.48c0,4.54 -3.69,8.22 -8.23,8.22c-5.77,0 -14.88,0 -20.66,0c-4.54,0 -8.22,-3.68 -8.22,-8.22c0,-46.94 0,-179.54 0,-226.48c0,-4.55 3.68,-8.23 8.22,-8.23c5.78,0 14.89,0 20.66,0z" id="fxMeu932c"/>
|
||||
<path d="m471.96,338.21c0.01,3.1 -2.5,5.62 -5.59,5.63c-32.02,0.09 -122.45,0.37 -154.46,0.47c-3.1,0.01 -5.61,-2.49 -5.62,-5.59c-0.02,-6.3 -0.06,-19.59 -0.08,-25.89c-0.01,-3.1 2.49,-5.62 5.59,-5.63c32.01,-0.09 122.44,-0.37 154.45,-0.47c3.1,-0.01 5.62,2.5 5.63,5.59c0.02,6.3 0.06,19.59 0.08,25.89z" id="h65nGmP2BL"/>
|
||||
</defs>
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<path fill="none" fill-opacity="null" id="svg_11" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02"/>
|
||||
<ellipse cx="103.84" cy="562.04" fill="#fefefe" id="svg_3" rx="80" ry="45" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-18.699, 103.843, 562.038)"/>
|
||||
<ellipse cx="506" cy="554" fill="#fefefe" id="svg_4" rx="77" ry="45" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-18.699, 506, 554)"/>
|
||||
<rect fill="#fefefe" height="359" id="svg_7" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" stroke-width="0" width="58" x="122" y="185"/>
|
||||
<rect fill="#fefefe" height="453" id="svg_8" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="58" x="522" y="84.5"/>
|
||||
<rect fill="#fefefe" height="37" id="svg_9" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-14.1985, 351.556, 146.245)" width="463.07" x="120.02" y="127.74"/>
|
||||
<rect fill="none" fill-opacity="null" height="0" id="svg_10" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="0" x="538.25" y="107.12"/>
|
||||
<path d="m537.42,112.06l0,-67.88l17.58,67.88z" fill="#fefefe" id="svg_16" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-90, 546.203, 78.1248)"/>
|
||||
<rect fill="#fefefe" height="0" id="svg_18" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="0" x="82.12" y="287.56"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" version="1.1">
|
||||
<!-- Created with SVG-edit - https://github.com/SVG-Edit/svgedit-->
|
||||
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<text fill="#fefefe" font-family="Serif" font-size="24" id="svg_1" stroke="#fefefe" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" text-anchor="middle" transform="matrix(1.0974, 0, 0, 1.0974, -4.98544, 4.97639)" x="14" xml:space="preserve" y="13">*</text>
|
||||
<rect fill="#fefefe" height="3.3" id="svg_2" stroke="#fefefe" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="matrix(1, 0, 0, 1, 0, 0)" width="5" x="1" y="12"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 815 B |
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 13.855469 0 l -1.539063 1.4375 c -0.453125 0.421875 -0.53125 1.148438 -0.269531 1.707031 l -5.886719 5.996094 c -0.011718 0 -0.019531 0 -0.03125 0 c -0.257812 -0.128906 -0.550781 -0.183594 -0.839844 -0.148437 c -0.328124 0.046874 -0.632812 0.199218 -0.867187 0.441406 l -3.945313 3.996094 c -0.3906245 0.375 -0.5468745 0.933593 -0.4062495 1.457031 c 0.1406255 0.523437 0.5546875 0.929687 1.0820315 1.058593 c 0.527344 0.132813 1.082031 -0.03125 1.453125 -0.425781 l 3.945312 -3.996093 c 0.472657 -0.453126 0.59375 -1.15625 0.296875 -1.738282 l 5.890625 -5.964844 c 0.558594 0.25 1.273438 0.148438 1.707031 -0.289062 l 1.414063 -1.5625 z m -10.308594 0.0898438 c -0.398437 0 -0.785156 0.0937502 -1.140625 0.2187502 l 1.882812 1.878906 c 0.390626 0.382812 0.390626 1 0 1.386719 l -0.710937 0.707031 c -0.386719 0.386719 -1 0.386719 -1.390625 0 l -1.882812 -1.878906 c -0.125 0.355468 -0.2187505 0.742187 -0.2187505 1.140625 c 0 1.90625 1.5507815 3.453125 3.4609375 3.453125 c 0.402344 0 0.789063 -0.09375 1.144531 -0.21875 l 1.175782 1.171875 h 0.058593 l 2.070313 -2.0625 l -1.203125 -1.203125 c 0.125 -0.359375 0.214843 -0.742188 0.214843 -1.140625 c 0 -1.90625 -1.546874 -3.4531252 -3.460937 -3.4531252 z m 6.550781 7.8906252 l -2.070312 2.066406 c 0.011718 0.027344 0.023437 0.058594 0.03125 0.089844 l 1.144531 1.140625 c -0.125 0.355468 -0.21875 0.742187 -0.21875 1.140625 c 0 1.902343 1.550781 3.449219 3.460937 3.449219 c 0.433594 0 0.855469 -0.101563 1.238282 -0.246094 l -2.007813 -2 c -0.386719 -0.386719 -0.386719 -1.035156 0 -1.417969 l 0.679688 -0.679687 c 0.195312 -0.191407 0.457031 -0.308594 0.710937 -0.308594 s 0.515625 0.117187 0.710938 0.308594 l 1.945312 1.941406 c 0.105469 -0.328125 0.183594 -0.683594 0.183594 -1.046875 c 0 -1.90625 -1.546875 -3.453125 -3.460938 -3.453125 c -0.398437 0 -0.785156 0.09375 -1.140624 0.21875 z m 0 0" fill="#202020"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="#202020">
|
||||
<path d="m 3 1 c -1.644531 0 -3 1.355469 -3 3 v 8 c 0 1.644531 1.355469 3 3 3 h 8.882812 c 0.832032 0 1.578126 -0.402344 2.054688 -0.9375 c 0.472656 -0.53125 0.738281 -1.167969 0.910156 -1.800781 l 0.972656 -2.609375 c 0.390626 -1.449219 -0.09375 -2.652344 -0.820312 -3.167969 c -0.484375 -0.34375 -0.714844 -0.292969 -1 -0.324219 v -1.160156 c 0 -0.855469 -0.558594 -1.589844 -1.09375 -1.828125 c -0.53125 -0.238281 -1.011719 -0.167969 -1.011719 -0.167969 l 0.105469 -0.003906 h -3.585938 l -1.707031 -1.707031 c -0.1875 -0.1875 -0.441406 -0.292969 -0.707031 -0.292969 z m 0 2 h 2.585938 l 1.707031 1.707031 c 0.1875 0.1875 0.441406 0.292969 0.707031 0.292969 h 4 c 0.035156 0 0.070312 -0.003906 0.105469 -0.007812 c 0 0 0.019531 0.019531 -0.011719 0.003906 c -0.035156 -0.011719 -0.09375 -0.25 -0.09375 0.003906 v 2 c 0 0.550781 0.449219 1 1 1 c 1 0 1.046875 0.703125 0.886719 1.128906 l -0.972657 2.609375 c -0.117187 0.4375 -0.296874 0.800781 -0.472656 0.996094 c -0.175781 0.199219 -0.285156 0.265625 -0.558594 0.265625 h -8.882812 c -0.570312 0 -1 -0.429688 -1 -1 v -8 c 0 -0.570312 0.46875 -0.792969 1 -1 z m 0 0"/>
|
||||
<path d="m 7 6 l 0.042969 0.003906 c -0.914063 -0.042968 -1.75 0.390625 -2.195313 0.96875 c -0.710937 1.222656 -1.15625 2.277344 -1.800781 3.71875 c -0.171875 0.523438 0.117187 1.089844 0.640625 1.261719 c 0.527344 0.171875 1.09375 -0.117187 1.261719 -0.640625 c 0.488281 -1.011719 0.921875 -1.816406 1.339843 -2.808594 c 0.210938 -0.503906 0.703126 -0.492187 0.898438 -0.503906 h 5.8125 c 0.550781 0 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m 0 0"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg width="640" height="640" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" version="1.1">
|
||||
<defs>
|
||||
<path d="m599.62,325.49c0,151.77 -123.21,274.98 -274.98,274.98c-151.76,0 -274.97,-123.21 -274.97,-274.98c0,-151.76 123.21,-274.97 274.97,-274.97c151.77,0 274.98,123.21 274.98,274.97z" id="c3Wyq0kfYS"/>
|
||||
<mask height="689.95" id="maskanTyyngos" maskUnits="userSpaceOnUse" width="689.95" x="-20.33" y="-19.48">
|
||||
<rect fill="white" height="689.95" id="svg_1" width="689.95" x="-20.33" y="-19.48"/>
|
||||
<use fill="black" id="svg_2" xlink:href="#c3Wyq0kfYS"/>
|
||||
</mask>
|
||||
<path d="m334.97,96.07c4.54,0 8.23,3.68 8.23,8.23c0,46.94 0,179.54 0,226.48c0,4.54 -3.69,8.22 -8.23,8.22c-5.77,0 -14.88,0 -20.66,0c-4.54,0 -8.22,-3.68 -8.22,-8.22c0,-46.94 0,-179.54 0,-226.48c0,-4.55 3.68,-8.23 8.22,-8.23c5.78,0 14.89,0 20.66,0z" id="fxMeu932c"/>
|
||||
<path d="m471.96,338.21c0.01,3.1 -2.5,5.62 -5.59,5.63c-32.02,0.09 -122.45,0.37 -154.46,0.47c-3.1,0.01 -5.61,-2.49 -5.62,-5.59c-0.02,-6.3 -0.06,-19.59 -0.08,-25.89c-0.01,-3.1 2.49,-5.62 5.59,-5.63c32.01,-0.09 122.44,-0.37 154.45,-0.47c3.1,-0.01 5.62,2.5 5.63,5.59c0.02,6.3 0.06,19.59 0.08,25.89z" id="h65nGmP2BL"/>
|
||||
</defs>
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<path fill="none" fill-opacity="null" id="svg_11" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02"/>
|
||||
<ellipse cx="103.84" cy="562.04" fill="#202020" id="svg_3" rx="80" ry="45" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-18.699, 103.843, 562.038)"/>
|
||||
<ellipse cx="506" cy="554" fill="#202020" id="svg_4" rx="77" ry="45" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-18.699, 506, 554)"/>
|
||||
<rect fill="#202020" height="359" id="svg_7" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" stroke-width="0" width="58" x="122" y="185"/>
|
||||
<rect fill="#202020" height="453" id="svg_8" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="58" x="522" y="84.5"/>
|
||||
<rect fill="#202020" height="37" id="svg_9" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-14.1985, 351.556, 146.245)" width="463.07" x="120.02" y="127.74"/>
|
||||
<rect fill="none" fill-opacity="null" height="0" id="svg_10" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="0" x="538.25" y="107.12"/>
|
||||
<path d="m537.42,112.06l0,-67.88l17.58,67.88z" fill="#202020" id="svg_16" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" transform="rotate(-90, 546.203, 78.1248)"/>
|
||||
<rect fill="#202020" height="0" id="svg_18" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="0.02" width="0" x="82.12" y="287.56"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" version="1.1">
|
||||
<!-- Created with SVG-edit - https://github.com/SVG-Edit/svgedit-->
|
||||
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<text fill="#202020" font-family="Serif" font-size="24" id="svg_1" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" text-anchor="middle" transform="matrix(1.0974, 0, 0, 1.0974, -4.98544, 4.97639)" x="14" xml:space="preserve" y="13">*</text>
|
||||
<rect fill="#202020" height="3.3" id="svg_2" stroke="#202020" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="matrix(1, 0, 0, 1, 0, 0)" width="5" x="1" y="12"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 815 B |
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 640 640" width="640" height="640"><defs><path d="M599.62 325.49C599.62 477.26 476.41 600.47 324.64 600.47C172.88 600.47 49.67 477.26 49.67 325.49C49.67 173.73 172.88 50.52 324.64 50.52C476.41 50.52 599.62 173.73 599.62 325.49Z" id="c3Wyq0kfYS"></path><mask id="maskanTyyngos" x="-20.33" y="-19.48" width="689.95" height="689.95" maskUnits="userSpaceOnUse"><rect x="-20.33" y="-19.48" width="689.95" height="689.95" fill="white"></rect><use xlink:href="#c3Wyq0kfYS" opacity="1" fill="black"></use></mask><path d="M334.97 96.07C339.51 96.07 343.2 99.75 343.2 104.3C343.2 151.24 343.2 283.84 343.2 330.78C343.2 335.32 339.51 339 334.97 339C329.2 339 320.09 339 314.31 339C309.77 339 306.09 335.32 306.09 330.78C306.09 283.84 306.09 151.24 306.09 104.3C306.09 99.75 309.77 96.07 314.31 96.07C320.09 96.07 329.2 96.07 334.97 96.07Z" id="fxMeu932c"></path><path d="M471.96 338.21C471.97 341.31 469.46 343.83 466.37 343.84C434.35 343.93 343.92 344.21 311.91 344.31C308.81 344.32 306.3 341.82 306.29 338.72C306.27 332.42 306.23 319.13 306.21 312.83C306.2 309.73 308.7 307.21 311.8 307.2C343.81 307.11 434.24 306.83 466.25 306.73C469.35 306.72 471.87 309.23 471.88 312.32C471.9 318.62 471.94 331.91 471.96 338.21Z" id="h65nGmP2BL"></path></defs><g><g><g><g mask="url(#maskanTyyngos)"><use xlink:href="#c3Wyq0kfYS" opacity="1" fill-opacity="0" stroke="#202020" stroke-width="70" stroke-opacity="1"></use></g></g><g><use xlink:href="#fxMeu932c" opacity="1" fill="#202020" fill-opacity="1"></use></g><g><use xlink:href="#h65nGmP2BL" opacity="1" fill="#202020" fill-opacity="1"></use></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,2 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 640 640" width="640" height="640"><defs><path d="M599.62 325.49C599.62 477.26 476.41 600.47 324.64 600.47C172.88 600.47 49.67 477.26 49.67 325.49C49.67 173.73 172.88 50.52 324.64 50.52C476.41 50.52 599.62 173.73 599.62 325.49Z" id="c3Wyq0kfYS"></path><mask id="maskanTyyngos" x="-20.33" y="-19.48" width="689.95" height="689.95" maskUnits="userSpaceOnUse"><rect x="-20.33" y="-19.48" width="689.95" height="689.95" fill="white"></rect><use xlink:href="#c3Wyq0kfYS" opacity="1" fill="black"></use></mask><path d="M334.97 96.07C339.51 96.07 343.2 99.75 343.2 104.3C343.2 151.24 343.2 283.84 343.2 330.78C343.2 335.32 339.51 339 334.97 339C329.2 339 320.09 339 314.31 339C309.77 339 306.09 335.32 306.09 330.78C306.09 283.84 306.09 151.24 306.09 104.3C306.09 99.75 309.77 96.07 314.31 96.07C320.09 96.07 329.2 96.07 334.97 96.07Z" id="fxMeu932c"></path><path d="M471.96 338.21C471.97 341.31 469.46 343.83 466.37 343.84C434.35 343.93 343.92 344.21 311.91 344.31C308.81 344.32 306.3 341.82 306.29 338.72C306.27 332.42 306.23 319.13 306.21 312.83C306.2 309.73 308.7 307.21 311.8 307.2C343.81 307.11 434.24 306.83 466.25 306.73C469.35 306.72 471.87 309.23 471.88 312.32C471.9 318.62 471.94 331.91 471.96 338.21Z" id="h65nGmP2BL"></path></defs><g><g><g><g mask="url(#maskanTyyngos)"><use xlink:href="#c3Wyq0kfYS" opacity="1" fill-opacity="0" stroke="#fefefe" stroke-width="70" stroke-opacity="1"></use></g></g><g><use xlink:href="#fxMeu932c" opacity="1" fill="#fefefe" fill-opacity="1"></use></g><g><use xlink:href="#h65nGmP2BL" opacity="1" fill="#fefefe" fill-opacity="1"></use></g></g></g></svg>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 640 640" width="640" height="640"><defs><path d="M599.62 325.49C599.62 477.26 476.41 600.47 324.64 600.47C172.88 600.47 49.67 477.26 49.67 325.49C49.67 173.73 172.88 50.52 324.64 50.52C476.41 50.52 599.62 173.73 599.62 325.49Z" id="c3Wyq0kfYS"></path><mask id="maskanTyyngos" x="-20.33" y="-19.48" width="689.95" height="689.95" maskUnits="userSpaceOnUse"><rect x="-20.33" y="-19.48" width="689.95" height="689.95" fill="white"></rect><use xlink:href="#c3Wyq0kfYS" opacity="1" fill="black"></use></mask><path d="M334.97 96.07C339.51 96.07 343.2 99.75 343.2 104.3C343.2 151.24 343.2 283.84 343.2 330.78C343.2 335.32 339.51 339 334.97 339C329.2 339 320.09 339 314.31 339C309.77 339 306.09 335.32 306.09 330.78C306.09 283.84 306.09 151.24 306.09 104.3C306.09 99.75 309.77 96.07 314.31 96.07C320.09 96.07 329.2 96.07 334.97 96.07Z" id="fxMeu932c"></path><path d="M471.96 338.21C471.97 341.31 469.46 343.83 466.37 343.84C434.35 343.93 343.92 344.21 311.91 344.31C308.81 344.32 306.3 341.82 306.29 338.72C306.27 332.42 306.23 319.13 306.21 312.83C306.2 309.73 308.7 307.21 311.8 307.2C343.81 307.11 434.24 306.83 466.25 306.73C469.35 306.72 471.87 309.23 471.88 312.32C471.9 318.62 471.94 331.91 471.96 338.21Z" id="h65nGmP2BL"></path></defs><g><g><g><g mask="url(#maskanTyyngos)"><use xlink:href="#c3Wyq0kfYS" opacity="1" fill-opacity="0" stroke="#d2d2d2" stroke-width="70" stroke-opacity="1"></use></g></g><g><use xlink:href="#fxMeu932c" opacity="1" fill="#d2d2d2" fill-opacity="1"></use></g><g><use xlink:href="#h65nGmP2BL" opacity="1" fill="#d2d2d2" fill-opacity="1"></use></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.8 KiB |
41032
deps/exprtk/exprtk.hpp
vendored
1
deps/libremidi
vendored
@@ -256,30 +256,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_26">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="warnPluginLoadFailure">
|
||||
<property name="text">
|
||||
<string>AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_19">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_24">
|
||||
<item>
|
||||
@@ -658,7 +634,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="advss::MacroTree" name="macros">
|
||||
<widget class="MacroTree" name="macros">
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -4563,7 +4539,7 @@
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>advss::MacroTree</class>
|
||||
<class>MacroTree</class>
|
||||
<extends>QListView</extends>
|
||||
<header>macro-tree.hpp</header>
|
||||
</customwidget>
|
||||
|
||||
@@ -9,15 +9,26 @@
|
||||
#include <obs-frontend-api.h>
|
||||
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "status-control.hpp"
|
||||
#include "scene-switch-helpers.hpp"
|
||||
#include "curl-helper.hpp"
|
||||
#include "platform-funcs.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "version.h"
|
||||
|
||||
namespace advss {
|
||||
const char *obs_module_text(const char *text)
|
||||
{
|
||||
return switcher->translate(text);
|
||||
}
|
||||
|
||||
obs_module_t *obs_current_module()
|
||||
{
|
||||
return switcher->modulePtr;
|
||||
}
|
||||
|
||||
SwitcherData *switcher = nullptr;
|
||||
SwitcherData *GetSwitcher()
|
||||
{
|
||||
return switcher;
|
||||
}
|
||||
|
||||
AdvSceneSwitcher *AdvSceneSwitcher::window = nullptr;
|
||||
|
||||
@@ -29,9 +40,11 @@ AdvSceneSwitcher::AdvSceneSwitcher(QWidget *parent)
|
||||
{
|
||||
switcher->settingsWindowOpened = true;
|
||||
ui->setupUi(this);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
switcher->Prune();
|
||||
LoadUI();
|
||||
loadUI();
|
||||
}
|
||||
|
||||
AdvSceneSwitcher::~AdvSceneSwitcher()
|
||||
@@ -42,76 +55,51 @@ AdvSceneSwitcher::~AdvSceneSwitcher()
|
||||
}
|
||||
}
|
||||
|
||||
static bool translationAvailable()
|
||||
bool translationAvailable()
|
||||
{
|
||||
return !!strcmp(obs_module_text("AdvSceneSwitcher.pluginName"),
|
||||
"AdvSceneSwitcher.pluginName");
|
||||
}
|
||||
|
||||
static void DisplayMissingDependencyWarning()
|
||||
void AdvSceneSwitcher::loadUI()
|
||||
{
|
||||
if (!switcher->warnPluginLoadFailure ||
|
||||
switcher->loadFailureLibs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString failedLibsString = "<ul>";
|
||||
for (const auto &lib : switcher->loadFailureLibs) {
|
||||
failedLibsString += "<li>" + lib + "</li>";
|
||||
}
|
||||
failedLibsString += "</ul>";
|
||||
QString warning(obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage"));
|
||||
DisplayMessage(warning.arg(failedLibsString));
|
||||
}
|
||||
|
||||
static void DisplayMissingDataDirWarning()
|
||||
{
|
||||
if (translationAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString msg = "Failed to find plug-in's 'data' directory.\n"
|
||||
"Please check installation instructions!\n\n"
|
||||
"Data most likely expected at:\n\n";
|
||||
if (!translationAvailable()) {
|
||||
QString msg = "Failed to find plug-in's 'data' directory.\n"
|
||||
"Please check installation instructions!\n\n"
|
||||
"Data most likely expected at:\n\n";
|
||||
#ifdef _WIN32
|
||||
msg += QString::fromStdString(
|
||||
(std::filesystem::current_path().string()));
|
||||
msg += "/";
|
||||
msg += QString::fromStdString(
|
||||
(std::filesystem::current_path().string()));
|
||||
msg += "/";
|
||||
#endif
|
||||
msg += obs_get_module_data_path(obs_current_module());
|
||||
DisplayMessage(msg);
|
||||
}
|
||||
msg += obs_get_module_data_path(obs_current_module());
|
||||
(void)DisplayMessage(msg);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::LoadUI()
|
||||
{
|
||||
DisplayMissingDataDirWarning();
|
||||
DisplayMissingDependencyWarning();
|
||||
setupGeneralTab();
|
||||
setupTitleTab();
|
||||
setupExecutableTab();
|
||||
setupRegionTab();
|
||||
setupPauseTab();
|
||||
setupSequenceTab();
|
||||
setupTransitionsTab();
|
||||
setupIdleTab();
|
||||
setupRandomTab();
|
||||
setupMediaTab();
|
||||
setupFileTab();
|
||||
setupTimeTab();
|
||||
setupAudioTab();
|
||||
setupVideoTab();
|
||||
setupNetworkTab();
|
||||
setupSceneGroupTab();
|
||||
setupTriggerTab();
|
||||
setupMacroTab();
|
||||
|
||||
SetupGeneralTab();
|
||||
SetupTitleTab();
|
||||
SetupExecutableTab();
|
||||
SetupRegionTab();
|
||||
SetupPauseTab();
|
||||
SetupSequenceTab();
|
||||
SetupTransitionsTab();
|
||||
SetupIdleTab();
|
||||
SetupRandomTab();
|
||||
SetupMediaTab();
|
||||
SetupFileTab();
|
||||
SetupTimeTab();
|
||||
SetupAudioTab();
|
||||
SetupVideoTab();
|
||||
SetupNetworkTab();
|
||||
SetupSceneGroupTab();
|
||||
SetupTriggerTab();
|
||||
SetupMacroTab();
|
||||
|
||||
SetDeprecationWarnings();
|
||||
SetTabOrder();
|
||||
SetCurrentTab();
|
||||
RestoreWindowGeo();
|
||||
CheckFirstTimeSetup();
|
||||
setDeprecationWarnings();
|
||||
setTabOrder();
|
||||
setCurrentTab();
|
||||
restoreWindowGeo();
|
||||
checkFirstTimeSetup();
|
||||
|
||||
loading = false;
|
||||
}
|
||||
@@ -119,15 +107,13 @@ void AdvSceneSwitcher::LoadUI()
|
||||
/******************************************************************************
|
||||
* Saving and loading
|
||||
******************************************************************************/
|
||||
static void AskForBackup(obs_data_t *obj);
|
||||
|
||||
static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
||||
{
|
||||
if (saving) {
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->Prune();
|
||||
obs_data_t *obj = obs_data_create();
|
||||
switcher->SaveSettings(obj);
|
||||
switcher->saveSettings(obj);
|
||||
obs_data_set_obj(save_data, "advanced-scene-switcher", obj);
|
||||
obs_data_release(obj);
|
||||
} else {
|
||||
@@ -141,10 +127,10 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
||||
if (!obj) {
|
||||
obj = obs_data_create();
|
||||
}
|
||||
if (switcher->VersionChanged(obj, g_GIT_SHA1)) {
|
||||
if (switcher->versionChanged(obj, g_GIT_SHA1)) {
|
||||
AskForBackup(obj);
|
||||
}
|
||||
switcher->LoadSettings(obj);
|
||||
switcher->loadSettings(obj);
|
||||
obs_data_release(obj);
|
||||
switcher->m.unlock();
|
||||
|
||||
@@ -154,34 +140,6 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
||||
}
|
||||
}
|
||||
|
||||
static void AskForBackup(obs_data_t *obj)
|
||||
{
|
||||
bool backupSettings = DisplayMessage(
|
||||
obs_module_text("AdvSceneSwitcher.askBackup"), true);
|
||||
|
||||
if (!backupSettings) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString path = QFileDialog::getSaveFileName(
|
||||
nullptr,
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle"),
|
||||
GetDefaultSettingsSaveLocation(),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType"));
|
||||
if (path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_data_save_json(obj, file.fileName().toUtf8().constData());
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Main switcher thread
|
||||
******************************************************************************/
|
||||
@@ -225,7 +183,7 @@ void SwitcherData::Thread()
|
||||
}
|
||||
|
||||
vblog(LOG_INFO, "try to sleep for %ld", duration.count());
|
||||
SetWaitScene();
|
||||
setWaitScene();
|
||||
cv.wait_for(lock, duration);
|
||||
|
||||
startTime = std::chrono::high_resolution_clock::now();
|
||||
@@ -239,13 +197,13 @@ void SwitcherData::Thread()
|
||||
if (checkPause()) {
|
||||
continue;
|
||||
}
|
||||
SetPreconditions();
|
||||
match = CheckForMatch(scene, transition, linger,
|
||||
setPreconditions();
|
||||
match = checkForMatch(scene, transition, linger,
|
||||
setPrevSceneAfterLinger, macroMatch);
|
||||
if (stop) {
|
||||
break;
|
||||
}
|
||||
CheckNoMatchSwitch(match, scene, transition, sleep);
|
||||
checkNoMatchSwitch(match, scene, transition, sleep);
|
||||
checkSwitchCooldown(match);
|
||||
|
||||
if (linger) {
|
||||
@@ -253,14 +211,14 @@ void SwitcherData::Thread()
|
||||
vblog(LOG_INFO, "sleep for %ld before switching scene",
|
||||
duration.count());
|
||||
|
||||
SetWaitScene();
|
||||
setWaitScene();
|
||||
cv.wait_for(lock, duration);
|
||||
|
||||
if (stop) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (SceneChangedDuringWait()) {
|
||||
if (sceneChangedDuringWait()) {
|
||||
vblog(LOG_INFO,
|
||||
"scene was changed manually - ignoring match");
|
||||
|
||||
@@ -271,13 +229,13 @@ void SwitcherData::Thread()
|
||||
}
|
||||
}
|
||||
|
||||
ResetForNextInterval();
|
||||
ClearWebsocketMessages();
|
||||
|
||||
if (match) {
|
||||
if (macroMatch) {
|
||||
RunMacros();
|
||||
runMacros();
|
||||
} else {
|
||||
SwitchScene({scene, transition, 0});
|
||||
switchScene({scene, transition, 0});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +248,7 @@ void SwitcherData::Thread()
|
||||
blog(LOG_INFO, "stopped");
|
||||
}
|
||||
|
||||
void SwitcherData::SetPreconditions()
|
||||
void SwitcherData::setPreconditions()
|
||||
{
|
||||
// Window title
|
||||
lastTitle = currentTitle;
|
||||
@@ -318,23 +276,13 @@ void SwitcherData::SetPreconditions()
|
||||
GetForegroundProcessName(currentForegroundProcess);
|
||||
|
||||
// Cursor
|
||||
std::pair<int, int> cursorPos = GetCursorPos();
|
||||
std::pair<int, int> cursorPos = getCursorPos();
|
||||
cursorPosChanged = cursorPos.first != switcher->lastCursorPos.first ||
|
||||
cursorPos.second != switcher->lastCursorPos.second;
|
||||
lastCursorPos = GetCursorPos();
|
||||
lastCursorPos = getCursorPos();
|
||||
}
|
||||
|
||||
void SwitcherData::ResetForNextInterval()
|
||||
{
|
||||
// Core reset functions
|
||||
ClearWebsocketMessages();
|
||||
// Plugin reset functions
|
||||
for (const auto &func : resetForNextIntervalFuncs) {
|
||||
func();
|
||||
}
|
||||
}
|
||||
|
||||
bool SwitcherData::CheckForMatch(OBSWeakSource &scene,
|
||||
bool SwitcherData::checkForMatch(OBSWeakSource &scene,
|
||||
OBSWeakSource &transition, int &linger,
|
||||
bool &setPrevSceneAfterLinger,
|
||||
bool ¯oMatch)
|
||||
@@ -384,7 +332,7 @@ bool SwitcherData::CheckForMatch(OBSWeakSource &scene,
|
||||
match = checkVideoSwitch(scene, transition);
|
||||
break;
|
||||
case macro_func:
|
||||
if (CheckMacros()) {
|
||||
if (checkMacros()) {
|
||||
match = true;
|
||||
macroMatch = true;
|
||||
}
|
||||
@@ -401,20 +349,48 @@ bool SwitcherData::CheckForMatch(OBSWeakSource &scene,
|
||||
return match;
|
||||
}
|
||||
|
||||
static void ResetMacros()
|
||||
void switchScene(const sceneSwitchInfo &sceneSwitch, bool force)
|
||||
{
|
||||
for (auto &m : switcher->macros) {
|
||||
m->ResetRunCount();
|
||||
m->ResetTimers();
|
||||
if (!sceneSwitch.scene && switcher->verbose) {
|
||||
blog(LOG_INFO, "nothing to switch to");
|
||||
return;
|
||||
}
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(sceneSwitch.scene);
|
||||
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
||||
|
||||
if (source && (source != currentSource || force)) {
|
||||
transitionData currentTransitionData;
|
||||
setNextTransition(sceneSwitch, currentSource,
|
||||
currentTransitionData);
|
||||
obs_frontend_set_current_scene(source);
|
||||
if (switcher->transitionOverrideOverride) {
|
||||
restoreTransitionOverride(source,
|
||||
currentTransitionData);
|
||||
}
|
||||
|
||||
if (switcher->verbose) {
|
||||
blog(LOG_INFO, "switched scene");
|
||||
}
|
||||
|
||||
if (switcher->networkConfig.ShouldSendSceneChange()) {
|
||||
switcher->server.sendMessage(sceneSwitch);
|
||||
}
|
||||
}
|
||||
obs_source_release(currentSource);
|
||||
obs_source_release(source);
|
||||
}
|
||||
|
||||
void switchPreviewScene(const OBSWeakSource &ws)
|
||||
{
|
||||
auto source = obs_weak_source_get_source(ws);
|
||||
obs_frontend_set_current_preview_scene(source);
|
||||
obs_source_release(source);
|
||||
}
|
||||
|
||||
void SwitcherData::Start()
|
||||
{
|
||||
if (!(th && th->isRunning())) {
|
||||
ResetForNextInterval();
|
||||
ResetMacros();
|
||||
|
||||
stop = false;
|
||||
th = new SwitcherThread();
|
||||
th->start((QThread::Priority)threadPriority);
|
||||
@@ -439,6 +415,14 @@ void SwitcherData::Start()
|
||||
}
|
||||
}
|
||||
|
||||
void ResetMacros()
|
||||
{
|
||||
for (auto &m : switcher->macros) {
|
||||
m->ResetRunCount();
|
||||
m->ResetTimers();
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::Stop()
|
||||
{
|
||||
if (th && th->isRunning()) {
|
||||
@@ -452,6 +436,7 @@ void SwitcherData::Stop()
|
||||
th = nullptr;
|
||||
|
||||
writeToStatusFile("Advanced Scene Switcher stopped");
|
||||
ResetMacros();
|
||||
}
|
||||
|
||||
server.stop();
|
||||
@@ -464,13 +449,13 @@ void SwitcherData::Stop()
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::SetWaitScene()
|
||||
void SwitcherData::setWaitScene()
|
||||
{
|
||||
waitScene = obs_frontend_get_current_scene();
|
||||
obs_source_release(waitScene);
|
||||
}
|
||||
|
||||
bool SwitcherData::SceneChangedDuringWait()
|
||||
bool SwitcherData::sceneChangedDuringWait()
|
||||
{
|
||||
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
||||
if (!currentSource) {
|
||||
@@ -483,7 +468,7 @@ bool SwitcherData::SceneChangedDuringWait()
|
||||
// Relies on the fact that switcher->currentScene will only be updated on event
|
||||
// OBS_FRONTEND_EVENT_SCENE_CHANGED but obs_frontend_get_current_scene() will
|
||||
// already return the scene to be transitioned to.
|
||||
bool SwitcherData::AnySceneTransitionStarted()
|
||||
bool SwitcherData::anySceneTransitionStarted()
|
||||
{
|
||||
auto currentSceneSrouce = obs_frontend_get_current_scene();
|
||||
auto currentScene = obs_source_get_weak_source(currentSceneSrouce);
|
||||
@@ -504,13 +489,13 @@ extern "C" void FreeSceneSwitcher()
|
||||
switcher = nullptr;
|
||||
}
|
||||
|
||||
static void handleSceneChange()
|
||||
void handleSceneChange()
|
||||
{
|
||||
switcher->lastSceneChangeTime =
|
||||
std::chrono::high_resolution_clock::now();
|
||||
|
||||
// Stop waiting if scene was changed
|
||||
if (switcher->SceneChangedDuringWait()) {
|
||||
if (switcher->sceneChangedDuringWait()) {
|
||||
switcher->cv.notify_one();
|
||||
}
|
||||
|
||||
@@ -538,33 +523,31 @@ static void handleSceneChange()
|
||||
}
|
||||
}
|
||||
|
||||
static void setLiveTime()
|
||||
void setLiveTime()
|
||||
{
|
||||
switcher->liveTime = QDateTime::currentDateTime();
|
||||
}
|
||||
|
||||
static void resetLiveTime()
|
||||
void resetLiveTime()
|
||||
{
|
||||
switcher->liveTime = QDateTime();
|
||||
}
|
||||
|
||||
static void checkAutoStartRecording()
|
||||
void checkAutoStartRecording()
|
||||
{
|
||||
if (switcher->autoStartEvent == SwitcherData::AutoStart::RECORDING ||
|
||||
switcher->autoStartEvent ==
|
||||
SwitcherData::AutoStart::RECORINDG_OR_STREAMING)
|
||||
if (switcher->autoStartEvent == AutoStartEvent::RECORDING ||
|
||||
switcher->autoStartEvent == AutoStartEvent::RECORINDG_OR_STREAMING)
|
||||
switcher->Start();
|
||||
}
|
||||
|
||||
static void checkAutoStartStreaming()
|
||||
void checkAutoStartStreaming()
|
||||
{
|
||||
if (switcher->autoStartEvent == SwitcherData::AutoStart::STREAMING ||
|
||||
switcher->autoStartEvent ==
|
||||
SwitcherData::AutoStart::RECORINDG_OR_STREAMING)
|
||||
if (switcher->autoStartEvent == AutoStartEvent::STREAMING ||
|
||||
switcher->autoStartEvent == AutoStartEvent::RECORINDG_OR_STREAMING)
|
||||
switcher->Start();
|
||||
}
|
||||
|
||||
static void handlePeviewSceneChange()
|
||||
void handlePeviewSceneChange()
|
||||
{
|
||||
if (switcher->networkConfig.ShouldSendPrviewSceneChange()) {
|
||||
auto source = obs_frontend_get_current_preview_scene();
|
||||
@@ -575,45 +558,43 @@ static void handlePeviewSceneChange()
|
||||
}
|
||||
}
|
||||
|
||||
static void setReplayBufferSaved()
|
||||
void setReplayBufferSaved()
|
||||
{
|
||||
switcher->replayBufferSaved = true;
|
||||
}
|
||||
|
||||
static void setTranstionEnd()
|
||||
void setTranstionEnd()
|
||||
{
|
||||
switcher->lastTransitionEndTime =
|
||||
std::chrono::high_resolution_clock::now();
|
||||
switcher->macroTransitionCv.notify_all();
|
||||
}
|
||||
|
||||
static void setStreamStarting()
|
||||
void setStreamStarting()
|
||||
{
|
||||
switcher->lastStreamStartingTime =
|
||||
std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
static void setStreamStopping()
|
||||
void setStreamStopping()
|
||||
{
|
||||
switcher->lastStreamStoppingTime =
|
||||
std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
static void handleExit()
|
||||
void handleExit()
|
||||
{
|
||||
if (!switcher) {
|
||||
return;
|
||||
}
|
||||
switcher->obsIsShuttingDown = true;
|
||||
if (switcher->shutdownConditionCount) {
|
||||
if (switcher && switcher->obsIsShuttingDown &&
|
||||
switcher->shutdownConditionCount) {
|
||||
switcher->Stop();
|
||||
switcher->CheckMacros();
|
||||
switcher->RunMacros();
|
||||
switcher->checkMacros();
|
||||
switcher->runMacros();
|
||||
}
|
||||
FreeSceneSwitcher();
|
||||
}
|
||||
|
||||
static void handleSceneCollectionChanging()
|
||||
void handleSceneCollectionChanging()
|
||||
{
|
||||
if (switcher->settingsWindowOpened) {
|
||||
AdvSceneSwitcher::window->close();
|
||||
@@ -679,7 +660,7 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadPlugins()
|
||||
void LoadPlugins()
|
||||
{
|
||||
QFileInfo libPath(
|
||||
QString(obs_get_module_binary_path(obs_current_module())));
|
||||
@@ -703,7 +684,6 @@ static void LoadPlugins()
|
||||
blog(LOG_WARNING, "failed to load \"%s\": %s",
|
||||
file.toStdString().c_str(),
|
||||
lib->errorString().toStdString().c_str());
|
||||
switcher->loadFailureLibs << file;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -723,12 +703,14 @@ void OpenSettingsWindow()
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void InitSceneSwitcher(obs_module_t *module, translateFunc translate)
|
||||
extern "C" void InitSceneSwitcher(obs_module_t *m, translateFunc t)
|
||||
{
|
||||
blog(LOG_INFO, "version: %s", g_GIT_TAG);
|
||||
blog(LOG_INFO, "version: %s", g_GIT_SHA1);
|
||||
|
||||
switcher = new SwitcherData(module, translate);
|
||||
switcher = new SwitcherData;
|
||||
switcher->modulePtr = m;
|
||||
switcher->translate = t;
|
||||
|
||||
PlatformInit();
|
||||
LoadPlugins();
|
||||
@@ -741,5 +723,3 @@ extern "C" void InitSceneSwitcher(obs_module_t *module, translateFunc translate)
|
||||
obs_module_text("AdvSceneSwitcher.pluginName"));
|
||||
action->connect(action, &QAction::triggered, OpenSettingsWindow);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
#pragma once
|
||||
#include "macro-segment-list.hpp"
|
||||
#include "log-helper.hpp"
|
||||
#include "switcher-data-structs.hpp"
|
||||
#include "platform-funcs.hpp"
|
||||
|
||||
#include <macro-segment-list.hpp>
|
||||
#include <ui_advanced-scene-switcher.h>
|
||||
|
||||
#define blog(level, msg, ...) blog(level, "[adv-ss] " msg, ##__VA_ARGS__)
|
||||
#define vblog(level, msg, ...) \
|
||||
if (switcher->verbose) { \
|
||||
blog(level, msg, ##__VA_ARGS__); \
|
||||
}
|
||||
|
||||
class QCloseEvent;
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionEdit;
|
||||
class MacroConditionEdit;
|
||||
class Duration;
|
||||
class SequenceWidget;
|
||||
struct SceneGroup;
|
||||
|
||||
/*******************************************************************************
|
||||
* Advanced Scene Switcher window
|
||||
@@ -32,54 +33,23 @@ public:
|
||||
void reject() override;
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
void LoadUI();
|
||||
void SetShowFrames();
|
||||
void SetHideFrames();
|
||||
void clearFrames(QListWidget *list);
|
||||
|
||||
void SetTabOrder();
|
||||
void SetCurrentTab();
|
||||
void RestoreWindowGeo();
|
||||
void CheckFirstTimeSetup();
|
||||
int IgnoreWindowsFindByData(const QString &window);
|
||||
int IgnoreIdleWindowsFindByData(const QString &window);
|
||||
|
||||
/* --- Begin of general tab section --- */
|
||||
public:
|
||||
void SetupGeneralTab();
|
||||
void UpdateNonMatchingScene(const QString &name);
|
||||
void SetDeprecationWarnings();
|
||||
void OpenSequenceExtendEdit(SequenceWidget *sw);
|
||||
void SetEditSceneGroup(SceneGroup &sg);
|
||||
|
||||
public slots:
|
||||
void on_noMatchDontSwitch_clicked();
|
||||
void on_noMatchSwitch_clicked();
|
||||
void on_noMatchRandomSwitch_clicked();
|
||||
void NoMatchDelayDurationChanged(const Duration &);
|
||||
void CooldownDurationChanged(const Duration &);
|
||||
void on_startupBehavior_currentIndexChanged(int index);
|
||||
void on_autoStartEvent_currentIndexChanged(int index);
|
||||
void on_noMatchSwitchScene_currentTextChanged(const QString &text);
|
||||
void on_checkInterval_valueChanged(int value);
|
||||
void on_tabMoved(int from, int to);
|
||||
void on_tabWidget_currentChanged(int index);
|
||||
void on_exportSettings_clicked();
|
||||
void on_importSettings_clicked();
|
||||
void on_verboseLogging_stateChanged(int state);
|
||||
void on_saveWindowGeo_stateChanged(int state);
|
||||
void on_showTrayNotifications_stateChanged(int state);
|
||||
void on_uiHintsDisable_stateChanged(int state);
|
||||
void on_warnPluginLoadFailure_stateChanged(int state);
|
||||
void on_hideLegacyTabs_stateChanged(int state);
|
||||
void on_priorityUp_clicked();
|
||||
void on_priorityDown_clicked();
|
||||
void on_threadPriority_currentTextChanged(const QString &text);
|
||||
|
||||
/* --- End of legacy tab section --- */
|
||||
|
||||
/* --- Begin of macro tab section --- */
|
||||
public:
|
||||
void SetupMacroTab();
|
||||
bool AddNewMacro(std::shared_ptr<Macro> &res, std::string &name,
|
||||
bool addNewMacro(std::shared_ptr<Macro> &res, std::string &name,
|
||||
std::string format = "");
|
||||
void RemoveMacro(std::shared_ptr<Macro> &);
|
||||
void RenameMacro(std::shared_ptr<Macro> &, const QString &name);
|
||||
std::shared_ptr<Macro> GetSelectedMacro();
|
||||
std::vector<std::shared_ptr<Macro>> GetSelectedMacros();
|
||||
std::shared_ptr<Macro> getSelectedMacro();
|
||||
std::vector<std::shared_ptr<Macro>> getSelectedMacros();
|
||||
void SetEditMacro(Macro &m);
|
||||
void SetMacroEditAreaDisabled(bool);
|
||||
void HighlightAction(int idx, QColor color = QColor(Qt::green));
|
||||
@@ -91,7 +61,68 @@ public:
|
||||
void SwapActions(Macro *m, int pos1, int pos2);
|
||||
void SwapConditions(Macro *m, int pos1, int pos2);
|
||||
|
||||
void loadUI();
|
||||
void setupGeneralTab();
|
||||
void setupTitleTab();
|
||||
void setupExecutableTab();
|
||||
void setupRegionTab();
|
||||
void setupPauseTab();
|
||||
void setupSequenceTab();
|
||||
void setupTransitionsTab();
|
||||
void setupIdleTab();
|
||||
void setupRandomTab();
|
||||
void setupMediaTab();
|
||||
void setupFileTab();
|
||||
void setupTimeTab();
|
||||
void setupAudioTab();
|
||||
void setupSceneGroupTab();
|
||||
void setupTriggerTab();
|
||||
void setupVideoTab();
|
||||
void setupNetworkTab();
|
||||
void setupMacroTab();
|
||||
void setDeprecationWarnings();
|
||||
void setTabOrder();
|
||||
void setCurrentTab();
|
||||
void restoreWindowGeo();
|
||||
void checkFirstTimeSetup();
|
||||
|
||||
signals:
|
||||
void MacroAdded(const QString &name);
|
||||
void MacroRemoved(const QString &name);
|
||||
void MacroRenamed(const QString &oldName, const QString &newName);
|
||||
void MacroSegmentOrderChanged();
|
||||
void HighlightMacrosChanged(bool value);
|
||||
void HighlightActionsChanged(bool value);
|
||||
void HighlightConditionsChanged(bool value);
|
||||
void SceneGroupAdded(const QString &name);
|
||||
void SceneGroupRemoved(const QString &name);
|
||||
void SceneGroupRenamed(const QString &oldName, const QString newName);
|
||||
void ConnectionAdded(const QString &);
|
||||
void ConnectionRenamed(const QString &oldName, const QString &newName);
|
||||
void ConnectionRemoved(const QString &);
|
||||
void VariableAdded(const QString &);
|
||||
void VariableRenamed(const QString &oldName, const QString &newName);
|
||||
void VariableRemoved(const QString &);
|
||||
|
||||
public slots:
|
||||
void on_windowUp_clicked();
|
||||
void on_windowDown_clicked();
|
||||
void on_windowAdd_clicked();
|
||||
void on_windowRemove_clicked();
|
||||
void on_noMatchDontSwitch_clicked();
|
||||
void on_noMatchSwitch_clicked();
|
||||
void on_noMatchRandomSwitch_clicked();
|
||||
void NoMatchDelayDurationChanged(double);
|
||||
void NoMatchDelayUnitChanged(DurationUnit);
|
||||
void CooldownDurationChanged(double);
|
||||
void CooldownUnitChanged(DurationUnit);
|
||||
void on_startupBehavior_currentIndexChanged(int index);
|
||||
void on_autoStartEvent_currentIndexChanged(int index);
|
||||
void on_noMatchSwitchScene_currentTextChanged(const QString &text);
|
||||
void on_checkInterval_valueChanged(int value);
|
||||
void on_tabMoved(int from, int to);
|
||||
void on_tabWidget_currentChanged(int index);
|
||||
|
||||
void on_macroAdd_clicked();
|
||||
void on_macroRemove_clicked();
|
||||
void on_macroUp_clicked();
|
||||
@@ -144,21 +175,135 @@ public slots:
|
||||
void HighlightOnChange();
|
||||
void on_macroProperties_clicked();
|
||||
|
||||
signals:
|
||||
void MacroAdded(const QString &name);
|
||||
void MacroRemoved(const QString &name);
|
||||
void MacroRenamed(const QString &oldName, const QString &newName);
|
||||
void MacroSegmentOrderChanged();
|
||||
void HighlightMacrosChanged(bool value);
|
||||
void HighlightActionsChanged(bool value);
|
||||
void HighlightConditionsChanged(bool value);
|
||||
void on_screenRegionSwitches_currentRowChanged(int idx);
|
||||
void on_showFrame_clicked();
|
||||
void on_screenRegionAdd_clicked();
|
||||
void on_screenRegionRemove_clicked();
|
||||
void on_screenRegionUp_clicked();
|
||||
void on_screenRegionDown_clicked();
|
||||
|
||||
void ConnectionAdded(const QString &);
|
||||
void ConnectionRenamed(const QString &oldName, const QString &newName);
|
||||
void ConnectionRemoved(const QString &);
|
||||
void VariableAdded(const QString &);
|
||||
void VariableRenamed(const QString &oldName, const QString &newName);
|
||||
void VariableRemoved(const QString &);
|
||||
void on_pauseUp_clicked();
|
||||
void on_pauseDown_clicked();
|
||||
void on_pauseAdd_clicked();
|
||||
void on_pauseRemove_clicked();
|
||||
|
||||
void on_ignoreWindows_currentRowChanged(int idx);
|
||||
void on_ignoreWindowsAdd_clicked();
|
||||
void on_ignoreWindowsRemove_clicked();
|
||||
|
||||
void on_sceneSequenceAdd_clicked();
|
||||
void on_sceneSequenceRemove_clicked();
|
||||
void on_sceneSequenceUp_clicked();
|
||||
void on_sceneSequenceDown_clicked();
|
||||
void on_sceneSequenceSave_clicked();
|
||||
void on_sceneSequenceLoad_clicked();
|
||||
void on_sequenceEdit_clicked();
|
||||
void on_sceneSequenceSwitches_itemDoubleClicked(QListWidgetItem *item);
|
||||
|
||||
void on_verboseLogging_stateChanged(int state);
|
||||
void on_saveWindowGeo_stateChanged(int state);
|
||||
void on_showTrayNotifications_stateChanged(int state);
|
||||
void on_uiHintsDisable_stateChanged(int state);
|
||||
void on_hideLegacyTabs_stateChanged(int state);
|
||||
|
||||
void on_exportSettings_clicked();
|
||||
void on_importSettings_clicked();
|
||||
|
||||
void on_transitionsAdd_clicked();
|
||||
void on_transitionsRemove_clicked();
|
||||
void on_transitionsUp_clicked();
|
||||
void on_transitionsDown_clicked();
|
||||
void on_defaultTransitionsAdd_clicked();
|
||||
void on_defaultTransitionsRemove_clicked();
|
||||
void on_defaultTransitionsUp_clicked();
|
||||
void on_defaultTransitionsDown_clicked();
|
||||
void on_transitionOverridecheckBox_stateChanged(int state);
|
||||
void on_adjustActiveTransitionType_stateChanged(int state);
|
||||
void defTransitionDelayValueChanged(int value);
|
||||
|
||||
void on_browseButton_clicked();
|
||||
void on_readFileCheckBox_stateChanged(int state);
|
||||
void on_readPathLineEdit_textChanged(const QString &text);
|
||||
void on_writePathLineEdit_textChanged(const QString &text);
|
||||
void on_browseButton_2_clicked();
|
||||
|
||||
void on_executableUp_clicked();
|
||||
void on_executableDown_clicked();
|
||||
void on_executableAdd_clicked();
|
||||
void on_executableRemove_clicked();
|
||||
|
||||
void on_idleCheckBox_stateChanged(int state);
|
||||
void on_ignoreIdleWindows_currentRowChanged(int idx);
|
||||
void on_ignoreIdleAdd_clicked();
|
||||
void on_ignoreIdleRemove_clicked();
|
||||
|
||||
void on_randomAdd_clicked();
|
||||
void on_randomRemove_clicked();
|
||||
|
||||
void on_fileAdd_clicked();
|
||||
void on_fileRemove_clicked();
|
||||
void on_fileSwitches_currentRowChanged(int idx);
|
||||
void on_fileUp_clicked();
|
||||
void on_fileDown_clicked();
|
||||
|
||||
void on_mediaAdd_clicked();
|
||||
void on_mediaRemove_clicked();
|
||||
void on_mediaUp_clicked();
|
||||
void on_mediaDown_clicked();
|
||||
|
||||
void on_timeAdd_clicked();
|
||||
void on_timeRemove_clicked();
|
||||
void on_timeUp_clicked();
|
||||
void on_timeDown_clicked();
|
||||
|
||||
void on_audioAdd_clicked();
|
||||
void on_audioRemove_clicked();
|
||||
void on_audioUp_clicked();
|
||||
void on_audioDown_clicked();
|
||||
void on_audioFallback_toggled(bool on);
|
||||
|
||||
void on_videoAdd_clicked();
|
||||
void on_videoRemove_clicked();
|
||||
void on_videoUp_clicked();
|
||||
void on_videoDown_clicked();
|
||||
void on_getScreenshot_clicked();
|
||||
|
||||
void on_serverSettings_toggled(bool on);
|
||||
void on_serverPort_valueChanged(int value);
|
||||
void on_lockToIPv4_stateChanged(int state);
|
||||
void on_serverRestart_clicked();
|
||||
void updateServerStatus();
|
||||
void on_clientSettings_toggled(bool on);
|
||||
void on_clientHostname_textChanged(const QString &text);
|
||||
void on_clientPort_valueChanged(int value);
|
||||
void on_sendSceneChange_stateChanged(int state);
|
||||
void on_restrictSend_stateChanged(int state);
|
||||
void on_sendPreview_stateChanged(int state);
|
||||
void on_clientReconnect_clicked();
|
||||
void updateClientStatus();
|
||||
|
||||
void on_sceneGroupAdd_clicked();
|
||||
void on_sceneGroupRemove_clicked();
|
||||
void on_sceneGroupUp_clicked();
|
||||
void on_sceneGroupDown_clicked();
|
||||
void on_sceneGroupName_editingFinished();
|
||||
void on_sceneGroups_currentRowChanged(int idx);
|
||||
|
||||
void on_sceneGroupSceneAdd_clicked();
|
||||
void on_sceneGroupSceneRemove_clicked();
|
||||
void on_sceneGroupSceneUp_clicked();
|
||||
void on_sceneGroupSceneDown_clicked();
|
||||
|
||||
void on_triggerAdd_clicked();
|
||||
void on_triggerRemove_clicked();
|
||||
void on_triggerUp_clicked();
|
||||
void on_triggerDown_clicked();
|
||||
|
||||
void on_priorityUp_clicked();
|
||||
void on_priorityDown_clicked();
|
||||
void on_threadPriority_currentTextChanged(const QString &text);
|
||||
|
||||
void updateScreenRegionCursorPos();
|
||||
|
||||
private:
|
||||
bool MacroTabIsInFocus();
|
||||
@@ -173,209 +318,29 @@ private:
|
||||
MacroSection lastInteracted = MacroSection::CONDITIONS;
|
||||
int currentConditionIdx = -1;
|
||||
int currentActionIdx = -1;
|
||||
|
||||
/* --- End of macro tab section --- */
|
||||
|
||||
/* --- Begin of legacy tab section --- */
|
||||
public:
|
||||
void ClearFrames(QListWidget *list);
|
||||
int IgnoreWindowsFindByData(const QString &window);
|
||||
int IgnoreIdleWindowsFindByData(const QString &window);
|
||||
void OpenSequenceExtendEdit(SequenceWidget *sw);
|
||||
|
||||
// Window tab
|
||||
public:
|
||||
void SetupTitleTab();
|
||||
public slots:
|
||||
void on_windowUp_clicked();
|
||||
void on_windowDown_clicked();
|
||||
void on_windowAdd_clicked();
|
||||
void on_windowRemove_clicked();
|
||||
void on_ignoreWindows_currentRowChanged(int idx);
|
||||
void on_ignoreWindowsAdd_clicked();
|
||||
void on_ignoreWindowsRemove_clicked();
|
||||
|
||||
// Screen region tab
|
||||
public:
|
||||
void SetupRegionTab();
|
||||
public slots:
|
||||
void SetShowFrames();
|
||||
void SetHideFrames();
|
||||
void on_screenRegionSwitches_currentRowChanged(int idx);
|
||||
void on_showFrame_clicked();
|
||||
void on_screenRegionAdd_clicked();
|
||||
void on_screenRegionRemove_clicked();
|
||||
void on_screenRegionUp_clicked();
|
||||
void on_screenRegionDown_clicked();
|
||||
void updateScreenRegionCursorPos();
|
||||
|
||||
// Pause tab
|
||||
public:
|
||||
void SetupPauseTab();
|
||||
public slots:
|
||||
void on_pauseUp_clicked();
|
||||
void on_pauseDown_clicked();
|
||||
void on_pauseAdd_clicked();
|
||||
void on_pauseRemove_clicked();
|
||||
|
||||
// Sequence tab
|
||||
public:
|
||||
void SetupSequenceTab();
|
||||
public slots:
|
||||
void on_sceneSequenceAdd_clicked();
|
||||
void on_sceneSequenceRemove_clicked();
|
||||
void on_sceneSequenceUp_clicked();
|
||||
void on_sceneSequenceDown_clicked();
|
||||
void on_sceneSequenceSave_clicked();
|
||||
void on_sceneSequenceLoad_clicked();
|
||||
void on_sequenceEdit_clicked();
|
||||
void on_sceneSequenceSwitches_itemDoubleClicked(QListWidgetItem *item);
|
||||
|
||||
// Transition tab
|
||||
public:
|
||||
void SetupTransitionsTab();
|
||||
public slots:
|
||||
void on_transitionsAdd_clicked();
|
||||
void on_transitionsRemove_clicked();
|
||||
void on_transitionsUp_clicked();
|
||||
void on_transitionsDown_clicked();
|
||||
void on_defaultTransitionsAdd_clicked();
|
||||
void on_defaultTransitionsRemove_clicked();
|
||||
void on_defaultTransitionsUp_clicked();
|
||||
void on_defaultTransitionsDown_clicked();
|
||||
void on_transitionOverridecheckBox_stateChanged(int state);
|
||||
void on_adjustActiveTransitionType_stateChanged(int state);
|
||||
void DefTransitionDelayValueChanged(int value);
|
||||
|
||||
// Executable tab
|
||||
public:
|
||||
void SetupExecutableTab();
|
||||
public slots:
|
||||
void on_executableUp_clicked();
|
||||
void on_executableDown_clicked();
|
||||
void on_executableAdd_clicked();
|
||||
void on_executableRemove_clicked();
|
||||
|
||||
// Idle tab
|
||||
public:
|
||||
void SetupIdleTab();
|
||||
public slots:
|
||||
void on_idleCheckBox_stateChanged(int state);
|
||||
void on_ignoreIdleWindows_currentRowChanged(int idx);
|
||||
void on_ignoreIdleAdd_clicked();
|
||||
void on_ignoreIdleRemove_clicked();
|
||||
|
||||
// Random tab
|
||||
public:
|
||||
void SetupRandomTab();
|
||||
public slots:
|
||||
void on_randomAdd_clicked();
|
||||
void on_randomRemove_clicked();
|
||||
|
||||
// File tab
|
||||
public:
|
||||
void SetupFileTab();
|
||||
public slots:
|
||||
void on_fileAdd_clicked();
|
||||
void on_fileRemove_clicked();
|
||||
void on_fileSwitches_currentRowChanged(int idx);
|
||||
void on_fileUp_clicked();
|
||||
void on_fileDown_clicked();
|
||||
void on_browseButton_clicked();
|
||||
void on_readFileCheckBox_stateChanged(int state);
|
||||
void on_readPathLineEdit_textChanged(const QString &text);
|
||||
void on_writePathLineEdit_textChanged(const QString &text);
|
||||
void on_browseButton_2_clicked();
|
||||
|
||||
// Media tab
|
||||
public:
|
||||
void SetupMediaTab();
|
||||
public slots:
|
||||
void on_mediaAdd_clicked();
|
||||
void on_mediaRemove_clicked();
|
||||
void on_mediaUp_clicked();
|
||||
void on_mediaDown_clicked();
|
||||
|
||||
// Time tab
|
||||
public:
|
||||
void SetupTimeTab();
|
||||
public slots:
|
||||
void on_timeAdd_clicked();
|
||||
void on_timeRemove_clicked();
|
||||
void on_timeUp_clicked();
|
||||
void on_timeDown_clicked();
|
||||
|
||||
// Video tab
|
||||
public:
|
||||
void SetupAudioTab();
|
||||
public slots:
|
||||
void on_audioAdd_clicked();
|
||||
void on_audioRemove_clicked();
|
||||
void on_audioUp_clicked();
|
||||
void on_audioDown_clicked();
|
||||
void on_audioFallback_toggled(bool on);
|
||||
|
||||
// Video tab
|
||||
public:
|
||||
void SetupVideoTab();
|
||||
public slots:
|
||||
void on_videoAdd_clicked();
|
||||
void on_videoRemove_clicked();
|
||||
void on_videoUp_clicked();
|
||||
void on_videoDown_clicked();
|
||||
void on_getScreenshot_clicked();
|
||||
|
||||
// Scene group tab
|
||||
public:
|
||||
void SetupNetworkTab();
|
||||
public slots:
|
||||
void on_serverSettings_toggled(bool on);
|
||||
void on_serverPort_valueChanged(int value);
|
||||
void on_lockToIPv4_stateChanged(int state);
|
||||
void on_serverRestart_clicked();
|
||||
void UpdateServerStatus();
|
||||
void on_clientSettings_toggled(bool on);
|
||||
void on_clientHostname_textChanged(const QString &text);
|
||||
void on_clientPort_valueChanged(int value);
|
||||
void on_sendSceneChange_stateChanged(int state);
|
||||
void on_restrictSend_stateChanged(int state);
|
||||
void on_sendPreview_stateChanged(int state);
|
||||
void on_clientReconnect_clicked();
|
||||
void UpdateClientStatus();
|
||||
|
||||
// Scene group tab
|
||||
public:
|
||||
void SetupSceneGroupTab();
|
||||
void SetEditSceneGroup(SceneGroup &sg);
|
||||
public slots:
|
||||
void on_sceneGroupAdd_clicked();
|
||||
void on_sceneGroupRemove_clicked();
|
||||
void on_sceneGroupUp_clicked();
|
||||
void on_sceneGroupDown_clicked();
|
||||
void on_sceneGroupName_editingFinished();
|
||||
void on_sceneGroups_currentRowChanged(int idx);
|
||||
void on_sceneGroupSceneAdd_clicked();
|
||||
void on_sceneGroupSceneRemove_clicked();
|
||||
void on_sceneGroupSceneUp_clicked();
|
||||
void on_sceneGroupSceneDown_clicked();
|
||||
|
||||
signals:
|
||||
void SceneGroupAdded(const QString &name);
|
||||
void SceneGroupRemoved(const QString &name);
|
||||
void SceneGroupRenamed(const QString &oldName, const QString newName);
|
||||
|
||||
// Trigger tab
|
||||
public:
|
||||
void SetupTriggerTab();
|
||||
public slots:
|
||||
void on_triggerAdd_clicked();
|
||||
void on_triggerRemove_clicked();
|
||||
void on_triggerUp_clicked();
|
||||
void on_triggerDown_clicked();
|
||||
|
||||
/* --- End of legacy tab section --- */
|
||||
};
|
||||
|
||||
void OpenSettingsWindow();
|
||||
|
||||
} // namespace advss
|
||||
/******************************************************************************
|
||||
* Sceneswitch helper
|
||||
******************************************************************************/
|
||||
void setNextTransition(const sceneSwitchInfo &ssi, obs_source_t *currentSource,
|
||||
transitionData &td);
|
||||
void overwriteTransitionOverride(const sceneSwitchInfo &ssi,
|
||||
transitionData &td);
|
||||
void restoreTransitionOverride(obs_source_t *scene, const transitionData &td);
|
||||
void switchScene(const sceneSwitchInfo &ssi, bool force = false);
|
||||
void switchPreviewScene(const OBSWeakSource &ws);
|
||||
|
||||
/******************************************************************************
|
||||
* Settings helper
|
||||
******************************************************************************/
|
||||
void AskForBackup(obs_data_t *obj);
|
||||
|
||||
/******************************************************************************
|
||||
* Main SwitcherData
|
||||
******************************************************************************/
|
||||
struct SwitcherData;
|
||||
extern SwitcherData *switcher;
|
||||
SwitcherData *GetSwitcher();
|
||||
|
||||
439
src/general.cpp
@@ -1,13 +1,11 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "status-control.hpp"
|
||||
#include "file-selection.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "version.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
namespace advss {
|
||||
#include <QStandardPaths>
|
||||
|
||||
void AdvSceneSwitcher::reject()
|
||||
{
|
||||
@@ -32,7 +30,7 @@ void AdvSceneSwitcher::on_noMatchDontSwitch_clicked()
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->switchIfNotMatching = SwitcherData::NoMatch::NO_SWITCH;
|
||||
switcher->switchIfNotMatching = NO_SWITCH;
|
||||
ui->noMatchSwitchScene->setEnabled(false);
|
||||
ui->randomDisabledWarning->setVisible(true);
|
||||
}
|
||||
@@ -44,7 +42,7 @@ void AdvSceneSwitcher::on_noMatchSwitch_clicked()
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->switchIfNotMatching = SwitcherData::NoMatch::SWITCH;
|
||||
switcher->switchIfNotMatching = SWITCH;
|
||||
ui->noMatchSwitchScene->setEnabled(true);
|
||||
UpdateNonMatchingScene(ui->noMatchSwitchScene->currentText());
|
||||
ui->randomDisabledWarning->setVisible(true);
|
||||
@@ -57,29 +55,49 @@ void AdvSceneSwitcher::on_noMatchRandomSwitch_clicked()
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->switchIfNotMatching = SwitcherData::NoMatch::RANDOM_SWITCH;
|
||||
switcher->switchIfNotMatching = RANDOM_SWITCH;
|
||||
ui->noMatchSwitchScene->setEnabled(false);
|
||||
ui->randomDisabledWarning->setVisible(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::NoMatchDelayDurationChanged(const Duration &dur)
|
||||
void AdvSceneSwitcher::NoMatchDelayDurationChanged(double sec)
|
||||
{
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->noMatchDelay = dur;
|
||||
switcher->noMatchDelay.seconds = sec;
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CooldownDurationChanged(const Duration &dur)
|
||||
void AdvSceneSwitcher::NoMatchDelayUnitChanged(DurationUnit unit)
|
||||
{
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->cooldown = dur;
|
||||
switcher->noMatchDelay.displayUnit = unit;
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CooldownDurationChanged(double sec)
|
||||
{
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->cooldown.seconds = sec;
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CooldownUnitChanged(DurationUnit unit)
|
||||
{
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->cooldown.displayUnit = unit;
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_startupBehavior_currentIndexChanged(int index)
|
||||
@@ -89,8 +107,7 @@ void AdvSceneSwitcher::on_startupBehavior_currentIndexChanged(int index)
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->startupBehavior =
|
||||
static_cast<SwitcherData::StartupBehavior>(index);
|
||||
switcher->startupBehavior = (StartupBehavior)index;
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_autoStartEvent_currentIndexChanged(int index)
|
||||
@@ -100,7 +117,7 @@ void AdvSceneSwitcher::on_autoStartEvent_currentIndexChanged(int index)
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->autoStartEvent = static_cast<SwitcherData::AutoStart>(index);
|
||||
switcher->autoStartEvent = static_cast<AutoStartEvent>(index);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_noMatchSwitchScene_currentTextChanged(
|
||||
@@ -175,16 +192,7 @@ void AdvSceneSwitcher::on_uiHintsDisable_stateChanged(int state)
|
||||
switcher->disableHints = state;
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_warnPluginLoadFailure_stateChanged(int state)
|
||||
{
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
switcher->warnPluginLoadFailure = state;
|
||||
}
|
||||
|
||||
static bool isLegacyTab(const QString &name)
|
||||
bool isLegacyTab(const QString &name)
|
||||
{
|
||||
return name == obs_module_text(
|
||||
"AdvSceneSwitcher.sceneGroupTab.title") ||
|
||||
@@ -229,7 +237,7 @@ void AdvSceneSwitcher::on_hideLegacyTabs_stateChanged(int state)
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetDeprecationWarnings()
|
||||
void AdvSceneSwitcher::setDeprecationWarnings()
|
||||
{
|
||||
QString toolTip =
|
||||
switcher->disableHints
|
||||
@@ -243,13 +251,70 @@ void AdvSceneSwitcher::SetDeprecationWarnings()
|
||||
}
|
||||
}
|
||||
|
||||
QString getDefaultSaveLocation()
|
||||
{
|
||||
QString desktopPath = QStandardPaths::writableLocation(
|
||||
QStandardPaths::DesktopLocation);
|
||||
|
||||
auto scName = obs_frontend_get_current_scene_collection();
|
||||
QString sceneCollectionName(scName);
|
||||
bfree(scName);
|
||||
|
||||
auto timestamp = QDateTime::currentDateTime();
|
||||
auto path = desktopPath + "/adv-ss-" + sceneCollectionName + "-" +
|
||||
timestamp.toString("yyyy.MM.dd.hh.mm.ss");
|
||||
|
||||
// Check if scene collection name contains invalid path characters
|
||||
QFile file(path);
|
||||
if (file.exists()) {
|
||||
return path;
|
||||
}
|
||||
|
||||
bool validPath = file.open(QIODevice::WriteOnly);
|
||||
if (validPath) {
|
||||
file.remove();
|
||||
return path;
|
||||
}
|
||||
|
||||
return desktopPath + "/adv-ss-" +
|
||||
timestamp.toString("yyyy.MM.dd.hh.mm.ss");
|
||||
}
|
||||
|
||||
void AskForBackup(obs_data_t *obj)
|
||||
{
|
||||
bool backupSettings = DisplayMessage(
|
||||
obs_module_text("AdvSceneSwitcher.askBackup"), true);
|
||||
|
||||
if (!backupSettings) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString path = QFileDialog::getSaveFileName(
|
||||
nullptr,
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle"),
|
||||
getDefaultSaveLocation(),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType"));
|
||||
if (path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_data_save_json(obj, file.fileName().toUtf8().constData());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_exportSettings_clicked()
|
||||
{
|
||||
QString directory = QFileDialog::getSaveFileName(
|
||||
this,
|
||||
tr(obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle")),
|
||||
GetDefaultSettingsSaveLocation(),
|
||||
getDefaultSaveLocation(),
|
||||
tr(obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType")));
|
||||
if (directory.isEmpty()) {
|
||||
@@ -262,7 +327,7 @@ void AdvSceneSwitcher::on_exportSettings_clicked()
|
||||
}
|
||||
|
||||
obs_data_t *obj = obs_data_create();
|
||||
switcher->SaveSettings(obj);
|
||||
switcher->saveSettings(obj);
|
||||
obs_data_save_json(obj, file.fileName().toUtf8().constData());
|
||||
obs_data_release(obj);
|
||||
}
|
||||
@@ -302,7 +367,7 @@ void AdvSceneSwitcher::on_importSettings_clicked()
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->LoadSettings(obj);
|
||||
switcher->loadSettings(obj);
|
||||
obs_data_release(obj);
|
||||
switcher->lastImportPath = path.toStdString();
|
||||
|
||||
@@ -318,7 +383,7 @@ void AdvSceneSwitcher::on_importSettings_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
static int findTabIndex(QTabWidget *tabWidget, int pos)
|
||||
int findTabIndex(QTabWidget *tabWidget, int pos)
|
||||
{
|
||||
int at = -1;
|
||||
|
||||
@@ -392,10 +457,10 @@ static int findTabIndex(QTabWidget *tabWidget, int pos)
|
||||
return at;
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetTabOrder()
|
||||
void AdvSceneSwitcher::setTabOrder()
|
||||
{
|
||||
if (!switcher->TabOrderValid()) {
|
||||
switcher->ResetTabOrder();
|
||||
if (!switcher->tabOrderValid()) {
|
||||
switcher->resetTabOrder();
|
||||
}
|
||||
|
||||
QTabBar *bar = ui->tabWidget->tabBar();
|
||||
@@ -410,22 +475,22 @@ void AdvSceneSwitcher::SetTabOrder()
|
||||
connect(bar, &QTabBar::tabMoved, this, &AdvSceneSwitcher::on_tabMoved);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetCurrentTab()
|
||||
void AdvSceneSwitcher::setCurrentTab()
|
||||
{
|
||||
if (switcher->lastOpenedTab >= 0) {
|
||||
ui->tabWidget->setCurrentIndex(switcher->lastOpenedTab);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RestoreWindowGeo()
|
||||
void AdvSceneSwitcher::restoreWindowGeo()
|
||||
{
|
||||
if (switcher->saveWindowGeo && WindowPosValid(switcher->windowPos)) {
|
||||
if (switcher->saveWindowGeo && windowPosValid(switcher->windowPos)) {
|
||||
this->resize(switcher->windowSize);
|
||||
this->move(switcher->windowPos);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CheckFirstTimeSetup()
|
||||
void AdvSceneSwitcher::checkFirstTimeSetup()
|
||||
{
|
||||
if (switcher->firstBoot && !switcher->disableHints) {
|
||||
switcher->firstBoot = false;
|
||||
@@ -446,7 +511,7 @@ void AdvSceneSwitcher::on_tabMoved(int from, int to)
|
||||
void AdvSceneSwitcher::on_tabWidget_currentChanged(int)
|
||||
{
|
||||
switcher->showFrame = false;
|
||||
ClearFrames(ui->screenRegionSwitches);
|
||||
clearFrames(ui->screenRegionSwitches);
|
||||
SetShowFrames();
|
||||
}
|
||||
|
||||
@@ -483,7 +548,7 @@ void AdvSceneSwitcher::on_adjustActiveTransitionType_stateChanged(int state)
|
||||
switcher->adjustActiveTransitionType = state;
|
||||
}
|
||||
|
||||
void SwitcherData::LoadSettings(obs_data_t *obj)
|
||||
void SwitcherData::loadSettings(obs_data_t *obj)
|
||||
{
|
||||
if (!obj) {
|
||||
return;
|
||||
@@ -492,9 +557,9 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
|
||||
// Needs to be loaded before any entries which might rely on scene group
|
||||
// selections to be available.
|
||||
loadSceneGroups(obj);
|
||||
LoadVariables(obj);
|
||||
LoadConnections(obj);
|
||||
LoadMacros(obj);
|
||||
loadVariables(obj);
|
||||
loadMacros(obj);
|
||||
loadConnections(obj);
|
||||
loadWindowTitleSwitches(obj);
|
||||
loadScreenRegionSwitches(obj);
|
||||
loadPauseSwitches(obj);
|
||||
@@ -510,24 +575,24 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
|
||||
loadVideoSwitches(obj);
|
||||
loadNetworkSettings(obj);
|
||||
loadSceneTriggers(obj);
|
||||
LoadGeneralSettings(obj);
|
||||
LoadHotkeys(obj);
|
||||
LoadUISettings(obj);
|
||||
loadGeneralSettings(obj);
|
||||
loadHotkeys(obj);
|
||||
loadUISettings(obj);
|
||||
|
||||
// Reset on startup and scene collection change
|
||||
switcher->lastOpenedTab = -1;
|
||||
}
|
||||
|
||||
void SwitcherData::SaveSettings(obs_data_t *obj)
|
||||
void SwitcherData::saveSettings(obs_data_t *obj)
|
||||
{
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
saveSceneGroups(obj);
|
||||
SaveMacros(obj);
|
||||
SaveConnections(obj);
|
||||
SaveVariables(obj);
|
||||
saveMacros(obj);
|
||||
saveConnections(obj);
|
||||
saveVariables(obj);
|
||||
saveWindowTitleSwitches(obj);
|
||||
saveScreenRegionSwitches(obj);
|
||||
savePauseSwitches(obj);
|
||||
@@ -543,29 +608,27 @@ void SwitcherData::SaveSettings(obs_data_t *obj)
|
||||
saveVideoSwitches(obj);
|
||||
saveNetworkSwitches(obj);
|
||||
saveSceneTriggers(obj);
|
||||
SaveGeneralSettings(obj);
|
||||
SaveHotkeys(obj);
|
||||
SaveUISettings(obj);
|
||||
SaveVersion(obj, g_GIT_SHA1);
|
||||
saveGeneralSettings(obj);
|
||||
saveHotkeys(obj);
|
||||
saveUISettings(obj);
|
||||
saveVersion(obj, g_GIT_SHA1);
|
||||
}
|
||||
|
||||
void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
|
||||
void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
||||
{
|
||||
obs_data_set_int(obj, "interval", interval);
|
||||
|
||||
std::string nonMatchingSceneName = GetWeakSourceName(nonMatchingScene);
|
||||
obs_data_set_string(obj, "non_matching_scene",
|
||||
nonMatchingSceneName.c_str());
|
||||
obs_data_set_int(obj, "switch_if_not_matching",
|
||||
static_cast<int>(switchIfNotMatching));
|
||||
noMatchDelay.Save(obj, "noMatchDelay");
|
||||
obs_data_set_int(obj, "switch_if_not_matching", switchIfNotMatching);
|
||||
noMatchDelay.Save(obj, "noMatchDelay", "noMatchDelayUnit");
|
||||
|
||||
cooldown.Save(obj, "cooldown");
|
||||
cooldown.Save(obj, "cooldown", "cooldownUnit");
|
||||
|
||||
obs_data_set_bool(obj, "active", sceneColletionStop ? true : !stop);
|
||||
sceneColletionStop = false;
|
||||
obs_data_set_int(obj, "startup_behavior",
|
||||
static_cast<int>(startupBehavior));
|
||||
obs_data_set_int(obj, "startup_behavior", startupBehavior);
|
||||
|
||||
obs_data_set_int(obj, "autoStartEvent",
|
||||
static_cast<int>(autoStartEvent));
|
||||
@@ -574,10 +637,19 @@ void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
|
||||
obs_data_set_bool(obj, "showSystemTrayNotifications",
|
||||
showSystemTrayNotifications);
|
||||
obs_data_set_bool(obj, "disableHints", disableHints);
|
||||
obs_data_set_bool(obj, "warnPluginLoadFailure", warnPluginLoadFailure);
|
||||
obs_data_set_bool(obj, "hideLegacyTabs", hideLegacyTabs);
|
||||
|
||||
SaveFunctionPriorities(obj, functionNamesByPriority);
|
||||
obs_data_set_int(obj, "priority0", functionNamesByPriority[0]);
|
||||
obs_data_set_int(obj, "priority1", functionNamesByPriority[1]);
|
||||
obs_data_set_int(obj, "priority2", functionNamesByPriority[2]);
|
||||
obs_data_set_int(obj, "priority3", functionNamesByPriority[3]);
|
||||
obs_data_set_int(obj, "priority4", functionNamesByPriority[4]);
|
||||
obs_data_set_int(obj, "priority5", functionNamesByPriority[5]);
|
||||
obs_data_set_int(obj, "priority6", functionNamesByPriority[6]);
|
||||
obs_data_set_int(obj, "priority7", functionNamesByPriority[7]);
|
||||
obs_data_set_int(obj, "priority8", functionNamesByPriority[8]);
|
||||
obs_data_set_int(obj, "priority9", functionNamesByPriority[9]);
|
||||
obs_data_set_int(obj, "priority10", functionNamesByPriority[10]);
|
||||
|
||||
obs_data_set_int(obj, "threadPriority", threadPriority);
|
||||
|
||||
@@ -589,56 +661,88 @@ void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
|
||||
obs_data_set_string(obj, "lastImportPath", lastImportPath.c_str());
|
||||
}
|
||||
|
||||
void SwitcherData::LoadGeneralSettings(obs_data_t *obj)
|
||||
void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
||||
{
|
||||
obs_data_set_default_int(obj, "interval", default_interval);
|
||||
interval = obs_data_get_int(obj, "interval");
|
||||
|
||||
obs_data_set_default_int(obj, "switch_if_not_matching",
|
||||
static_cast<int>(NoMatch::NO_SWITCH));
|
||||
obs_data_set_default_int(obj, "switch_if_not_matching", NO_SWITCH);
|
||||
switchIfNotMatching =
|
||||
(NoMatch)obs_data_get_int(obj, "switch_if_not_matching");
|
||||
std::string nonMatchingSceneName =
|
||||
obs_data_get_string(obj, "non_matching_scene");
|
||||
nonMatchingScene = GetWeakSourceByName(nonMatchingSceneName.c_str());
|
||||
noMatchDelay.Load(obj, "noMatchDelay");
|
||||
noMatchDelay.Load(obj, "noMatchDelay", "noMatchDelayUnit");
|
||||
|
||||
cooldown.Load(obj, "cooldown");
|
||||
cooldown.Load(obj, "cooldown", "cooldownUnit");
|
||||
|
||||
stop = !obs_data_get_bool(obj, "active");
|
||||
startupBehavior =
|
||||
(StartupBehavior)obs_data_get_int(obj, "startup_behavior");
|
||||
if (startupBehavior == StartupBehavior::START) {
|
||||
if (startupBehavior == START) {
|
||||
stop = false;
|
||||
}
|
||||
if (startupBehavior == StartupBehavior::STOP) {
|
||||
if (startupBehavior == STOP) {
|
||||
stop = true;
|
||||
}
|
||||
|
||||
autoStartEvent =
|
||||
static_cast<AutoStart>(obs_data_get_int(obj, "autoStartEvent"));
|
||||
autoStartEvent = static_cast<AutoStartEvent>(
|
||||
obs_data_get_int(obj, "autoStartEvent"));
|
||||
|
||||
verbose = obs_data_get_bool(obj, "verbose");
|
||||
showSystemTrayNotifications =
|
||||
obs_data_get_bool(obj, "showSystemTrayNotifications");
|
||||
disableHints = obs_data_get_bool(obj, "disableHints");
|
||||
obs_data_set_default_bool(obj, "warnPluginLoadFailure", true);
|
||||
warnPluginLoadFailure = obs_data_get_bool(obj, "warnPluginLoadFailure");
|
||||
obs_data_set_default_bool(obj, "hideLegacyTabs", true);
|
||||
hideLegacyTabs = obs_data_get_bool(obj, "hideLegacyTabs");
|
||||
|
||||
SetDefaultFunctionPriorities(obj);
|
||||
LoadFunctionPriorities(obj, functionNamesByPriority);
|
||||
if (!PrioFuncsValid()) {
|
||||
functionNamesByPriority = GetDefaultFunctionPriorityList();
|
||||
obs_data_set_default_int(obj, "priority0", default_priority_0);
|
||||
obs_data_set_default_int(obj, "priority1", default_priority_1);
|
||||
obs_data_set_default_int(obj, "priority2", default_priority_2);
|
||||
obs_data_set_default_int(obj, "priority3", default_priority_3);
|
||||
obs_data_set_default_int(obj, "priority4", default_priority_4);
|
||||
obs_data_set_default_int(obj, "priority5", default_priority_5);
|
||||
obs_data_set_default_int(obj, "priority6", default_priority_6);
|
||||
obs_data_set_default_int(obj, "priority7", default_priority_7);
|
||||
obs_data_set_default_int(obj, "priority8", default_priority_8);
|
||||
|
||||
functionNamesByPriority[0] = (obs_data_get_int(obj, "priority0"));
|
||||
functionNamesByPriority[1] = (obs_data_get_int(obj, "priority1"));
|
||||
functionNamesByPriority[2] = (obs_data_get_int(obj, "priority2"));
|
||||
functionNamesByPriority[3] = (obs_data_get_int(obj, "priority3"));
|
||||
functionNamesByPriority[4] = (obs_data_get_int(obj, "priority4"));
|
||||
functionNamesByPriority[5] = (obs_data_get_int(obj, "priority5"));
|
||||
functionNamesByPriority[6] = (obs_data_get_int(obj, "priority6"));
|
||||
functionNamesByPriority[7] = (obs_data_get_int(obj, "priority7"));
|
||||
functionNamesByPriority[8] = (obs_data_get_int(obj, "priority8"));
|
||||
functionNamesByPriority[9] = (obs_data_get_int(obj, "priority9"));
|
||||
functionNamesByPriority[10] = (obs_data_get_int(obj, "priority10"));
|
||||
if (!prioFuncsValid()) {
|
||||
functionNamesByPriority[0] = (default_priority_0);
|
||||
functionNamesByPriority[1] = (default_priority_1);
|
||||
functionNamesByPriority[2] = (default_priority_2);
|
||||
functionNamesByPriority[3] = (default_priority_3);
|
||||
functionNamesByPriority[4] = (default_priority_4);
|
||||
functionNamesByPriority[5] = (default_priority_5);
|
||||
functionNamesByPriority[6] = (default_priority_6);
|
||||
functionNamesByPriority[7] = (default_priority_7);
|
||||
functionNamesByPriority[8] = (default_priority_8);
|
||||
functionNamesByPriority[9] = (default_priority_9);
|
||||
functionNamesByPriority[10] = (default_priority_10);
|
||||
}
|
||||
|
||||
obs_data_set_default_int(obj, "threadPriority",
|
||||
QThread::NormalPriority);
|
||||
threadPriority = obs_data_get_int(obj, "threadPriority");
|
||||
|
||||
transitionOverrideOverride =
|
||||
obs_data_get_bool(obj, "transitionOverrideOverride");
|
||||
// TODO: Remove this fallback in future version
|
||||
if (obs_data_has_user_value(obj, "tansitionOverrideOverride")) {
|
||||
transitionOverrideOverride =
|
||||
obs_data_get_bool(obj, "tansitionOverrideOverride");
|
||||
} else {
|
||||
transitionOverrideOverride =
|
||||
obs_data_get_bool(obj, "transitionOverrideOverride");
|
||||
}
|
||||
adjustActiveTransitionType =
|
||||
obs_data_get_bool(obj, "adjustActiveTransitionType");
|
||||
|
||||
@@ -651,8 +755,7 @@ void SwitcherData::LoadGeneralSettings(obs_data_t *obj)
|
||||
lastImportPath = obs_data_get_string(obj, "lastImportPath");
|
||||
}
|
||||
|
||||
static void saveSplitterPos(QList<int> &sizes, obs_data_t *obj,
|
||||
const std::string name)
|
||||
void saveSplitterPos(QList<int> &sizes, obs_data_t *obj, const std::string name)
|
||||
{
|
||||
auto array = obs_data_array_create();
|
||||
for (int i = 0; i < sizes.count(); ++i) {
|
||||
@@ -665,8 +768,7 @@ static void saveSplitterPos(QList<int> &sizes, obs_data_t *obj,
|
||||
obs_data_array_release(array);
|
||||
}
|
||||
|
||||
static void loadSplitterPos(QList<int> &sizes, obs_data_t *obj,
|
||||
const std::string name)
|
||||
void loadSplitterPos(QList<int> &sizes, obs_data_t *obj, const std::string name)
|
||||
{
|
||||
sizes.clear();
|
||||
obs_data_array_t *array = obs_data_get_array(obj, name.c_str());
|
||||
@@ -679,7 +781,7 @@ static void loadSplitterPos(QList<int> &sizes, obs_data_t *obj,
|
||||
obs_data_array_release(array);
|
||||
}
|
||||
|
||||
void SwitcherData::SaveUISettings(obs_data_t *obj)
|
||||
void SwitcherData::saveUISettings(obs_data_t *obj)
|
||||
{
|
||||
obs_data_set_int(obj, "generalTabPos", tabOrder[0]);
|
||||
obs_data_set_int(obj, "macroTabPos", tabOrder[1]);
|
||||
@@ -712,7 +814,7 @@ void SwitcherData::SaveUISettings(obs_data_t *obj)
|
||||
"macroListMacroEditSplitterPosition");
|
||||
}
|
||||
|
||||
void SwitcherData::LoadUISettings(obs_data_t *obj)
|
||||
void SwitcherData::loadUISettings(obs_data_t *obj)
|
||||
{
|
||||
obs_data_set_default_int(obj, "generalTabPos", 0);
|
||||
obs_data_set_default_int(obj, "macroTabPos", 1);
|
||||
@@ -753,8 +855,8 @@ void SwitcherData::LoadUISettings(obs_data_t *obj)
|
||||
tabOrder.emplace_back((int)(obs_data_get_int(obj, "sceneGroupTabPos")));
|
||||
tabOrder.emplace_back((int)(obs_data_get_int(obj, "triggerTabPos")));
|
||||
|
||||
if (!TabOrderValid()) {
|
||||
ResetTabOrder();
|
||||
if (!tabOrderValid()) {
|
||||
resetTabOrder();
|
||||
}
|
||||
|
||||
saveWindowGeo = obs_data_get_bool(obj, "saveWindowGeo");
|
||||
@@ -768,7 +870,7 @@ void SwitcherData::LoadUISettings(obs_data_t *obj)
|
||||
"macroListMacroEditSplitterPosition");
|
||||
}
|
||||
|
||||
bool SwitcherData::TabOrderValid()
|
||||
bool SwitcherData::tabOrderValid()
|
||||
{
|
||||
auto tmp = std::vector<int>(tab_count);
|
||||
std::iota(tmp.begin(), tmp.end(), 0);
|
||||
@@ -782,13 +884,13 @@ bool SwitcherData::TabOrderValid()
|
||||
return true;
|
||||
}
|
||||
|
||||
void SwitcherData::ResetTabOrder()
|
||||
void SwitcherData::resetTabOrder()
|
||||
{
|
||||
tabOrder = std::vector<int>(tab_count);
|
||||
std::iota(tabOrder.begin(), tabOrder.end(), 0);
|
||||
}
|
||||
|
||||
void SwitcherData::CheckNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
||||
void SwitcherData::checkNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
||||
OBSWeakSource &transition, int &sleep)
|
||||
{
|
||||
if (match) {
|
||||
@@ -800,12 +902,12 @@ void SwitcherData::CheckNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
||||
return;
|
||||
}
|
||||
|
||||
if (switchIfNotMatching == NoMatch::SWITCH && nonMatchingScene) {
|
||||
if (switchIfNotMatching == SWITCH && nonMatchingScene) {
|
||||
match = true;
|
||||
scene = nonMatchingScene;
|
||||
transition = nullptr;
|
||||
}
|
||||
if (switchIfNotMatching == NoMatch::RANDOM_SWITCH) {
|
||||
if (switchIfNotMatching == RANDOM_SWITCH) {
|
||||
match = checkRandom(scene, transition, sleep);
|
||||
}
|
||||
}
|
||||
@@ -824,7 +926,7 @@ void SwitcherData::checkSwitchCooldown(bool &match)
|
||||
}
|
||||
}
|
||||
|
||||
static void populateStartupBehavior(QComboBox *cb)
|
||||
void populateStartupBehavior(QComboBox *cb)
|
||||
{
|
||||
cb->addItem(obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.status.onStartup.asLastRun"));
|
||||
@@ -834,7 +936,7 @@ static void populateStartupBehavior(QComboBox *cb)
|
||||
"AdvSceneSwitcher.generalTab.status.onStartup.doNotStart"));
|
||||
}
|
||||
|
||||
static void populateAutoStartEventSelection(QComboBox *cb)
|
||||
void populateAutoStartEventSelection(QComboBox *cb)
|
||||
{
|
||||
cb->addItem(obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.status.autoStart.never"));
|
||||
@@ -846,8 +948,53 @@ static void populateAutoStartEventSelection(QComboBox *cb)
|
||||
"AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming"));
|
||||
}
|
||||
|
||||
static void populatePriorityFunctionList(QListWidget *list)
|
||||
void AdvSceneSwitcher::setupGeneralTab()
|
||||
{
|
||||
populateSceneSelection(ui->noMatchSwitchScene, false);
|
||||
|
||||
if (switcher->switchIfNotMatching == SWITCH) {
|
||||
ui->noMatchSwitch->setChecked(true);
|
||||
ui->noMatchSwitchScene->setEnabled(true);
|
||||
} else if (switcher->switchIfNotMatching == NO_SWITCH) {
|
||||
ui->noMatchDontSwitch->setChecked(true);
|
||||
ui->noMatchSwitchScene->setEnabled(false);
|
||||
} else {
|
||||
ui->noMatchRandomSwitch->setChecked(true);
|
||||
ui->noMatchSwitchScene->setEnabled(false);
|
||||
}
|
||||
ui->noMatchSwitchScene->setCurrentText(
|
||||
GetWeakSourceName(switcher->nonMatchingScene).c_str());
|
||||
|
||||
DurationSelection *noMatchDelay = new DurationSelection();
|
||||
noMatchDelay->SetDuration(switcher->noMatchDelay);
|
||||
noMatchDelay->setToolTip(obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip"));
|
||||
ui->noMatchLayout->addWidget(noMatchDelay);
|
||||
QWidget::connect(noMatchDelay, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(NoMatchDelayDurationChanged(double)));
|
||||
QWidget::connect(noMatchDelay, SIGNAL(UnitChanged(DurationUnit)), this,
|
||||
SLOT(NoMatchDelayUnitChanged(DurationUnit)));
|
||||
|
||||
ui->checkInterval->setValue(switcher->interval);
|
||||
|
||||
DurationSelection *cooldownTime = new DurationSelection();
|
||||
cooldownTime->SetDuration(switcher->cooldown);
|
||||
cooldownTime->setToolTip(obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint"));
|
||||
ui->cooldownLayout->addWidget(cooldownTime);
|
||||
ui->cooldownLayout->addStretch();
|
||||
QWidget::connect(cooldownTime, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(CooldownDurationChanged(double)));
|
||||
QWidget::connect(cooldownTime, SIGNAL(UnitChanged(DurationUnit)), this,
|
||||
SLOT(CooldownUnitChanged(DurationUnit)));
|
||||
|
||||
ui->verboseLogging->setChecked(switcher->verbose);
|
||||
ui->saveWindowGeo->setChecked(switcher->saveWindowGeo);
|
||||
ui->showTrayNotifications->setChecked(
|
||||
switcher->showSystemTrayNotifications);
|
||||
ui->uiHintsDisable->setChecked(switcher->disableHints);
|
||||
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
|
||||
|
||||
for (int p : switcher->functionNamesByPriority) {
|
||||
std::string s = "";
|
||||
switch (p) {
|
||||
@@ -897,114 +1044,26 @@ static void populatePriorityFunctionList(QListWidget *list)
|
||||
break;
|
||||
}
|
||||
QString text(s.c_str());
|
||||
QListWidgetItem *item = new QListWidgetItem(text, list);
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->priorityList);
|
||||
item->setData(Qt::UserRole, text);
|
||||
}
|
||||
}
|
||||
|
||||
static void populateThreadPriorityList(QComboBox *list)
|
||||
{
|
||||
for (int i = 0; i < (int)switcher->threadPriorities.size(); ++i) {
|
||||
list->addItem(switcher->threadPriorities[i].name.c_str());
|
||||
list->setItemData(
|
||||
ui->threadPriority->addItem(
|
||||
switcher->threadPriorities[i].name.c_str());
|
||||
ui->threadPriority->setItemData(
|
||||
i, switcher->threadPriorities[i].description.c_str(),
|
||||
Qt::ToolTipRole);
|
||||
if (switcher->threadPriority ==
|
||||
switcher->threadPriorities[i].value) {
|
||||
list->setCurrentText(
|
||||
ui->threadPriority->setCurrentText(
|
||||
switcher->threadPriorities[i].name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool isGeneralTab(const QString &name)
|
||||
{
|
||||
return name == obs_module_text("AdvSceneSwitcher.generalTab.title");
|
||||
}
|
||||
|
||||
static int getGeneralTabIdx(QTabWidget *tabWidget)
|
||||
{
|
||||
for (int idx = 0; idx < tabWidget->count(); idx++) {
|
||||
if (isGeneralTab(tabWidget->tabText(idx))) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void setupGeneralTabInactiveWarning(QTabWidget *tabs)
|
||||
{
|
||||
auto callback = [tabs]() {
|
||||
const bool isRunning = switcher && switcher->th &&
|
||||
switcher->th->isRunning();
|
||||
auto idx = getGeneralTabIdx(tabs);
|
||||
tabs->setTabIcon(
|
||||
idx,
|
||||
isRunning ? QIcon()
|
||||
: QIcon::fromTheme(
|
||||
"obs",
|
||||
QIcon(":/res/images/warning.svg")));
|
||||
};
|
||||
|
||||
auto inactiveTimer = new QTimer(tabs);
|
||||
inactiveTimer->setInterval(1000);
|
||||
QObject::connect(inactiveTimer, &QTimer::timeout, callback);
|
||||
inactiveTimer->start();
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupGeneralTab()
|
||||
{
|
||||
PopulateSceneSelection(ui->noMatchSwitchScene, false);
|
||||
|
||||
if (switcher->switchIfNotMatching == SwitcherData::NoMatch::SWITCH) {
|
||||
ui->noMatchSwitch->setChecked(true);
|
||||
ui->noMatchSwitchScene->setEnabled(true);
|
||||
} else if (switcher->switchIfNotMatching ==
|
||||
SwitcherData::NoMatch::NO_SWITCH) {
|
||||
ui->noMatchDontSwitch->setChecked(true);
|
||||
ui->noMatchSwitchScene->setEnabled(false);
|
||||
} else {
|
||||
ui->noMatchRandomSwitch->setChecked(true);
|
||||
ui->noMatchSwitchScene->setEnabled(false);
|
||||
}
|
||||
ui->noMatchSwitchScene->setCurrentText(
|
||||
GetWeakSourceName(switcher->nonMatchingScene).c_str());
|
||||
|
||||
DurationSelection *noMatchDelay = new DurationSelection();
|
||||
noMatchDelay->SetDuration(switcher->noMatchDelay);
|
||||
noMatchDelay->setToolTip(obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip"));
|
||||
ui->noMatchLayout->addWidget(noMatchDelay);
|
||||
QWidget::connect(noMatchDelay,
|
||||
SIGNAL(DurationChanged(const Duration &)), this,
|
||||
SLOT(NoMatchDelayDurationChanged(const Duration &)));
|
||||
|
||||
ui->checkInterval->setValue(switcher->interval);
|
||||
|
||||
DurationSelection *cooldownTime = new DurationSelection();
|
||||
cooldownTime->SetDuration(switcher->cooldown);
|
||||
cooldownTime->setToolTip(obs_module_text(
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint"));
|
||||
ui->cooldownLayout->addWidget(cooldownTime);
|
||||
ui->cooldownLayout->addStretch();
|
||||
QWidget::connect(cooldownTime,
|
||||
SIGNAL(DurationChanged(const Duration &)), this,
|
||||
SLOT(CooldownDurationChanged(const Duration &)));
|
||||
|
||||
ui->verboseLogging->setChecked(switcher->verbose);
|
||||
ui->saveWindowGeo->setChecked(switcher->saveWindowGeo);
|
||||
ui->showTrayNotifications->setChecked(
|
||||
switcher->showSystemTrayNotifications);
|
||||
ui->uiHintsDisable->setChecked(switcher->disableHints);
|
||||
ui->warnPluginLoadFailure->setChecked(switcher->warnPluginLoadFailure);
|
||||
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
|
||||
|
||||
populatePriorityFunctionList(ui->priorityList);
|
||||
populateThreadPriorityList(ui->threadPriority);
|
||||
|
||||
populateStartupBehavior(ui->startupBehavior);
|
||||
ui->startupBehavior->setCurrentIndex(
|
||||
static_cast<int>(switcher->startupBehavior));
|
||||
ui->startupBehavior->setCurrentIndex(switcher->startupBehavior);
|
||||
|
||||
populateAutoStartEventSelection(ui->autoStartEvent);
|
||||
ui->autoStartEvent->setCurrentIndex(
|
||||
@@ -1021,10 +1080,6 @@ void AdvSceneSwitcher::SetupGeneralTab()
|
||||
// Hide the now empty invisible shell of the statusControl widget
|
||||
// as otherwise it could block user input
|
||||
statusControl->hide();
|
||||
setupGeneralTabInactiveWarning(ui->tabWidget);
|
||||
|
||||
MinimizeSizeOfColumn(ui->statusLayout, 0);
|
||||
setWindowTitle(windowTitle() + " - " + g_GIT_TAG);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
#include "hotkey.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include <obs-module.h>
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
|
||||
namespace advss {
|
||||
|
||||
std::vector<std::weak_ptr<Hotkey>> Hotkey::_registeredHotkeys = {};
|
||||
uint32_t Hotkey::_hotkeyCounter = 1;
|
||||
|
||||
@@ -120,7 +117,7 @@ void Hotkey::ClearAllHotkeys()
|
||||
_registeredHotkeys.clear();
|
||||
}
|
||||
|
||||
static void startHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
||||
void startHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
||||
{
|
||||
if (pressed) {
|
||||
if (!(switcher->th && switcher->th->isRunning())) {
|
||||
@@ -129,7 +126,7 @@ static void startHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
||||
}
|
||||
}
|
||||
|
||||
static void stopHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
||||
void stopHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
||||
{
|
||||
if (pressed) {
|
||||
if (switcher->th && switcher->th->isRunning()) {
|
||||
@@ -138,8 +135,8 @@ static void stopHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
||||
}
|
||||
}
|
||||
|
||||
static void startStopToggleHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||
bool pressed)
|
||||
void startStopToggleHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||
bool pressed)
|
||||
{
|
||||
if (pressed) {
|
||||
if (switcher->th && switcher->th->isRunning()) {
|
||||
@@ -150,8 +147,8 @@ static void startStopToggleHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||
}
|
||||
}
|
||||
|
||||
static void upMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||
bool pressed)
|
||||
void upMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||
bool pressed)
|
||||
{
|
||||
if (pressed && switcher->settingsWindowOpened &&
|
||||
AdvSceneSwitcher::window) {
|
||||
@@ -161,8 +158,8 @@ static void upMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||
}
|
||||
}
|
||||
|
||||
static void downMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||
bool pressed)
|
||||
void downMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||
bool pressed)
|
||||
{
|
||||
if (pressed && switcher->settingsWindowOpened &&
|
||||
AdvSceneSwitcher::window) {
|
||||
@@ -172,8 +169,8 @@ static void downMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||
}
|
||||
}
|
||||
|
||||
static void removeMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||
bool pressed)
|
||||
void removeMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||
bool pressed)
|
||||
{
|
||||
if (pressed && switcher->settingsWindowOpened &&
|
||||
AdvSceneSwitcher::window) {
|
||||
@@ -183,7 +180,7 @@ static void removeMacroSegmentHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *,
|
||||
}
|
||||
}
|
||||
|
||||
static void registerHotkeys()
|
||||
void registerHotkeys()
|
||||
{
|
||||
switcher->startHotkey = obs_hotkey_register_frontend(
|
||||
"startSwitcherHotkey",
|
||||
@@ -216,14 +213,14 @@ static void registerHotkeys()
|
||||
switcher->hotkeysRegistered = true;
|
||||
}
|
||||
|
||||
static void saveHotkey(obs_data_t *obj, obs_hotkey_id id, const char *name)
|
||||
void saveHotkey(obs_data_t *obj, obs_hotkey_id id, const char *name)
|
||||
{
|
||||
obs_data_array_t *a = obs_hotkey_save(id);
|
||||
obs_data_set_array(obj, name, a);
|
||||
obs_data_array_release(a);
|
||||
}
|
||||
|
||||
void SwitcherData::SaveHotkeys(obs_data_t *obj)
|
||||
void SwitcherData::saveHotkeys(obs_data_t *obj)
|
||||
{
|
||||
saveHotkey(obj, startHotkey, "startHotkey");
|
||||
saveHotkey(obj, stopHotkey, "stopHotkey");
|
||||
@@ -233,14 +230,14 @@ void SwitcherData::SaveHotkeys(obs_data_t *obj)
|
||||
saveHotkey(obj, removeMacroSegment, "removeMacroSegmentHotkey");
|
||||
}
|
||||
|
||||
static void loadHotkey(obs_data_t *obj, obs_hotkey_id id, const char *name)
|
||||
void loadHotkey(obs_data_t *obj, obs_hotkey_id id, const char *name)
|
||||
{
|
||||
obs_data_array_t *a = obs_data_get_array(obj, name);
|
||||
obs_hotkey_load(id, a);
|
||||
obs_data_array_release(a);
|
||||
}
|
||||
|
||||
void SwitcherData::LoadHotkeys(obs_data_t *obj)
|
||||
void SwitcherData::loadHotkeys(obs_data_t *obj)
|
||||
{
|
||||
if (!hotkeysRegistered) {
|
||||
registerHotkeys();
|
||||
@@ -252,5 +249,3 @@ void SwitcherData::LoadHotkeys(obs_data_t *obj)
|
||||
loadHotkey(obj, downMacroSegment, "downMacroSegmentHotkey");
|
||||
loadHotkey(obj, removeMacroSegment, "removeMacroSegmentHotkey");
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
|
||||
namespace advss {
|
||||
|
||||
extern bool canSimulateKeyPresses;
|
||||
|
||||
class Hotkey {
|
||||
@@ -163,4 +161,4 @@ enum class HotkeyType {
|
||||
Key_NumpadEnter
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
void registerHotkeys();
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <thread>
|
||||
|
||||
namespace advss {
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
bool SceneTrigger::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
@@ -159,7 +156,7 @@ void SceneTrigger::logMatch()
|
||||
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());
|
||||
actionName.c_str(), duration.seconds);
|
||||
}
|
||||
|
||||
void frontEndActionThread(sceneTriggerAction action, double delay)
|
||||
@@ -269,14 +266,14 @@ void SceneTrigger::performAction()
|
||||
|
||||
if (isFrontendAction(triggerAction)) {
|
||||
t = std::thread(frontEndActionThread, triggerAction,
|
||||
duration.Seconds());
|
||||
duration.seconds);
|
||||
} else if (isAudioAction(triggerAction)) {
|
||||
bool mute = triggerAction == sceneTriggerAction::MUTE_SOURCE;
|
||||
t = std::thread(muteThread, audioSource, duration.Seconds(),
|
||||
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);
|
||||
t = std::thread(statusThread, duration.seconds, stop);
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignoring unknown action '%d'",
|
||||
static_cast<int>(triggerAction));
|
||||
@@ -352,7 +349,7 @@ void SwitcherData::loadSceneTriggers(obs_data_t *obj)
|
||||
obs_data_array_release(triggerArray);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupTriggerTab()
|
||||
void AdvSceneSwitcher::setupTriggerTab()
|
||||
{
|
||||
for (auto &s : switcher->sceneTriggers) {
|
||||
QListWidgetItem *item;
|
||||
@@ -401,7 +398,7 @@ void SceneTrigger::load(obs_data_t *obj)
|
||||
|
||||
static inline void populateTriggers(QComboBox *list)
|
||||
{
|
||||
AddSelectionEntry(
|
||||
addSelectionEntry(
|
||||
list,
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none"));
|
||||
@@ -416,7 +413,7 @@ static inline void populateTriggers(QComboBox *list)
|
||||
|
||||
inline void populateActions(QComboBox *list)
|
||||
{
|
||||
AddSelectionEntry(
|
||||
addSelectionEntry(
|
||||
list,
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none"));
|
||||
@@ -463,15 +460,17 @@ SceneTriggerWidget::SceneTriggerWidget(QWidget *parent, SceneTrigger *s)
|
||||
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(duration, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(DurationChanged(double)));
|
||||
QWidget::connect(duration, SIGNAL(UnitChanged(DurationUnit)), this,
|
||||
SLOT(DurationUnitChanged(DurationUnit)));
|
||||
QWidget::connect(audioSources,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
SLOT(AudioSourceChanged(const QString &)));
|
||||
|
||||
populateTriggers(triggers);
|
||||
populateActions(actions);
|
||||
PopulateAudioSelection(audioSources);
|
||||
populateAudioSelection(audioSources);
|
||||
|
||||
if (s) {
|
||||
triggers->setCurrentIndex(static_cast<int>(s->triggerType));
|
||||
@@ -495,7 +494,7 @@ SceneTriggerWidget::SceneTriggerWidget(QWidget *parent, SceneTrigger *s)
|
||||
{"{{audioSources}}", audioSources},
|
||||
{"{{duration}}", duration},
|
||||
{"{{scenes}}", scenes}};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.sceneTriggerTab.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.sceneTriggerTab.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -553,14 +552,24 @@ void SceneTriggerWidget::TriggerActionChanged(int index)
|
||||
}
|
||||
}
|
||||
|
||||
void SceneTriggerWidget::DurationChanged(const Duration &duration)
|
||||
void SceneTriggerWidget::DurationChanged(double seconds)
|
||||
{
|
||||
if (loading || !switchData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->duration = duration;
|
||||
switchData->duration.seconds = seconds;
|
||||
}
|
||||
|
||||
void SceneTriggerWidget::DurationUnitChanged(DurationUnit unit)
|
||||
{
|
||||
if (loading || !switchData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->duration.displayUnit = unit;
|
||||
}
|
||||
|
||||
void SceneTriggerWidget::AudioSourceChanged(const QString &text)
|
||||
@@ -572,5 +581,3 @@ void SceneTriggerWidget::AudioSourceChanged(const QString &text)
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->audioSource = GetWeakSourceByQString(text);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
#include "switch-generic.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class sceneTriggerType {
|
||||
NONE = 0,
|
||||
SCENE_ACTIVE = 1,
|
||||
@@ -73,7 +71,8 @@ public:
|
||||
private slots:
|
||||
void TriggerTypeChanged(int index);
|
||||
void TriggerActionChanged(int index);
|
||||
void DurationChanged(const Duration &);
|
||||
void DurationChanged(double seconds);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
void AudioSourceChanged(const QString &text);
|
||||
|
||||
private:
|
||||
@@ -84,5 +83,3 @@ private:
|
||||
|
||||
SceneTrigger *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "volume-control.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
namespace advss {
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "volume-control.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
bool AudioSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
@@ -215,7 +212,7 @@ void SwitcherData::loadAudioSwitches(obs_data_t *obj)
|
||||
audioFallback.load(obj);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupAudioTab()
|
||||
void AdvSceneSwitcher::setupAudioTab()
|
||||
{
|
||||
for (auto &s : switcher->audioSwitches) {
|
||||
QListWidgetItem *item;
|
||||
@@ -441,15 +438,15 @@ AudioSwitchWidget::AudioSwitchWidget(QWidget *parent, AudioSwitch *s)
|
||||
SLOT(VolumeThresholdChanged(int)));
|
||||
QWidget::connect(condition, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(duration, SIGNAL(DurationChanged(const Duration &)),
|
||||
this, SLOT(DurationChanged(const Duration &)));
|
||||
QWidget::connect(duration, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(DurationChanged(double)));
|
||||
QWidget::connect(audioSources,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
SLOT(SourceChanged(const QString &)));
|
||||
QWidget::connect(ignoreInactiveSource, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(IgnoreInactiveChanged(int)));
|
||||
|
||||
PopulateAudioSelection(audioSources);
|
||||
populateAudioSelection(audioSources);
|
||||
populateConditionSelection(condition);
|
||||
|
||||
if (s) {
|
||||
@@ -470,7 +467,7 @@ AudioSwitchWidget::AudioSwitchWidget(QWidget *parent, AudioSwitch *s)
|
||||
{"{{ignoreInactiveSource}}", ignoreInactiveSource},
|
||||
{"{{scenes}}", scenes},
|
||||
{"{{transitions}}", transitions}};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.audioTab.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.audioTab.entry"),
|
||||
switchLayout, widgetPlaceholders);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
@@ -557,14 +554,14 @@ void AudioSwitchWidget::ConditionChanged(int cond)
|
||||
switchData->condition = (audioCondition)cond;
|
||||
}
|
||||
|
||||
void AudioSwitchWidget::DurationChanged(const Duration &dur)
|
||||
void AudioSwitchWidget::DurationChanged(double sec)
|
||||
{
|
||||
if (loading || !switchData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->duration = dur;
|
||||
switchData->duration.seconds = sec;
|
||||
}
|
||||
|
||||
void AudioSwitchWidget::IgnoreInactiveChanged(int state)
|
||||
@@ -583,8 +580,8 @@ AudioSwitchFallbackWidget::AudioSwitchFallbackWidget(QWidget *parent,
|
||||
{
|
||||
duration = new DurationSelection(this, false);
|
||||
|
||||
QWidget::connect(duration, SIGNAL(DurationChanged(const Duration &)),
|
||||
this, SLOT(DurationChanged(const Duration &)));
|
||||
QWidget::connect(duration, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(DurationChanged(double)));
|
||||
|
||||
if (s) {
|
||||
duration->SetDuration(s->duration);
|
||||
@@ -595,7 +592,7 @@ AudioSwitchFallbackWidget::AudioSwitchFallbackWidget(QWidget *parent,
|
||||
{"{{scenes}}", scenes},
|
||||
{"{{duration}}", duration},
|
||||
{"{{transitions}}", transitions}};
|
||||
PlaceWidgets(
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.audioTab.multiMatchfallback"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
@@ -605,14 +602,12 @@ AudioSwitchFallbackWidget::AudioSwitchFallbackWidget(QWidget *parent,
|
||||
loading = false;
|
||||
}
|
||||
|
||||
void AudioSwitchFallbackWidget::DurationChanged(const Duration &dur)
|
||||
void AudioSwitchFallbackWidget::DurationChanged(double sec)
|
||||
{
|
||||
if (loading || !switchData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->duration = dur;
|
||||
switchData->duration.seconds = sec;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
#include "duration-control.hpp"
|
||||
#include "volume-control.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr auto audio_func = 8;
|
||||
|
||||
typedef enum {
|
||||
@@ -77,7 +75,7 @@ private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void VolumeThresholdChanged(int vol);
|
||||
void ConditionChanged(int cond);
|
||||
void DurationChanged(const Duration &);
|
||||
void DurationChanged(double dur);
|
||||
void IgnoreInactiveChanged(int state);
|
||||
|
||||
private:
|
||||
@@ -98,12 +96,10 @@ public:
|
||||
AudioSwitchFallbackWidget(QWidget *parent, AudioSwitchFallback *s);
|
||||
|
||||
private slots:
|
||||
void DurationChanged(const Duration &dur);
|
||||
void DurationChanged(double dur);
|
||||
|
||||
private:
|
||||
DurationSelection *duration;
|
||||
|
||||
AudioSwitchFallback *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "platform-funcs.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
bool ExecutableSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
|
||||
@@ -103,7 +99,7 @@ bool SwitcherData::checkExeSwitch(OBSWeakSource &scene,
|
||||
bool equals = runningProcesses.contains(s.exe);
|
||||
bool matches = (runningProcesses.indexOf(
|
||||
QRegularExpression(s.exe)) != -1);
|
||||
bool focus = (!s.inFocus || IsInFocus(s.exe));
|
||||
bool focus = (!s.inFocus || isInFocus(s.exe));
|
||||
|
||||
// True if current window is ignored AND switch equals OR matches last window
|
||||
bool ignore =
|
||||
@@ -160,7 +156,7 @@ void SwitcherData::loadExecutableSwitches(obs_data_t *obj)
|
||||
obs_data_array_release(executableArray);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupExecutableTab()
|
||||
void AdvSceneSwitcher::setupExecutableTab()
|
||||
{
|
||||
for (auto &s : switcher->executableSwitches) {
|
||||
QListWidgetItem *item;
|
||||
@@ -212,7 +208,7 @@ ExecutableSwitchWidget::ExecutableSwitchWidget(QWidget *parent,
|
||||
QWidget::connect(requiresFocus, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(FocusChanged(int)));
|
||||
|
||||
PopulateProcessSelection(processes);
|
||||
populateProcessSelection(processes);
|
||||
|
||||
processes->setEditable(true);
|
||||
processes->setMaxVisibleItems(20);
|
||||
@@ -228,7 +224,7 @@ ExecutableSwitchWidget::ExecutableSwitchWidget(QWidget *parent,
|
||||
{"{{requiresFocus}}", requiresFocus},
|
||||
{"{{scenes}}", scenes},
|
||||
{"{{transitions}}", transitions}};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.executableTab.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.executableTab.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -276,5 +272,3 @@ void ExecutableSwitchWidget::FocusChanged(int state)
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->inFocus = state;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#include <QCheckBox>
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr auto exe_func = 3;
|
||||
|
||||
struct ExecutableSwitch : SceneSwitcherEntry {
|
||||
@@ -44,5 +42,3 @@ private:
|
||||
|
||||
ExecutableSwitch *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "curl-helper.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QFileDialog>
|
||||
#include <QTextStream>
|
||||
@@ -11,7 +6,9 @@
|
||||
#include <regex>
|
||||
#include <curl/curl.h>
|
||||
|
||||
namespace advss {
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "curl-helper.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
bool FileSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
@@ -212,7 +209,7 @@ bool matchFileContent(QString &filedata, FileSwitch &s)
|
||||
}
|
||||
|
||||
QString text = QString::fromStdString(s.text);
|
||||
return CompareIgnoringLineEnding(text, filedata);
|
||||
return compareIgnoringLineEnding(text, filedata);
|
||||
}
|
||||
|
||||
bool checkRemoteFileContent(FileSwitch &s)
|
||||
@@ -414,7 +411,7 @@ void SwitcherData::loadFileSwitches(obs_data_t *obj)
|
||||
fileIO.writePath = obs_data_get_string(obj, "writePath");
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupFileTab()
|
||||
void AdvSceneSwitcher::setupFileTab()
|
||||
{
|
||||
ui->remoteFileWarningLabel->setText(
|
||||
obs_module_text("AdvSceneSwitcher.fileTab.remoteFileWarning1") +
|
||||
@@ -545,11 +542,11 @@ FileSwitchWidget::FileSwitchWidget(QWidget *parent, FileSwitch *s)
|
||||
QHBoxLayout *line1Layout = new QHBoxLayout;
|
||||
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||
QHBoxLayout *line3Layout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry2"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry2"),
|
||||
line2Layout, widgetPlaceholders, false);
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry3"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.fileTab.entry3"),
|
||||
line3Layout, widgetPlaceholders);
|
||||
mainLayout->addLayout(line1Layout);
|
||||
mainLayout->addLayout(line2Layout);
|
||||
@@ -668,5 +665,3 @@ void FileSwitchWidget::CheckFileContentChanged(int state)
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->onlyMatchIfChanged = state;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -8,11 +8,8 @@
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
#include <QPlainTextEdit>
|
||||
#include <QDateTime>
|
||||
#include <obs-module.h>
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr auto read_file_func = 0;
|
||||
|
||||
typedef enum {
|
||||
@@ -80,5 +77,3 @@ static inline QString MakeFileSwitchName(const QString &scene,
|
||||
const QString &fileName,
|
||||
const QString &text, bool useRegex,
|
||||
bool useTime, bool onlyMatchIfChanged);
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
constexpr auto previous_scene_name = "Previous Scene";
|
||||
constexpr auto current_transition_name = "Current Transition";
|
||||
|
||||
namespace advss {
|
||||
|
||||
static inline bool SceneGroupValid(SceneGroup *group)
|
||||
{
|
||||
if (group) {
|
||||
@@ -214,9 +208,9 @@ SwitchWidget::SwitchWidget(QWidget *parent, SceneSwitcherEntry *s,
|
||||
SIGNAL(SceneGroupRenamed(const QString &, const QString &)),
|
||||
this, SLOT(SceneGroupRename(const QString &, const QString &)));
|
||||
|
||||
PopulateSceneSelection(scenes, usePreviousScene, false, false,
|
||||
populateSceneSelection(scenes, usePreviousScene, false, false,
|
||||
addSceneGroup, &switcher->sceneGroups);
|
||||
PopulateTransitionSelection(transitions, addCurrentTransition);
|
||||
populateTransitionSelection(transitions, addCurrentTransition);
|
||||
|
||||
switchData = s;
|
||||
showSwitchData();
|
||||
@@ -306,5 +300,3 @@ void SwitchWidget::TransitionChanged(const QString &text)
|
||||
switchData->transition = GetWeakTransitionByQString(text);
|
||||
switchData->useCurrentTransition = switchData->transition == nullptr;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#include "scene-group.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class SwitchTargetType {
|
||||
Scene,
|
||||
SceneGroup,
|
||||
@@ -97,5 +95,3 @@ protected:
|
||||
|
||||
SceneSwitcherEntry *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "platform-funcs.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <regex>
|
||||
|
||||
namespace advss {
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
bool IdleData::pause = false;
|
||||
IdleWidget *idleWidget = nullptr;
|
||||
@@ -42,7 +38,7 @@ bool SwitcherData::checkIdleSwitch(OBSWeakSource &scene,
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignoreIdle && SecondsSinceLastInput() > idleData.time) {
|
||||
if (!ignoreIdle && secondsSinceLastInput() > idleData.time) {
|
||||
if (idleData.alreadySwitched) {
|
||||
return false;
|
||||
}
|
||||
@@ -209,9 +205,9 @@ void SwitcherData::loadIdleSwitches(obs_data_t *obj)
|
||||
idleData.load(obj);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupIdleTab()
|
||||
void AdvSceneSwitcher::setupIdleTab()
|
||||
{
|
||||
PopulateWindowSelection(ui->ignoreIdleWindowsWindows);
|
||||
populateWindowSelection(ui->ignoreIdleWindowsWindows);
|
||||
|
||||
for (auto &window : switcher->ignoreIdleWindows) {
|
||||
QString text = QString::fromStdString(window);
|
||||
@@ -271,7 +267,7 @@ IdleWidget::IdleWidget(QWidget *parent, IdleData *s)
|
||||
{"{{duration}}", duration},
|
||||
{"{{scenes}}", scenes},
|
||||
{"{{transitions}}", transitions}};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.idleTab.idleswitch"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.idleTab.idleswitch"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -289,5 +285,3 @@ void IdleWidget::DurationChanged(int dur)
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->idleData.time = dur;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr auto default_idle_time = 60;
|
||||
constexpr auto idle_func = 2;
|
||||
|
||||
@@ -38,5 +36,3 @@ private:
|
||||
|
||||
IdleData *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
bool MediaSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
|
||||
@@ -235,7 +232,7 @@ void SwitcherData::loadMediaSwitches(obs_data_t *obj)
|
||||
obs_data_array_release(mediaArray);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupMediaTab()
|
||||
void AdvSceneSwitcher::setupMediaTab()
|
||||
{
|
||||
for (auto &s : switcher->mediaSwitches) {
|
||||
QListWidgetItem *item;
|
||||
@@ -463,7 +460,7 @@ MediaSwitchWidget::MediaSwitchWidget(QWidget *parent, MediaSwitch *s)
|
||||
QWidget::connect(time, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(TimeChanged(int)));
|
||||
|
||||
PopulateMediaSelection(mediaSources);
|
||||
populateMediaSelection(mediaSources);
|
||||
populateMediaStates(states);
|
||||
populateTimeRestrictions(timeRestrictions);
|
||||
|
||||
@@ -486,7 +483,7 @@ MediaSwitchWidget::MediaSwitchWidget(QWidget *parent, MediaSwitch *s)
|
||||
{"{{time}}", time},
|
||||
{"{{scenes}}", scenes},
|
||||
{"{{transitions}}", transitions}};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.mediaTab.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.mediaTab.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -563,5 +560,3 @@ void MediaSwitchWidget::TimeChanged(int time)
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->time = time;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr auto media_func = 6;
|
||||
|
||||
typedef enum {
|
||||
@@ -85,5 +83,3 @@ private:
|
||||
|
||||
MediaSwitch *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -7,12 +7,8 @@ Most of this code is based on https://github.com/Palakis/obs-websocket
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "scene-switch-helpers.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
#define PARAM_SERVER_ENABLE "ServerEnabled"
|
||||
#define PARAM_SERVER_PORT "ServerPort"
|
||||
#define PARAM_LOCKTOIPV4 "LockToIPv4"
|
||||
@@ -128,9 +124,10 @@ WSServer::WSServer() : QObject(nullptr), _connections(), _clMutex()
|
||||
_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));
|
||||
_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()
|
||||
@@ -224,7 +221,7 @@ void WSServer::stop()
|
||||
blog(LOG_INFO, "server stopped successfully");
|
||||
}
|
||||
|
||||
void WSServer::sendMessage(SceneSwitchInfo sceneSwitch, bool preview)
|
||||
void WSServer::sendMessage(sceneSwitchInfo sceneSwitch, bool preview)
|
||||
{
|
||||
if (!sceneSwitch.scene) {
|
||||
return;
|
||||
@@ -308,9 +305,9 @@ std::string processMessage(std::string payload)
|
||||
"'";
|
||||
}
|
||||
if (preview) {
|
||||
SwitchPreviewScene(scene);
|
||||
switchPreviewScene(scene);
|
||||
} else {
|
||||
SwitchScene({scene, transition, duration});
|
||||
switchScene({scene, transition, duration});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -364,10 +361,11 @@ WSClient::WSClient() : QObject(nullptr)
|
||||
_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));
|
||||
_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()
|
||||
@@ -503,7 +501,7 @@ void SwitcherData::saveNetworkSwitches(obs_data_t *obj)
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupNetworkTab()
|
||||
void AdvSceneSwitcher::setupNetworkTab()
|
||||
{
|
||||
ui->serverSettings->setChecked(switcher->networkConfig.ServerEnabled);
|
||||
ui->serverPort->setValue(switcher->networkConfig.ServerPort);
|
||||
@@ -521,9 +519,9 @@ void AdvSceneSwitcher::SetupNetworkTab()
|
||||
|
||||
QTimer *statusTimer = new QTimer(this);
|
||||
connect(statusTimer, SIGNAL(timeout()), this,
|
||||
SLOT(UpdateClientStatus()));
|
||||
SLOT(updateClientStatus()));
|
||||
connect(statusTimer, SIGNAL(timeout()), this,
|
||||
SLOT(UpdateServerStatus()));
|
||||
SLOT(updateServerStatus()));
|
||||
statusTimer->start(500);
|
||||
}
|
||||
|
||||
@@ -574,7 +572,7 @@ void AdvSceneSwitcher::on_serverRestart_clicked()
|
||||
switcher->networkConfig.LockToIPv4);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::UpdateServerStatus()
|
||||
void AdvSceneSwitcher::updateServerStatus()
|
||||
{
|
||||
switch (switcher->serverStatus) {
|
||||
case ServerStatus::NOT_RUNNING:
|
||||
@@ -672,7 +670,7 @@ void AdvSceneSwitcher::on_clientReconnect_clicked()
|
||||
switcher->client.connect(switcher->networkConfig.GetClientUri());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::UpdateClientStatus()
|
||||
void AdvSceneSwitcher::updateClientStatus()
|
||||
{
|
||||
switch (switcher->clientStatus) {
|
||||
case ClientStatus::DISCONNECTED:
|
||||
@@ -711,5 +709,3 @@ Compatability::StdFunctionRunnable::StdFunctionRunnable(
|
||||
: cb(std::move(func))
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -19,13 +19,11 @@ Most of this code is based on https://github.com/Palakis/obs-websocket
|
||||
#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;
|
||||
struct sceneSwitchInfo;
|
||||
|
||||
class NetworkConfig {
|
||||
public:
|
||||
@@ -62,7 +60,7 @@ public:
|
||||
virtual ~WSServer();
|
||||
void start(quint16 port, bool lockToIPv4);
|
||||
void stop();
|
||||
void sendMessage(SceneSwitchInfo sceneSwitch, bool preview = false);
|
||||
void sendMessage(sceneSwitchInfo sceneSwitch, bool preview = false);
|
||||
QThreadPool *threadPool() { return &_threadPool; }
|
||||
|
||||
private:
|
||||
@@ -133,5 +131,3 @@ public:
|
||||
|
||||
QRunnable *CreateFunctionRunnable(std::function<void()> func);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <regex>
|
||||
|
||||
namespace advss {
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
static QMetaObject::Connection addPulse;
|
||||
|
||||
@@ -247,7 +244,7 @@ void SwitcherData::loadPauseSwitches(obs_data_t *obj)
|
||||
obs_data_array_release(pauseArray);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupPauseTab()
|
||||
void AdvSceneSwitcher::setupPauseTab()
|
||||
{
|
||||
for (auto &s : switcher->pauseEntries) {
|
||||
QListWidgetItem *item;
|
||||
@@ -312,7 +309,7 @@ PauseEntryWidget::PauseEntryWidget(QWidget *parent, PauseEntry *s)
|
||||
|
||||
populatePauseTypes(pauseTypes);
|
||||
populatePauseTargets(pauseTargets);
|
||||
PopulateWindowSelection(windows);
|
||||
populateWindowSelection(windows);
|
||||
|
||||
windows->setEditable(true);
|
||||
windows->setMaxVisibleItems(20);
|
||||
@@ -338,7 +335,7 @@ PauseEntryWidget::PauseEntryWidget(QWidget *parent, PauseEntry *s)
|
||||
{"{{pauseTargets}}", pauseTargets},
|
||||
{"{{windows}}", windows}};
|
||||
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.pauseTab.pauseEntry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.pauseTab.pauseEntry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -413,5 +410,3 @@ bool PauseEntry::valid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class PauseType {
|
||||
Scene,
|
||||
Window,
|
||||
@@ -72,5 +70,3 @@ private:
|
||||
|
||||
PauseEntry *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
78
src/legacy/switch-priority.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
|
||||
void AdvSceneSwitcher::on_threadPriority_currentTextChanged(const QString &text)
|
||||
{
|
||||
if (loading || ui->threadPriority->count() !=
|
||||
(int)switcher->threadPriorities.size())
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
for (auto p : switcher->threadPriorities) {
|
||||
if (p.name == text.toUtf8().constData()) {
|
||||
switcher->threadPriority = p.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_priorityUp_clicked()
|
||||
{
|
||||
int currentIndex = ui->priorityList->currentRow();
|
||||
if (currentIndex != -1 && currentIndex != 0) {
|
||||
ui->priorityList->insertItem(
|
||||
currentIndex - 1,
|
||||
ui->priorityList->takeItem(currentIndex));
|
||||
ui->priorityList->setCurrentRow(currentIndex - 1);
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
iter_swap(switcher->functionNamesByPriority.begin() +
|
||||
currentIndex,
|
||||
switcher->functionNamesByPriority.begin() +
|
||||
currentIndex - 1);
|
||||
}
|
||||
ui->macroPriorityWarning->setVisible(
|
||||
switcher->functionNamesByPriority[0] != macro_func);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_priorityDown_clicked()
|
||||
{
|
||||
int currentIndex = ui->priorityList->currentRow();
|
||||
if (currentIndex != -1 &&
|
||||
currentIndex != ui->priorityList->count() - 1) {
|
||||
ui->priorityList->insertItem(
|
||||
currentIndex + 1,
|
||||
ui->priorityList->takeItem(currentIndex));
|
||||
ui->priorityList->setCurrentRow(currentIndex + 1);
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
iter_swap(switcher->functionNamesByPriority.begin() +
|
||||
currentIndex,
|
||||
switcher->functionNamesByPriority.begin() +
|
||||
currentIndex + 1);
|
||||
}
|
||||
ui->macroPriorityWarning->setVisible(
|
||||
switcher->functionNamesByPriority[0] != macro_func);
|
||||
}
|
||||
|
||||
bool SwitcherData::prioFuncsValid()
|
||||
{
|
||||
auto fNBPCopy = functionNamesByPriority;
|
||||
|
||||
std::sort(fNBPCopy.begin(), fNBPCopy.end());
|
||||
auto it = std::unique(fNBPCopy.begin(), fNBPCopy.end());
|
||||
bool wasUnique = (it == fNBPCopy.end());
|
||||
|
||||
if (!wasUnique) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int p : functionNamesByPriority) {
|
||||
if (p < 0 || p > 10) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <random>
|
||||
|
||||
namespace advss {
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
bool RandomSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
@@ -116,7 +113,7 @@ void SwitcherData::loadRandomSwitches(obs_data_t *obj)
|
||||
obs_data_array_release(randomArray);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupRandomTab()
|
||||
void AdvSceneSwitcher::setupRandomTab()
|
||||
{
|
||||
for (auto &s : switcher->randomSwitches) {
|
||||
QListWidgetItem *item;
|
||||
@@ -143,8 +140,7 @@ void AdvSceneSwitcher::SetupRandomTab()
|
||||
border-radius: 7px; \
|
||||
border-color: rgb(0,0,0,0) \
|
||||
}");
|
||||
if (switcher->switchIfNotMatching !=
|
||||
SwitcherData::NoMatch::RANDOM_SWITCH) {
|
||||
if (switcher->switchIfNotMatching != RANDOM_SWITCH) {
|
||||
if (!switcher->disableHints) {
|
||||
PulseWidget(ui->randomDisabledWarning, QColor(Qt::red),
|
||||
QColor(0, 0, 0, 0));
|
||||
@@ -186,7 +182,7 @@ RandomSwitchWidget::RandomSwitchWidget(QWidget *parent, RandomSwitch *s)
|
||||
{"{{scenes}}", scenes},
|
||||
{"{{transitions}}", transitions},
|
||||
{"{{delay}}", delay}};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.randomTab.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.randomTab.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -224,5 +220,3 @@ void RandomSwitchWidget::DelayChanged(double d)
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->delay = d;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
struct RandomSwitch : SceneSwitcherEntry {
|
||||
static bool pause;
|
||||
double delay = 0.0;
|
||||
@@ -38,5 +36,3 @@ private:
|
||||
|
||||
RandomSwitch *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
namespace advss {
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
bool ScreenRegionSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
|
||||
void AdvSceneSwitcher::ClearFrames(QListWidget *list)
|
||||
void AdvSceneSwitcher::clearFrames(QListWidget *list)
|
||||
{
|
||||
for (int i = 0; i < list->count(); ++i) {
|
||||
ScreenRegionWidget *sw =
|
||||
@@ -51,7 +48,7 @@ void AdvSceneSwitcher::on_showFrame_clicked()
|
||||
showCurrentFrame(ui->screenRegionSwitches);
|
||||
} else {
|
||||
SetShowFrames();
|
||||
ClearFrames(ui->screenRegionSwitches);
|
||||
clearFrames(ui->screenRegionSwitches);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +59,7 @@ void AdvSceneSwitcher::on_screenRegionSwitches_currentRowChanged(int idx)
|
||||
}
|
||||
|
||||
if (switcher->showFrame) {
|
||||
ClearFrames(ui->screenRegionSwitches);
|
||||
clearFrames(ui->screenRegionSwitches);
|
||||
showCurrentFrame(ui->screenRegionSwitches);
|
||||
}
|
||||
}
|
||||
@@ -156,7 +153,7 @@ bool SwitcherData::checkScreenRegionSwitch(OBSWeakSource &scene,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::pair<int, int> cursorPos = GetCursorPos();
|
||||
std::pair<int, int> cursorPos = getCursorPos();
|
||||
int minRegionSize = 99999;
|
||||
bool match = false;
|
||||
|
||||
@@ -191,7 +188,7 @@ bool SwitcherData::checkScreenRegionSwitch(OBSWeakSource &scene,
|
||||
|
||||
void AdvSceneSwitcher::updateScreenRegionCursorPos()
|
||||
{
|
||||
std::pair<int, int> position = GetCursorPos();
|
||||
std::pair<int, int> position = getCursorPos();
|
||||
ui->cursorXPosition->setText(QString::number(position.first));
|
||||
ui->cursorYPosition->setText(QString::number(position.second));
|
||||
}
|
||||
@@ -231,7 +228,7 @@ void SwitcherData::loadScreenRegionSwitches(obs_data_t *obj)
|
||||
obs_data_array_release(screenRegionArray);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupRegionTab()
|
||||
void AdvSceneSwitcher::setupRegionTab()
|
||||
{
|
||||
for (auto &s : switcher->screenRegionSwitches) {
|
||||
QListWidgetItem *item;
|
||||
@@ -321,7 +318,7 @@ ScreenRegionWidget::ScreenRegionWidget(QWidget *parent, ScreenRegionSwitch *s)
|
||||
QWidget::connect(maxY, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(MaxYChanged(int)));
|
||||
|
||||
PopulateSceneSelection(
|
||||
populateSceneSelection(
|
||||
excludeScenes, false, false, false, false, nullptr, true,
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.screenRegionTab.excludeScenes.None"),
|
||||
@@ -345,7 +342,7 @@ ScreenRegionWidget::ScreenRegionWidget(QWidget *parent, ScreenRegionSwitch *s)
|
||||
{"{{scenes}}", scenes},
|
||||
{"{{transitions}}", transitions},
|
||||
{"{{excludeScenes}}", excludeScenes}};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.screenRegionTab.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.screenRegionTab.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -458,5 +455,3 @@ void ScreenRegionWidget::drawFrame()
|
||||
switchData->maxY - switchData->minY);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#include <QSpinBox>
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr auto screen_region_func = 4;
|
||||
|
||||
struct ScreenRegionSwitch : SceneSwitcherEntry {
|
||||
@@ -57,5 +55,3 @@ private:
|
||||
|
||||
void drawFrame();
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QTextStream>
|
||||
#include <QScrollArea>
|
||||
|
||||
namespace advss {
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
constexpr auto max_extend_text_size = 150;
|
||||
|
||||
@@ -281,7 +278,7 @@ void SwitcherData::loadSceneSequenceSwitches(obs_data_t *obj)
|
||||
obs_data_array_release(sceneSequenceArray);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupSequenceTab()
|
||||
void AdvSceneSwitcher::setupSequenceTab()
|
||||
{
|
||||
for (auto &s : switcher->sceneSequenceSwitches) {
|
||||
QListWidgetItem *item;
|
||||
@@ -458,7 +455,7 @@ bool SceneSequenceSwitch::checkDurationMatchInterruptible()
|
||||
|
||||
void SceneSequenceSwitch::prepareUninterruptibleMatch(int &linger)
|
||||
{
|
||||
int dur = delay.Milliseconds();
|
||||
int dur = delay.seconds * 1000;
|
||||
if (dur > 0) {
|
||||
linger = dur;
|
||||
}
|
||||
@@ -591,8 +588,10 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s,
|
||||
QWidget::connect(scenes, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SceneChanged(const QString &)));
|
||||
|
||||
QWidget::connect(delay, SIGNAL(DurationChanged(const Duration &)), this,
|
||||
SLOT(DelayChanged(const Duration &)));
|
||||
QWidget::connect(delay, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(DelayChanged(double)));
|
||||
QWidget::connect(delay, SIGNAL(UnitChanged(DurationUnit)), this,
|
||||
SLOT(DelayUnitsChanged(DurationUnit)));
|
||||
QWidget::connect(startScenes,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
SLOT(StartSceneChanged(const QString &)));
|
||||
@@ -604,7 +603,7 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s,
|
||||
QWidget::connect(reduce, SIGNAL(clicked()), this,
|
||||
SLOT(ReduceClicked()));
|
||||
|
||||
PopulateSceneSelection(startScenes);
|
||||
populateSceneSelection(startScenes);
|
||||
interruptible->setToolTip(obs_module_text(
|
||||
"AdvSceneSwitcher.sceneSequenceTab.interruptibleHint"));
|
||||
|
||||
@@ -616,7 +615,7 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s,
|
||||
{"{{scenes}}", scenes},
|
||||
{"{{delay}}", delay},
|
||||
{"{{transitions}}", transitions}};
|
||||
PlaceWidgets(
|
||||
placeWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.sceneSequenceTab.extendEntry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
@@ -629,7 +628,7 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s,
|
||||
{"{{delay}}", delay},
|
||||
{"{{transitions}}", transitions},
|
||||
{"{{interruptible}}", interruptible}};
|
||||
PlaceWidgets(obs_module_text(
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.sceneSequenceTab.entry"),
|
||||
startSequence, widgetPlaceholders);
|
||||
|
||||
@@ -690,14 +689,24 @@ void SequenceWidget::swapSwitchData(SequenceWidget *s1, SequenceWidget *s2)
|
||||
s2->setSwitchData(t);
|
||||
}
|
||||
|
||||
void SequenceWidget::DelayChanged(const Duration &delay)
|
||||
void SequenceWidget::DelayChanged(double sec)
|
||||
{
|
||||
if (loading || !switchData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->delay = delay;
|
||||
switchData->delay.seconds = sec;
|
||||
}
|
||||
|
||||
void SequenceWidget::DelayUnitsChanged(DurationUnit unit)
|
||||
{
|
||||
if (loading || !switchData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->delay.displayUnit = unit;
|
||||
}
|
||||
|
||||
void SequenceWidget::setExtendedSequenceStartScene()
|
||||
@@ -796,5 +805,3 @@ void SequenceWidget::ReduceClicked()
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
#include "switch-generic.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr auto round_trip_func = 1;
|
||||
|
||||
struct SceneSequenceSwitch : SceneSwitcherEntry {
|
||||
@@ -61,7 +59,8 @@ public:
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const QString &text);
|
||||
void DelayChanged(const Duration &delay);
|
||||
void DelayChanged(double delay);
|
||||
void DelayUnitsChanged(DurationUnit);
|
||||
void StartSceneChanged(const QString &text);
|
||||
void InterruptibleChanged(int state);
|
||||
void ExtendClicked();
|
||||
@@ -84,5 +83,3 @@ protected:
|
||||
|
||||
SceneSequenceSwitch *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
bool TimeSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
|
||||
@@ -182,7 +179,7 @@ void SwitcherData::loadTimeSwitches(obs_data_t *obj)
|
||||
obs_data_array_release(timeArray);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupTimeTab()
|
||||
void AdvSceneSwitcher::setupTimeTab()
|
||||
{
|
||||
for (auto &s : switcher->timeSwitches) {
|
||||
QListWidgetItem *item;
|
||||
@@ -261,7 +258,7 @@ TimeSwitchWidget::TimeSwitchWidget(QWidget *parent, TimeSwitch *s)
|
||||
{"{{time}}", time},
|
||||
{"{{scenes}}", scenes},
|
||||
{"{{transitions}}", transitions}};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.timeTab.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.timeTab.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -309,5 +306,3 @@ void TimeSwitchWidget::TimeChanged(const QTime &time)
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->time = time;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr auto time_func = 7;
|
||||
|
||||
typedef enum {
|
||||
@@ -56,5 +54,3 @@ private:
|
||||
|
||||
TimeSwitch *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <thread>
|
||||
|
||||
namespace advss {
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
constexpr auto default_def_transition_dealy = 300;
|
||||
bool DefaultSceneTransition::pause = false;
|
||||
@@ -172,7 +169,7 @@ void SwitcherData::checkDefaultSceneTransitions()
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::DefTransitionDelayValueChanged(int value)
|
||||
void AdvSceneSwitcher::defTransitionDelayValueChanged(int value)
|
||||
{
|
||||
if (loading) {
|
||||
return;
|
||||
@@ -182,6 +179,104 @@ void AdvSceneSwitcher::DefTransitionDelayValueChanged(int value)
|
||||
DefaultSceneTransition::delay = value;
|
||||
}
|
||||
|
||||
std::pair<obs_weak_source_t *, int> getNextTransition(obs_weak_source_t *scene1,
|
||||
obs_weak_source_t *scene2)
|
||||
{
|
||||
obs_weak_source_t *ws = nullptr;
|
||||
int duration = 0;
|
||||
if (scene1 && scene2) {
|
||||
for (SceneTransition &t : switcher->sceneTransitions) {
|
||||
if (!t.initialized()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t.scene == scene1 && t.scene2 == scene2) {
|
||||
ws = t.transition;
|
||||
duration = t.duration * 1000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::make_pair(ws, duration);
|
||||
}
|
||||
|
||||
void overwriteTransitionOverride(const sceneSwitchInfo &ssi, transitionData &td)
|
||||
{
|
||||
obs_source_t *scene = obs_weak_source_get_source(ssi.scene);
|
||||
obs_data_t *data = obs_source_get_private_settings(scene);
|
||||
|
||||
td.name = obs_data_get_string(data, "transition");
|
||||
td.duration = obs_data_get_int(data, "transition_duration");
|
||||
|
||||
std::string name = GetWeakSourceName(ssi.transition);
|
||||
|
||||
obs_data_set_string(data, "transition", name.c_str());
|
||||
obs_data_set_int(data, "transition_duration", ssi.duration);
|
||||
|
||||
obs_data_release(data);
|
||||
obs_source_release(scene);
|
||||
}
|
||||
|
||||
void restoreTransitionOverride(obs_source_t *scene, const transitionData &td)
|
||||
{
|
||||
obs_data_t *data = obs_source_get_private_settings(scene);
|
||||
|
||||
obs_data_set_string(data, "transition", td.name.c_str());
|
||||
obs_data_set_int(data, "transition_duration", td.duration);
|
||||
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void setNextTransition(const sceneSwitchInfo &sceneSwitch,
|
||||
obs_source_t *currentSource, transitionData &td)
|
||||
{
|
||||
// Priority:
|
||||
// 1. Transition tab
|
||||
// 2. Individual switcher entry
|
||||
// 3. Current transition settings
|
||||
|
||||
// Transition Tab
|
||||
obs_weak_source_t *currentScene =
|
||||
obs_source_get_weak_source(currentSource);
|
||||
auto tinfo = getNextTransition(currentScene, sceneSwitch.scene);
|
||||
obs_weak_source_release(currentScene);
|
||||
|
||||
OBSWeakSource nextTransition = tinfo.first;
|
||||
int nextTransitionDuration = tinfo.second;
|
||||
|
||||
// Individual switcher entry
|
||||
if (!nextTransition) {
|
||||
nextTransition = sceneSwitch.transition;
|
||||
}
|
||||
if (!nextTransitionDuration) {
|
||||
nextTransitionDuration = sceneSwitch.duration;
|
||||
}
|
||||
|
||||
// Current transition settings
|
||||
if (!nextTransition) {
|
||||
auto ct = obs_frontend_get_current_transition();
|
||||
nextTransition = obs_source_get_weak_source(ct);
|
||||
obs_weak_source_release(nextTransition);
|
||||
obs_source_release(ct);
|
||||
}
|
||||
if (!nextTransitionDuration) {
|
||||
nextTransitionDuration = obs_frontend_get_transition_duration();
|
||||
}
|
||||
|
||||
if (switcher->adjustActiveTransitionType) {
|
||||
obs_frontend_set_transition_duration(nextTransitionDuration);
|
||||
auto t = obs_weak_source_get_source(nextTransition);
|
||||
obs_frontend_set_current_transition(t);
|
||||
obs_source_release(t);
|
||||
}
|
||||
|
||||
if (switcher->transitionOverrideOverride) {
|
||||
overwriteTransitionOverride({sceneSwitch.scene, nextTransition,
|
||||
nextTransitionDuration},
|
||||
td);
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::saveSceneTransitions(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *sceneTransitionsArray = obs_data_array_create();
|
||||
@@ -254,7 +349,7 @@ void SwitcherData::loadSceneTransitions(obs_data_t *obj)
|
||||
obs_data_get_int(obj, "defTransitionDelay");
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupTransitionsTab()
|
||||
void AdvSceneSwitcher::setupTransitionsTab()
|
||||
{
|
||||
for (auto &s : switcher->sceneTransitions) {
|
||||
QListWidgetItem *item;
|
||||
@@ -302,11 +397,11 @@ void AdvSceneSwitcher::SetupTransitionsTab()
|
||||
"AdvSceneSwitcher.transitionTab.defaultTransition.delay.help"));
|
||||
|
||||
QWidget::connect(defTransitionDelay, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(DefTransitionDelayValueChanged(int)));
|
||||
SLOT(defTransitionDelayValueChanged(int)));
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{defTransitionDelay}}", defTransitionDelay}};
|
||||
PlaceWidgets(
|
||||
placeWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.transitionTab.defaultTransition.delay"),
|
||||
ui->defTransitionDelayLayout, widgetPlaceholders);
|
||||
@@ -354,7 +449,7 @@ TransitionSwitchWidget::TransitionSwitchWidget(QWidget *parent,
|
||||
QWidget::connect(duration, SIGNAL(valueChanged(double)), this,
|
||||
SLOT(DurationChanged(double)));
|
||||
|
||||
PopulateSceneSelection(scenes2);
|
||||
populateSceneSelection(scenes2);
|
||||
|
||||
if (s) {
|
||||
scenes2->setCurrentText(GetWeakSourceName(s->scene2).c_str());
|
||||
@@ -367,7 +462,7 @@ TransitionSwitchWidget::TransitionSwitchWidget(QWidget *parent,
|
||||
{"{{scenes2}}", scenes2},
|
||||
{"{{duration}}", duration},
|
||||
{"{{transitions}}", transitions}};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.transitionTab.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.transitionTab.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -423,7 +518,7 @@ DefTransitionSwitchWidget::DefTransitionSwitchWidget(QWidget *parent,
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", scenes}, {"{{transitions}}", transitions}};
|
||||
PlaceWidgets(
|
||||
placeWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.transitionTab.defaultTransitionEntry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
@@ -497,5 +592,3 @@ void DefaultSceneTransition::setTransition()
|
||||
t = std::thread(setTransitionDelayed, transition, delay);
|
||||
t.detach();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
struct SceneTransition : SceneSwitcherEntry {
|
||||
OBSWeakSource scene2 = nullptr;
|
||||
double duration = 0.3;
|
||||
@@ -79,5 +77,3 @@ public:
|
||||
private:
|
||||
DefaultSceneTransition *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QBuffer>
|
||||
#include <QToolTip>
|
||||
#include <thread>
|
||||
|
||||
namespace advss {
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
bool VideoSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
@@ -185,7 +182,7 @@ void SwitcherData::loadVideoSwitches(obs_data_t *obj)
|
||||
obs_data_array_release(videoArray);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupVideoTab()
|
||||
void AdvSceneSwitcher::setupVideoTab()
|
||||
{
|
||||
for (auto &s : switcher->videoSwitches) {
|
||||
QListWidgetItem *item;
|
||||
@@ -431,7 +428,7 @@ VideoSwitchWidget::VideoSwitchWidget(QWidget *parent, VideoSwitch *s)
|
||||
{"{{ignoreInactiveSource}}", ignoreInactiveSource},
|
||||
{"{{scenes}}", scenes},
|
||||
{"{{transitions}}", transitions}};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.videoTab.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.videoTab.entry"),
|
||||
switchLayout, widgetPlaceholders);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
@@ -580,5 +577,3 @@ void VideoSwitchWidget::IgnoreInactiveChanged(int state)
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->ignoreInactiveSource = state;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
#include "switch-generic.hpp"
|
||||
#include "screenshot-helper.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr auto video_func = 9;
|
||||
|
||||
enum class videoSwitchType {
|
||||
@@ -82,5 +80,3 @@ private:
|
||||
|
||||
VideoSwitch *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "platform-funcs.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <regex>
|
||||
|
||||
namespace advss {
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
bool WindowSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
@@ -181,8 +177,8 @@ void checkWindowTitleSwitchDirect(WindowSwitch &s,
|
||||
OBSWeakSource &transition)
|
||||
{
|
||||
bool focus = (!s.focus || s.window == currentWindowTitle);
|
||||
bool fullscreen = (!s.fullscreen || IsFullscreen(s.window));
|
||||
bool max = (!s.maximized || IsMaximized(s.window));
|
||||
bool fullscreen = (!s.fullscreen || isFullscreen(s.window));
|
||||
bool max = (!s.maximized || isMaximized(s.window));
|
||||
|
||||
if (focus && fullscreen && max) {
|
||||
match = true;
|
||||
@@ -207,8 +203,8 @@ void checkWindowTitleSwitchRegex(WindowSwitch &s,
|
||||
}
|
||||
|
||||
bool focus = (!s.focus || window == currentWindowTitle);
|
||||
bool fullscreen = (!s.fullscreen || IsFullscreen(window));
|
||||
bool max = (!s.maximized || IsMaximized(window));
|
||||
bool fullscreen = (!s.fullscreen || isFullscreen(window));
|
||||
bool max = (!s.maximized || isMaximized(window));
|
||||
|
||||
if (focus && fullscreen && max) {
|
||||
match = true;
|
||||
@@ -319,7 +315,7 @@ void SwitcherData::loadWindowTitleSwitches(obs_data_t *obj)
|
||||
obs_data_array_release(ignoreWindowsArray);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupTitleTab()
|
||||
void AdvSceneSwitcher::setupTitleTab()
|
||||
{
|
||||
for (auto &s : switcher->windowSwitches) {
|
||||
QListWidgetItem *item;
|
||||
@@ -340,7 +336,7 @@ void AdvSceneSwitcher::SetupTitleTab()
|
||||
ui->windowHelp->setVisible(false);
|
||||
}
|
||||
|
||||
PopulateWindowSelection(ui->ignoreWindowsWindows);
|
||||
populateWindowSelection(ui->ignoreWindowsWindows);
|
||||
|
||||
for (auto &window : switcher->ignoreWindowsSwitches) {
|
||||
QString text = QString::fromStdString(window);
|
||||
@@ -398,7 +394,7 @@ WindowSwitchWidget::WindowSwitchWidget(QWidget *parent, WindowSwitch *s)
|
||||
QWidget::connect(focused, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(FocusChanged(int)));
|
||||
|
||||
PopulateWindowSelection(windows);
|
||||
populateWindowSelection(windows);
|
||||
|
||||
windows->setEditable(true);
|
||||
windows->setMaxVisibleItems(20);
|
||||
@@ -418,7 +414,7 @@ WindowSwitchWidget::WindowSwitchWidget(QWidget *parent, WindowSwitch *s)
|
||||
{"{{fullscreen}}", fullscreen},
|
||||
{"{{maximized}}", maximized},
|
||||
{"{{focused}}", focused}};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.windowTitleTab.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.windowTitleTab.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -486,5 +482,3 @@ void WindowSwitchWidget::FocusChanged(int state)
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switchData->focus = state;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr auto window_title_func = 5;
|
||||
|
||||
struct WindowSwitch : SceneSwitcherEntry {
|
||||
@@ -49,5 +47,3 @@ private:
|
||||
|
||||
WindowSwitch *switchData;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
namespace advss {
|
||||
|
||||
static Display *xdisplay = 0;
|
||||
|
||||
static QLibrary *libXtstHandle = nullptr;
|
||||
@@ -317,7 +315,7 @@ bool windowStatesAreSet(const std::string &windowTitle,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsMaximized(const std::string &title)
|
||||
bool isMaximized(const std::string &title)
|
||||
{
|
||||
std::vector<QString> states;
|
||||
states.emplace_back("_NET_WM_STATE_MAXIMIZED_VERT");
|
||||
@@ -325,19 +323,13 @@ bool IsMaximized(const std::string &title)
|
||||
return windowStatesAreSet(title, states);
|
||||
}
|
||||
|
||||
bool IsFullscreen(const std::string &title)
|
||||
bool isFullscreen(const std::string &title)
|
||||
{
|
||||
std::vector<QString> states;
|
||||
states.emplace_back("_NET_WM_STATE_FULLSCREEN");
|
||||
return windowStatesAreSet(title, states);
|
||||
}
|
||||
|
||||
std::optional<std::string> GetTextInWindow(const std::string &window)
|
||||
{
|
||||
// Not implemented
|
||||
return {};
|
||||
}
|
||||
|
||||
#ifdef USE_PROCPS
|
||||
void GetProcessList(QStringList &processes)
|
||||
{
|
||||
@@ -436,7 +428,7 @@ void GetForegroundProcessName(std::string &proc)
|
||||
proc = getProcNameFromPid(pid);
|
||||
}
|
||||
|
||||
bool IsInFocus(const QString &executable)
|
||||
bool isInFocus(const QString &executable)
|
||||
{
|
||||
std::string current;
|
||||
GetForegroundProcessName(current);
|
||||
@@ -450,7 +442,7 @@ bool IsInFocus(const QString &executable)
|
||||
return (equals || matches);
|
||||
}
|
||||
|
||||
int SecondsSinceLastInput()
|
||||
int secondsSinceLastInput()
|
||||
{
|
||||
if (!canGetIdleTime) {
|
||||
return 0;
|
||||
@@ -667,5 +659,3 @@ void PlatformCleanup()
|
||||
}
|
||||
cleanupDisplay();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#include "macro-action-audio.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr int64_t nsPerMs = 1000000;
|
||||
const std::string MacroActionAudio::id = "audio";
|
||||
|
||||
@@ -116,7 +114,7 @@ void MacroActionAudio::FadeVolume()
|
||||
int nrSteps = 0;
|
||||
float volStep = 0.;
|
||||
if (_fadeType == FadeType::DURATION) {
|
||||
nrSteps = _duration.Milliseconds() / fadeInterval.count();
|
||||
nrSteps = _duration.seconds * 1000 / fadeInterval.count();
|
||||
volStep = volDiff / nrSteps;
|
||||
} else {
|
||||
volStep = _rate / 1000.0f;
|
||||
@@ -214,7 +212,7 @@ void MacroActionAudio::LogAction() const
|
||||
vblog(LOG_INFO,
|
||||
"performed action \"%s\" for source \"%s\" with volume %d with fade %d %f",
|
||||
it->second.c_str(), _audioSource.ToString(true).c_str(),
|
||||
_volume.GetValue(), _fade, _duration.Seconds());
|
||||
_volume, _fade, _duration.seconds);
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown audio action %d",
|
||||
static_cast<int>(_action));
|
||||
@@ -227,16 +225,15 @@ bool MacroActionAudio::Save(obs_data_t *obj) const
|
||||
_duration.Save(obj);
|
||||
_audioSource.Save(obj, "audioSource");
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
obs_data_set_int(obj, "syncOffset", _syncOffset);
|
||||
obs_data_set_int(obj, "monitor", _monitorType);
|
||||
_syncOffset.Save(obj, "syncOffset");
|
||||
_balance.Save(obj, "balance");
|
||||
_volume.Save(obj, "volume");
|
||||
_rate.Save(obj, "rate");
|
||||
obs_data_set_double(obj, "balance", _balance);
|
||||
obs_data_set_int(obj, "volume", _volume);
|
||||
obs_data_set_double(obj, "rate", _rate);
|
||||
obs_data_set_bool(obj, "fade", _fade);
|
||||
obs_data_set_int(obj, "fadeType", static_cast<int>(_fadeType));
|
||||
obs_data_set_bool(obj, "wait", _wait);
|
||||
obs_data_set_bool(obj, "abortActiveFade", _abortActiveFade);
|
||||
obs_data_set_int(obj, "version", 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -246,19 +243,12 @@ bool MacroActionAudio::Load(obs_data_t *obj)
|
||||
_duration.Load(obj);
|
||||
_audioSource.Load(obj, "audioSource");
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
_syncOffset = obs_data_get_int(obj, "syncOffset");
|
||||
_monitorType = static_cast<obs_monitoring_type>(
|
||||
obs_data_get_int(obj, "monitor"));
|
||||
if (!obs_data_has_user_value(obj, "version")) {
|
||||
_syncOffset = obs_data_get_int(obj, "syncOffset");
|
||||
_balance = obs_data_get_double(obj, "balance");
|
||||
_volume = obs_data_get_int(obj, "volume");
|
||||
_rate = obs_data_get_double(obj, "rate");
|
||||
} else {
|
||||
_syncOffset.Load(obj, "syncOffset");
|
||||
_balance.Load(obj, "balance");
|
||||
_volume.Load(obj, "volume");
|
||||
_rate.Load(obj, "rate");
|
||||
}
|
||||
_balance = obs_data_get_double(obj, "balance");
|
||||
_volume = obs_data_get_int(obj, "volume");
|
||||
_rate = obs_data_get_double(obj, "rate");
|
||||
_fade = obs_data_get_bool(obj, "fade");
|
||||
if (obs_data_has_user_value(obj, "wait")) {
|
||||
_wait = obs_data_get_bool(obj, "wait");
|
||||
@@ -312,16 +302,16 @@ MacroActionAudioEdit::MacroActionAudioEdit(
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||
_actions(new QComboBox),
|
||||
_fadeTypes(new QComboBox),
|
||||
_syncOffset(new VariableSpinBox),
|
||||
_syncOffset(new QSpinBox),
|
||||
_monitorTypes(new QComboBox),
|
||||
_balance(new SliderSpinBox(
|
||||
0., 1., "",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.audio.balance.description"))),
|
||||
_volumePercent(new VariableSpinBox),
|
||||
_volumePercent(new QSpinBox),
|
||||
_fade(new QCheckBox),
|
||||
_duration(new DurationSelection(parent, false)),
|
||||
_rate(new VariableDoubleSpinBox),
|
||||
_rate(new QDoubleSpinBox),
|
||||
_wait(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.audio.fade.wait"))),
|
||||
_abortActiveFade(new QCheckBox(
|
||||
@@ -346,35 +336,27 @@ MacroActionAudioEdit::MacroActionAudioEdit(
|
||||
sources.sort();
|
||||
_sources->SetSourceNameList(sources);
|
||||
populateFadeTypeSelection(_fadeTypes);
|
||||
PopulateMonitorTypeSelection(_monitorTypes);
|
||||
populateMonitorTypeSelection(_monitorTypes);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||
SLOT(SourceChanged(const SourceSelection &)));
|
||||
QWidget::connect(
|
||||
_syncOffset,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||
this, SLOT(SyncOffsetChanged(const NumberVariable<int> &)));
|
||||
QWidget::connect(
|
||||
_balance,
|
||||
SIGNAL(DoubleValueChanged(const NumberVariable<double> &)),
|
||||
this, SLOT(BalanceChanged(const NumberVariable<double> &)));
|
||||
QWidget::connect(_syncOffset, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(SyncOffsetChanged(int)));
|
||||
QWidget::connect(_balance, SIGNAL(DoubleValueChanged(double)), this,
|
||||
SLOT(BalanceChanged(double)));
|
||||
QWidget::connect(_monitorTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(MonitorTypeChanged(int)));
|
||||
QWidget::connect(
|
||||
_volumePercent,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||
this, SLOT(VolumeChanged(const NumberVariable<int> &)));
|
||||
QWidget::connect(_volumePercent, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(VolumeChanged(int)));
|
||||
QWidget::connect(_fade, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(FadeChanged(int)));
|
||||
QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)),
|
||||
this, SLOT(DurationChanged(const Duration &)));
|
||||
QWidget::connect(
|
||||
_rate,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
|
||||
this, SLOT(RateChanged(const NumberVariable<double> &)));
|
||||
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(DurationChanged(double)));
|
||||
QWidget::connect(_rate, SIGNAL(valueChanged(double)), this,
|
||||
SLOT(RateChanged(double)));
|
||||
QWidget::connect(_wait, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(WaitChanged(int)));
|
||||
QWidget::connect(_abortActiveFade, SIGNAL(stateChanged(int)), this,
|
||||
@@ -397,10 +379,10 @@ MacroActionAudioEdit::MacroActionAudioEdit(
|
||||
{"{{fadeTypes}}", _fadeTypes},
|
||||
};
|
||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.audio.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.audio.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
_fadeTypeLayout = new QHBoxLayout;
|
||||
PlaceWidgets(
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.audio.fade.duration"),
|
||||
_fadeTypeLayout, widgetPlaceholders);
|
||||
|
||||
@@ -419,7 +401,7 @@ MacroActionAudioEdit::MacroActionAudioEdit(
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
static bool hasVolumeControl(MacroActionAudio::Action action)
|
||||
bool hasVolumeControl(MacroActionAudio::Action action)
|
||||
{
|
||||
return action == MacroActionAudio::Action::SOURCE_VOLUME ||
|
||||
action == MacroActionAudio::Action::MASTER_VOLUME;
|
||||
@@ -447,7 +429,7 @@ void MacroActionAudioEdit::SetWidgetVisibility()
|
||||
_fadeTypeLayout->removeWidget(_fadeTypes);
|
||||
_fadeTypeLayout->removeWidget(_duration);
|
||||
_fadeTypeLayout->removeWidget(_rate);
|
||||
ClearLayout(_fadeTypeLayout);
|
||||
clearLayout(_fadeTypeLayout);
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{fade}}", _fade},
|
||||
{"{{duration}}", _duration},
|
||||
@@ -455,12 +437,12 @@ void MacroActionAudioEdit::SetWidgetVisibility()
|
||||
{"{{fadeTypes}}", _fadeTypes},
|
||||
};
|
||||
if (_entryData->_fadeType == MacroActionAudio::FadeType::DURATION) {
|
||||
PlaceWidgets(
|
||||
placeWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.audio.fade.duration"),
|
||||
_fadeTypeLayout, widgetPlaceholders);
|
||||
} else {
|
||||
PlaceWidgets(obs_module_text(
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.action.audio.fade.rate"),
|
||||
_fadeTypeLayout, widgetPlaceholders);
|
||||
}
|
||||
@@ -470,9 +452,9 @@ void MacroActionAudioEdit::SetWidgetVisibility()
|
||||
_rate->setVisible(_entryData->_fadeType ==
|
||||
MacroActionAudio::FadeType::RATE);
|
||||
|
||||
SetLayoutVisible(_fadeTypeLayout,
|
||||
setLayoutVisible(_fadeTypeLayout,
|
||||
hasVolumeControl(_entryData->_action));
|
||||
SetLayoutVisible(_fadeOptionsLayout,
|
||||
setLayoutVisible(_fadeOptionsLayout,
|
||||
hasVolumeControl(_entryData->_action));
|
||||
adjustSize();
|
||||
}
|
||||
@@ -486,13 +468,13 @@ void MacroActionAudioEdit::UpdateEntryData()
|
||||
_sources->SetSource(_entryData->_audioSource);
|
||||
_actions->setCurrentIndex(
|
||||
_actions->findData(static_cast<int>(_entryData->_action)));
|
||||
_syncOffset->SetValue(_entryData->_syncOffset);
|
||||
_syncOffset->setValue(_entryData->_syncOffset);
|
||||
_monitorTypes->setCurrentIndex(_entryData->_monitorType);
|
||||
_balance->SetDoubleValue(_entryData->_balance);
|
||||
_volumePercent->SetValue(_entryData->_volume);
|
||||
_volumePercent->setValue(_entryData->_volume);
|
||||
_fade->setChecked(_entryData->_fade);
|
||||
_duration->SetDuration(_entryData->_duration);
|
||||
_rate->SetValue(_entryData->_rate);
|
||||
_rate->setValue(_entryData->_rate);
|
||||
_wait->setChecked(_entryData->_wait);
|
||||
_abortActiveFade->setChecked(_entryData->_abortActiveFade);
|
||||
_fadeTypes->setCurrentIndex(static_cast<int>(_entryData->_fadeType));
|
||||
@@ -505,7 +487,7 @@ void MacroActionAudioEdit::SourceChanged(const SourceSelection &source)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_audioSource = source;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
@@ -517,19 +499,19 @@ void MacroActionAudioEdit::ActionChanged(int idx)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<MacroActionAudio::Action>(
|
||||
_actions->itemData(idx).toInt());
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionAudioEdit::SyncOffsetChanged(const NumberVariable<int> &value)
|
||||
void MacroActionAudioEdit::SyncOffsetChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_syncOffset = value;
|
||||
}
|
||||
|
||||
@@ -539,27 +521,27 @@ void MacroActionAudioEdit::MonitorTypeChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_monitorType = static_cast<obs_monitoring_type>(value);
|
||||
}
|
||||
|
||||
void MacroActionAudioEdit::BalanceChanged(const NumberVariable<double> &value)
|
||||
void MacroActionAudioEdit::BalanceChanged(double value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_balance = value;
|
||||
}
|
||||
|
||||
void MacroActionAudioEdit::VolumeChanged(const NumberVariable<int> &value)
|
||||
void MacroActionAudioEdit::VolumeChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_volume = value;
|
||||
}
|
||||
|
||||
@@ -569,28 +551,28 @@ void MacroActionAudioEdit::FadeChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_fade = value;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionAudioEdit::DurationChanged(const Duration &dur)
|
||||
void MacroActionAudioEdit::DurationChanged(double seconds)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_duration = dur;
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration.seconds = seconds;
|
||||
}
|
||||
|
||||
void MacroActionAudioEdit::RateChanged(const NumberVariable<double> &value)
|
||||
void MacroActionAudioEdit::RateChanged(double value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rate = value;
|
||||
}
|
||||
|
||||
@@ -600,7 +582,7 @@ void MacroActionAudioEdit::WaitChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_wait = value;
|
||||
}
|
||||
|
||||
@@ -610,7 +592,7 @@ void MacroActionAudioEdit::AbortActiveFadeChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_abortActiveFade = value;
|
||||
}
|
||||
|
||||
@@ -620,9 +602,7 @@ void MacroActionAudioEdit::FadeTypeChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_fadeType = static_cast<MacroActionAudio::FadeType>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#include <QCheckBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionAudio : public MacroAction {
|
||||
public:
|
||||
MacroActionAudio(Macro *m) : MacroAction(m) {}
|
||||
@@ -44,13 +42,13 @@ public:
|
||||
|
||||
Action _action = Action::MUTE;
|
||||
FadeType _fadeType = FadeType::DURATION;
|
||||
NumberVariable<int> _syncOffset = 0;
|
||||
int64_t _syncOffset = 0;
|
||||
obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE;
|
||||
NumberVariable<double> _balance = 0.5;
|
||||
NumberVariable<int> _volume = 0;
|
||||
double _balance = 0.5;
|
||||
int _volume = 0;
|
||||
bool _fade = false;
|
||||
Duration _duration;
|
||||
NumberVariable<double> _rate = 100.;
|
||||
double _rate = 100.;
|
||||
bool _wait = false;
|
||||
bool _abortActiveFade = false;
|
||||
|
||||
@@ -86,13 +84,13 @@ public:
|
||||
private slots:
|
||||
void SourceChanged(const SourceSelection &);
|
||||
void ActionChanged(int value);
|
||||
void SyncOffsetChanged(const NumberVariable<int> &value);
|
||||
void SyncOffsetChanged(int value);
|
||||
void MonitorTypeChanged(int value);
|
||||
void BalanceChanged(const NumberVariable<double> &value);
|
||||
void VolumeChanged(const NumberVariable<int> &value);
|
||||
void BalanceChanged(double value);
|
||||
void VolumeChanged(int value);
|
||||
void FadeChanged(int value);
|
||||
void DurationChanged(const Duration &seconds);
|
||||
void RateChanged(const NumberVariable<double> &value);
|
||||
void DurationChanged(double seconds);
|
||||
void RateChanged(double value);
|
||||
void WaitChanged(int value);
|
||||
void AbortActiveFadeChanged(int value);
|
||||
void FadeTypeChanged(int value);
|
||||
@@ -103,13 +101,13 @@ protected:
|
||||
SourceSelectionWidget *_sources;
|
||||
QComboBox *_actions;
|
||||
QComboBox *_fadeTypes;
|
||||
VariableSpinBox *_syncOffset;
|
||||
QSpinBox *_syncOffset;
|
||||
QComboBox *_monitorTypes;
|
||||
SliderSpinBox *_balance;
|
||||
VariableSpinBox *_volumePercent;
|
||||
QSpinBox *_volumePercent;
|
||||
QCheckBox *_fade;
|
||||
DurationSelection *_duration;
|
||||
VariableDoubleSpinBox *_rate;
|
||||
QDoubleSpinBox *_rate;
|
||||
QCheckBox *_wait;
|
||||
QCheckBox *_abortActiveFade;
|
||||
QHBoxLayout *_fadeTypeLayout;
|
||||
@@ -121,5 +119,3 @@ private:
|
||||
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "macro-action-scene-switch.hpp"
|
||||
#include "section.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
std::map<std::string, MacroActionInfo> &MacroActionFactory::GetMap()
|
||||
{
|
||||
static std::map<std::string, MacroActionInfo> _methods;
|
||||
@@ -157,7 +154,7 @@ std::shared_ptr<MacroSegment> MacroActionEdit::Data()
|
||||
|
||||
void AdvSceneSwitcher::AddMacroAction(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
@@ -196,7 +193,7 @@ void AdvSceneSwitcher::AddMacroAction(int idx)
|
||||
|
||||
void AdvSceneSwitcher::on_actionAdd_clicked()
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
@@ -214,7 +211,7 @@ void AdvSceneSwitcher::on_actionAdd_clicked()
|
||||
|
||||
void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
@@ -240,7 +237,7 @@ void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
||||
void AdvSceneSwitcher::on_actionRemove_clicked()
|
||||
{
|
||||
if (currentActionIdx == -1) {
|
||||
auto macro = GetSelectedMacro();
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
@@ -292,7 +289,7 @@ void AdvSceneSwitcher::SwapActions(Macro *m, int pos1, int pos2)
|
||||
|
||||
void AdvSceneSwitcher::MoveMacroActionUp(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
@@ -307,7 +304,7 @@ void AdvSceneSwitcher::MoveMacroActionUp(int idx)
|
||||
|
||||
void AdvSceneSwitcher::MoveMacroActionDown(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
@@ -322,7 +319,7 @@ void AdvSceneSwitcher::MoveMacroActionDown(int idx)
|
||||
|
||||
void AdvSceneSwitcher::MacroActionSelectionChanged(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
@@ -342,7 +339,7 @@ void AdvSceneSwitcher::MacroActionSelectionChanged(int idx)
|
||||
|
||||
void AdvSceneSwitcher::MacroActionReorder(int to, int from)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
@@ -364,5 +361,3 @@ void AdvSceneSwitcher::MacroActionReorder(int to, int from)
|
||||
HighlightAction(to);
|
||||
emit(MacroSegmentOrderChanged());
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
#include <QComboBox>
|
||||
#include <memory>
|
||||
|
||||
namespace advss {
|
||||
|
||||
struct MacroActionInfo {
|
||||
using TCreateMethod = std::shared_ptr<MacroAction> (*)(Macro *m);
|
||||
using TCreateWidgetMethod = QWidget *(*)(QWidget *parent,
|
||||
@@ -53,5 +51,3 @@ private:
|
||||
std::shared_ptr<MacroAction> *_entryData;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#include "macro-action-file.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QFileDialog>
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionFile::id = "file";
|
||||
|
||||
bool MacroActionFile::_registered = MacroActionFactory::Register(
|
||||
@@ -56,7 +55,7 @@ void MacroActionFile::LogAction() const
|
||||
bool MacroActionFile::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_file.Save(obj, "file");
|
||||
obs_data_set_string(obj, "file", _file.c_str());
|
||||
_text.Save(obj, "text");
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
return true;
|
||||
@@ -65,7 +64,7 @@ bool MacroActionFile::Save(obs_data_t *obj) const
|
||||
bool MacroActionFile::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_file.Load(obj, "file");
|
||||
_file = obs_data_get_string(obj, "file");
|
||||
_text.Load(obj, "text");
|
||||
_action = static_cast<FileAction>(obs_data_get_int(obj, "action"));
|
||||
return true;
|
||||
@@ -73,7 +72,7 @@ bool MacroActionFile::Load(obs_data_t *obj)
|
||||
|
||||
std::string MacroActionFile::GetShortDesc() const
|
||||
{
|
||||
return _file.UnresolvedValue();
|
||||
return _file;
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
@@ -107,7 +106,7 @@ MacroActionFileEdit::MacroActionFileEdit(
|
||||
{"{{matchText}}", _text},
|
||||
{"{{actions}}", _actions},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.file.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.file.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
@@ -140,7 +139,7 @@ void MacroActionFileEdit::PathChanged(const QString &text)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_file = text.toUtf8().constData();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
@@ -152,7 +151,7 @@ void MacroActionFileEdit::TextChanged()
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_text = _text->toPlainText().toStdString();
|
||||
|
||||
adjustSize();
|
||||
@@ -165,8 +164,6 @@ void MacroActionFileEdit::ActionChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<FileAction>(value);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
#include <QSpinBox>
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class FileAction {
|
||||
WRITE,
|
||||
APPEND,
|
||||
@@ -26,8 +24,9 @@ public:
|
||||
return std::make_shared<MacroActionFile>(m);
|
||||
}
|
||||
|
||||
StringVariable _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
StringVariable _text = obs_module_text("AdvSceneSwitcher.enterText");
|
||||
std::string _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
VariableResolvingString _text =
|
||||
obs_module_text("AdvSceneSwitcher.enterText");
|
||||
FileAction _action = FileAction::WRITE;
|
||||
|
||||
private:
|
||||
@@ -67,5 +66,3 @@ protected:
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include "macro-action-filter.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionFilter::id = "filter";
|
||||
|
||||
bool MacroActionFilter::_registered = MacroActionFactory::Register(
|
||||
@@ -19,9 +18,24 @@ const static std::map<MacroActionFilter::Action, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.filter.type.settings"},
|
||||
};
|
||||
|
||||
void MacroActionFilter::ResolveVariables()
|
||||
{
|
||||
if (_source.GetType() == SourceSelection::Type::SOURCE) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string name = GetWeakSourceName(_filter);
|
||||
if (!name.empty()) {
|
||||
_filterName = name;
|
||||
}
|
||||
_filter = GetWeakFilterByName(_source.GetSource(), _filterName.c_str());
|
||||
}
|
||||
|
||||
bool MacroActionFilter::PerformAction()
|
||||
{
|
||||
auto s = obs_weak_source_get_source(_filter.GetFilter(_source));
|
||||
ResolveVariables();
|
||||
|
||||
auto s = obs_weak_source_get_source(_filter);
|
||||
switch (_action) {
|
||||
case Action::ENABLE:
|
||||
obs_source_set_enabled(s, true);
|
||||
@@ -30,7 +44,7 @@ bool MacroActionFilter::PerformAction()
|
||||
obs_source_set_enabled(s, false);
|
||||
break;
|
||||
case Action::SETTINGS:
|
||||
SetSourceSettings(s, _settings);
|
||||
setSourceSettings(s, _settings);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -45,7 +59,7 @@ void MacroActionFilter::LogAction() const
|
||||
if (it != actionTypes.end()) {
|
||||
vblog(LOG_INFO,
|
||||
"performed action \"%s\" for filter \"%s\" on source \"%s\"",
|
||||
it->second.c_str(), _filter.ToString().c_str(),
|
||||
it->second.c_str(), GetWeakSourceName(_filter).c_str(),
|
||||
_source.ToString(true).c_str());
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown filter action %d",
|
||||
@@ -57,7 +71,7 @@ bool MacroActionFilter::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_source.Save(obj);
|
||||
_filter.Save(obj, "filter");
|
||||
obs_data_set_string(obj, "filter", _filterName.c_str());
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
_settings.Save(obj, "settings");
|
||||
return true;
|
||||
@@ -67,7 +81,9 @@ bool MacroActionFilter::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_source.Load(obj);
|
||||
_filter.Load(obj, _source, "filter");
|
||||
_filterName = obs_data_get_string(obj, "filter");
|
||||
_filter = GetWeakFilterByQString(_source.GetSource(),
|
||||
_filterName.c_str());
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
_settings.Load(obj, "settings");
|
||||
return true;
|
||||
@@ -75,8 +91,8 @@ bool MacroActionFilter::Load(obs_data_t *obj)
|
||||
|
||||
std::string MacroActionFilter::GetShortDesc() const
|
||||
{
|
||||
if (!_filter.ToString().empty() && !_source.ToString().empty()) {
|
||||
return _source.ToString() + " - " + _filter.ToString();
|
||||
if (_filter && !_source.ToString().empty()) {
|
||||
return _source.ToString() + " - " + GetWeakSourceName(_filter);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -92,7 +108,7 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionFilter> entryData)
|
||||
: QWidget(parent),
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||
_filters(new FilterSelectionWidget(this, _sources, true)),
|
||||
_filters(new QComboBox()),
|
||||
_actions(new QComboBox()),
|
||||
_getSettings(new QPushButton(obs_module_text(
|
||||
"AdvSceneSwitcher.action.filter.getSettings"))),
|
||||
@@ -110,9 +126,8 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||
SLOT(SourceChanged(const SourceSelection &)));
|
||||
QWidget::connect(_filters,
|
||||
SIGNAL(FilterChanged(const FilterSelection &)), this,
|
||||
SLOT(FilterChanged(const FilterSelection &)));
|
||||
QWidget::connect(_filters, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(FilterChanged(const QString &)));
|
||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||
SLOT(GetSettingsClicked()));
|
||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||
@@ -125,13 +140,12 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
{"{{actions}}", _actions}, {"{{settings}}", _settings},
|
||||
{"{{getSettings}}", _getSettings},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.filter.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.filter.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||
buttonLayout->addWidget(_getSettings);
|
||||
buttonLayout->addStretch();
|
||||
buttonLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
@@ -152,7 +166,9 @@ void MacroActionFilterEdit::UpdateEntryData()
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_sources->SetSource(_entryData->_source);
|
||||
_filters->SetFilter(_entryData->_source, _entryData->_filter);
|
||||
populateFilterSelection(_filters, _entryData->_source.GetSource());
|
||||
_filters->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_filter).c_str());
|
||||
_settings->setPlainText(_entryData->_settings);
|
||||
SetWidgetVisibility(_entryData->_action ==
|
||||
MacroActionFilter::Action::SETTINGS);
|
||||
@@ -166,19 +182,25 @@ void MacroActionFilterEdit::SourceChanged(const SourceSelection &source)
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_source = source;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = source;
|
||||
}
|
||||
_filters->clear();
|
||||
populateFilterSelection(_filters, _entryData->_source.GetSource());
|
||||
_filters->adjustSize();
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::FilterChanged(const FilterSelection &filter)
|
||||
void MacroActionFilterEdit::FilterChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_filter = filter;
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_filterName = text.toStdString();
|
||||
_entryData->_filter =
|
||||
GetWeakFilterByQString(_entryData->_source.GetSource(), text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
@@ -189,7 +211,7 @@ void MacroActionFilterEdit::ActionChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<MacroActionFilter::Action>(value);
|
||||
SetWidgetVisibility(_entryData->_action ==
|
||||
MacroActionFilter::Action::SETTINGS);
|
||||
@@ -197,13 +219,13 @@ void MacroActionFilterEdit::ActionChanged(int value)
|
||||
|
||||
void MacroActionFilterEdit::GetSettingsClicked()
|
||||
{
|
||||
if (_loading || !_entryData ||
|
||||
!_entryData->_filter.GetFilter(_entryData->_source)) {
|
||||
if (_loading || !_entryData || !_entryData->_source.GetSource() ||
|
||||
!_entryData->_filter) {
|
||||
return;
|
||||
}
|
||||
|
||||
_settings->setPlainText(FormatJsonString(GetSourceSettings(
|
||||
_entryData->_filter.GetFilter(_entryData->_source))));
|
||||
_settings->setPlainText(
|
||||
formatJsonString(getSourceSettings(_entryData->_filter)));
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SettingsChanged()
|
||||
@@ -212,7 +234,7 @@ void MacroActionFilterEdit::SettingsChanged()
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_settings = _settings->toPlainText().toStdString();
|
||||
|
||||
adjustSize();
|
||||
@@ -224,7 +246,4 @@ void MacroActionFilterEdit::SetWidgetVisibility(bool showSettings)
|
||||
_settings->setVisible(showSettings);
|
||||
_getSettings->setVisible(showSettings);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -2,14 +2,11 @@
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "variable-text-edit.hpp"
|
||||
#include "source-selection.hpp"
|
||||
#include "filter-selection.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QSpinBox>
|
||||
#include <QPushButton>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionFilter : public MacroAction {
|
||||
public:
|
||||
MacroActionFilter(Macro *m) : MacroAction(m) {}
|
||||
@@ -31,13 +28,18 @@ public:
|
||||
};
|
||||
|
||||
SourceSelection _source;
|
||||
FilterSelection _filter;
|
||||
OBSWeakSource _filter;
|
||||
Action _action = Action::ENABLE;
|
||||
StringVariable _settings = "";
|
||||
VariableResolvingString _settings = "";
|
||||
|
||||
private:
|
||||
void ResolveVariables();
|
||||
std::string _filterName = "";
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
|
||||
friend class MacroActionFilterEdit;
|
||||
};
|
||||
|
||||
class MacroActionFilterEdit : public QWidget {
|
||||
@@ -58,7 +60,7 @@ public:
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const SourceSelection &);
|
||||
void FilterChanged(const FilterSelection &);
|
||||
void FilterChanged(const QString &);
|
||||
void ActionChanged(int value);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
@@ -67,7 +69,7 @@ signals:
|
||||
|
||||
protected:
|
||||
SourceSelectionWidget *_sources;
|
||||
FilterSelectionWidget *_filters;
|
||||
QComboBox *_filters;
|
||||
QComboBox *_actions;
|
||||
QPushButton *_getSettings;
|
||||
VariableTextEdit *_settings;
|
||||
@@ -77,5 +79,3 @@ private:
|
||||
void SetWidgetVisibility(bool);
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
#include "macro-action-hotkey.hpp"
|
||||
#include "platform-funcs.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <obs-interaction.h>
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionHotkey::id = "hotkey";
|
||||
|
||||
bool MacroActionHotkey::_registered = MacroActionFactory::Register(
|
||||
@@ -133,8 +130,7 @@ static std::unordered_map<HotkeyType, long> keyTable = {
|
||||
//{HotkeyType::Key_NumpadEnter, ???},
|
||||
};
|
||||
|
||||
static obs_key_combination
|
||||
keysToOBSKeycombo(const std::vector<HotkeyType> &keys)
|
||||
obs_key_combination keysToOBSKeycombo(const std::vector<HotkeyType> &keys)
|
||||
{
|
||||
obs_key_combination combo{};
|
||||
auto it = keyTable.find(keys.back());
|
||||
@@ -182,7 +178,7 @@ keysToOBSKeycombo(const std::vector<HotkeyType> &keys)
|
||||
return combo;
|
||||
}
|
||||
|
||||
static void InjectKeys(const std::vector<HotkeyType> &keys, int duration)
|
||||
void InjectKeys(const std::vector<HotkeyType> &keys, int duration)
|
||||
{
|
||||
auto combo = keysToOBSKeycombo(keys);
|
||||
if (obs_key_combination_is_empty(combo)) {
|
||||
@@ -228,7 +224,7 @@ bool MacroActionHotkey::PerformAction()
|
||||
}
|
||||
|
||||
if (!keys.empty()) {
|
||||
int dur = _duration.Milliseconds();
|
||||
int dur = _duration;
|
||||
if (_onlySendToObs || !canSimulateKeyPresses) {
|
||||
std::thread t([keys, dur]() { InjectKeys(keys, dur); });
|
||||
t.detach();
|
||||
@@ -258,9 +254,8 @@ bool MacroActionHotkey::Save(obs_data_t *obj) const
|
||||
obs_data_set_bool(obj, "right_alt", _rightAlt);
|
||||
obs_data_set_bool(obj, "left_meta", _leftMeta);
|
||||
obs_data_set_bool(obj, "right_meta", _rightMeta);
|
||||
_duration.Save(obj);
|
||||
obs_data_set_int(obj, "duration", _duration);
|
||||
obs_data_set_bool(obj, "onlyOBS", _onlySendToObs);
|
||||
obs_data_set_int(obj, "version", 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -276,11 +271,7 @@ bool MacroActionHotkey::Load(obs_data_t *obj)
|
||||
_rightAlt = obs_data_get_bool(obj, "right_alt");
|
||||
_leftMeta = obs_data_get_bool(obj, "left_meta");
|
||||
_rightMeta = obs_data_get_bool(obj, "right_meta");
|
||||
if (!obs_data_has_user_value(obj, "version")) {
|
||||
_duration = obs_data_get_int(obj, "duration") / 1000.0;
|
||||
} else {
|
||||
_duration.Load(obj);
|
||||
}
|
||||
_duration = obs_data_get_int(obj, "duration");
|
||||
_onlySendToObs = obs_data_get_bool(obj, "onlyOBS");
|
||||
return true;
|
||||
}
|
||||
@@ -397,30 +388,32 @@ static inline void populateKeySelection(QComboBox *list)
|
||||
|
||||
MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionHotkey> entryData)
|
||||
: QWidget(parent),
|
||||
_keys(new QComboBox()),
|
||||
_leftShift(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftShift"))),
|
||||
_rightShift(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.action.hotkey.rightShift"))),
|
||||
_leftCtrl(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftCtrl"))),
|
||||
_rightCtrl(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightCtrl"))),
|
||||
_leftAlt(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftAlt"))),
|
||||
_rightAlt(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightAlt"))),
|
||||
_leftMeta(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftMeta"))),
|
||||
_rightMeta(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightMeta"))),
|
||||
_duration(new DurationSelection(this, false)),
|
||||
_onlySendToOBS(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.onlyOBS"))),
|
||||
_noKeyPressSimulationWarning(new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.disabled")))
|
||||
: QWidget(parent)
|
||||
{
|
||||
_keys = new QComboBox();
|
||||
_leftShift = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftShift"));
|
||||
_rightShift = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightShift"));
|
||||
_leftCtrl = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftCtrl"));
|
||||
_rightCtrl = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightCtrl"));
|
||||
_leftAlt = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftAlt"));
|
||||
_rightAlt = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightAlt"));
|
||||
_leftMeta = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftMeta"));
|
||||
_rightMeta = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightMeta"));
|
||||
_duration = new QSpinBox();
|
||||
_duration->setMaximum(5000);
|
||||
_onlySendToOBS = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.onlyOBS"));
|
||||
_noKeyPressSimulationWarning = new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.disabled"));
|
||||
|
||||
populateKeySelection(_keys);
|
||||
|
||||
QWidget::connect(_keys, SIGNAL(currentIndexChanged(int)), this,
|
||||
@@ -441,8 +434,8 @@ MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
||||
SLOT(LMetaChanged(int)));
|
||||
QWidget::connect(_rightMeta, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(RMetaChanged(int)));
|
||||
QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)),
|
||||
this, SLOT(DurationChanged(const Duration &)));
|
||||
QWidget::connect(_duration, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(DurationChanged(int)));
|
||||
QWidget::connect(_onlySendToOBS, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(OnlySendToOBSChanged(int)));
|
||||
|
||||
@@ -451,7 +444,7 @@ MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
||||
{"{{keys}}", _keys},
|
||||
{"{{duration}}", _duration},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.hotkey.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.hotkey.entry"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
|
||||
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||
@@ -500,7 +493,7 @@ void MacroActionHotkeyEdit::UpdateEntryData()
|
||||
_rightAlt->setChecked(_entryData->_rightAlt);
|
||||
_leftMeta->setChecked(_entryData->_leftMeta);
|
||||
_rightMeta->setChecked(_entryData->_rightMeta);
|
||||
_duration->SetDuration(_entryData->_duration);
|
||||
_duration->setValue(_entryData->_duration);
|
||||
_onlySendToOBS->setChecked(_entryData->_onlySendToObs ||
|
||||
!canSimulateKeyPresses);
|
||||
SetWarningVisibility();
|
||||
@@ -512,7 +505,7 @@ void MacroActionHotkeyEdit::LShiftChanged(int state)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_leftShift = state;
|
||||
}
|
||||
|
||||
@@ -522,7 +515,7 @@ void MacroActionHotkeyEdit::RShiftChanged(int state)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rightShift = state;
|
||||
}
|
||||
|
||||
@@ -532,7 +525,7 @@ void MacroActionHotkeyEdit::LCtrlChanged(int state)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_leftCtrl = state;
|
||||
}
|
||||
|
||||
@@ -542,7 +535,7 @@ void MacroActionHotkeyEdit::RCtrlChanged(int state)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rightCtrl = state;
|
||||
}
|
||||
|
||||
@@ -552,7 +545,7 @@ void MacroActionHotkeyEdit::LAltChanged(int state)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_leftAlt = state;
|
||||
}
|
||||
|
||||
@@ -562,7 +555,7 @@ void MacroActionHotkeyEdit::RAltChanged(int state)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rightAlt = state;
|
||||
}
|
||||
|
||||
@@ -572,7 +565,7 @@ void MacroActionHotkeyEdit::LMetaChanged(int state)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_leftMeta = state;
|
||||
}
|
||||
|
||||
@@ -582,18 +575,18 @@ void MacroActionHotkeyEdit::RMetaChanged(int state)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rightMeta = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::DurationChanged(const Duration &dur)
|
||||
void MacroActionHotkeyEdit::DurationChanged(int ms)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_duration = dur;
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration = ms;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::OnlySendToOBSChanged(int state)
|
||||
@@ -602,7 +595,7 @@ void MacroActionHotkeyEdit::OnlySendToOBSChanged(int state)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_onlySendToObs = state;
|
||||
SetWarningVisibility();
|
||||
}
|
||||
@@ -613,8 +606,6 @@ void MacroActionHotkeyEdit::KeyChanged(int key)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_key = static_cast<HotkeyType>(key);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "hotkey.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionHotkey : public MacroAction {
|
||||
public:
|
||||
MacroActionHotkey(Macro *m) : MacroAction(m) {}
|
||||
@@ -33,7 +30,7 @@ public:
|
||||
bool _rightAlt = false;
|
||||
bool _leftMeta = false;
|
||||
bool _rightMeta = false;
|
||||
Duration _duration = 0.3;
|
||||
int _duration = 300; // in ms
|
||||
#ifdef __APPLE__
|
||||
bool _onlySendToObs = true;
|
||||
#else
|
||||
@@ -71,7 +68,7 @@ private slots:
|
||||
void RAltChanged(int state);
|
||||
void LMetaChanged(int state);
|
||||
void RMetaChanged(int state);
|
||||
void DurationChanged(const Duration &);
|
||||
void DurationChanged(int ms);
|
||||
void OnlySendToOBSChanged(int state);
|
||||
|
||||
protected:
|
||||
@@ -84,7 +81,7 @@ protected:
|
||||
QCheckBox *_rightAlt;
|
||||
QCheckBox *_leftMeta;
|
||||
QCheckBox *_rightMeta;
|
||||
DurationSelection *_duration;
|
||||
QSpinBox *_duration;
|
||||
QCheckBox *_onlySendToOBS;
|
||||
QLabel *_noKeyPressSimulationWarning;
|
||||
|
||||
@@ -95,5 +92,3 @@ private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#include "macro-action-http.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "curl-helper.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionHttp::id = "http";
|
||||
|
||||
bool MacroActionHttp::_registered = MacroActionFactory::Register(
|
||||
@@ -18,37 +16,22 @@ const static std::map<MacroActionHttp::Method, std::string> methods = {
|
||||
"AdvSceneSwitcher.action.http.type.post"},
|
||||
};
|
||||
|
||||
static size_t DropCB(void *, size_t size, size_t nmemb, std::string *)
|
||||
size_t DropCB(void *, size_t size, size_t nmemb, std::string *)
|
||||
{
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
static size_t WriteCB(void *ptr, size_t size, size_t nmemb, std::string *buffer)
|
||||
size_t WriteCB(void *ptr, size_t size, size_t nmemb, std::string *buffer)
|
||||
{
|
||||
buffer->append((char *)ptr, nmemb);
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
void MacroActionHttp::SetupHeaders()
|
||||
{
|
||||
if (!_setHeaders) {
|
||||
return;
|
||||
}
|
||||
struct curl_slist *headers = nullptr;
|
||||
for (auto &header : _headers) {
|
||||
headers = switcher->curl.SlistAppend(headers, header.c_str());
|
||||
}
|
||||
if (!_headers.empty()) {
|
||||
switcher->curl.SetOpt(CURLOPT_HTTPHEADER, headers);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionHttp::Get()
|
||||
{
|
||||
switcher->curl.SetOpt(CURLOPT_URL, _url.c_str());
|
||||
switcher->curl.SetOpt(CURLOPT_HTTPGET, 1L);
|
||||
switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.Milliseconds());
|
||||
SetupHeaders();
|
||||
switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.seconds * 1000);
|
||||
|
||||
std::string response;
|
||||
if (IsReferencedInVars()) {
|
||||
@@ -66,8 +49,7 @@ void MacroActionHttp::Post()
|
||||
{
|
||||
switcher->curl.SetOpt(CURLOPT_URL, _url.c_str());
|
||||
switcher->curl.SetOpt(CURLOPT_POSTFIELDS, _data.c_str());
|
||||
switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.Milliseconds());
|
||||
SetupHeaders();
|
||||
switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.seconds * 1000);
|
||||
switcher->curl.Perform();
|
||||
}
|
||||
|
||||
@@ -108,10 +90,8 @@ void MacroActionHttp::LogAction() const
|
||||
bool MacroActionHttp::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_url.Save(obj, "url");
|
||||
obs_data_set_string(obj, "url", _url.c_str());
|
||||
_data.Save(obj, "data");
|
||||
obs_data_set_bool(obj, "setHeaders", _setHeaders);
|
||||
_headers.Save(obj, "headers", "header");
|
||||
obs_data_set_int(obj, "method", static_cast<int>(_method));
|
||||
_timeout.Save(obj);
|
||||
return true;
|
||||
@@ -120,10 +100,8 @@ bool MacroActionHttp::Save(obs_data_t *obj) const
|
||||
bool MacroActionHttp::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_url.Load(obj, "url");
|
||||
_url = obs_data_get_string(obj, "url");
|
||||
_data.Load(obj, "data");
|
||||
_setHeaders = obs_data_get_bool(obj, "setHeaders");
|
||||
_headers.Load(obj, "headers", "header");
|
||||
_method = static_cast<Method>(obs_data_get_int(obj, "method"));
|
||||
_timeout.Load(obj);
|
||||
return true;
|
||||
@@ -131,7 +109,7 @@ bool MacroActionHttp::Load(obs_data_t *obj)
|
||||
|
||||
std::string MacroActionHttp::GetShortDesc() const
|
||||
{
|
||||
return _url.UnresolvedValue();
|
||||
return _url;
|
||||
}
|
||||
|
||||
static inline void populateMethodSelection(QComboBox *list)
|
||||
@@ -144,15 +122,9 @@ static inline void populateMethodSelection(QComboBox *list)
|
||||
MacroActionHttpEdit::MacroActionHttpEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionHttp> entryData)
|
||||
: QWidget(parent),
|
||||
_url(new VariableLineEdit(this)),
|
||||
_url(new QLineEdit()),
|
||||
_methods(new QComboBox()),
|
||||
_data(new VariableTextEdit(this)),
|
||||
_setHeaders(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.http.setHeaders"))),
|
||||
_headerListLayout(new QVBoxLayout()),
|
||||
_headerList(new StringListEdit(
|
||||
this, obs_module_text("AdvSceneSwitcher.action.http.headers"),
|
||||
obs_module_text("AdvSceneSwitcher.action.http.addHeader"))),
|
||||
_timeout(new DurationSelection(this, false))
|
||||
{
|
||||
populateMethodSelection(_methods);
|
||||
@@ -163,13 +135,8 @@ MacroActionHttpEdit::MacroActionHttpEdit(
|
||||
SLOT(DataChanged()));
|
||||
QWidget::connect(_methods, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(MethodChanged(int)));
|
||||
QWidget::connect(_setHeaders, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(SetHeadersChanged(int)));
|
||||
QWidget::connect(_headerList,
|
||||
SIGNAL(StringListChanged(const StringList &)), this,
|
||||
SLOT(HeadersChanged(const StringList &)));
|
||||
QWidget::connect(_timeout, SIGNAL(DurationChanged(const Duration &)),
|
||||
this, SLOT(TimeoutChanged(const Duration &)));
|
||||
QWidget::connect(_timeout, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(TimeoutChanged(double)));
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{url}}", _url},
|
||||
@@ -178,22 +145,16 @@ MacroActionHttpEdit::MacroActionHttpEdit(
|
||||
{"{{timeout}}", _timeout},
|
||||
};
|
||||
auto *actionLayout = new QHBoxLayout;
|
||||
PlaceWidgets(
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.http.entry.line1"),
|
||||
actionLayout, widgetPlaceholders);
|
||||
auto *timeoutLayout = new QHBoxLayout;
|
||||
PlaceWidgets(
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.http.entry.line2"),
|
||||
timeoutLayout, widgetPlaceholders);
|
||||
|
||||
_headerListLayout->addWidget(new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.action.http.headers")));
|
||||
_headerListLayout->addWidget(_headerList);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(actionLayout);
|
||||
mainLayout->addWidget(_setHeaders);
|
||||
mainLayout->addLayout(_headerListLayout);
|
||||
mainLayout->addWidget(_data);
|
||||
mainLayout->addLayout(timeoutLayout);
|
||||
setLayout(mainLayout);
|
||||
@@ -209,10 +170,8 @@ void MacroActionHttpEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
|
||||
_url->setText(_entryData->_url);
|
||||
_url->setText(QString::fromStdString(_entryData->_url));
|
||||
_data->setPlainText(_entryData->_data);
|
||||
_setHeaders->setChecked(_entryData->_setHeaders);
|
||||
_headerList->SetStringList(_entryData->_headers);
|
||||
_methods->setCurrentIndex(static_cast<int>(_entryData->_method));
|
||||
_timeout->SetDuration(_entryData->_timeout);
|
||||
SetWidgetVisibility();
|
||||
@@ -224,7 +183,7 @@ void MacroActionHttpEdit::URLChanged()
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_url = _url->text().toStdString();
|
||||
emit(HeaderInfoChanged(_url->text()));
|
||||
}
|
||||
@@ -235,48 +194,33 @@ void MacroActionHttpEdit::MethodChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_method = static_cast<MacroActionHttp::Method>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::TimeoutChanged(const Duration &dur)
|
||||
void MacroActionHttpEdit::TimeoutChanged(double seconds)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_timeout = dur;
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::SetHeadersChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_setHeaders = value;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::HeadersChanged(const StringList &headers)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_headers = headers;
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_timeout.seconds = seconds;
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::SetWidgetVisibility()
|
||||
{
|
||||
_data->setVisible(_entryData->_method == MacroActionHttp::Method::POST);
|
||||
SetLayoutVisible(_headerListLayout, _entryData->_setHeaders);
|
||||
switch (_entryData->_method) {
|
||||
case MacroActionHttp::Method::GET:
|
||||
_data->hide();
|
||||
break;
|
||||
case MacroActionHttp::Method::POST:
|
||||
_data->show();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
@@ -288,11 +232,9 @@ void MacroActionHttpEdit::DataChanged()
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_data = _data->toPlainText().toUtf8().constData();
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "variable-text-edit.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
#include "duration-control.hpp"
|
||||
#include "string-list.hpp"
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionHttp : public MacroAction {
|
||||
public:
|
||||
@@ -30,15 +25,13 @@ public:
|
||||
POST,
|
||||
};
|
||||
|
||||
StringVariable _url = obs_module_text("AdvSceneSwitcher.enterURL");
|
||||
StringVariable _data = obs_module_text("AdvSceneSwitcher.enterText");
|
||||
bool _setHeaders = false;
|
||||
StringList _headers;
|
||||
std::string _url = obs_module_text("AdvSceneSwitcher.enterURL");
|
||||
VariableResolvingString _data =
|
||||
obs_module_text("AdvSceneSwitcher.enterText");
|
||||
Method _method = Method::GET;
|
||||
Duration _timeout = Duration(1.0);
|
||||
Duration _timeout;
|
||||
|
||||
private:
|
||||
void SetupHeaders();
|
||||
void Get();
|
||||
void Post();
|
||||
|
||||
@@ -66,9 +59,7 @@ private slots:
|
||||
void DataChanged();
|
||||
void URLChanged();
|
||||
void MethodChanged(int);
|
||||
void TimeoutChanged(const Duration &seconds);
|
||||
void SetHeadersChanged(int);
|
||||
void HeadersChanged(const StringList &);
|
||||
void TimeoutChanged(double seconds);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
@@ -78,14 +69,9 @@ protected:
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
VariableLineEdit *_url;
|
||||
QLineEdit *_url;
|
||||
QComboBox *_methods;
|
||||
VariableTextEdit *_data;
|
||||
QCheckBox *_setHeaders;
|
||||
QVBoxLayout *_headerListLayout;
|
||||
StringListEdit *_headerList;
|
||||
DurationSelection *_timeout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#include "macro-action-macro.hpp"
|
||||
#include "macro.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionMacro::id = "macro";
|
||||
|
||||
bool MacroActionMacro::_registered = MacroActionFactory::Register(
|
||||
@@ -23,28 +21,27 @@ const static std::map<PerformMacroAction, std::string> actionTypes = {
|
||||
|
||||
bool MacroActionMacro::PerformAction()
|
||||
{
|
||||
auto macro = _macro.GetMacro();
|
||||
if (!macro) {
|
||||
if (!_macro.get()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (_action) {
|
||||
case PerformMacroAction::PAUSE:
|
||||
macro->SetPaused();
|
||||
_macro->SetPaused();
|
||||
break;
|
||||
case PerformMacroAction::UNPAUSE:
|
||||
macro->SetPaused(false);
|
||||
_macro->SetPaused(false);
|
||||
break;
|
||||
case PerformMacroAction::RESET_COUNTER:
|
||||
macro->ResetRunCount();
|
||||
_macro->ResetRunCount();
|
||||
break;
|
||||
case PerformMacroAction::RUN:
|
||||
if (!macro->Paused()) {
|
||||
macro->PerformActions();
|
||||
if (!_macro->Paused()) {
|
||||
_macro->PerformActions();
|
||||
}
|
||||
break;
|
||||
case PerformMacroAction::STOP:
|
||||
macro->Stop();
|
||||
_macro->Stop();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -54,27 +51,26 @@ bool MacroActionMacro::PerformAction()
|
||||
|
||||
void MacroActionMacro::LogAction() const
|
||||
{
|
||||
auto macro = _macro.GetMacro();
|
||||
if (!macro) {
|
||||
if (!_macro.get()) {
|
||||
return;
|
||||
}
|
||||
switch (_action) {
|
||||
case PerformMacroAction::PAUSE:
|
||||
vblog(LOG_INFO, "paused \"%s\"", macro->Name().c_str());
|
||||
vblog(LOG_INFO, "paused \"%s\"", _macro->Name().c_str());
|
||||
break;
|
||||
case PerformMacroAction::UNPAUSE:
|
||||
vblog(LOG_INFO, "unpaused \"%s\"", macro->Name().c_str());
|
||||
vblog(LOG_INFO, "unpaused \"%s\"", _macro->Name().c_str());
|
||||
break;
|
||||
case PerformMacroAction::RESET_COUNTER:
|
||||
vblog(LOG_INFO, "reset counter for \"%s\"",
|
||||
macro->Name().c_str());
|
||||
_macro->Name().c_str());
|
||||
break;
|
||||
case PerformMacroAction::RUN:
|
||||
vblog(LOG_INFO, "run nested macro \"%s\"",
|
||||
macro->Name().c_str());
|
||||
_macro->Name().c_str());
|
||||
break;
|
||||
case PerformMacroAction::STOP:
|
||||
vblog(LOG_INFO, "stopped macro \"%s\"", macro->Name().c_str());
|
||||
vblog(LOG_INFO, "stopped macro \"%s\"", _macro->Name().c_str());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -100,7 +96,10 @@ bool MacroActionMacro::Load(obs_data_t *obj)
|
||||
|
||||
std::string MacroActionMacro::GetShortDesc() const
|
||||
{
|
||||
return _macro.Name();
|
||||
if (_macro.get()) {
|
||||
return _macro->Name();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
@@ -121,6 +120,8 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
||||
|
||||
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(MacroChanged(const QString &)));
|
||||
QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this,
|
||||
SLOT(MacroRemove(const QString &)));
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
|
||||
@@ -129,7 +130,7 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
||||
{"{{actions}}", _actions},
|
||||
{"{{macros}}", _macros},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.macro.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.macro.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -144,7 +145,7 @@ void MacroActionMacroEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_macros->SetCurrentMacro(_entryData->_macro);
|
||||
_macros->SetCurrentMacro(_entryData->_macro.get());
|
||||
if (_entryData->_action == PerformMacroAction::RUN ||
|
||||
_entryData->_action == PerformMacroAction::STOP) {
|
||||
_macros->HideSelectedMacro();
|
||||
@@ -157,8 +158,8 @@ void MacroActionMacroEdit::MacroChanged(const QString &text)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_macro = text;
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_macro.UpdateRef(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
@@ -169,7 +170,7 @@ void MacroActionMacroEdit::ActionChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<PerformMacroAction>(value);
|
||||
|
||||
if (_entryData->_action == PerformMacroAction::RUN ||
|
||||
@@ -180,4 +181,9 @@ void MacroActionMacroEdit::ActionChanged(int value)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
void MacroActionMacroEdit::MacroRemove(const QString &)
|
||||
{
|
||||
if (_entryData) {
|
||||
_entryData->_macro.UpdateRef();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class PerformMacroAction {
|
||||
PAUSE,
|
||||
UNPAUSE,
|
||||
@@ -53,6 +51,7 @@ public:
|
||||
|
||||
private slots:
|
||||
void MacroChanged(const QString &text);
|
||||
void MacroRemove(const QString &name);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
@@ -66,5 +65,3 @@ private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include "macro-action-media.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionMedia::id = "media";
|
||||
|
||||
bool MacroActionMedia::_registered = MacroActionFactory::Register(
|
||||
@@ -49,7 +48,7 @@ bool MacroActionMedia::PerformAction()
|
||||
obs_source_media_previous(source);
|
||||
break;
|
||||
case MediaAction::SEEK:
|
||||
obs_source_media_set_time(source, _seek.Milliseconds());
|
||||
obs_source_media_set_time(source, _seek.seconds * 1000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -117,8 +116,10 @@ MacroActionMediaEdit::MacroActionMediaEdit(
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||
SLOT(SourceChanged(const SourceSelection &)));
|
||||
QWidget::connect(_seek, SIGNAL(DurationChanged(const Duration &)), this,
|
||||
SLOT(DurationChanged(const Duration &)));
|
||||
QWidget::connect(_seek, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(DurationChanged(double)));
|
||||
QWidget::connect(_seek, SIGNAL(UnitChanged(DurationUnit)), this,
|
||||
SLOT(DurationUnitChanged(DurationUnit)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
@@ -126,7 +127,7 @@ MacroActionMediaEdit::MacroActionMediaEdit(
|
||||
{"{{actions}}", _actions},
|
||||
{"{{duration}}", _seek},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.media.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.media.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -153,7 +154,7 @@ void MacroActionMediaEdit::SourceChanged(const SourceSelection &source)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_mediaSource = source;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
@@ -165,19 +166,29 @@ void MacroActionMediaEdit::ActionChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<MediaAction>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::DurationChanged(const Duration &dur)
|
||||
void MacroActionMediaEdit::DurationChanged(double seconds)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_seek = dur;
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_seek.seconds = seconds;
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::DurationUnitChanged(DurationUnit unit)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_seek.displayUnit = unit;
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::SetWidgetVisibility()
|
||||
@@ -188,5 +199,3 @@ void MacroActionMediaEdit::SetWidgetVisibility()
|
||||
_seek->setVisible(_entryData->_action == MediaAction::SEEK);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#include <QSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class MediaAction {
|
||||
PLAY,
|
||||
PAUSE,
|
||||
@@ -60,7 +58,8 @@ public:
|
||||
private slots:
|
||||
void SourceChanged(const SourceSelection &);
|
||||
void ActionChanged(int value);
|
||||
void DurationChanged(const Duration &value);
|
||||
void DurationChanged(double value);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
@@ -76,5 +75,3 @@ private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,318 +0,0 @@
|
||||
#include "macro-action-osc.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <system_error>
|
||||
#include <QGroupBox>
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionOSC::id = "osc";
|
||||
|
||||
bool MacroActionOSC::_registered = MacroActionFactory::Register(
|
||||
MacroActionOSC::id, {MacroActionOSC::Create, MacroActionOSCEdit::Create,
|
||||
"AdvSceneSwitcher.action.osc"});
|
||||
|
||||
MacroActionOSC::MacroActionOSC(Macro *m)
|
||||
: MacroAction(m),
|
||||
_ctx(asio::io_context()),
|
||||
_tcpSocket(asio::ip::tcp::socket(_ctx)),
|
||||
_udpSocket(asio::ip::udp::socket(_ctx))
|
||||
{
|
||||
}
|
||||
|
||||
void MacroActionOSC::SendOSCTCPMessage(const asio::mutable_buffer &buffer)
|
||||
{
|
||||
try {
|
||||
asio::write(_tcpSocket, asio::buffer(buffer));
|
||||
} catch (const std::exception &e) {
|
||||
blog(LOG_WARNING,
|
||||
"failed to send OSC message \"%s\" via TCP %s %d: %s",
|
||||
_message.ToString().c_str(), _ip.c_str(), _port.GetValue(),
|
||||
e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionOSC::SendOSCUDPMessage(const asio::mutable_buffer &buffer)
|
||||
{
|
||||
try {
|
||||
_udpSocket.send_to(buffer, _updEndpoint);
|
||||
} catch (const std::exception &e) {
|
||||
blog(LOG_WARNING,
|
||||
"failed to send OSC message \"%s\" via UDP %s %d: %s",
|
||||
_message.ToString().c_str(), _ip.c_str(), _port.GetValue(),
|
||||
e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionOSC::UDPReconnect()
|
||||
{
|
||||
asio::error_code ec;
|
||||
asio::ip::udp::resolver resolver(_ctx);
|
||||
auto endpoints = resolver.resolve(asio::ip::udp::v4(), _ip.c_str(),
|
||||
std::to_string(_port.GetValue()), ec);
|
||||
if (ec) {
|
||||
endpoints = resolver.resolve(asio::ip::udp::v6(), _ip.c_str(),
|
||||
std::to_string(_port.GetValue()),
|
||||
ec);
|
||||
}
|
||||
if (ec) {
|
||||
blog(LOG_WARNING, "failed to get IP for \"%s\": %s",
|
||||
_ip.c_str(), ec.message().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
_updEndpoint = endpoints.begin()->endpoint();
|
||||
_udpSocket = asio::ip::udp::socket(_ctx);
|
||||
_udpSocket.open(endpoints.begin()->endpoint().protocol());
|
||||
} catch (const std::exception &e) {
|
||||
blog(LOG_WARNING, "failed to connect to UDP %s %d: %s",
|
||||
_ip.c_str(), _port.GetValue(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionOSC::TCPReconnect()
|
||||
{
|
||||
asio::error_code ec;
|
||||
asio::ip::tcp::resolver resolver(_ctx);
|
||||
auto endpoints = resolver.resolve(asio::ip::tcp::v4(), _ip.c_str(),
|
||||
std::to_string(_port.GetValue()), ec);
|
||||
if (ec) {
|
||||
endpoints = resolver.resolve(asio::ip::tcp::v6(), _ip.c_str(),
|
||||
std::to_string(_port.GetValue()),
|
||||
ec);
|
||||
}
|
||||
if (ec) {
|
||||
blog(LOG_WARNING, "failed to get IP for \"%s\": %s",
|
||||
_ip.c_str(), ec.message().c_str());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
_tcpSocket = asio::ip::tcp::socket(_ctx);
|
||||
_tcpSocket.connect(endpoints.begin()->endpoint());
|
||||
} catch (const std::exception &e) {
|
||||
blog(LOG_WARNING, "failed to connect to TCP %s %d: %s",
|
||||
_ip.c_str(), _port.GetValue(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionOSC::CheckReconnect()
|
||||
{
|
||||
if (_protocol == Protocol::TCP &&
|
||||
(_reconnect || !_tcpSocket.is_open())) {
|
||||
TCPReconnect();
|
||||
}
|
||||
|
||||
if (_protocol == Protocol::UDP &&
|
||||
(_reconnect || !_udpSocket.is_open())) {
|
||||
UDPReconnect();
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionOSC::PerformAction()
|
||||
{
|
||||
auto buffer = _message.GetBuffer();
|
||||
if (!buffer.has_value()) {
|
||||
blog(LOG_WARNING, "failed to create or fill OSC buffer!");
|
||||
return true;
|
||||
}
|
||||
|
||||
CheckReconnect();
|
||||
|
||||
if (_protocol == Protocol::TCP &&
|
||||
(_reconnect || !_tcpSocket.is_open())) {
|
||||
TCPReconnect();
|
||||
}
|
||||
|
||||
if (_protocol == Protocol::UDP &&
|
||||
(_reconnect || !_udpSocket.is_open())) {
|
||||
UDPReconnect();
|
||||
}
|
||||
|
||||
auto rawMessage = asio::buffer(*buffer);
|
||||
|
||||
switch (_protocol) {
|
||||
case MacroActionOSC::Protocol::TCP:
|
||||
SendOSCTCPMessage(rawMessage);
|
||||
break;
|
||||
case MacroActionOSC::Protocol::UDP:
|
||||
SendOSCUDPMessage(rawMessage);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionOSC::LogAction() const
|
||||
{
|
||||
vblog(LOG_INFO, "sending OSC message '%s' to %s %s %d",
|
||||
_message.ToString().c_str(),
|
||||
_protocol == Protocol::UDP ? "UDP" : "TCP", _ip.c_str(),
|
||||
_port.GetValue());
|
||||
}
|
||||
|
||||
bool MacroActionOSC::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "protocol", static_cast<int>(_protocol));
|
||||
_ip.Save(obj, "ip");
|
||||
_port.Save(obj, "port");
|
||||
_message.Save(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionOSC::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_protocol = static_cast<Protocol>(obs_data_get_int(obj, "protocol"));
|
||||
_ip.Load(obj, "ip");
|
||||
_port.Load(obj, "port");
|
||||
_message.Load(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionOSC::SetProtocol(Protocol p)
|
||||
{
|
||||
_protocol = p;
|
||||
_reconnect = true;
|
||||
}
|
||||
|
||||
void MacroActionOSC::SetIP(const std::string &ip)
|
||||
{
|
||||
_ip = ip;
|
||||
_reconnect = true;
|
||||
}
|
||||
|
||||
void MacroActionOSC::SetPortNr(IntVariable port)
|
||||
{
|
||||
_port = port;
|
||||
_reconnect = true;
|
||||
}
|
||||
|
||||
static void populateProtocolSelection(QComboBox *list)
|
||||
{
|
||||
list->addItem("TCP");
|
||||
list->addItem("UDP");
|
||||
}
|
||||
|
||||
MacroActionOSCEdit::MacroActionOSCEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionOSC> entryData)
|
||||
: QWidget(parent),
|
||||
_protocol(new QComboBox(this)),
|
||||
_ip(new VariableLineEdit(this)),
|
||||
_port(new VariableSpinBox(this)),
|
||||
_message(new OSCMessageEdit(this))
|
||||
{
|
||||
populateProtocolSelection(_protocol);
|
||||
_port->setMaximum(65535);
|
||||
|
||||
auto networkGroup =
|
||||
new QGroupBox(obs_module_text("AdvSceneSwitcher.osc.network"));
|
||||
auto networkLayout = new QGridLayout;
|
||||
int row = 0;
|
||||
networkLayout->addWidget(
|
||||
new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.osc.network.protocol")),
|
||||
row, 0);
|
||||
networkLayout->addWidget(_protocol, row, 1);
|
||||
++row;
|
||||
networkLayout->addWidget(
|
||||
new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.osc.network.address")),
|
||||
row, 0);
|
||||
networkLayout->addWidget(_ip, row, 1);
|
||||
++row;
|
||||
networkLayout->addWidget(new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.osc.network.port")),
|
||||
row, 0);
|
||||
networkLayout->addWidget(_port, row, 1);
|
||||
networkGroup->setLayout(networkLayout);
|
||||
|
||||
auto messageGroup =
|
||||
new QGroupBox(obs_module_text("AdvSceneSwitcher.osc.message"));
|
||||
auto messageLayout = new QHBoxLayout();
|
||||
messageLayout->addWidget(_message);
|
||||
messageGroup->setLayout(messageLayout);
|
||||
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(networkGroup);
|
||||
mainLayout->addWidget(messageGroup);
|
||||
setLayout(mainLayout);
|
||||
|
||||
QWidget::connect(_ip, SIGNAL(editingFinished()), this,
|
||||
SLOT(IpChanged()));
|
||||
QWidget::connect(_protocol, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ProtocolChanged(int)));
|
||||
QWidget::connect(
|
||||
_port,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||
this, SLOT(PortChanged(const NumberVariable<int> &)));
|
||||
QWidget::connect(_message, SIGNAL(MessageChanged(const OSCMessage &)),
|
||||
this, SLOT(MessageChanged(const OSCMessage &)));
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionOSCEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_protocol->setCurrentIndex(static_cast<int>(_entryData->GetProtocol()));
|
||||
_ip->setText(_entryData->GetIP());
|
||||
_port->SetValue(_entryData->GetPortNr());
|
||||
_message->SetMessage(_entryData->_message);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionOSCEdit::IpChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->SetIP(_ip->text().toStdString());
|
||||
}
|
||||
|
||||
void MacroActionOSCEdit::ProtocolChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->SetProtocol(static_cast<MacroActionOSC::Protocol>(value));
|
||||
}
|
||||
|
||||
void MacroActionOSCEdit::PortChanged(const NumberVariable<int> &value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->SetPortNr(value);
|
||||
}
|
||||
|
||||
void MacroActionOSCEdit::MessageChanged(const OSCMessage &m)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_message = m;
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
@@ -1,94 +0,0 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "osc-helpers.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <asio.hpp>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionOSC : public MacroAction {
|
||||
public:
|
||||
MacroActionOSC(Macro *m);
|
||||
bool PerformAction();
|
||||
void LogAction() const;
|
||||
bool Save(obs_data_t *obj) const;
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() const { return id; };
|
||||
static std::shared_ptr<MacroAction> Create(Macro *m)
|
||||
{
|
||||
return std::make_shared<MacroActionOSC>(m);
|
||||
}
|
||||
|
||||
enum class Protocol {
|
||||
TCP,
|
||||
UDP,
|
||||
};
|
||||
|
||||
void SetProtocol(Protocol);
|
||||
Protocol GetProtocol() const { return _protocol; }
|
||||
void SetIP(const std::string &);
|
||||
StringVariable GetIP() const { return _ip; }
|
||||
void SetPortNr(IntVariable);
|
||||
IntVariable GetPortNr() { return _port; }
|
||||
|
||||
OSCMessage _message;
|
||||
|
||||
private:
|
||||
void SendOSCTCPMessage(const asio::mutable_buffer &);
|
||||
void SendOSCUDPMessage(const asio::mutable_buffer &);
|
||||
|
||||
void CheckReconnect();
|
||||
void TCPReconnect();
|
||||
void UDPReconnect();
|
||||
|
||||
Protocol _protocol = Protocol::UDP;
|
||||
StringVariable _ip = "localhost";
|
||||
IntVariable _port = 12345;
|
||||
bool _reconnect = true;
|
||||
|
||||
asio::io_context _ctx;
|
||||
asio::ip::tcp::socket _tcpSocket;
|
||||
asio::ip::udp::socket _udpSocket;
|
||||
asio::ip::udp::endpoint _updEndpoint;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionOSCEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionOSCEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroActionOSC> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionOSCEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionOSC>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void IpChanged();
|
||||
void MessageChanged(const OSCMessage &);
|
||||
void ProtocolChanged(int);
|
||||
void PortChanged(const NumberVariable<int> &value);
|
||||
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<MacroActionOSC> _entryData;
|
||||
|
||||
private:
|
||||
QComboBox *_protocol;
|
||||
VariableLineEdit *_ip;
|
||||
VariableSpinBox *_port;
|
||||
OSCMessageEdit *_message;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
@@ -1,20 +1,15 @@
|
||||
#include "macro-action-plugin-state.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <thread>
|
||||
#include <QMainWindow>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionPluginState::id = "plugin_state";
|
||||
|
||||
bool MacroActionPluginState::_registered = MacroActionFactory::Register(
|
||||
MacroActionPluginState::id,
|
||||
{MacroActionPluginState::Create, MacroActionPluginStateEdit::Create,
|
||||
"AdvSceneSwitcher.action.pluginState"});
|
||||
"AdvSceneSwitcher.action.PluginState"});
|
||||
|
||||
const static std::map<PluginStateAction, std::string> actionTypes = {
|
||||
{PluginStateAction::STOP,
|
||||
@@ -23,26 +18,24 @@ const static std::map<PluginStateAction, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.pluginState.type.noMatch"},
|
||||
{PluginStateAction::IMPORT_SETTINGS,
|
||||
"AdvSceneSwitcher.action.pluginState.type.import"},
|
||||
{PluginStateAction::TERMINATE,
|
||||
"AdvSceneSwitcher.action.pluginState.type.terminate"},
|
||||
};
|
||||
|
||||
const static std::map<SwitcherData::NoMatch, std::string> noMatchValues = {
|
||||
{SwitcherData::NoMatch::NO_SWITCH,
|
||||
const static std::map<NoMatch, std::string> noMatchValues = {
|
||||
{NO_SWITCH,
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch"},
|
||||
{SwitcherData::NoMatch::SWITCH,
|
||||
{SWITCH,
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo"},
|
||||
{SwitcherData::NoMatch::RANDOM_SWITCH,
|
||||
{RANDOM_SWITCH,
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom"},
|
||||
};
|
||||
|
||||
static void stopPlugin()
|
||||
void stopPlugin()
|
||||
{
|
||||
std::thread t([]() { switcher->Stop(); });
|
||||
t.detach();
|
||||
}
|
||||
|
||||
static void importSettings(const std::string &path)
|
||||
void importSettings(const std::string &path)
|
||||
{
|
||||
if (switcher->settingsWindowOpened) {
|
||||
return;
|
||||
@@ -51,91 +44,18 @@ static void importSettings(const std::string &path)
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
switcher->LoadSettings(obj);
|
||||
switcher->loadSettings(obj);
|
||||
obs_data_release(obj);
|
||||
}
|
||||
|
||||
static void setNoMatchBehaviour(int value, OBSWeakSource &scene)
|
||||
void setNoMatchBehaviour(int value, OBSWeakSource &scene)
|
||||
{
|
||||
switcher->switchIfNotMatching =
|
||||
static_cast<SwitcherData::NoMatch>(value);
|
||||
if (switcher->switchIfNotMatching == SwitcherData::NoMatch::SWITCH) {
|
||||
switcher->switchIfNotMatching = static_cast<NoMatch>(value);
|
||||
if (switcher->switchIfNotMatching == SWITCH) {
|
||||
switcher->nonMatchingScene = scene;
|
||||
}
|
||||
}
|
||||
|
||||
static void closeOBSWindow()
|
||||
{
|
||||
blog(LOG_WARNING, "closing OBS window now!");
|
||||
auto obsWindow =
|
||||
static_cast<QMainWindow *>(obs_frontend_get_main_window());
|
||||
if (obsWindow) {
|
||||
obsWindow->close();
|
||||
} else {
|
||||
blog(LOG_WARNING,
|
||||
"OBS shutdown was aborted - failed to get QMainWindow");
|
||||
}
|
||||
}
|
||||
|
||||
static void terminateOBS(void *)
|
||||
{
|
||||
static std::mutex mtx;
|
||||
static std::mutex waitMutex;
|
||||
static std::condition_variable cv;
|
||||
static bool abortTerminate;
|
||||
static bool stopWaiting;
|
||||
static std::chrono::high_resolution_clock::time_point
|
||||
lastShutdownAttempt{};
|
||||
|
||||
// Don't allow multiple simultaneous instances of the shutdown dialog
|
||||
std::unique_lock<std::mutex> lock(mtx, std::try_to_lock);
|
||||
if (!lock.owns_lock()) {
|
||||
blog(LOG_INFO,
|
||||
"OBS shutdown dialog already triggered - ignoring additional request");
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent the user from locking himself out of controlling OBS by
|
||||
// continuously opening the shutdown dialog
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
if (lastShutdownAttempt + 5s > now) {
|
||||
blog(LOG_INFO,
|
||||
"OBS shutdown dialog already triggered recently - ignoring request");
|
||||
return;
|
||||
}
|
||||
lastShutdownAttempt = now;
|
||||
|
||||
abortTerminate = false;
|
||||
stopWaiting = false;
|
||||
|
||||
// Give the user a 10s grace period during which the shutdown can be aborted
|
||||
std::thread thread([]() {
|
||||
std::unique_lock<std::mutex> lock(waitMutex);
|
||||
if (cv.wait_for(lock, 10s, [] { return stopWaiting; })) {
|
||||
if (abortTerminate) {
|
||||
blog(LOG_INFO, "OBS shutdown was aborted");
|
||||
} else {
|
||||
closeOBSWindow();
|
||||
}
|
||||
} else {
|
||||
closeOBSWindow();
|
||||
}
|
||||
});
|
||||
thread.detach();
|
||||
|
||||
// Ask the user how to proceed
|
||||
abortTerminate = !DisplayMessage(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.pluginState.terminateConfirm"),
|
||||
true, false);
|
||||
stopWaiting = true;
|
||||
|
||||
// This closes OBS immediately if shutdown was confirmed
|
||||
cv.notify_all();
|
||||
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
bool MacroActionPluginState::PerformAction()
|
||||
{
|
||||
switch (_action) {
|
||||
@@ -150,14 +70,6 @@ bool MacroActionPluginState::PerformAction()
|
||||
// There is no point in continuing
|
||||
// The settings will be invalid
|
||||
return false;
|
||||
case PluginStateAction::TERMINATE: {
|
||||
std::thread thread([]() {
|
||||
obs_queue_task(OBS_TASK_UI, terminateOBS, nullptr,
|
||||
false);
|
||||
});
|
||||
thread.detach();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -177,9 +89,6 @@ void MacroActionPluginState::LogAction() const
|
||||
vblog(LOG_INFO, "importing settings from %s",
|
||||
_settingsPath.c_str());
|
||||
break;
|
||||
case PluginStateAction::TERMINATE:
|
||||
vblog(LOG_INFO, "sending terminate signal to OBS in 10s");
|
||||
break;
|
||||
default:
|
||||
blog(LOG_WARNING, "ignored unknown pluginState action %d",
|
||||
static_cast<int>(_action));
|
||||
@@ -193,7 +102,7 @@ bool MacroActionPluginState::Save(obs_data_t *obj) const
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
obs_data_set_int(obj, "value", _value);
|
||||
obs_data_set_string(obj, "scene", GetWeakSourceName(_scene).c_str());
|
||||
_settingsPath.Save(obj, "settingsPath");
|
||||
obs_data_set_string(obj, "settingsPath", _settingsPath.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -205,7 +114,7 @@ bool MacroActionPluginState::Load(obs_data_t *obj)
|
||||
_value = obs_data_get_int(obj, "value");
|
||||
const char *sceneName = obs_data_get_string(obj, "scene");
|
||||
_scene = GetWeakSourceByName(sceneName);
|
||||
_settingsPath.Load(obj, "settingsPath");
|
||||
_settingsPath = obs_data_get_string(obj, "settingsPath");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -238,7 +147,7 @@ MacroActionPluginStateEdit::MacroActionPluginStateEdit(
|
||||
"AdvSceneSwitcher.action.pluginState.importWarning"));
|
||||
|
||||
populateActionSelection(_actions);
|
||||
PopulateSceneSelection(_scenes);
|
||||
populateSceneSelection(_scenes);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
@@ -257,7 +166,7 @@ MacroActionPluginStateEdit::MacroActionPluginStateEdit(
|
||||
{"{{settings}}", _settings},
|
||||
{"{{settingsWarning}}", _settingsWarning},
|
||||
};
|
||||
PlaceWidgets(
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.pluginState.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
@@ -276,7 +185,7 @@ void MacroActionPluginStateEdit::UpdateEntryData()
|
||||
populateValueSelection(_values, _entryData->_action);
|
||||
_values->setCurrentIndex(_entryData->_value);
|
||||
_scenes->setCurrentText(GetWeakSourceName(_entryData->_scene).c_str());
|
||||
_settings->SetPath(_entryData->_settingsPath);
|
||||
_settings->SetPath(QString::fromStdString(_entryData->_settingsPath));
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
@@ -287,7 +196,7 @@ void MacroActionPluginStateEdit::ActionChanged(int value)
|
||||
}
|
||||
|
||||
{
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<PluginStateAction>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
@@ -302,7 +211,7 @@ void MacroActionPluginStateEdit::ValueChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_value = value;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
@@ -313,7 +222,7 @@ void MacroActionPluginStateEdit::SceneChanged(const QString &text)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_scene = GetWeakSourceByQString(text);
|
||||
}
|
||||
|
||||
@@ -323,7 +232,7 @@ void MacroActionPluginStateEdit::PathChanged(const QString &text)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_settingsPath = text.toStdString();
|
||||
}
|
||||
|
||||
@@ -342,8 +251,7 @@ void MacroActionPluginStateEdit::SetWidgetVisibility()
|
||||
break;
|
||||
case PluginStateAction::NO_MATCH_BEHAVIOUR:
|
||||
_values->show();
|
||||
if (static_cast<SwitcherData::NoMatch>(_entryData->_value) ==
|
||||
SwitcherData::NoMatch::SWITCH) {
|
||||
if ((NoMatch)_entryData->_value == SWITCH) {
|
||||
_scenes->show();
|
||||
}
|
||||
break;
|
||||
@@ -355,5 +263,3 @@ void MacroActionPluginStateEdit::SetWidgetVisibility()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -5,13 +5,10 @@
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QLabel>
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class PluginStateAction {
|
||||
STOP,
|
||||
NO_MATCH_BEHAVIOUR,
|
||||
IMPORT_SETTINGS,
|
||||
TERMINATE,
|
||||
};
|
||||
|
||||
class MacroActionPluginState : public MacroAction {
|
||||
@@ -29,7 +26,7 @@ public:
|
||||
|
||||
PluginStateAction _action = PluginStateAction::STOP;
|
||||
int _value = 0;
|
||||
StringVariable _settingsPath;
|
||||
std::string _settingsPath;
|
||||
OBSWeakSource _scene;
|
||||
|
||||
private:
|
||||
@@ -72,5 +69,3 @@ private:
|
||||
void SetWidgetVisibility();
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include "macro-action-profile.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionProfile::id = "profile";
|
||||
|
||||
bool MacroActionProfile::_registered = MacroActionFactory::Register(
|
||||
@@ -45,7 +44,7 @@ MacroActionProfileEdit::MacroActionProfileEdit(
|
||||
: QWidget(parent)
|
||||
{
|
||||
_profiles = new QComboBox();
|
||||
PopulateProfileSelection(_profiles);
|
||||
populateProfileSelection(_profiles);
|
||||
QWidget::connect(_profiles, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(ProfileChanged(const QString &)));
|
||||
|
||||
@@ -53,7 +52,7 @@ MacroActionProfileEdit::MacroActionProfileEdit(
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{profiles}}", _profiles},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.profile.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.profile.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -77,10 +76,8 @@ void MacroActionProfileEdit::ProfileChanged(const QString &text)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_profile = text.toStdString();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionProfile : public MacroAction {
|
||||
public:
|
||||
MacroActionProfile(Macro *m) : MacroAction(m) {}
|
||||
@@ -54,5 +52,3 @@ protected:
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
#include "macro-action-projector.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionProjector::id = "projector";
|
||||
|
||||
bool MacroActionProjector::_registered = MacroActionFactory::Register(
|
||||
@@ -117,6 +115,46 @@ static inline void populateWindowTypes(QComboBox *list)
|
||||
"AdvSceneSwitcher.action.projector.fullscreen"));
|
||||
}
|
||||
|
||||
static QStringList getMonitorNames()
|
||||
{
|
||||
QStringList monitorNames;
|
||||
QList<QScreen *> screens = QGuiApplication::screens();
|
||||
for (int i = 0; i < screens.size(); i++) {
|
||||
QScreen *screen = screens[i];
|
||||
QRect screenGeometry = screen->geometry();
|
||||
qreal ratio = screen->devicePixelRatio();
|
||||
QString name = "";
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
name = screen->name();
|
||||
#else
|
||||
name = screen->model().simplified();
|
||||
if (name.length() > 1 && name.endsWith("-")) {
|
||||
name.chop(1);
|
||||
}
|
||||
#endif
|
||||
name = name.simplified();
|
||||
|
||||
if (name.length() == 0) {
|
||||
name = QString("%1 %2")
|
||||
.arg(obs_module_text(
|
||||
"AdvSceneSwitcher.action.projector.display"))
|
||||
.arg(QString::number(i + 1));
|
||||
}
|
||||
QString str =
|
||||
QString("%1: %2x%3 @ %4,%5")
|
||||
.arg(name,
|
||||
QString::number(screenGeometry.width() *
|
||||
ratio),
|
||||
QString::number(screenGeometry.height() *
|
||||
ratio),
|
||||
QString::number(screenGeometry.x()),
|
||||
QString::number(screenGeometry.y()));
|
||||
|
||||
monitorNames << str;
|
||||
}
|
||||
return monitorNames;
|
||||
}
|
||||
|
||||
MacroActionProjectorEdit::MacroActionProjectorEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionProjector> entryData)
|
||||
: QWidget(parent),
|
||||
@@ -133,7 +171,7 @@ MacroActionProjectorEdit::MacroActionProjectorEdit(
|
||||
auto sources = GetSourceNames();
|
||||
sources.sort();
|
||||
_sources->SetSourceNameList(sources);
|
||||
_monitors->addItems(GetMonitorNames());
|
||||
_monitors->addItems(getMonitorNames());
|
||||
|
||||
QWidget::connect(_windowTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(WindowTypeChanged(int)));
|
||||
@@ -153,12 +191,12 @@ MacroActionProjectorEdit::MacroActionProjectorEdit(
|
||||
{"{{monitors}}", _monitors},
|
||||
};
|
||||
|
||||
PlaceWidgets(obs_module_text(
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.action.projector.entry.monitor"),
|
||||
_monitorSelection, widgetPlaceholders);
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.projector.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.projector.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
mainLayout->insertLayout(mainLayout->count() - 1, _monitorSelection);
|
||||
setLayout(mainLayout);
|
||||
@@ -187,7 +225,7 @@ void MacroActionProjectorEdit::SceneChanged(const SceneSelection &s)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_scene = s;
|
||||
}
|
||||
|
||||
@@ -197,7 +235,7 @@ void MacroActionProjectorEdit::SourceChanged(const SourceSelection &source)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = source;
|
||||
}
|
||||
|
||||
@@ -207,17 +245,17 @@ void MacroActionProjectorEdit::MonitorChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_monitor = value;
|
||||
}
|
||||
|
||||
void MacroActionProjectorEdit::WindowTypeChanged(int)
|
||||
void MacroActionProjectorEdit::WindowTypeChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_fullscreen =
|
||||
_windowTypes->currentText() ==
|
||||
obs_module_text("AdvSceneSwitcher.action.projector.fullscreen");
|
||||
@@ -230,7 +268,7 @@ void MacroActionProjectorEdit::TypeChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_type = static_cast<MacroActionProjector::Type>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
@@ -245,10 +283,8 @@ void MacroActionProjectorEdit::SetWidgetVisibility()
|
||||
MacroActionProjector::Type::SCENE);
|
||||
_sources->setVisible(_entryData->_type ==
|
||||
MacroActionProjector::Type::SOURCE);
|
||||
SetLayoutVisible(_monitorSelection, _entryData->_fullscreen);
|
||||
setLayoutVisible(_monitorSelection, _entryData->_fullscreen);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
#include "scene-selection.hpp"
|
||||
#include "source-selection.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionProjector : public MacroAction {
|
||||
public:
|
||||
MacroActionProjector(Macro *m) : MacroAction(m) {}
|
||||
@@ -73,5 +71,3 @@ private:
|
||||
void SetWidgetVisibility();
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
#include "macro-action-random.hpp"
|
||||
#include "macro.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionRandom::id = "random";
|
||||
|
||||
bool MacroActionRandom::_registered = MacroActionFactory::Register(
|
||||
@@ -13,30 +11,22 @@ bool MacroActionRandom::_registered = MacroActionFactory::Register(
|
||||
{MacroActionRandom::Create, MacroActionRandomEdit::Create,
|
||||
"AdvSceneSwitcher.action.random"});
|
||||
|
||||
static bool validNextMacro(const std::shared_ptr<Macro> ¯o)
|
||||
std::vector<MacroRef> getNextMacros(std::vector<MacroRef> ¯os,
|
||||
MacroRef &lastRandomMacro, bool allowRepeat)
|
||||
{
|
||||
return macro && !macro->Paused();
|
||||
}
|
||||
|
||||
static std::vector<std::shared_ptr<Macro>>
|
||||
getNextMacros(std::vector<MacroRef> ¯os, MacroRef &lastRandomMacroRef,
|
||||
bool allowRepeat)
|
||||
{
|
||||
std::vector<std::shared_ptr<Macro>> res;
|
||||
std::vector<MacroRef> res;
|
||||
if (macros.size() == 1) {
|
||||
auto macro = macros[0].GetMacro();
|
||||
if (validNextMacro(macro)) {
|
||||
res.push_back(macro);
|
||||
if (!macros[0].get() || macros[0]->Paused()) {
|
||||
return res;
|
||||
} else {
|
||||
return macros;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
auto lastRandomMacro = lastRandomMacroRef.GetMacro();
|
||||
for (auto &m : macros) {
|
||||
auto macro = m.GetMacro();
|
||||
if (validNextMacro(macro) &&
|
||||
(allowRepeat || (lastRandomMacro != macro))) {
|
||||
res.push_back(macro);
|
||||
if (m.get() && !m->Paused() &&
|
||||
(allowRepeat || (lastRandomMacro.get() != m.get()))) {
|
||||
res.push_back(m);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
@@ -52,7 +42,7 @@ bool MacroActionRandom::PerformAction()
|
||||
if (macros.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
if (macros.size() == 1) {
|
||||
if (macros.size() == 1 && macros[0].get()) {
|
||||
lastRandomMacro = macros[0];
|
||||
return macros[0]->PerformActions();
|
||||
}
|
||||
@@ -102,7 +92,7 @@ MacroActionRandomEdit::MacroActionRandomEdit(
|
||||
|
||||
auto *entryLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.random.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.random.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
@@ -136,7 +126,8 @@ void MacroActionRandomEdit::MacroRemove(const QString &)
|
||||
|
||||
auto it = _entryData->_macros.begin();
|
||||
while (it != _entryData->_macros.end()) {
|
||||
if (!it->GetMacro()) {
|
||||
it->UpdateRef();
|
||||
if (it->get() == nullptr) {
|
||||
it = _entryData->_macros.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
@@ -151,7 +142,7 @@ void MacroActionRandomEdit::Add(const std::string &name)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
MacroRef macro(name);
|
||||
_entryData->_macros.push_back(macro);
|
||||
_allowRepeat->setVisible(ShouldShowAllowRepeat());
|
||||
@@ -164,7 +155,7 @@ void MacroActionRandomEdit::Remove(int idx)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_macros.erase(std::next(_entryData->_macros.begin(), idx));
|
||||
_allowRepeat->setVisible(ShouldShowAllowRepeat());
|
||||
adjustSize();
|
||||
@@ -177,7 +168,7 @@ void MacroActionRandomEdit::Replace(int idx, const std::string &name)
|
||||
}
|
||||
|
||||
MacroRef macro(name);
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_macros[idx] = macro;
|
||||
adjustSize();
|
||||
}
|
||||
@@ -188,7 +179,7 @@ void MacroActionRandomEdit::AllowRepeatChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_allowRepeat = value;
|
||||
}
|
||||
|
||||
@@ -197,13 +188,11 @@ bool MacroActionRandomEdit::ShouldShowAllowRepeat()
|
||||
if (_entryData->_macros.size() <= 1) {
|
||||
return false;
|
||||
}
|
||||
const auto macro = _entryData->_macros[0].GetMacro();
|
||||
const auto macro = _entryData->_macros[0];
|
||||
for (const auto &m : _entryData->_macros) {
|
||||
if (macro != m.GetMacro()) {
|
||||
if (macro.get() != m.get()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#include <QListWidget>
|
||||
#include <QCheckBox>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionRandom : public MultiMacroRefAction {
|
||||
public:
|
||||
MacroActionRandom(Macro *m) : MacroAction(m), MultiMacroRefAction(m) {}
|
||||
@@ -62,5 +60,3 @@ private:
|
||||
QCheckBox *_allowRepeat;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "macro-action-recording.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <util/config-file.h>
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionRecord::id = "recording";
|
||||
|
||||
bool MacroActionRecord::_registered = MacroActionFactory::Register(
|
||||
@@ -12,80 +9,45 @@ bool MacroActionRecord::_registered = MacroActionFactory::Register(
|
||||
{MacroActionRecord::Create, MacroActionRecordEdit::Create,
|
||||
"AdvSceneSwitcher.action.recording"});
|
||||
|
||||
const static std::map<MacroActionRecord::Action, std::string> actionTypes = {
|
||||
{MacroActionRecord::Action::STOP,
|
||||
"AdvSceneSwitcher.action.recording.type.stop"},
|
||||
{MacroActionRecord::Action::START,
|
||||
"AdvSceneSwitcher.action.recording.type.start"},
|
||||
{MacroActionRecord::Action::PAUSE,
|
||||
"AdvSceneSwitcher.action.recording.type.pause"},
|
||||
{MacroActionRecord::Action::UNPAUSE,
|
||||
const static std::map<RecordAction, std::string> actionTypes = {
|
||||
{RecordAction::STOP, "AdvSceneSwitcher.action.recording.type.stop"},
|
||||
{RecordAction::START, "AdvSceneSwitcher.action.recording.type.start"},
|
||||
{RecordAction::PAUSE, "AdvSceneSwitcher.action.recording.type.pause"},
|
||||
{RecordAction::UNPAUSE,
|
||||
"AdvSceneSwitcher.action.recording.type.unpause"},
|
||||
{MacroActionRecord::Action::SPLIT,
|
||||
"AdvSceneSwitcher.action.recording.type.split"},
|
||||
{MacroActionRecord::Action::FOLDER,
|
||||
"AdvSceneSwitcher.action.recording.type.changeOutputFolder"},
|
||||
{MacroActionRecord::Action::FILE_FORMAT,
|
||||
"AdvSceneSwitcher.action.recording.type.changeOutputFileFormat"},
|
||||
{RecordAction::SPLIT, "AdvSceneSwitcher.action.recording.type.split"},
|
||||
};
|
||||
|
||||
bool MacroActionRecord::PerformAction()
|
||||
{
|
||||
switch (_action) {
|
||||
case Action::STOP:
|
||||
case RecordAction::STOP:
|
||||
if (obs_frontend_recording_active()) {
|
||||
obs_frontend_recording_stop();
|
||||
}
|
||||
break;
|
||||
case Action::START:
|
||||
case RecordAction::START:
|
||||
if (!obs_frontend_recording_active()) {
|
||||
obs_frontend_recording_start();
|
||||
}
|
||||
break;
|
||||
case Action::PAUSE:
|
||||
case RecordAction::PAUSE:
|
||||
if (obs_frontend_recording_active() &&
|
||||
!obs_frontend_recording_paused()) {
|
||||
obs_frontend_recording_pause(true);
|
||||
}
|
||||
break;
|
||||
case Action::UNPAUSE:
|
||||
case RecordAction::UNPAUSE:
|
||||
if (obs_frontend_recording_active() &&
|
||||
obs_frontend_recording_paused()) {
|
||||
obs_frontend_recording_pause(false);
|
||||
}
|
||||
break;
|
||||
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(28, 0, 0)
|
||||
case Action::SPLIT:
|
||||
case RecordAction::SPLIT:
|
||||
obs_frontend_recording_split_file();
|
||||
break;
|
||||
#endif
|
||||
case Action::FOLDER: {
|
||||
std::string folder = _folder; // Trigger variable resolve
|
||||
|
||||
auto conf = obs_frontend_get_profile_config();
|
||||
config_set_string(conf, "SimpleOutput", "FilePath",
|
||||
folder.c_str());
|
||||
config_set_string(conf, "AdvOut", "FFFilePath", folder.c_str());
|
||||
config_set_string(conf, "AdvOut", "RecFilePath",
|
||||
folder.c_str());
|
||||
if (config_save(conf) != CONFIG_SUCCESS) {
|
||||
blog(LOG_WARNING,
|
||||
"failed to set recoding output folder");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Action::FILE_FORMAT: {
|
||||
std::string format = _fileFormat; // Trigger variable resolve
|
||||
|
||||
auto conf = obs_frontend_get_profile_config();
|
||||
config_set_string(conf, "Output", "FilenameFormatting",
|
||||
format.c_str());
|
||||
if (config_save(conf) != CONFIG_SUCCESS) {
|
||||
blog(LOG_WARNING,
|
||||
"failed to set recoding file format string");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -107,17 +69,13 @@ bool MacroActionRecord::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
_folder.Save(obj, "folder");
|
||||
_fileFormat.Save(obj, "format");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionRecord::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
_folder.Load(obj, "folder");
|
||||
_fileFormat.Load(obj, "format");
|
||||
_action = static_cast<RecordAction>(obs_data_get_int(obj, "action"));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -135,27 +93,21 @@ MacroActionRecordEdit::MacroActionRecordEdit(
|
||||
_pauseHint(new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.action.recording.pause.hint"))),
|
||||
_splitHint(new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.action.recording.split.hint"))),
|
||||
_recordFolder(new FileSelection(FileSelection::Type::FOLDER, this)),
|
||||
_recordFileFormat(new VariableLineEdit(this))
|
||||
"AdvSceneSwitcher.action.recording.split.hint")))
|
||||
{
|
||||
populateActionSelection(_actions);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_recordFolder, SIGNAL(PathChanged(const QString &)),
|
||||
this, SLOT(FolderChanged(const QString &)));
|
||||
QWidget::connect(_recordFileFormat, SIGNAL(editingFinished()), this,
|
||||
SLOT(FormatStringChanged()));
|
||||
|
||||
auto mainLayout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.recording.entry"),
|
||||
mainLayout,
|
||||
{{"{{actions}}", _actions},
|
||||
{"{{pauseHint}}", _pauseHint},
|
||||
{"{{splitHint}}", _splitHint},
|
||||
{"{{recordFolder}}", _recordFolder},
|
||||
{"{{recordFileFormat}}", _recordFileFormat}});
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{actions}}", _actions},
|
||||
{"{{pauseHint}}", _pauseHint},
|
||||
{"{{splitHint}}", _splitHint},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.recording.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -169,46 +121,18 @@ void MacroActionRecordEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_recordFolder->SetPath(_entryData->_folder);
|
||||
_recordFileFormat->setText(_entryData->_fileFormat);
|
||||
SetWidgetVisibility();
|
||||
SetLabelVisibility();
|
||||
}
|
||||
|
||||
static bool isPauseAction(MacroActionRecord::Action a)
|
||||
bool isPauseAction(RecordAction a)
|
||||
{
|
||||
return a == MacroActionRecord::Action::PAUSE ||
|
||||
a == MacroActionRecord::Action::UNPAUSE;
|
||||
return a == RecordAction::PAUSE || a == RecordAction::UNPAUSE;
|
||||
}
|
||||
|
||||
void MacroActionRecordEdit::FolderChanged(const QString &folder)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_folder = folder.toStdString();
|
||||
}
|
||||
|
||||
void MacroActionRecordEdit::FormatStringChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_fileFormat = _recordFileFormat->text().toStdString();
|
||||
}
|
||||
|
||||
void MacroActionRecordEdit::SetWidgetVisibility()
|
||||
void MacroActionRecordEdit::SetLabelVisibility()
|
||||
{
|
||||
_pauseHint->setVisible(isPauseAction(_entryData->_action));
|
||||
_splitHint->setVisible(_entryData->_action ==
|
||||
MacroActionRecord::Action::SPLIT);
|
||||
_recordFolder->setVisible(_entryData->_action ==
|
||||
MacroActionRecord::Action::FOLDER);
|
||||
_recordFileFormat->setVisible(_entryData->_action ==
|
||||
MacroActionRecord::Action::FILE_FORMAT);
|
||||
_splitHint->setVisible(_entryData->_action == RecordAction::SPLIT);
|
||||
}
|
||||
|
||||
void MacroActionRecordEdit::ActionChanged(int value)
|
||||
@@ -217,9 +141,7 @@ void MacroActionRecordEdit::ActionChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<MacroActionRecord::Action>(value);
|
||||
SetWidgetVisibility();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<RecordAction>(value);
|
||||
SetLabelVisibility();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "file-selection.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
|
||||
#include <QDir>
|
||||
#include <QComboBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
namespace advss {
|
||||
enum class RecordAction {
|
||||
STOP,
|
||||
START,
|
||||
PAUSE,
|
||||
UNPAUSE,
|
||||
SPLIT,
|
||||
};
|
||||
|
||||
class MacroActionRecord : public MacroAction {
|
||||
public:
|
||||
@@ -22,19 +25,7 @@ public:
|
||||
return std::make_shared<MacroActionRecord>(m);
|
||||
}
|
||||
|
||||
enum class Action {
|
||||
STOP,
|
||||
START,
|
||||
PAUSE,
|
||||
UNPAUSE,
|
||||
SPLIT,
|
||||
FOLDER,
|
||||
FILE_FORMAT,
|
||||
};
|
||||
Action _action = Action::STOP;
|
||||
|
||||
StringVariable _folder = QDir::homePath().toStdString() + "/Videos";
|
||||
StringVariable _fileFormat = "%CCYY-%MM-%DD %hh-%mm-%ss";
|
||||
RecordAction _action = RecordAction::STOP;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -59,22 +50,16 @@ public:
|
||||
|
||||
private slots:
|
||||
void ActionChanged(int value);
|
||||
void FolderChanged(const QString &);
|
||||
void FormatStringChanged();
|
||||
|
||||
protected:
|
||||
QComboBox *_actions;
|
||||
QLabel *_pauseHint;
|
||||
QLabel *_splitHint;
|
||||
FileSelection *_recordFolder;
|
||||
VariableLineEdit *_recordFileFormat;
|
||||
std::shared_ptr<MacroActionRecord> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
void SetLabelVisibility();
|
||||
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include "macro-action-replay-buffer.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionReplayBuffer::id = "replay_buffer";
|
||||
|
||||
bool MacroActionReplayBuffer::_registered = MacroActionFactory::Register(
|
||||
@@ -90,7 +89,7 @@ MacroActionReplayBufferEdit::MacroActionReplayBufferEdit(
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{actions}}", _actions},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.replay.entry"),
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.replay.entry"),
|
||||
layout, widgetPlaceholders);
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(layout);
|
||||
@@ -118,11 +117,9 @@ void MacroActionReplayBufferEdit::ActionChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<ReplayBufferAction>(value);
|
||||
_saveWarning->setVisible(_entryData->_action ==
|
||||
ReplayBufferAction::SAVE);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class ReplayBufferAction {
|
||||
STOP,
|
||||
START,
|
||||
@@ -60,5 +58,3 @@ protected:
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#include "macro-action-run.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "name-dialog.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QProcess>
|
||||
#include <QFileDialog>
|
||||
#include <QDesktopServices>
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionRun::id = "run";
|
||||
|
||||
bool MacroActionRun::_registered = MacroActionFactory::Register(
|
||||
@@ -14,53 +15,137 @@ bool MacroActionRun::_registered = MacroActionFactory::Register(
|
||||
|
||||
bool MacroActionRun::PerformAction()
|
||||
{
|
||||
bool procStarted = QProcess::startDetached(
|
||||
QString::fromStdString(_procConfig.Path()), _procConfig.Args(),
|
||||
QString::fromStdString(_procConfig.WorkingDir()));
|
||||
if (!procStarted && _procConfig.Args().empty()) {
|
||||
if (!QProcess::startDetached(
|
||||
QString::fromStdString(_path), _args,
|
||||
QString::fromStdString(_workingDirectory)) &&
|
||||
_args.empty()) {
|
||||
vblog(LOG_INFO, "run \"%s\" using QDesktopServices",
|
||||
_procConfig.Path().c_str());
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(
|
||||
QString::fromStdString(_procConfig.Path())));
|
||||
_path.c_str());
|
||||
QDesktopServices::openUrl(
|
||||
QUrl::fromLocalFile(QString::fromStdString(_path)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionRun::LogAction() const
|
||||
{
|
||||
vblog(LOG_INFO, "run \"%s\"", _procConfig.UnresolvedPath().c_str());
|
||||
vblog(LOG_INFO, "run \"%s\"", _path.c_str());
|
||||
}
|
||||
|
||||
bool MacroActionRun::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_procConfig.Save(obj);
|
||||
obs_data_set_string(obj, "path", _path.c_str());
|
||||
obs_data_set_string(obj, "workingDirectory", _workingDirectory.c_str());
|
||||
obs_data_array_t *args = obs_data_array_create();
|
||||
for (auto &arg : _args) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
obs_data_set_string(array_obj, "arg",
|
||||
arg.toStdString().c_str());
|
||||
obs_data_array_push_back(args, array_obj);
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "args", args);
|
||||
obs_data_array_release(args);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionRun::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_procConfig.Load(obj);
|
||||
_path = obs_data_get_string(obj, "path");
|
||||
_workingDirectory = obs_data_get_string(obj, "workingDirectory");
|
||||
obs_data_array_t *args = obs_data_get_array(obj, "args");
|
||||
size_t count = obs_data_array_count(args);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj = obs_data_array_item(args, i);
|
||||
_args << QString::fromStdString(
|
||||
obs_data_get_string(array_obj, "arg"));
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(args);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionRun::GetShortDesc() const
|
||||
{
|
||||
return _procConfig.UnresolvedPath();
|
||||
return _path;
|
||||
}
|
||||
|
||||
MacroActionRunEdit::MacroActionRunEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionRun> entryData)
|
||||
: QWidget(parent), _procConfig(new ProcessConfigEdit(this))
|
||||
: QWidget(parent),
|
||||
_filePath(new FileSelection()),
|
||||
_argList(new QListWidget()),
|
||||
_addArg(new QPushButton()),
|
||||
_removeArg(new QPushButton()),
|
||||
_argUp(new QPushButton()),
|
||||
_argDown(new QPushButton()),
|
||||
_workingDirectory(new FileSelection(FileSelection::Type::FOLDER))
|
||||
{
|
||||
QWidget::connect(_procConfig,
|
||||
SIGNAL(ConfigChanged(const ProcessConfig &)), this,
|
||||
SLOT(ProcessConfigChanged(const ProcessConfig &)));
|
||||
_addArg->setMaximumWidth(22);
|
||||
_addArg->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("addIconSmall")));
|
||||
_addArg->setFlat(true);
|
||||
_removeArg->setMaximumWidth(22);
|
||||
_removeArg->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("removeIconSmall")));
|
||||
_removeArg->setFlat(true);
|
||||
_argUp->setMaximumWidth(22);
|
||||
_argUp->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("upArrowIconSmall")));
|
||||
_argUp->setFlat(true);
|
||||
_argDown->setMaximumWidth(22);
|
||||
_argDown->setProperty(
|
||||
"themeID", QVariant(QString::fromUtf8("downArrowIconSmall")));
|
||||
_argDown->setFlat(true);
|
||||
|
||||
auto *layout = new QVBoxLayout;
|
||||
layout->addWidget(_procConfig);
|
||||
setLayout(layout);
|
||||
QWidget::connect(_filePath, SIGNAL(PathChanged(const QString &)), this,
|
||||
SLOT(PathChanged(const QString &)));
|
||||
QWidget::connect(_addArg, SIGNAL(clicked()), this, SLOT(AddArg()));
|
||||
QWidget::connect(_removeArg, SIGNAL(clicked()), this,
|
||||
SLOT(RemoveArg()));
|
||||
QWidget::connect(_argUp, SIGNAL(clicked()), this, SLOT(ArgUp()));
|
||||
QWidget::connect(_argDown, SIGNAL(clicked()), this, SLOT(ArgDown()));
|
||||
QWidget::connect(_argList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
|
||||
this, SLOT(ArgItemClicked(QListWidgetItem *)));
|
||||
QWidget::connect(_workingDirectory,
|
||||
SIGNAL(PathChanged(const QString &)), this,
|
||||
SLOT(WorkingDirectoryChanged(const QString &)));
|
||||
|
||||
auto *entryLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{filePath}}", _filePath},
|
||||
{"{{workingDirectory}}", _workingDirectory},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.run.entry"),
|
||||
entryLayout, widgetPlaceholders, false);
|
||||
|
||||
auto argButtonLayout = new QHBoxLayout;
|
||||
argButtonLayout->addWidget(_addArg);
|
||||
argButtonLayout->addWidget(_removeArg);
|
||||
QFrame *line = new QFrame();
|
||||
line->setFrameShape(QFrame::VLine);
|
||||
line->setFrameShadow(QFrame::Sunken);
|
||||
argButtonLayout->addWidget(line);
|
||||
argButtonLayout->addWidget(_argUp);
|
||||
argButtonLayout->addWidget(_argDown);
|
||||
argButtonLayout->addStretch();
|
||||
|
||||
auto workingDirectoryLayout = new QHBoxLayout;
|
||||
placeWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.run.entry.workingDirectory"),
|
||||
workingDirectoryLayout, widgetPlaceholders, false);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.action.run.arguments")));
|
||||
mainLayout->addWidget(_argList);
|
||||
mainLayout->addLayout(argButtonLayout);
|
||||
mainLayout->addLayout(workingDirectoryLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
@@ -72,21 +157,142 @@ void MacroActionRunEdit::UpdateEntryData()
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
_procConfig->SetProcessConfig(_entryData->_procConfig);
|
||||
_filePath->SetPath(QString::fromStdString(_entryData->_path));
|
||||
for (auto &arg : _entryData->_args) {
|
||||
QListWidgetItem *item = new QListWidgetItem(arg, _argList);
|
||||
item->setData(Qt::UserRole, arg);
|
||||
}
|
||||
_workingDirectory->SetPath(
|
||||
QString::fromStdString(_entryData->_workingDirectory));
|
||||
SetArgListSize();
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::ProcessConfigChanged(const ProcessConfig &conf)
|
||||
void MacroActionRunEdit::PathChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_procConfig = conf;
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_path = text.toUtf8().constData();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
void MacroActionRunEdit::AddArg()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
bool accepted = AdvSSNameDialog::AskForName(
|
||||
this,
|
||||
obs_module_text("AdvSceneSwitcher.action.run.addArgument"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.run.addArgumentDescription"),
|
||||
name, "", 170, false);
|
||||
|
||||
if (!accepted || name.empty()) {
|
||||
return;
|
||||
}
|
||||
auto arg = QString::fromStdString(name);
|
||||
QVariant v = QVariant::fromValue(arg);
|
||||
QListWidgetItem *item = new QListWidgetItem(arg, _argList);
|
||||
item->setData(Qt::UserRole, arg);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_args << arg;
|
||||
SetArgListSize();
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::RemoveArg()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
int idx = _argList->currentRow();
|
||||
if (idx == -1) {
|
||||
return;
|
||||
}
|
||||
_entryData->_args.removeAt(idx);
|
||||
|
||||
QListWidgetItem *item = _argList->currentItem();
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
delete item;
|
||||
SetArgListSize();
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::ArgUp()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
int idx = _argList->currentRow();
|
||||
if (idx != -1 && idx != 0) {
|
||||
_argList->insertItem(idx - 1, _argList->takeItem(idx));
|
||||
_argList->setCurrentRow(idx - 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_args.move(idx, idx - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::ArgDown()
|
||||
{
|
||||
int idx = _argList->currentRow();
|
||||
if (idx != -1 && idx != _argList->count() - 1) {
|
||||
_argList->insertItem(idx + 1, _argList->takeItem(idx));
|
||||
_argList->setCurrentRow(idx + 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_args.move(idx, idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::ArgItemClicked(QListWidgetItem *item)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
bool accepted = AdvSSNameDialog::AskForName(
|
||||
this,
|
||||
obs_module_text("AdvSceneSwitcher.action.run.addArgument"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.run.addArgumentDescription"),
|
||||
name, item->text(), 170, false);
|
||||
|
||||
if (!accepted || name.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto arg = QString::fromStdString(name);
|
||||
QVariant v = QVariant::fromValue(arg);
|
||||
item->setText(arg);
|
||||
item->setData(Qt::UserRole, arg);
|
||||
int idx = _argList->currentRow();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_args[idx] = arg;
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::WorkingDirectoryChanged(const QString &path)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_entryData->_workingDirectory = path.toStdString();
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::SetArgListSize()
|
||||
{
|
||||
setHeightToContentHeight(_argList);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "process-config.hpp"
|
||||
#include "file-selection.hpp"
|
||||
|
||||
namespace advss {
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QListWidget>
|
||||
#include <QStringList>
|
||||
|
||||
class MacroActionRun : public MacroAction {
|
||||
public:
|
||||
@@ -18,7 +21,9 @@ public:
|
||||
return std::make_shared<MacroActionRun>(m);
|
||||
}
|
||||
|
||||
ProcessConfig _procConfig;
|
||||
std::string _path = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
std::string _workingDirectory = "";
|
||||
QStringList _args;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -41,7 +46,13 @@ public:
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ProcessConfigChanged(const ProcessConfig &);
|
||||
void PathChanged(const QString &text);
|
||||
void AddArg();
|
||||
void RemoveArg();
|
||||
void ArgUp();
|
||||
void ArgDown();
|
||||
void ArgItemClicked(QListWidgetItem *);
|
||||
void WorkingDirectoryChanged(const QString &text);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
@@ -49,8 +60,14 @@ protected:
|
||||
std::shared_ptr<MacroActionRun> _entryData;
|
||||
|
||||
private:
|
||||
ProcessConfigEdit *_procConfig;
|
||||
void SetArgListSize();
|
||||
|
||||
FileSelection *_filePath;
|
||||
QListWidget *_argList;
|
||||
QPushButton *_addArg;
|
||||
QPushButton *_removeArg;
|
||||
QPushButton *_argUp;
|
||||
QPushButton *_argDown;
|
||||
FileSelection *_workingDirectory;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#include "macro-action-scene-collection.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionSceneCollection::id = "scene_collection";
|
||||
|
||||
bool MacroActionSceneCollection::_registered = MacroActionFactory::Register(
|
||||
@@ -62,7 +60,7 @@ void populateSceneCollectionSelection(QComboBox *box)
|
||||
}
|
||||
bfree(sceneCollections);
|
||||
box->model()->sort(0);
|
||||
AddSelectionEntry(
|
||||
addSelectionEntry(
|
||||
box, obs_module_text("AdvSceneSwitcher.selectSceneCollection"),
|
||||
false);
|
||||
box->setCurrentIndex(0);
|
||||
@@ -82,7 +80,7 @@ MacroActionSceneCollectionEdit::MacroActionSceneCollectionEdit(
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{sceneCollections}}", _sceneCollections},
|
||||
};
|
||||
PlaceWidgets(obs_module_text(
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.action.sceneCollection.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
@@ -112,10 +110,8 @@ void MacroActionSceneCollectionEdit::SceneCollectionChanged(const QString &text)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_sceneCollection = text.toStdString();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionSceneCollection : public MacroAction {
|
||||
public:
|
||||
MacroActionSceneCollection(Macro *m) : MacroAction(m) {}
|
||||
@@ -55,5 +53,3 @@ protected:
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||