mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
Compare commits
78 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
faf0866f1b | ||
|
228afd3405 | ||
|
0548c7798a | ||
|
6c9fd55c63 | ||
![]() |
7e3f2a82f0 | ||
|
65396e1db7 | ||
|
f8bc7c4f59 | ||
|
9e48274617 | ||
![]() |
3b7c1c5381 | ||
|
20551043f9 | ||
![]() |
086bf06008 | ||
|
6483dcaef0 | ||
|
71920c484b | ||
|
0eda8f9406 | ||
|
3b873ceb30 | ||
|
36f50adf8a | ||
![]() |
acd1af12a1 | ||
|
eb2882515f | ||
|
5c3c4c76c8 | ||
|
8c80e0745a | ||
|
5b4aa9dabd | ||
|
ee283c7141 | ||
|
179e197bd5 | ||
|
5fc39ef054 | ||
|
74719ce502 | ||
|
9123879c76 | ||
|
9db7464faa | ||
|
e2b8a06d94 | ||
|
af31f1adca | ||
|
4410e30684 | ||
|
2c884ca690 | ||
|
f72f23a9d7 | ||
|
a589e80bdb | ||
|
305afd763d | ||
|
42e7eb6c34 | ||
|
bdf812dc09 | ||
|
c8cf2d94ac | ||
![]() |
d2d4bfb3e7 | ||
|
d5077fca03 | ||
|
4a647c5262 | ||
|
3ea3d3228b | ||
|
e94f9194a2 | ||
![]() |
9ee6e2ff2a | ||
|
b61a5c2431 | ||
![]() |
fbd4cfb4af | ||
|
e5aa4c2f69 | ||
![]() |
4cf8de8382 | ||
|
7adfb5874c | ||
|
f18f46543b | ||
|
f40426efa1 | ||
|
830f7eb931 | ||
![]() |
5e3fff78f3 | ||
|
b53527cba8 | ||
![]() |
b806a0cfb1 | ||
|
1d0db34bb2 | ||
![]() |
690726d281 | ||
|
ef4142fe75 | ||
|
caaec5d97f | ||
|
6c67b276a7 | ||
![]() |
fad7dfd55c | ||
|
a5c459b6d4 | ||
|
899a9b3801 | ||
|
939e503736 | ||
|
5b149add99 | ||
|
50b57d38d0 | ||
![]() |
9b58dd1627 | ||
|
81b307e5ad | ||
![]() |
52733ddce7 | ||
|
444caeb1d7 | ||
![]() |
f03e82c3f8 | ||
|
bbdc5bc823 | ||
|
9ecc9532e8 | ||
|
0189c3a3f5 | ||
![]() |
f48fcc06ec | ||
|
f43ef8e2da | ||
|
7a1c71bb96 | ||
|
cf285b3761 | ||
![]() |
ede66a68cb |
131
.clang-format
131
.clang-format
@ -1,6 +1,6 @@
|
||||
# please use clang-format version 8 or later
|
||||
# please use clang-format version 16 or later
|
||||
|
||||
Standard: Cpp11
|
||||
Standard: c++17
|
||||
AccessModifierOffset: -8
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
@ -8,14 +8,14 @@ AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
#AllowAllArgumentsOnNextLine: false # requires clang-format 9
|
||||
#AllowAllConstructorInitializersOnNextLine: false # requires clang-format 9
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
#AllowShortLambdasOnASingleLine: Inline # requires clang-format 9
|
||||
AllowShortLambdasOnASingleLine: Inline
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
@ -53,10 +53,11 @@ Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros:
|
||||
ForEachMacros:
|
||||
- 'json_object_foreach'
|
||||
- 'json_object_foreach_safe'
|
||||
- 'json_array_foreach'
|
||||
- 'HASH_ITER'
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
@ -65,7 +66,7 @@ IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: All
|
||||
#ObjCBinPackProtocolList: Auto # requires clang-format 7
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 8
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
@ -83,13 +84,13 @@ ReflowComments: false
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: false
|
||||
SpaceAfterCStyleCast: false
|
||||
#SpaceAfterLogicalNot: false # requires clang-format 9
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
#SpaceBeforeCtorInitializerColon: true # requires clang-format 7
|
||||
#SpaceBeforeInheritanceColon: true # requires clang-format 7
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
#SpaceBeforeRangeBasedForLoopColon: true # requires clang-format 7
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
@ -97,11 +98,111 @@ SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
#StatementMacros: # requires clang-format 8
|
||||
# - 'Q_OBJECT'
|
||||
StatementMacros:
|
||||
- 'Q_OBJECT'
|
||||
TabWidth: 8
|
||||
#TypenameMacros: # requires clang-format 9
|
||||
# - 'DARRAY'
|
||||
TypenameMacros:
|
||||
- 'DARRAY'
|
||||
UseTab: ForContinuationAndIndentation
|
||||
---
|
||||
Language: ObjC
|
||||
AccessModifierOffset: 2
|
||||
AlignArrayOfStructures: Right
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveBitFields: None
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: None
|
||||
AttributeMacros: ['__unused', '__autoreleasing', '_Nonnull', '__bridge']
|
||||
BitFieldColonSpacing: Both
|
||||
#BreakBeforeBraces: Webkit
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: true
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: true
|
||||
BreakAfterAttributes: Never
|
||||
BreakArrays: false
|
||||
BreakBeforeConceptDeclarations: Allowed
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakInheritanceList: AfterComma
|
||||
ColumnLimit: 120
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: true
|
||||
IndentExternBlock: Indent
|
||||
IndentGotoLabels: false
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: true
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
LambdaBodyIndentation: Signature
|
||||
NamespaceIndentation: All
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCBreakBeforeNestedBlockParam: false
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PPIndentWidth: -1
|
||||
PackConstructorInitializers: NextLine
|
||||
QualifierAlignment: Leave
|
||||
ReferenceAlignment: Right
|
||||
RemoveSemicolon: false
|
||||
RequiresClausePosition: WithPreceding
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Always
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: false
|
||||
#SortUsingDeclarations: LexicographicNumeric
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
Standard: c++17
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
|
2
.github/workflows/crowdin_upload.yml
vendored
2
.github/workflows/crowdin_upload.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
||||
if: github.repository_owner == 'obsproject'
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 100
|
||||
- name: Upload US English Language Files 🇺🇸
|
||||
|
2
.github/workflows/generate_docs.yml
vendored
2
.github/workflows/generate_docs.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
||||
IS_CI: "true"
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: ${{ github.workspace }}/obs-websocket
|
||||
- name: 'Generate docs'
|
||||
|
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
if: contains(github.event.head_commit.message, '[skip ci]') != true
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Generate docs
|
||||
run: cd docs && ./build_docs.sh
|
||||
- name: Run markdownlint-cli
|
||||
|
@ -2,9 +2,11 @@ cmake_minimum_required(VERSION 3.16...3.25)
|
||||
|
||||
legacy_check()
|
||||
|
||||
set(obs-websocket_VERSION 5.3.4)
|
||||
set(obs-websocket_VERSION 5.5.2)
|
||||
set(OBS_WEBSOCKET_RPC_VERSION 1)
|
||||
|
||||
include(cmake/obs-websocket-api.cmake)
|
||||
|
||||
option(ENABLE_WEBSOCKET "Enable building OBS with websocket plugin" ON)
|
||||
if(NOT ENABLE_WEBSOCKET)
|
||||
target_disable(obs-websocket)
|
||||
@ -12,7 +14,7 @@ if(NOT ENABLE_WEBSOCKET)
|
||||
endif()
|
||||
|
||||
# Find Qt
|
||||
find_qt(COMPONENTS Core Widgets Svg Network)
|
||||
find_package(Qt6 REQUIRED Core Widgets Svg Network)
|
||||
|
||||
# Find nlohmann JSON
|
||||
find_package(nlohmann_json 3 REQUIRED)
|
||||
@ -31,51 +33,52 @@ find_package(Asio 1.12.1 REQUIRED)
|
||||
add_library(obs-websocket MODULE)
|
||||
add_library(OBS::websocket ALIAS obs-websocket)
|
||||
|
||||
target_sources(obs-websocket PRIVATE)
|
||||
|
||||
target_sources(
|
||||
obs-websocket
|
||||
PRIVATE src/obs-websocket.cpp
|
||||
src/obs-websocket.h
|
||||
PRIVATE # cmake-format: sortable
|
||||
src/Config.cpp
|
||||
src/Config.h
|
||||
lib/obs-websocket-api.h
|
||||
src/forms/ConnectInfo.cpp
|
||||
src/forms/ConnectInfo.h
|
||||
src/forms/resources.qrc
|
||||
src/forms/SettingsDialog.cpp
|
||||
src/forms/SettingsDialog.h
|
||||
src/obs-websocket.cpp
|
||||
src/obs-websocket.h
|
||||
src/WebSocketApi.cpp
|
||||
src/WebSocketApi.h)
|
||||
|
||||
target_sources(
|
||||
obs-websocket
|
||||
PRIVATE src/websocketserver/WebSocketServer.cpp
|
||||
src/websocketserver/WebSocketServer_Protocol.cpp
|
||||
src/websocketserver/WebSocketServer.h
|
||||
PRIVATE # cmake-format: sortable
|
||||
src/websocketserver/rpc/WebSocketSession.h
|
||||
src/websocketserver/types/WebSocketCloseCode.h
|
||||
src/websocketserver/types/WebSocketOpCode.h)
|
||||
src/websocketserver/types/WebSocketOpCode.h
|
||||
src/websocketserver/WebSocketServer.cpp
|
||||
src/websocketserver/WebSocketServer.h
|
||||
src/websocketserver/WebSocketServer_Protocol.cpp)
|
||||
|
||||
target_sources(
|
||||
obs-websocket
|
||||
PRIVATE src/eventhandler/EventHandler.cpp
|
||||
PRIVATE # cmake-format: sortable
|
||||
src/eventhandler/EventHandler.cpp
|
||||
src/eventhandler/EventHandler.h
|
||||
src/eventhandler/EventHandler_Config.cpp
|
||||
src/eventhandler/EventHandler_General.cpp
|
||||
src/eventhandler/EventHandler_Filters.cpp
|
||||
src/eventhandler/EventHandler_General.cpp
|
||||
src/eventhandler/EventHandler_Inputs.cpp
|
||||
src/eventhandler/EventHandler_MediaInputs.cpp
|
||||
src/eventhandler/EventHandler_Outputs.cpp
|
||||
src/eventhandler/EventHandler_Scenes.cpp
|
||||
src/eventhandler/EventHandler_SceneItems.cpp
|
||||
src/eventhandler/EventHandler_Scenes.cpp
|
||||
src/eventhandler/EventHandler_Transitions.cpp
|
||||
src/eventhandler/EventHandler_Ui.cpp
|
||||
src/eventhandler/types/EventSubscription.h)
|
||||
|
||||
target_sources(
|
||||
obs-websocket
|
||||
PRIVATE src/requesthandler/RequestBatchHandler.cpp
|
||||
PRIVATE # cmake-format: sortable
|
||||
src/requesthandler/RequestBatchHandler.cpp
|
||||
src/requesthandler/RequestBatchHandler.h
|
||||
src/requesthandler/RequestHandler.cpp
|
||||
src/requesthandler/RequestHandler.h
|
||||
@ -85,10 +88,10 @@ target_sources(
|
||||
src/requesthandler/RequestHandler_Inputs.cpp
|
||||
src/requesthandler/RequestHandler_MediaInputs.cpp
|
||||
src/requesthandler/RequestHandler_Outputs.cpp
|
||||
src/requesthandler/RequestHandler_Sources.cpp
|
||||
src/requesthandler/RequestHandler_Record.cpp
|
||||
src/requesthandler/RequestHandler_Scenes.cpp
|
||||
src/requesthandler/RequestHandler_SceneItems.cpp
|
||||
src/requesthandler/RequestHandler_Scenes.cpp
|
||||
src/requesthandler/RequestHandler_Sources.cpp
|
||||
src/requesthandler/RequestHandler_Stream.cpp
|
||||
src/requesthandler/RequestHandler_Transitions.cpp
|
||||
src/requesthandler/RequestHandler_Ui.cpp
|
||||
@ -98,12 +101,13 @@ target_sources(
|
||||
src/requesthandler/rpc/RequestBatchRequest.h
|
||||
src/requesthandler/rpc/RequestResult.cpp
|
||||
src/requesthandler/rpc/RequestResult.h
|
||||
src/requesthandler/types/RequestStatus.h
|
||||
src/requesthandler/types/RequestBatchExecutionType.h)
|
||||
src/requesthandler/types/RequestBatchExecutionType.h
|
||||
src/requesthandler/types/RequestStatus.h)
|
||||
|
||||
target_sources(
|
||||
obs-websocket
|
||||
PRIVATE src/utils/Compat.cpp
|
||||
PRIVATE # cmake-format: sortable
|
||||
src/utils/Compat.cpp
|
||||
src/utils/Compat.h
|
||||
src/utils/Crypto.cpp
|
||||
src/utils/Crypto.h
|
||||
@ -115,8 +119,8 @@ target_sources(
|
||||
src/utils/Obs_ArrayHelper.cpp
|
||||
src/utils/Obs_NumberHelper.cpp
|
||||
src/utils/Obs_ObjectHelper.cpp
|
||||
src/utils/Obs_StringHelper.cpp
|
||||
src/utils/Obs_SearchHelper.cpp
|
||||
src/utils/Obs_StringHelper.cpp
|
||||
src/utils/Obs_VolumeMeter.cpp
|
||||
src/utils/Obs_VolumeMeter.h
|
||||
src/utils/Obs_VolumeMeter_Helpers.h
|
||||
@ -133,19 +137,27 @@ target_compile_definitions(
|
||||
|
||||
target_compile_options(
|
||||
obs-websocket
|
||||
PRIVATE
|
||||
$<$<PLATFORM_ID:Windows>:/wd4267>
|
||||
$<$<PLATFORM_ID:Windows>:/wd4996>
|
||||
$<$<PLATFORM_ID:Darwin,Linux,FreeBSD>:-Wall>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,GNU,AppleClang,Clang>:-Wno-error=float-conversion;-Wno-error=shadow>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wno-error=format-overflow;-Wno-error=int-conversion;-Wno-error=comment>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-error=null-pointer-subtraction;-Wno-error=deprecated-declarations;-Wno-error=implicit-int-conversion;-Wno-error=shorten-64-to-32;-Wno-comma;-Wno-quoted-include-in-framework-header>
|
||||
)
|
||||
PRIVATE $<$<PLATFORM_ID:Windows>:/wd4267>
|
||||
$<$<PLATFORM_ID:Windows>:/wd4996>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,GNU,AppleClang,Clang>:-Wall>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,GNU,AppleClang,Clang>:-Wno-error=float-conversion>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,GNU,AppleClang,Clang>:-Wno-error=shadow>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wno-error=format-overflow>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wno-error=int-conversion>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wno-error=comment>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wno-error=deprecated-declarations>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-error=null-pointer-subtraction>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-error=deprecated-declarations>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-error=implicit-int-conversion>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-error=shorten-64-to-32>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-comma>
|
||||
$<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-quoted-include-in-framework-header>)
|
||||
|
||||
target_link_libraries(
|
||||
obs-websocket
|
||||
PRIVATE OBS::libobs
|
||||
OBS::frontend-api
|
||||
OBS::websocket-api
|
||||
Qt::Core
|
||||
Qt::Widgets
|
||||
Qt::Svg
|
||||
@ -155,6 +167,8 @@ target_link_libraries(
|
||||
Asio::Asio
|
||||
qrcodegencpp::qrcodegencpp)
|
||||
|
||||
target_link_options(obs-websocket PRIVATE $<$<PLATFORM_ID:Windows>:/IGNORE:4099>)
|
||||
|
||||
set_target_properties_obs(
|
||||
obs-websocket
|
||||
PROPERTIES FOLDER plugins
|
||||
@ -168,6 +182,4 @@ if(OS_WINDOWS)
|
||||
TARGET obs-websocket
|
||||
APPEND
|
||||
PROPERTY AUTORCC_OPTIONS --format-version 1)
|
||||
|
||||
target_link_options(obs-websocket PRIVATE /IGNORE:4099)
|
||||
endif()
|
||||
|
@ -41,6 +41,8 @@ It is **highly recommended** to keep obs-websocket protected with a password aga
|
||||
- [Aitum](https://aitum.tv/)
|
||||
- [Kruiz Control](https://github.com/Kruiser8/Kruiz-Control)
|
||||
- [Bitfocus Companion Module](https://bitfocus.io/companion/)
|
||||
- [MacroGraph](https://github.com/Brendonovich/macrograph) - hosted client [here](https://macrograph.brendonovich.dev/)
|
||||
- [MATRIC](https://matricapp.com/)
|
||||
|
||||
### Client libraries (for developers)
|
||||
|
||||
@ -49,7 +51,7 @@ Here's a list of available language APIs for obs-websocket:
|
||||
- Python 3.7+ (Asyncio): [simpleobsws](https://github.com/IRLToolkit/simpleobsws/tree/master) by IRLToolkit
|
||||
- Python 3.10+ (Non-Asyncio): [obsws-python](https://pypi.org/project/obsws-python) by aatikturk and onyx-and-iris
|
||||
- Rust: [obws](https://github.com/dnaka91/obws) by dnaka91
|
||||
- Godot 3.4.x: [obs-websocket-gd](https://github.com/you-win/obs-websocket-gd) by you-win
|
||||
- Godot 4.0.x: [obs-websocket-gd](https://github.com/you-win/obs-websocket-gd) by you-win
|
||||
- Javascript (Node and web): [obs-websocket-js](https://github.com/obs-websocket-community-projects/obs-websocket-js) by OBS Websocket Community
|
||||
- C (uses obs-websocket-js): [v8-libwebsocket-obs-websocket](https://github.com/dgatwood/v8-libwebsocket-obs-websocket)
|
||||
- Go: [goobs](https://github.com/andreykaipov/goobs) by andreykaipov
|
||||
|
@ -1,8 +1,23 @@
|
||||
project(obs-websocket VERSION 5.3.4)
|
||||
project(obs-websocket VERSION 5.5.2)
|
||||
set(OBS_WEBSOCKET_RPC_VERSION 1)
|
||||
|
||||
option(ENABLE_WEBSOCKET "Enable building OBS with websocket plugin" ON)
|
||||
|
||||
add_library(obs-websocket-api INTERFACE)
|
||||
add_library(OBS::websocket-api ALIAS obs-websocket-api)
|
||||
|
||||
target_sources(obs-websocket-api INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib/obs-websocket-api.h>
|
||||
$<INSTALL_INTERFACE:${OBS_INCLUDE_DESTINATION}/obs-websocket-api.h>)
|
||||
|
||||
target_link_libraries(obs-websocket-api INTERFACE OBS::libobs)
|
||||
|
||||
target_include_directories(obs-websocket-api INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib>
|
||||
$<INSTALL_INTERFACE:${OBS_INCLUDE_DESTINATION}>)
|
||||
|
||||
set_target_properties(obs-websocket-api PROPERTIES PUBLIC_HEADER lib/obs-websocket-api.h)
|
||||
|
||||
export_target(obs-websocket-api)
|
||||
|
||||
if(NOT ENABLE_WEBSOCKET OR NOT ENABLE_UI)
|
||||
message(STATUS "OBS: DISABLED obs-websocket")
|
||||
return()
|
||||
@ -56,7 +71,6 @@ target_sources(
|
||||
src/obs-websocket.h
|
||||
src/Config.cpp
|
||||
src/Config.h
|
||||
lib/obs-websocket-api.h
|
||||
src/forms/SettingsDialog.cpp
|
||||
src/forms/SettingsDialog.h
|
||||
src/forms/ConnectInfo.cpp
|
||||
@ -133,6 +147,7 @@ target_link_libraries(
|
||||
obs-websocket
|
||||
PRIVATE OBS::libobs
|
||||
OBS::frontend-api
|
||||
OBS::websocket-api
|
||||
Qt::Core
|
||||
Qt::Widgets
|
||||
Qt::Svg
|
||||
|
14
cmake/obs-websocket-api.cmake
Normal file
14
cmake/obs-websocket-api.cmake
Normal file
@ -0,0 +1,14 @@
|
||||
add_library(obs-websocket-api INTERFACE)
|
||||
add_library(OBS::websocket-api ALIAS obs-websocket-api)
|
||||
|
||||
target_sources(obs-websocket-api INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib/obs-websocket-api.h>
|
||||
$<INSTALL_INTERFACE:${OBS_INCLUDE_DESTINATION}/obs-websocket-api.h>)
|
||||
|
||||
target_link_libraries(obs-websocket-api INTERFACE OBS::libobs)
|
||||
|
||||
target_include_directories(obs-websocket-api INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib>"
|
||||
"$<INSTALL_INTERFACE:${OBS_INCLUDE_DESTINATION}>")
|
||||
|
||||
set_target_properties(obs-websocket-api PROPERTIES PREFIX "" PUBLIC_HEADER lib/obs-websocket-api.h)
|
||||
|
||||
target_export(obs-websocket-api)
|
8
cmake/obs-websocket-apiConfig.cmake.in
Normal file
8
cmake/obs-websocket-apiConfig.cmake.in
Normal file
@ -0,0 +1,8 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
find_dependency(libobs REQUIRED)
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
|
||||
check_required_components("@PROJECT_NAME@")
|
@ -10,6 +10,7 @@ OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Waarskuwing: Tans regstreeks"
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Dit lyk of ’n afvoer (stroom, opname, ens.) tans aktief is."
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Is u seker u wil u verbindingsinligting laat sien?"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Waarskuwing: potensiële beveiligingsprobleem"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websok bewaar die bedienerwagwoord as platteks. Dit word ten sterkste aanbeveel om ’n wagwoord wat deur obs-websok geskep is te gebruik."
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Is u seker u wil u eie wagwoord gebruik?"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Fout: Ongeldige opstalling"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="U moet ’n wagwoord van meet as 6 karakters gebruik."
|
||||
@ -18,6 +19,9 @@ OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Afstandsadres"
|
||||
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Sessieduur"
|
||||
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Boodskappe In/Uit"
|
||||
OBSWebSocket.SessionTable.IdentifiedTitle="Geïdentifiseer"
|
||||
OBSWebSocket.SessionTable.KickButtonColumnTitle="Verwyder?"
|
||||
OBSWebSocket.SessionTable.KickButtonText="Verwyder"
|
||||
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket-verbindingsinligting"
|
||||
OBSWebSocket.ConnectInfo.CopyText="Kopieer"
|
||||
OBSWebSocket.ConnectInfo.ServerIp="Bediener-IP (beste skatting)"
|
||||
OBSWebSocket.ConnectInfo.ServerPort="Bedienerpoort"
|
||||
|
41
data/locale/be-BY.ini
Normal file
41
data/locale/be-BY.ini
Normal file
@ -0,0 +1,41 @@
|
||||
OBSWebSocket.Plugin.Description="Аддаленае кіраванне OBS Studio праз WebSocket"
|
||||
OBSWebSocket.Settings.DialogTitle="Налады сервера WebSocket"
|
||||
OBSWebSocket.Settings.PluginSettingsTitle="Налады плагіна"
|
||||
OBSWebSocket.Settings.ServerEnable="Уключыць сервер WebSocket"
|
||||
OBSWebSocket.Settings.AlertsEnable="Уключыць апавяшчэнні ў вобласці апавяшчэнняў"
|
||||
OBSWebSocket.Settings.DebugEnable="Уключыць журнал адладкі"
|
||||
OBSWebSocket.Settings.DebugEnableHoverText="Уключае журнал адладкі толькі для бягучага сеансу OBS. Пасля перазапуску будзе выключана.\nКаб праграма запускалася з уключанай наладай, выкарыстайце параметр --websocket_debug"
|
||||
OBSWebSocket.Settings.ServerSettingsTitle="Налады сервера"
|
||||
OBSWebSocket.Settings.AuthRequired="Уключыць аўтэнтыфікацыю"
|
||||
OBSWebSocket.Settings.Password="Пароль сервера"
|
||||
OBSWebSocket.Settings.GeneratePassword="Згенераваць"
|
||||
OBSWebSocket.Settings.ServerPort="Порт сервера"
|
||||
OBSWebSocket.Settings.ShowConnectInfo="Паказаць звесткі пра злучэнне"
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Увага: ідзе трансляцыя"
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Выглядае, што ў бягучы момант ідзе вывад (стрым, запіс і г. д.)."
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Ці вы ўпэўненыя, што хочаце паказаць вашы звесткі пра злучэнне?"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Увага: магчымая небяспека"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket захоўвае пароль сервера ў выглядзе звычайнага тэксту. Настойліва рэкамендуецца выкарыстоўваць пароль, які згенеруе obs-websocket."
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Ці вы ўпэўненыя, што хочаце карыстацца сваім паролем?"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Увага: памылковая канфігурацыя"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Пароль павінен утрымліваць 6 або больш сімвалаў."
|
||||
OBSWebSocket.SessionTable.Title="Злучаныя сеансы WebSocket"
|
||||
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Аддалены адрас"
|
||||
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Даўжыня сеансу"
|
||||
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Паведамленні I/O"
|
||||
OBSWebSocket.SessionTable.IdentifiedTitle="Ідэнтыфікавана"
|
||||
OBSWebSocket.SessionTable.KickButtonColumnTitle="Выгнаць?"
|
||||
OBSWebSocket.SessionTable.KickButtonText="Выгнаць"
|
||||
OBSWebSocket.ConnectInfo.DialogTitle="Звесткі пра злучэнне WebSocket"
|
||||
OBSWebSocket.ConnectInfo.CopyText="Скапіяваць"
|
||||
OBSWebSocket.ConnectInfo.ServerIp="IP сервера (найлепшая здагадка)"
|
||||
OBSWebSocket.ConnectInfo.ServerPort="Порт сервера"
|
||||
OBSWebSocket.ConnectInfo.ServerPassword="Пароль сервера"
|
||||
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[аўтэнтыфікацыя адкл.]"
|
||||
OBSWebSocket.ConnectInfo.QrTitle="QR-код злучэння"
|
||||
OBSWebSocket.TrayNotification.Identified.Title="Новае злучэнне WebSocket"
|
||||
OBSWebSocket.TrayNotification.Identified.Body="Кліент %1 ідэнтыфікаваны."
|
||||
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Збой аўтэнтыфікацыі WebSocket"
|
||||
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Кліент %1 не прайшоў аўтэнтыфікацыю."
|
||||
OBSWebSocket.TrayNotification.Disconnected.Title="Кліент WebSocket адключаны"
|
||||
OBSWebSocket.TrayNotification.Disconnected.Body="Кліент %1 адключаны."
|
@ -1,4 +1,5 @@
|
||||
OBSWebSocket.Plugin.Description="Fjernstyring af OBS Studio via WebSocket"
|
||||
OBSWebSocket.Settings.DialogTitle="WebSocket-serverindstillinger"
|
||||
OBSWebSocket.Settings.PluginSettingsTitle="Plugin-indstillinger"
|
||||
OBSWebSocket.Settings.ServerEnable="Aktivér WebSocket-server"
|
||||
OBSWebSocket.Settings.AlertsEnable="Aktivér Systembakke Alarmer"
|
||||
|
@ -16,9 +16,9 @@ OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Il semble qu'une sortie (st
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Êtes-vous sûr de vouloir afficher vos informations de connexion ?"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Avertissement : Problème potentiel de sécurité"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket enregistre le mot de passe du serveur en texte brut. L'utilisation d'un mot de passe généré par obs-websocket est fortement recommandée."
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Êtes-vous sûr de vouloir utiliser votre propre mot de passe ?"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Êtes-vous sûr(e) de vouloir utiliser votre propre mot de passe ?"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Erreur : Configuration invalide"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Vous devez utiliser un mot de passe d'au moins 6 caractères"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Vous devez utiliser un mot de passe de 6 caractères ou plus."
|
||||
OBSWebSocket.SessionTable.Title="Sessions WebSocket connectées"
|
||||
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Adresse distante"
|
||||
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Durée de session"
|
||||
@ -30,7 +30,7 @@ OBSWebSocket.ConnectInfo.DialogTitle="Informations de connexion WebSocket"
|
||||
OBSWebSocket.ConnectInfo.CopyText="Copier"
|
||||
OBSWebSocket.ConnectInfo.ServerIp="IP du serveur (meilleure estimation)"
|
||||
OBSWebSocket.ConnectInfo.ServerPort="Port serveur"
|
||||
OBSWebSocket.ConnectInfo.ServerPassword="Mot de passe serveur"
|
||||
OBSWebSocket.ConnectInfo.ServerPassword="Mot de passe du serveur"
|
||||
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Authentification désactivée]"
|
||||
OBSWebSocket.ConnectInfo.QrTitle="QR code de connexion"
|
||||
OBSWebSocket.TrayNotification.Identified.Title="Nouvelle connexion WebSocket"
|
||||
|
@ -8,7 +8,7 @@ OBSWebSocket.Settings.DebugEnableHoverText="Aktifkan pencatatan awakutu untuk pe
|
||||
OBSWebSocket.Settings.ServerSettingsTitle="Pengaturan Server"
|
||||
OBSWebSocket.Settings.AuthRequired="Aktifkan Autentikasi"
|
||||
OBSWebSocket.Settings.Password="Kata Sandi Server"
|
||||
OBSWebSocket.Settings.GeneratePassword="Ciptakan Kata Sandi"
|
||||
OBSWebSocket.Settings.GeneratePassword="Buat Kata Sandi"
|
||||
OBSWebSocket.Settings.ServerPort="Port Server"
|
||||
OBSWebSocket.Settings.ShowConnectInfo="Tampilkan Informasi Koneksi"
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Peringatan: Saat Ini Siaran Langsung"
|
||||
@ -16,7 +16,7 @@ OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Sepertinya sebuah output (s
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Anda yakin ingin melihat informasi koneksi Anda?"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Peringatan: Potensi Masalah Keamanan"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket menyimpan kata sandi server sebagai teks biasa. Sangat disarankan untuk menggunakan kata sandi yang diciptakan oleh obs-websocket."
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Anda yakin ingin menggunakan kata sandi Anda sendiri?"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Apakah Anda yakin ingin menggunakan kata sandi sendiri?"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Galat: Konfigurasi Tidak Berlaku"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Anda harus menggunakan kata sandi yang minimal 6 karakter atau lebih."
|
||||
OBSWebSocket.SessionTable.Title="Sesi WebSocket yang Terhubung"
|
||||
|
@ -1,4 +1,5 @@
|
||||
OBSWebSocket.Plugin.Description="Kawalan-jauh OBS Studio melalui WebSocket"
|
||||
OBSWebSocket.Settings.DialogTitle="Tetapan Pelayan WebSocket"
|
||||
OBSWebSocket.Settings.PluginSettingsTitle="Tetapan Pemalam"
|
||||
OBSWebSocket.Settings.ServerEnable="Benarkan pelayan WebSocket"
|
||||
OBSWebSocket.Settings.AlertsEnable="Benarkan Amaran Talam Sistem"
|
||||
|
@ -1,2 +1,25 @@
|
||||
OBSWebSocket.Settings.DialogTitle="WebSocket-tjenerinnstillinger"
|
||||
OBSWebSocket.Settings.PluginSettingsTitle="Utvidelsesinnstillinger"
|
||||
OBSWebSocket.Settings.ServerSettingsTitle="Tjenerinnstillinger"
|
||||
OBSWebSocket.Settings.AuthRequired="Skru på autentisering"
|
||||
OBSWebSocket.Settings.Password="Server Passord"
|
||||
OBSWebSocket.Settings.GeneratePassword="Generer Passord"
|
||||
OBSWebSocket.Settings.ShowConnectInfo="Vis tilkoblingsinfo"
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Advarsel: For øyeblikket på direktesending"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Advarsel: Potensielt sikkerhetsproblem"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Feil: Ugyldig konfigurasjon"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Du må bruke et passord på minst 6 tegn."
|
||||
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Ekstern adresse"
|
||||
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Øktens varighet"
|
||||
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Innboks/Utboks"
|
||||
OBSWebSocket.SessionTable.IdentifiedTitle="Identifisert"
|
||||
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket-tilkoblingsinfo"
|
||||
OBSWebSocket.ConnectInfo.CopyText="Kopier"
|
||||
OBSWebSocket.ConnectInfo.ServerIp="Tjenerens IP (beste gjetning)"
|
||||
OBSWebSocket.ConnectInfo.ServerPort="Tjenerport"
|
||||
OBSWebSocket.ConnectInfo.ServerPassword="Tjenerpassord"
|
||||
OBSWebSocket.ConnectInfo.QrTitle="QR-tilkobling"
|
||||
OBSWebSocket.TrayNotification.Identified.Title="Ny WebSocket-tilkobling"
|
||||
OBSWebSocket.TrayNotification.Identified.Body="Klient %1 er identifisert."
|
||||
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket-klient koblet fra"
|
||||
OBSWebSocket.TrayNotification.Disconnected.Body="Klient %1 koblet fra."
|
||||
|
@ -18,7 +18,7 @@ OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Ostrzeżenie: Potencjalny p
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket przechowuje hasło serwera jako zwykły tekst. Wysoce zalecane jest użycie hasła generowanego przez obs-websocket."
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Czy na pewno chcesz użyć własnego hasła?"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Błąd: Nieprawidłowa konfiguracja"
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Musisz użyć hasła, które ma 6 lub więcej znaków."
|
||||
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Hasło musi zawierać 6 lub więcej znaków."
|
||||
OBSWebSocket.SessionTable.Title="Podłączone sesje WebSocket"
|
||||
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Adres zdalny"
|
||||
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Czas trwania sesji"
|
||||
|
@ -12,7 +12,7 @@ OBSWebSocket.Settings.GeneratePassword="Generează parola"
|
||||
OBSWebSocket.Settings.ServerPort="Portul serverului"
|
||||
OBSWebSocket.Settings.ShowConnectInfo="Afișează informațiile conexiunii"
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Avertisment: În prezent în direct"
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Se pare că un output (transmisiune, înregistrare etc.) este activ în prezent."
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Se pare că un output (stream, înregistrare etc.) este activ în prezent."
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Sigur vrei să afișezi informațiile de conectare?"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Avertisment: Potențială problemă de securitate"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket stochează parola serverului ca text simplu. Este foarte recomandat să folosiți o parolă generată de obs-websocket."
|
||||
|
@ -28,7 +28,7 @@ OBSWebSocket.SessionTable.KickButtonColumnTitle="Выгнать?"
|
||||
OBSWebSocket.SessionTable.KickButtonText="Выгнать"
|
||||
OBSWebSocket.ConnectInfo.DialogTitle="Сведения о подключении WebSocket"
|
||||
OBSWebSocket.ConnectInfo.CopyText="Копировать"
|
||||
OBSWebSocket.ConnectInfo.ServerIp="IP сервера (лучшая догадка)"
|
||||
OBSWebSocket.ConnectInfo.ServerIp="IP сервера (вероятный)"
|
||||
OBSWebSocket.ConnectInfo.ServerPort="Порт сервера"
|
||||
OBSWebSocket.ConnectInfo.ServerPassword="Пароль сервера"
|
||||
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Вход отключён]"
|
||||
|
@ -1,6 +1,6 @@
|
||||
OBSWebSocket.Plugin.Description="Fjärrkontroll av OBS Studio via WebSocket"
|
||||
OBSWebSocket.Settings.DialogTitle="WebSocket-serverinställningar"
|
||||
OBSWebSocket.Settings.PluginSettingsTitle="Insticksmodulsinställningar"
|
||||
OBSWebSocket.Settings.PluginSettingsTitle="Insticksprogramsinställningar"
|
||||
OBSWebSocket.Settings.ServerEnable="Aktivera WebSocket-server"
|
||||
OBSWebSocket.Settings.AlertsEnable="Aktivera systemfältsmeddelanden"
|
||||
OBSWebSocket.Settings.DebugEnable="Aktivera felsökningsloggning"
|
||||
@ -11,7 +11,7 @@ OBSWebSocket.Settings.Password="Serverlösenord"
|
||||
OBSWebSocket.Settings.GeneratePassword="Generera lösenord"
|
||||
OBSWebSocket.Settings.ServerPort="Serverport"
|
||||
OBSWebSocket.Settings.ShowConnectInfo="Visa anslutningsinformation"
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Varning: Sänder för närvarande"
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Varning: Direktsändning pågår"
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Det verkar som om en utmatning (ström, inspelning, etc.) är för närvarande aktiv."
|
||||
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Är du säker på att du vill visa din anslutningsinformation?"
|
||||
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Varning: Potentiellt säkerhetsproblem"
|
||||
|
@ -29,7 +29,7 @@ OBSWebSocket.SessionTable.KickButtonText="Çıkar"
|
||||
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket Bağlanma Bilgileri"
|
||||
OBSWebSocket.ConnectInfo.CopyText="Kopyala"
|
||||
OBSWebSocket.ConnectInfo.ServerIp="Sunucu IP (En İyi Tahmin)"
|
||||
OBSWebSocket.ConnectInfo.ServerPort="Sunucu Kapısı"
|
||||
OBSWebSocket.ConnectInfo.ServerPort="Sunucu Portu"
|
||||
OBSWebSocket.ConnectInfo.ServerPassword="Sunucu Parolası"
|
||||
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Doğrulama Devre Dışı]"
|
||||
OBSWebSocket.ConnectInfo.QrTitle="Kare Kod ile Bağlan"
|
||||
|
9
data/locale/tt-RU.ini
Normal file
9
data/locale/tt-RU.ini
Normal file
@ -0,0 +1,9 @@
|
||||
OBSWebSocket.Settings.ServerSettingsTitle="Сервер көйләүләре"
|
||||
OBSWebSocket.Settings.Password="Сервер серсүзе"
|
||||
OBSWebSocket.Settings.GeneratePassword="Серсүзне ясау"
|
||||
OBSWebSocket.Settings.ServerPort="Сервер порты"
|
||||
OBSWebSocket.SessionTable.KickButtonColumnTitle="Чыгарыргамы?"
|
||||
OBSWebSocket.SessionTable.KickButtonText="Чыгару"
|
||||
OBSWebSocket.ConnectInfo.CopyText="Күчермә алу"
|
||||
OBSWebSocket.ConnectInfo.ServerPort="Сервер порты"
|
||||
OBSWebSocket.ConnectInfo.ServerPassword="Сервер серсүзе"
|
2
data/locale/ug-CN.ini
Normal file
2
data/locale/ug-CN.ini
Normal file
@ -0,0 +1,2 @@
|
||||
OBSWebSocket.Settings.GeneratePassword="ئىم ھاسىللا"
|
||||
OBSWebSocket.ConnectInfo.CopyText="كۆچۈر"
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
|
||||
#include <obs.h>
|
||||
|
||||
#define OBS_WEBSOCKET_API_VERSION 2
|
||||
#define OBS_WEBSOCKET_API_VERSION 3
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -30,6 +30,7 @@ extern "C" {
|
||||
|
||||
typedef void *obs_websocket_vendor;
|
||||
typedef void (*obs_websocket_request_callback_function)(obs_data_t *, obs_data_t *, void *);
|
||||
typedef void (*obs_websocket_event_callback_function)(uint64_t, const char *, const char *, void *);
|
||||
|
||||
struct obs_websocket_request_response {
|
||||
unsigned int status_code;
|
||||
@ -44,7 +45,12 @@ struct obs_websocket_request_callback {
|
||||
void *priv_data;
|
||||
};
|
||||
|
||||
inline proc_handler_t *_ph;
|
||||
struct obs_websocket_event_callback {
|
||||
obs_websocket_event_callback_function callback;
|
||||
void *priv_data;
|
||||
};
|
||||
|
||||
static proc_handler_t *_ph;
|
||||
|
||||
/* ==================== INTERNAL API FUNCTIONS ==================== */
|
||||
|
||||
@ -53,7 +59,7 @@ static inline proc_handler_t *obs_websocket_get_ph(void)
|
||||
proc_handler_t *global_ph = obs_get_proc_handler();
|
||||
assert(global_ph != NULL);
|
||||
|
||||
calldata_t cd = {0};
|
||||
calldata_t cd = {0, 0, 0, 0};
|
||||
if (!proc_handler_call(global_ph, "obs_websocket_api_get_ph", &cd))
|
||||
blog(LOG_DEBUG, "Unable to fetch obs-websocket proc handler object. obs-websocket not installed?");
|
||||
proc_handler_t *ret = (proc_handler_t *)calldata_ptr(&cd, "ph");
|
||||
@ -91,7 +97,7 @@ static inline unsigned int obs_websocket_get_api_version(void)
|
||||
if (!obs_websocket_ensure_ph())
|
||||
return 0;
|
||||
|
||||
calldata_t cd = {0};
|
||||
calldata_t cd = {0, 0, 0, 0};
|
||||
|
||||
if (!proc_handler_call(_ph, "get_api_version", &cd))
|
||||
return 1; // API v1 does not include get_api_version
|
||||
@ -104,7 +110,11 @@ static inline unsigned int obs_websocket_get_api_version(void)
|
||||
}
|
||||
|
||||
// Calls an obs-websocket request. Free response with `obs_websocket_request_response_free()`
|
||||
static inline obs_websocket_request_response *obs_websocket_call_request(const char *request_type, obs_data_t *request_data = NULL)
|
||||
static inline struct obs_websocket_request_response *obs_websocket_call_request(const char *request_type, obs_data_t *request_data
|
||||
#ifdef __cplusplus
|
||||
= NULL
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (!obs_websocket_ensure_ph())
|
||||
return NULL;
|
||||
@ -113,14 +123,13 @@ static inline obs_websocket_request_response *obs_websocket_call_request(const c
|
||||
if (request_data)
|
||||
request_data_string = obs_data_get_json(request_data);
|
||||
|
||||
calldata_t cd = {0};
|
||||
|
||||
calldata_t cd = {0, 0, 0, 0};
|
||||
calldata_set_string(&cd, "request_type", request_type);
|
||||
calldata_set_string(&cd, "request_data", request_data_string);
|
||||
|
||||
proc_handler_call(_ph, "call_request", &cd);
|
||||
|
||||
auto ret = (struct obs_websocket_request_response *)calldata_ptr(&cd, "response");
|
||||
struct obs_websocket_request_response *ret = (struct obs_websocket_request_response *)calldata_ptr(&cd, "response");
|
||||
|
||||
calldata_free(&cd);
|
||||
|
||||
@ -140,6 +149,46 @@ static inline void obs_websocket_request_response_free(struct obs_websocket_requ
|
||||
bfree(response);
|
||||
}
|
||||
|
||||
// Register an event handler to receive obs-websocket events
|
||||
static inline bool obs_websocket_register_event_callback(obs_websocket_event_callback_function event_callback, void *priv_data)
|
||||
{
|
||||
if (!obs_websocket_ensure_ph())
|
||||
return false;
|
||||
|
||||
struct obs_websocket_event_callback cb = {event_callback, priv_data};
|
||||
|
||||
calldata_t cd = {0, 0, 0, 0};
|
||||
calldata_set_ptr(&cd, "callback", &cb);
|
||||
|
||||
proc_handler_call(_ph, "register_event_callback", &cd);
|
||||
|
||||
bool ret = calldata_bool(&cd, "success");
|
||||
|
||||
calldata_free(&cd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Unregister an existing event handler
|
||||
static inline bool obs_websocket_unregister_event_callback(obs_websocket_event_callback_function event_callback, void *priv_data)
|
||||
{
|
||||
if (!obs_websocket_ensure_ph())
|
||||
return false;
|
||||
|
||||
struct obs_websocket_event_callback cb = {event_callback, priv_data};
|
||||
|
||||
calldata_t cd = {0, 0, 0, 0};
|
||||
calldata_set_ptr(&cd, "callback", &cb);
|
||||
|
||||
proc_handler_call(_ph, "unregister_event_callback", &cd);
|
||||
|
||||
bool ret = calldata_bool(&cd, "success");
|
||||
|
||||
calldata_free(&cd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ==================== VENDOR API FUNCTIONS ==================== */
|
||||
|
||||
// ALWAYS CALL ONLY VIA `obs_module_post_load()` CALLBACK!
|
||||
@ -149,8 +198,7 @@ static inline obs_websocket_vendor obs_websocket_register_vendor(const char *ven
|
||||
if (!obs_websocket_ensure_ph())
|
||||
return NULL;
|
||||
|
||||
calldata_t cd = {0};
|
||||
|
||||
calldata_t cd = {0, 0, 0, 0};
|
||||
calldata_set_string(&cd, "name", vendor_name);
|
||||
|
||||
proc_handler_call(_ph, "vendor_register", &cd);
|
||||
@ -164,12 +212,9 @@ static inline obs_websocket_vendor obs_websocket_register_vendor(const char *ven
|
||||
static inline bool obs_websocket_vendor_register_request(obs_websocket_vendor vendor, const char *request_type,
|
||||
obs_websocket_request_callback_function request_callback, void *priv_data)
|
||||
{
|
||||
calldata_t cd = {0};
|
||||
|
||||
struct obs_websocket_request_callback cb = {};
|
||||
cb.callback = request_callback;
|
||||
cb.priv_data = priv_data;
|
||||
struct obs_websocket_request_callback cb = {request_callback, priv_data};
|
||||
|
||||
calldata_t cd = {0, 0, 0, 0};
|
||||
calldata_set_string(&cd, "type", request_type);
|
||||
calldata_set_ptr(&cd, "callback", &cb);
|
||||
|
||||
@ -182,8 +227,7 @@ static inline bool obs_websocket_vendor_register_request(obs_websocket_vendor ve
|
||||
// Unregisters an existing vendor request
|
||||
static inline bool obs_websocket_vendor_unregister_request(obs_websocket_vendor vendor, const char *request_type)
|
||||
{
|
||||
calldata_t cd = {0};
|
||||
|
||||
calldata_t cd = {0, 0, 0, 0};
|
||||
calldata_set_string(&cd, "type", request_type);
|
||||
|
||||
bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_unregister", &cd);
|
||||
@ -196,8 +240,7 @@ static inline bool obs_websocket_vendor_unregister_request(obs_websocket_vendor
|
||||
// Emits an event under the vendor's name
|
||||
static inline bool obs_websocket_vendor_emit_event(obs_websocket_vendor vendor, const char *event_name, obs_data_t *event_data)
|
||||
{
|
||||
calldata_t cd = {0};
|
||||
|
||||
calldata_t cd = {0, 0, 0, 0};
|
||||
calldata_set_string(&cd, "type", event_name);
|
||||
calldata_set_ptr(&cd, "data", (void *)event_data);
|
||||
|
||||
|
179
src/Config.cpp
179
src/Config.cpp
@ -17,60 +17,80 @@ You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include <obs-frontend-api.h>
|
||||
|
||||
#include "Config.h"
|
||||
#include "utils/Crypto.h"
|
||||
#include "utils/Platform.h"
|
||||
#include "utils/Obs.h"
|
||||
|
||||
#define CONFIG_SECTION_NAME "OBSWebSocket"
|
||||
#define CONFIG_PARAM_FIRSTLOAD "FirstLoad"
|
||||
#define CONFIG_PARAM_ENABLED "ServerEnabled"
|
||||
#define CONFIG_PARAM_PORT "ServerPort"
|
||||
#define CONFIG_PARAM_ALERTS "AlertsEnabled"
|
||||
#define CONFIG_PARAM_AUTHREQUIRED "AuthRequired"
|
||||
#define CONFIG_PARAM_PASSWORD "ServerPassword"
|
||||
|
||||
#define PARAM_FIRSTLOAD "FirstLoad"
|
||||
#define PARAM_ENABLED "ServerEnabled"
|
||||
#define PARAM_PORT "ServerPort"
|
||||
#define PARAM_ALERTS "AlertsEnabled"
|
||||
#define PARAM_AUTHREQUIRED "AuthRequired"
|
||||
#define PARAM_PASSWORD "ServerPassword"
|
||||
#define CONFIG_FILE_NAME "config.json"
|
||||
#define PARAM_FIRSTLOAD "first_load"
|
||||
#define PARAM_ENABLED "server_enabled"
|
||||
#define PARAM_PORT "server_port"
|
||||
#define PARAM_ALERTS "alerts_enabled"
|
||||
#define PARAM_AUTHREQUIRED "auth_required"
|
||||
#define PARAM_PASSWORD "server_password"
|
||||
|
||||
#define CMDLINE_WEBSOCKET_PORT "websocket_port"
|
||||
#define CMDLINE_WEBSOCKET_IPV4_ONLY "websocket_ipv4_only"
|
||||
#define CMDLINE_WEBSOCKET_PASSWORD "websocket_password"
|
||||
#define CMDLINE_WEBSOCKET_DEBUG "websocket_debug"
|
||||
|
||||
Config::Config()
|
||||
void Config::Load(json config)
|
||||
{
|
||||
SetDefaultsToGlobalStore();
|
||||
}
|
||||
|
||||
void Config::Load()
|
||||
{
|
||||
config_t *obsConfig = GetConfigStore();
|
||||
if (!obsConfig) {
|
||||
blog(LOG_ERROR, "[Config::Load] Unable to fetch OBS config!");
|
||||
return;
|
||||
// Only load from plugin config directory if there hasn't been a migration
|
||||
if (config.is_null()) {
|
||||
std::string configFilePath = Utils::Obs::StringHelper::GetModuleConfigPath(CONFIG_FILE_NAME);
|
||||
Utils::Json::GetJsonFileContent(configFilePath, config); // Fetch the existing config, which may not exist
|
||||
}
|
||||
|
||||
FirstLoad = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD);
|
||||
ServerEnabled = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED);
|
||||
AlertsEnabled = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS);
|
||||
ServerPort = config_get_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT);
|
||||
AuthRequired = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED);
|
||||
ServerPassword = config_get_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD);
|
||||
if (!config.is_object()) {
|
||||
blog(LOG_INFO, "[Config::Load] Existing configuration not found, using defaults.");
|
||||
config = json::object();
|
||||
}
|
||||
|
||||
if (config.contains(PARAM_FIRSTLOAD) && config[PARAM_FIRSTLOAD].is_boolean())
|
||||
FirstLoad = config[PARAM_FIRSTLOAD];
|
||||
if (config.contains(PARAM_ENABLED) && config[PARAM_ENABLED].is_boolean())
|
||||
ServerEnabled = config[PARAM_ENABLED];
|
||||
if (config.contains(PARAM_ALERTS) && config[PARAM_ALERTS].is_boolean())
|
||||
AlertsEnabled = config[PARAM_ALERTS];
|
||||
if (config.contains(PARAM_PORT) && config[PARAM_PORT].is_number_unsigned())
|
||||
ServerPort = config[PARAM_PORT];
|
||||
if (config.contains(PARAM_AUTHREQUIRED) && config[PARAM_AUTHREQUIRED].is_boolean())
|
||||
AuthRequired = config[PARAM_AUTHREQUIRED];
|
||||
if (config.contains(PARAM_PASSWORD) && config[PARAM_PASSWORD].is_string())
|
||||
ServerPassword = config[PARAM_PASSWORD];
|
||||
|
||||
// Set server password and save it to the config before processing overrides,
|
||||
// so that there is always a true configured password regardless of if
|
||||
// future loads use the override flag.
|
||||
if (FirstLoad) {
|
||||
FirstLoad = false;
|
||||
if (ServerPassword.isEmpty()) {
|
||||
if (ServerPassword.empty()) {
|
||||
blog(LOG_INFO, "[Config::Load] (FirstLoad) Generating new server password.");
|
||||
ServerPassword = QString::fromStdString(Utils::Crypto::GeneratePassword());
|
||||
ServerPassword = Utils::Crypto::GeneratePassword();
|
||||
} else {
|
||||
blog(LOG_INFO, "[Config::Load] (FirstLoad) Not generating new password since one is already configured.");
|
||||
}
|
||||
Save();
|
||||
}
|
||||
|
||||
// If there are migrated settings, write them to disk before processing arguments.
|
||||
if (!config.empty())
|
||||
Save();
|
||||
|
||||
// Process `--websocket_port` override
|
||||
QString portArgument = Utils::Platform::GetCommandLineArgument(CMDLINE_WEBSOCKET_PORT);
|
||||
if (portArgument != "") {
|
||||
@ -97,7 +117,7 @@ void Config::Load()
|
||||
blog(LOG_INFO, "[Config::Load] --websocket_password passed. Overriding WebSocket password.");
|
||||
PasswordOverridden = true;
|
||||
AuthRequired = true;
|
||||
ServerPassword = passwordArgument;
|
||||
ServerPassword = passwordArgument.toStdString();
|
||||
}
|
||||
|
||||
// Process `--websocket_debug` override
|
||||
@ -110,43 +130,98 @@ void Config::Load()
|
||||
|
||||
void Config::Save()
|
||||
{
|
||||
config_t *obsConfig = GetConfigStore();
|
||||
if (!obsConfig) {
|
||||
blog(LOG_ERROR, "[Config::Save] Unable to fetch OBS config!");
|
||||
return;
|
||||
}
|
||||
json config;
|
||||
|
||||
config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD, FirstLoad);
|
||||
config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED, ServerEnabled);
|
||||
if (!PortOverridden) {
|
||||
config_set_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, ServerPort);
|
||||
}
|
||||
config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, AlertsEnabled);
|
||||
std::string configFilePath = Utils::Obs::StringHelper::GetModuleConfigPath(CONFIG_FILE_NAME);
|
||||
Utils::Json::GetJsonFileContent(configFilePath, config); // Fetch the existing config, which may not exist
|
||||
|
||||
config[PARAM_FIRSTLOAD] = FirstLoad.load();
|
||||
config[PARAM_ENABLED] = ServerEnabled.load();
|
||||
if (!PortOverridden)
|
||||
config[PARAM_PORT] = ServerPort.load();
|
||||
config[PARAM_ALERTS] = AlertsEnabled.load();
|
||||
if (!PasswordOverridden) {
|
||||
config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired);
|
||||
config_set_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD, QT_TO_UTF8(ServerPassword));
|
||||
config[PARAM_AUTHREQUIRED] = AuthRequired.load();
|
||||
config[PARAM_PASSWORD] = ServerPassword;
|
||||
}
|
||||
|
||||
config_save(obsConfig);
|
||||
if (Utils::Json::SetJsonFileContent(configFilePath, config))
|
||||
blog(LOG_DEBUG, "[Config::Save] Saved config.");
|
||||
else
|
||||
blog(LOG_ERROR, "[Config::Save] Failed to write config file!");
|
||||
}
|
||||
|
||||
void Config::SetDefaultsToGlobalStore()
|
||||
// Finds any old values in global.ini and removes them, then returns the values as JSON
|
||||
json MigrateGlobalConfigData()
|
||||
{
|
||||
config_t *obsConfig = GetConfigStore();
|
||||
if (!obsConfig) {
|
||||
blog(LOG_ERROR, "[Config::SetDefaultsToGlobalStore] Unable to fetch OBS config!");
|
||||
return;
|
||||
// Get existing global config
|
||||
config_t *config = obs_frontend_get_global_config();
|
||||
json ret;
|
||||
|
||||
// Move values to temporary JSON blob
|
||||
if (config_has_user_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_FIRSTLOAD)) {
|
||||
ret[PARAM_FIRSTLOAD] = config_get_bool(config, CONFIG_SECTION_NAME, CONFIG_PARAM_FIRSTLOAD);
|
||||
config_remove_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_FIRSTLOAD);
|
||||
}
|
||||
if (config_has_user_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_ENABLED)) {
|
||||
ret[PARAM_ENABLED] = config_get_bool(config, CONFIG_SECTION_NAME, CONFIG_PARAM_ENABLED);
|
||||
config_remove_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_ENABLED);
|
||||
}
|
||||
if (config_has_user_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_PORT)) {
|
||||
ret[PARAM_PORT] = config_get_uint(config, CONFIG_SECTION_NAME, CONFIG_PARAM_PORT);
|
||||
config_remove_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_PORT);
|
||||
}
|
||||
if (config_has_user_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_ALERTS)) {
|
||||
ret[PARAM_ALERTS] = config_get_bool(config, CONFIG_SECTION_NAME, CONFIG_PARAM_ALERTS);
|
||||
config_remove_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_ALERTS);
|
||||
}
|
||||
if (config_has_user_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_AUTHREQUIRED)) {
|
||||
ret[PARAM_AUTHREQUIRED] = config_get_bool(config, CONFIG_SECTION_NAME, CONFIG_PARAM_AUTHREQUIRED);
|
||||
config_remove_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_AUTHREQUIRED);
|
||||
}
|
||||
if (config_has_user_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_PASSWORD)) {
|
||||
ret[PARAM_PASSWORD] = config_get_string(config, CONFIG_SECTION_NAME, CONFIG_PARAM_PASSWORD);
|
||||
config_remove_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_PASSWORD);
|
||||
}
|
||||
|
||||
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD, FirstLoad);
|
||||
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED, ServerEnabled);
|
||||
config_set_default_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, ServerPort);
|
||||
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, AlertsEnabled);
|
||||
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired);
|
||||
config_set_default_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD, QT_TO_UTF8(ServerPassword));
|
||||
if (!ret.is_null()) {
|
||||
blog(LOG_INFO, "[MigrateGlobalConfigData] Some configurations have been migrated from old config");
|
||||
config_save(config);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
config_t *Config::GetConfigStore()
|
||||
// Migration from storing persistent data in obsWebSocketPersistentData.json to the module config directory
|
||||
// This will overwrite any persistent data in the destination. People doing manual OBS config modification be warned!
|
||||
bool MigratePersistentData()
|
||||
{
|
||||
return obs_frontend_get_global_config();
|
||||
std::error_code ec;
|
||||
|
||||
// Ensure module config directory exists
|
||||
auto moduleConfigDirectory = std::filesystem::u8path(Utils::Obs::StringHelper::GetModuleConfigPath(""));
|
||||
if (!std::filesystem::exists(moduleConfigDirectory, ec))
|
||||
std::filesystem::create_directories(moduleConfigDirectory, ec);
|
||||
if (ec) {
|
||||
blog(LOG_ERROR, "[MigratePersistentData] Failed to create directory `%s`: %s", moduleConfigDirectory.c_str(),
|
||||
ec.message().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Move any existing persistent data to module config directory, then delete old file
|
||||
auto oldPersistentDataPath = std::filesystem::u8path(Utils::Obs::StringHelper::GetCurrentProfilePath() +
|
||||
"/../../../obsWebSocketPersistentData.json");
|
||||
if (std::filesystem::exists(oldPersistentDataPath, ec)) {
|
||||
auto persistentDataPath =
|
||||
std::filesystem::u8path(Utils::Obs::StringHelper::GetModuleConfigPath("persistent_data.json"));
|
||||
std::filesystem::copy_file(oldPersistentDataPath, persistentDataPath, ec);
|
||||
std::filesystem::remove(oldPersistentDataPath, ec);
|
||||
blog(LOG_INFO, "[MigratePersistentData] Persistent data migrated to new path");
|
||||
}
|
||||
if (ec) {
|
||||
blog(LOG_ERROR, "[MigratePersistentData] Failed to move persistent data: %s", ec.message().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
11
src/Config.h
11
src/Config.h
@ -23,14 +23,12 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
#include <QString>
|
||||
#include <util/config-file.h>
|
||||
|
||||
#include "utils/Json.h"
|
||||
#include "plugin-macros.generated.h"
|
||||
|
||||
struct Config {
|
||||
Config();
|
||||
void Load();
|
||||
void Load(json config = nullptr);
|
||||
void Save();
|
||||
void SetDefaultsToGlobalStore();
|
||||
static config_t *GetConfigStore();
|
||||
|
||||
std::atomic<bool> PortOverridden = false;
|
||||
std::atomic<bool> PasswordOverridden = false;
|
||||
@ -42,5 +40,8 @@ struct Config {
|
||||
std::atomic<bool> DebugEnabled = false;
|
||||
std::atomic<bool> AlertsEnabled = false;
|
||||
std::atomic<bool> AuthRequired = true;
|
||||
QString ServerPassword;
|
||||
std::string ServerPassword;
|
||||
};
|
||||
|
||||
json MigrateGlobalConfigData();
|
||||
bool MigratePersistentData();
|
||||
|
@ -18,7 +18,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
|
||||
#include "WebSocketApi.h"
|
||||
#include "requesthandler/RequestHandler.h"
|
||||
#include "obs-websocket.h"
|
||||
#include "utils/Json.h"
|
||||
|
||||
#define RETURN_STATUS(status) \
|
||||
@ -48,14 +47,19 @@ WebSocketApi::WebSocketApi()
|
||||
|
||||
proc_handler_add(_procHandler, "bool get_api_version(out int version)", &get_api_version, nullptr);
|
||||
proc_handler_add(_procHandler, "bool call_request(in string request_type, in string request_data, out ptr response)",
|
||||
&call_request, nullptr);
|
||||
proc_handler_add(_procHandler, "bool vendor_register(in string name, out ptr vendor)", &vendor_register_cb, this);
|
||||
proc_handler_add(_procHandler, "bool vendor_request_register(in ptr vendor, in string type, in ptr callback)",
|
||||
&vendor_request_register_cb, this);
|
||||
proc_handler_add(_procHandler, "bool vendor_request_unregister(in ptr vendor, in string type)",
|
||||
&vendor_request_unregister_cb, this);
|
||||
proc_handler_add(_procHandler, "bool vendor_event_emit(in ptr vendor, in string type, in ptr data)", &vendor_event_emit_cb,
|
||||
&call_request, this);
|
||||
proc_handler_add(_procHandler, "bool register_event_callback(in ptr callback, out bool success)", ®ister_event_callback,
|
||||
this);
|
||||
proc_handler_add(_procHandler, "bool unregister_event_callback(in ptr callback, out bool success)",
|
||||
&unregister_event_callback, this);
|
||||
proc_handler_add(_procHandler, "bool vendor_register(in string name, out ptr vendor)", &vendor_register_cb, this);
|
||||
proc_handler_add(_procHandler,
|
||||
"bool vendor_request_register(in ptr vendor, in string type, in ptr callback, out bool success)",
|
||||
&vendor_request_register_cb, this);
|
||||
proc_handler_add(_procHandler, "bool vendor_request_unregister(in ptr vendor, in string type, out bool success)",
|
||||
&vendor_request_unregister_cb, this);
|
||||
proc_handler_add(_procHandler, "bool vendor_event_emit(in ptr vendor, in string type, in ptr data, out bool success)",
|
||||
&vendor_event_emit_cb, this);
|
||||
|
||||
proc_handler_t *ph = obs_get_proc_handler();
|
||||
assert(ph != NULL);
|
||||
@ -71,6 +75,10 @@ WebSocketApi::~WebSocketApi()
|
||||
|
||||
proc_handler_destroy(_procHandler);
|
||||
|
||||
size_t numEventCallbacks = _eventCallbacks.size();
|
||||
_eventCallbacks.clear();
|
||||
blog_debug("[WebSocketApi::~WebSocketApi] Deleted %ld event callbacks", numEventCallbacks);
|
||||
|
||||
for (auto vendor : _vendors) {
|
||||
blog_debug("[WebSocketApi::~WebSocketApi] Deleting vendor: %s", vendor.first.c_str());
|
||||
delete vendor.second;
|
||||
@ -79,9 +87,21 @@ WebSocketApi::~WebSocketApi()
|
||||
blog_debug("[WebSocketApi::~WebSocketApi] Finished.");
|
||||
}
|
||||
|
||||
void WebSocketApi::SetEventCallback(EventCallback cb)
|
||||
void WebSocketApi::BroadcastEvent(uint64_t requiredIntent, const std::string &eventType, const json &eventData, uint8_t rpcVersion)
|
||||
{
|
||||
_eventCallback = cb;
|
||||
if (!_obsReady)
|
||||
return;
|
||||
|
||||
// Only broadcast events applicable to the latest RPC version
|
||||
if (rpcVersion && rpcVersion != CURRENT_RPC_VERSION)
|
||||
return;
|
||||
|
||||
std::string eventDataString = eventData.dump();
|
||||
|
||||
std::shared_lock l(_mutex);
|
||||
|
||||
for (auto &cb : _eventCallbacks)
|
||||
cb.callback(requiredIntent, eventType.c_str(), eventDataString.c_str(), cb.priv_data);
|
||||
}
|
||||
|
||||
enum WebSocketApi::RequestReturnCode WebSocketApi::PerformVendorRequest(std::string vendorName, std::string requestType,
|
||||
@ -126,14 +146,27 @@ void WebSocketApi::get_api_version(void *, calldata_t *cd)
|
||||
RETURN_SUCCESS();
|
||||
}
|
||||
|
||||
void WebSocketApi::call_request(void *, calldata_t *cd)
|
||||
void WebSocketApi::call_request(void *priv_data, calldata_t *cd)
|
||||
{
|
||||
auto c = static_cast<WebSocketApi *>(priv_data);
|
||||
|
||||
#if !defined(PLUGIN_TESTS)
|
||||
if (!c->_obsReady)
|
||||
RETURN_FAILURE();
|
||||
#endif
|
||||
|
||||
const char *request_type = calldata_string(cd, "request_type");
|
||||
const char *request_data = calldata_string(cd, "request_data");
|
||||
|
||||
if (!request_type)
|
||||
RETURN_FAILURE();
|
||||
|
||||
#ifdef PLUGIN_TESTS
|
||||
// Allow plugin tests to complete, even though OBS wouldn't be ready at the time of the test
|
||||
if (!c->_obsReady && std::string(request_type) != "GetVersion")
|
||||
RETURN_FAILURE();
|
||||
#endif
|
||||
|
||||
auto response = static_cast<obs_websocket_request_response *>(bzalloc(sizeof(struct obs_websocket_request_response)));
|
||||
if (!response)
|
||||
RETURN_FAILURE();
|
||||
@ -162,6 +195,52 @@ void WebSocketApi::call_request(void *, calldata_t *cd)
|
||||
RETURN_SUCCESS();
|
||||
}
|
||||
|
||||
void WebSocketApi::register_event_callback(void *priv_data, calldata_t *cd)
|
||||
{
|
||||
auto c = static_cast<WebSocketApi *>(priv_data);
|
||||
|
||||
void *voidCallback;
|
||||
if (!calldata_get_ptr(cd, "callback", &voidCallback) || !voidCallback) {
|
||||
blog(LOG_WARNING, "[WebSocketApi::register_event_callback] Failed due to missing `callback` pointer.");
|
||||
RETURN_FAILURE();
|
||||
}
|
||||
|
||||
auto cb = static_cast<obs_websocket_event_callback *>(voidCallback);
|
||||
|
||||
std::unique_lock l(c->_mutex);
|
||||
|
||||
int64_t foundIndex = c->GetEventCallbackIndex(*cb);
|
||||
if (foundIndex != -1)
|
||||
RETURN_FAILURE();
|
||||
|
||||
c->_eventCallbacks.push_back(*cb);
|
||||
|
||||
RETURN_SUCCESS();
|
||||
}
|
||||
|
||||
void WebSocketApi::unregister_event_callback(void *priv_data, calldata_t *cd)
|
||||
{
|
||||
auto c = static_cast<WebSocketApi *>(priv_data);
|
||||
|
||||
void *voidCallback;
|
||||
if (!calldata_get_ptr(cd, "callback", &voidCallback) || !voidCallback) {
|
||||
blog(LOG_WARNING, "[WebSocketApi::register_event_callback] Failed due to missing `callback` pointer.");
|
||||
RETURN_FAILURE();
|
||||
}
|
||||
|
||||
auto cb = static_cast<obs_websocket_event_callback *>(voidCallback);
|
||||
|
||||
std::unique_lock l(c->_mutex);
|
||||
|
||||
int64_t foundIndex = c->GetEventCallbackIndex(*cb);
|
||||
if (foundIndex == -1)
|
||||
RETURN_FAILURE();
|
||||
|
||||
c->_eventCallbacks.erase(c->_eventCallbacks.begin() + foundIndex);
|
||||
|
||||
RETURN_SUCCESS();
|
||||
}
|
||||
|
||||
void WebSocketApi::vendor_register_cb(void *priv_data, calldata_t *cd)
|
||||
{
|
||||
auto c = static_cast<WebSocketApi *>(priv_data);
|
||||
@ -172,7 +251,7 @@ void WebSocketApi::vendor_register_cb(void *priv_data, calldata_t *cd)
|
||||
RETURN_FAILURE();
|
||||
}
|
||||
|
||||
// Theoretically doesn't need a mutex, but it's good to be safe.
|
||||
// Theoretically doesn't need a mutex due to module load being single-thread, but it's good to be safe.
|
||||
std::unique_lock l(c->_mutex);
|
||||
|
||||
if (c->_vendors.count(vendorName)) {
|
||||
@ -289,10 +368,10 @@ void WebSocketApi::vendor_event_emit_cb(void *priv_data, calldata_t *cd)
|
||||
|
||||
auto eventData = static_cast<obs_data_t *>(voidEventData);
|
||||
|
||||
if (!c->_eventCallback)
|
||||
if (!c->_vendorEventCallback)
|
||||
RETURN_FAILURE();
|
||||
|
||||
c->_eventCallback(v->_name, eventType, eventData);
|
||||
c->_vendorEventCallback(v->_name, eventType, eventData);
|
||||
|
||||
RETURN_SUCCESS();
|
||||
}
|
||||
|
@ -23,9 +23,12 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <atomic>
|
||||
#include <obs.h>
|
||||
#include <obs-websocket-api.h>
|
||||
|
||||
#include "../lib/obs-websocket-api.h"
|
||||
#include "utils/Json.h"
|
||||
#include "plugin-macros.generated.h"
|
||||
|
||||
class WebSocketApi {
|
||||
public:
|
||||
@ -35,8 +38,6 @@ public:
|
||||
NoVendorRequest,
|
||||
};
|
||||
|
||||
typedef std::function<void(std::string, std::string, obs_data_t *)> EventCallback;
|
||||
|
||||
struct Vendor {
|
||||
std::shared_mutex _mutex;
|
||||
std::string _name;
|
||||
@ -45,23 +46,44 @@ public:
|
||||
|
||||
WebSocketApi();
|
||||
~WebSocketApi();
|
||||
|
||||
void SetEventCallback(EventCallback cb);
|
||||
|
||||
void BroadcastEvent(uint64_t requiredIntent, const std::string &eventType, const json &eventData = nullptr,
|
||||
uint8_t rpcVersion = 0);
|
||||
void SetObsReady(bool ready) { _obsReady = ready; }
|
||||
enum RequestReturnCode PerformVendorRequest(std::string vendorName, std::string requestName, obs_data_t *requestData,
|
||||
obs_data_t *responseData);
|
||||
|
||||
// Callback for when a vendor emits an event
|
||||
typedef std::function<void(std::string, std::string, obs_data_t *)> VendorEventCallback;
|
||||
inline void SetVendorEventCallback(VendorEventCallback cb) { _vendorEventCallback = cb; }
|
||||
|
||||
private:
|
||||
inline int64_t GetEventCallbackIndex(obs_websocket_event_callback &cb)
|
||||
{
|
||||
for (int64_t i = 0; i < (int64_t)_eventCallbacks.size(); i++) {
|
||||
auto currentCb = _eventCallbacks[i];
|
||||
if (currentCb.callback == cb.callback && currentCb.priv_data == cb.priv_data)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Proc handlers
|
||||
static void get_ph_cb(void *priv_data, calldata_t *cd);
|
||||
static void get_api_version(void *, calldata_t *cd);
|
||||
static void call_request(void *, calldata_t *cd);
|
||||
static void register_event_callback(void *, calldata_t *cd);
|
||||
static void unregister_event_callback(void *, calldata_t *cd);
|
||||
static void vendor_register_cb(void *priv_data, calldata_t *cd);
|
||||
static void vendor_request_register_cb(void *priv_data, calldata_t *cd);
|
||||
static void vendor_request_unregister_cb(void *priv_data, calldata_t *cd);
|
||||
static void vendor_event_emit_cb(void *priv_data, calldata_t *cd);
|
||||
|
||||
private:
|
||||
std::shared_mutex _mutex;
|
||||
EventCallback _eventCallback;
|
||||
proc_handler_t *_procHandler;
|
||||
std::map<std::string, Vendor *> _vendors;
|
||||
std::vector<obs_websocket_event_callback> _eventCallbacks;
|
||||
|
||||
std::atomic<bool> _obsReady = false;
|
||||
|
||||
VendorEventCallback _vendorEventCallback;
|
||||
};
|
||||
|
@ -27,10 +27,11 @@ EventHandler::EventHandler()
|
||||
|
||||
signal_handler_t *coreSignalHandler = obs_get_signal_handler();
|
||||
if (coreSignalHandler) {
|
||||
signal_handler_connect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this);
|
||||
signal_handler_connect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this);
|
||||
signal_handler_connect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this);
|
||||
signal_handler_connect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this);
|
||||
coreSignals.emplace_back(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this);
|
||||
coreSignals.emplace_back(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this);
|
||||
coreSignals.emplace_back(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this);
|
||||
coreSignals.emplace_back(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this);
|
||||
coreSignals.emplace_back(coreSignalHandler, "source_update", SourceUpdatedMultiHandler, this);
|
||||
} else {
|
||||
blog(LOG_ERROR, "[EventHandler::EventHandler] Unable to get libobs signal handler!");
|
||||
}
|
||||
@ -44,15 +45,7 @@ EventHandler::~EventHandler()
|
||||
|
||||
obs_frontend_remove_event_callback(OnFrontendEvent, this);
|
||||
|
||||
signal_handler_t *coreSignalHandler = obs_get_signal_handler();
|
||||
if (coreSignalHandler) {
|
||||
signal_handler_disconnect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this);
|
||||
signal_handler_disconnect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this);
|
||||
signal_handler_disconnect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this);
|
||||
signal_handler_disconnect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this);
|
||||
} else {
|
||||
blog(LOG_ERROR, "[EventHandler::~EventHandler] Unable to get libobs signal handler!");
|
||||
}
|
||||
coreSignals.clear();
|
||||
|
||||
// Revoke callbacks of all inputs and scenes, in case some still have our callbacks attached
|
||||
auto enumInputs = [](void *param, obs_source_t *source) {
|
||||
@ -71,58 +64,47 @@ EventHandler::~EventHandler()
|
||||
blog_debug("[EventHandler::~EventHandler] Finished.");
|
||||
}
|
||||
|
||||
void EventHandler::SetBroadcastCallback(EventHandler::BroadcastCallback cb)
|
||||
// Function to increment or decrement refcounts for high volume event subscriptions
|
||||
void EventHandler::ProcessSubscriptionChange(bool type, uint64_t eventSubscriptions)
|
||||
{
|
||||
_broadcastCallback = cb;
|
||||
}
|
||||
|
||||
void EventHandler::SetObsReadyCallback(EventHandler::ObsReadyCallback cb)
|
||||
{
|
||||
_obsReadyCallback = cb;
|
||||
}
|
||||
|
||||
// Function to increment refcounts for high volume event subscriptions
|
||||
void EventHandler::ProcessSubscription(uint64_t eventSubscriptions)
|
||||
{
|
||||
if ((eventSubscriptions & EventSubscription::InputVolumeMeters) != 0) {
|
||||
if (_inputVolumeMetersRef.fetch_add(1) == 0) {
|
||||
if (_inputVolumeMetersHandler)
|
||||
blog(LOG_WARNING, "[EventHandler::ProcessSubscription] Input volume meter handler already exists!");
|
||||
else
|
||||
_inputVolumeMetersHandler = std::make_unique<Utils::Obs::VolumeMeter::Handler>(
|
||||
std::bind(&EventHandler::HandleInputVolumeMeters, this, std::placeholders::_1));
|
||||
if (type) {
|
||||
if ((eventSubscriptions & EventSubscription::InputVolumeMeters) != 0) {
|
||||
if (_inputVolumeMetersRef.fetch_add(1) == 0) {
|
||||
if (_inputVolumeMetersHandler)
|
||||
blog(LOG_WARNING,
|
||||
"[EventHandler::ProcessSubscription] Input volume meter handler already exists!");
|
||||
else
|
||||
_inputVolumeMetersHandler = std::make_unique<Utils::Obs::VolumeMeter::Handler>(
|
||||
std::bind(&EventHandler::HandleInputVolumeMeters, this, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
if ((eventSubscriptions & EventSubscription::InputActiveStateChanged) != 0)
|
||||
_inputActiveStateChangedRef++;
|
||||
if ((eventSubscriptions & EventSubscription::InputShowStateChanged) != 0)
|
||||
_inputShowStateChangedRef++;
|
||||
if ((eventSubscriptions & EventSubscription::SceneItemTransformChanged) != 0)
|
||||
_sceneItemTransformChangedRef++;
|
||||
} else {
|
||||
if ((eventSubscriptions & EventSubscription::InputVolumeMeters) != 0) {
|
||||
if (_inputVolumeMetersRef.fetch_sub(1) == 1)
|
||||
_inputVolumeMetersHandler.reset();
|
||||
}
|
||||
if ((eventSubscriptions & EventSubscription::InputActiveStateChanged) != 0)
|
||||
_inputActiveStateChangedRef--;
|
||||
if ((eventSubscriptions & EventSubscription::InputShowStateChanged) != 0)
|
||||
_inputShowStateChangedRef--;
|
||||
if ((eventSubscriptions & EventSubscription::SceneItemTransformChanged) != 0)
|
||||
_sceneItemTransformChangedRef--;
|
||||
}
|
||||
if ((eventSubscriptions & EventSubscription::InputActiveStateChanged) != 0)
|
||||
_inputActiveStateChangedRef++;
|
||||
if ((eventSubscriptions & EventSubscription::InputShowStateChanged) != 0)
|
||||
_inputShowStateChangedRef++;
|
||||
if ((eventSubscriptions & EventSubscription::SceneItemTransformChanged) != 0)
|
||||
_sceneItemTransformChangedRef++;
|
||||
}
|
||||
|
||||
// Function to decrement refcounts for high volume event subscriptions
|
||||
void EventHandler::ProcessUnsubscription(uint64_t eventSubscriptions)
|
||||
{
|
||||
if ((eventSubscriptions & EventSubscription::InputVolumeMeters) != 0) {
|
||||
if (_inputVolumeMetersRef.fetch_sub(1) == 1)
|
||||
_inputVolumeMetersHandler.reset();
|
||||
}
|
||||
if ((eventSubscriptions & EventSubscription::InputActiveStateChanged) != 0)
|
||||
_inputActiveStateChangedRef--;
|
||||
if ((eventSubscriptions & EventSubscription::InputShowStateChanged) != 0)
|
||||
_inputShowStateChangedRef--;
|
||||
if ((eventSubscriptions & EventSubscription::SceneItemTransformChanged) != 0)
|
||||
_sceneItemTransformChangedRef--;
|
||||
}
|
||||
|
||||
// Function required in order to use default arguments
|
||||
void EventHandler::BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion)
|
||||
{
|
||||
if (!_broadcastCallback)
|
||||
if (!_eventCallback)
|
||||
return;
|
||||
|
||||
_broadcastCallback(requiredIntent, eventType, eventData, rpcVersion);
|
||||
_eventCallback(requiredIntent, eventType, eventData, rpcVersion);
|
||||
}
|
||||
|
||||
// Connect source signals for Inputs, Scenes, and Transitions. Filters are automatically connected.
|
||||
@ -387,12 +369,21 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_
|
||||
break;
|
||||
case OBS_FRONTEND_EVENT_RECORDING_STARTED:
|
||||
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED);
|
||||
{
|
||||
OBSOutputAutoRelease recordOutput = obs_frontend_get_recording_output();
|
||||
if (recordOutput) {
|
||||
signal_handler_t *sh = obs_output_get_signal_handler(recordOutput);
|
||||
eventHandler->recordFileChangedSignal.Connect(sh, "file_changed", HandleRecordFileChanged,
|
||||
private_data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OBS_FRONTEND_EVENT_RECORDING_STOPPING:
|
||||
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING);
|
||||
break;
|
||||
case OBS_FRONTEND_EVENT_RECORDING_STOPPED:
|
||||
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED);
|
||||
eventHandler->recordFileChangedSignal.Disconnect();
|
||||
break;
|
||||
case OBS_FRONTEND_EVENT_RECORDING_PAUSED:
|
||||
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_PAUSED);
|
||||
@ -588,6 +579,26 @@ void EventHandler::SourceRenamedMultiHandler(void *param, calldata_t *data)
|
||||
}
|
||||
}
|
||||
|
||||
void EventHandler::SourceUpdatedMultiHandler(void *param, calldata_t *data)
|
||||
{
|
||||
auto eventHandler = static_cast<EventHandler *>(param);
|
||||
|
||||
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
switch (obs_source_get_type(source)) {
|
||||
case OBS_SOURCE_TYPE_INPUT:
|
||||
eventHandler->HandleInputSettingsChanged(source);
|
||||
break;
|
||||
case OBS_SOURCE_TYPE_FILTER:
|
||||
eventHandler->HandleSourceFilterSettingsChanged(source);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EventHandler::StreamOutputReconnectHandler(void *param, calldata_t *)
|
||||
{
|
||||
auto eventHandler = static_cast<EventHandler *>(param);
|
||||
|
@ -34,21 +34,26 @@ public:
|
||||
EventHandler();
|
||||
~EventHandler();
|
||||
|
||||
typedef std::function<void(uint64_t, std::string, json, uint8_t)>
|
||||
BroadcastCallback; // uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion
|
||||
void SetBroadcastCallback(BroadcastCallback cb);
|
||||
typedef std::function<void(bool)> ObsReadyCallback; // bool ready
|
||||
void SetObsReadyCallback(ObsReadyCallback cb);
|
||||
void ProcessSubscriptionChange(bool type, uint64_t eventSubscriptions);
|
||||
|
||||
void ProcessSubscription(uint64_t eventSubscriptions);
|
||||
void ProcessUnsubscription(uint64_t eventSubscriptions);
|
||||
// Callback when an event fires
|
||||
typedef std::function<void(uint64_t, std::string, json, uint8_t)>
|
||||
EventCallback; // uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion
|
||||
inline void SetEventCallback(EventCallback cb) { _eventCallback = cb; }
|
||||
|
||||
// Callback when OBS becomes ready or non-ready
|
||||
typedef std::function<void(bool)> ObsReadyCallback; // bool ready
|
||||
inline void SetObsReadyCallback(ObsReadyCallback cb) { _obsReadyCallback = cb; }
|
||||
|
||||
private:
|
||||
BroadcastCallback _broadcastCallback;
|
||||
EventCallback _eventCallback;
|
||||
ObsReadyCallback _obsReadyCallback;
|
||||
|
||||
std::atomic<bool> _obsReady = false;
|
||||
|
||||
std::vector<OBSSignal> coreSignals;
|
||||
OBSSignal recordFileChangedSignal;
|
||||
|
||||
std::unique_ptr<Utils::Obs::VolumeMeter::Handler> _inputVolumeMetersHandler;
|
||||
std::atomic<uint64_t> _inputVolumeMetersRef = 0;
|
||||
std::atomic<uint64_t> _inputActiveStateChangedRef = 0;
|
||||
@ -69,9 +74,10 @@ private:
|
||||
static void SourceCreatedMultiHandler(void *param, calldata_t *data);
|
||||
static void SourceDestroyedMultiHandler(void *param, calldata_t *data);
|
||||
static void SourceRemovedMultiHandler(void *param, calldata_t *data);
|
||||
|
||||
// Signal handler: source
|
||||
static void SourceRenamedMultiHandler(void *param, calldata_t *data);
|
||||
static void SourceUpdatedMultiHandler(void *param, calldata_t *data);
|
||||
|
||||
// Signal handler: media sources
|
||||
static void SourceMediaPauseMultiHandler(void *param, calldata_t *data);
|
||||
static void SourceMediaPlayMultiHandler(void *param, calldata_t *data);
|
||||
static void SourceMediaRestartMultiHandler(void *param, calldata_t *data);
|
||||
@ -106,7 +112,7 @@ private:
|
||||
void HandleInputCreated(obs_source_t *source);
|
||||
void HandleInputRemoved(obs_source_t *source);
|
||||
void HandleInputNameChanged(obs_source_t *source, std::string oldInputName, std::string inputName);
|
||||
void HandleInputVolumeMeters(std::vector<json> inputs); // AudioMeter::Handler callback
|
||||
void HandleInputSettingsChanged(obs_source_t *source);
|
||||
static void HandleInputActiveStateChanged(void *param,
|
||||
calldata_t *data); // Direct callback
|
||||
static void HandleInputShowStateChanged(void *param,
|
||||
@ -123,6 +129,7 @@ private:
|
||||
calldata_t *data); // Direct callback
|
||||
static void HandleInputAudioMonitorTypeChanged(void *param,
|
||||
calldata_t *data); // Direct callback
|
||||
void HandleInputVolumeMeters(std::vector<json> inputs); // AudioMeter::Handler callback
|
||||
|
||||
// Transitions
|
||||
void HandleCurrentSceneTransitionChanged();
|
||||
@ -144,12 +151,14 @@ private:
|
||||
void HandleSourceFilterCreated(obs_source_t *source, obs_source_t *filter);
|
||||
void HandleSourceFilterRemoved(obs_source_t *source, obs_source_t *filter);
|
||||
static void HandleSourceFilterNameChanged(void *param,
|
||||
calldata_t *data); // Direct callback
|
||||
calldata_t *data); // Direct callback
|
||||
void HandleSourceFilterSettingsChanged(obs_source_t *source);
|
||||
static void HandleSourceFilterEnableStateChanged(void *param, calldata_t *data); // Direct callback
|
||||
|
||||
// Outputs
|
||||
void HandleStreamStateChanged(ObsOutputState state);
|
||||
void HandleRecordStateChanged(ObsOutputState state);
|
||||
static void HandleRecordFileChanged(void *param, calldata_t *data); // Direct callback
|
||||
void HandleReplayBufferStateChanged(ObsOutputState state);
|
||||
void HandleVirtualcamStateChanged(ObsOutputState state);
|
||||
void HandleReplayBufferSaved();
|
||||
|
@ -163,6 +163,32 @@ void EventHandler::HandleSourceFilterNameChanged(void *param, calldata_t *data)
|
||||
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterNameChanged", eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* An source filter's settings have changed (been updated).
|
||||
*
|
||||
* @dataField sourceName | String | Name of the source the filter is on
|
||||
* @dataField filterName | String | Name of the filter
|
||||
* @dataField filterSettings | Object | New settings object of the filter
|
||||
*
|
||||
* @eventType SourceFilterSettingsChanged
|
||||
* @eventSubscription Filters
|
||||
* @complexity 3
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.4.0
|
||||
* @api events
|
||||
* @category filters
|
||||
*/
|
||||
void EventHandler::HandleSourceFilterSettingsChanged(obs_source_t *source)
|
||||
{
|
||||
OBSDataAutoRelease filterSettings = obs_source_get_settings(source);
|
||||
|
||||
json eventData;
|
||||
eventData["sourceName"] = obs_source_get_name(obs_filter_get_parent(source));
|
||||
eventData["filterName"] = obs_source_get_name(source);
|
||||
eventData["filterSettings"] = Utils::Json::ObsDataToJson(filterSettings);
|
||||
BroadcastEvent(EventSubscription::Filters, "SourceFilterSettingsChanged", eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* A source filter's enable state has changed.
|
||||
*
|
||||
|
@ -23,6 +23,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
* An input has been created.
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
* @dataField inputKind | String | The kind of the input
|
||||
* @dataField unversionedInputKind | String | The unversioned kind of input (aka no `_v2` stuff)
|
||||
* @dataField inputSettings | Object | The settings configured to the input when it was created
|
||||
@ -44,6 +45,7 @@ void EventHandler::HandleInputCreated(obs_source_t *source)
|
||||
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventData["inputKind"] = inputKind;
|
||||
eventData["unversionedInputKind"] = obs_source_get_unversioned_id(source);
|
||||
eventData["inputSettings"] = Utils::Json::ObsDataToJson(inputSettings);
|
||||
@ -55,6 +57,7 @@ void EventHandler::HandleInputCreated(obs_source_t *source)
|
||||
* An input has been removed.
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
*
|
||||
* @eventType InputRemoved
|
||||
* @eventSubscription Inputs
|
||||
@ -68,12 +71,14 @@ void EventHandler::HandleInputRemoved(obs_source_t *source)
|
||||
{
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
BroadcastEvent(EventSubscription::Inputs, "InputRemoved", eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of an input has changed.
|
||||
*
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
* @dataField oldInputName | String | Old name of the input
|
||||
* @dataField inputName | String | New name of the input
|
||||
*
|
||||
@ -85,20 +90,50 @@ void EventHandler::HandleInputRemoved(obs_source_t *source)
|
||||
* @api events
|
||||
* @category inputs
|
||||
*/
|
||||
void EventHandler::HandleInputNameChanged(obs_source_t *, std::string oldInputName, std::string inputName)
|
||||
void EventHandler::HandleInputNameChanged(obs_source_t *source, std::string oldInputName, std::string inputName)
|
||||
{
|
||||
json eventData;
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventData["oldInputName"] = oldInputName;
|
||||
eventData["inputName"] = inputName;
|
||||
BroadcastEvent(EventSubscription::Inputs, "InputNameChanged", eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* An input's settings have changed (been updated).
|
||||
*
|
||||
* Note: On some inputs, changing values in the properties dialog will cause an immediate update. Pressing the "Cancel" button will revert the settings, resulting in another event being fired.
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
* @dataField inputSettings | Object | New settings object of the input
|
||||
*
|
||||
* @eventType InputSettingsChanged
|
||||
* @eventSubscription Inputs
|
||||
* @complexity 3
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.4.0
|
||||
* @api events
|
||||
* @category inputs
|
||||
*/
|
||||
void EventHandler::HandleInputSettingsChanged(obs_source_t *source)
|
||||
{
|
||||
OBSDataAutoRelease inputSettings = obs_source_get_settings(source);
|
||||
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventData["inputSettings"] = Utils::Json::ObsDataToJson(inputSettings);
|
||||
BroadcastEvent(EventSubscription::Inputs, "InputSettingsChanged", eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* An input's active state has changed.
|
||||
*
|
||||
* When an input is active, it means it's being shown by the program feed.
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
* @dataField videoActive | Boolean | Whether the input is active
|
||||
*
|
||||
* @eventType InputActiveStateChanged
|
||||
@ -125,6 +160,7 @@ void EventHandler::HandleInputActiveStateChanged(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventData["videoActive"] = obs_source_active(source);
|
||||
eventHandler->BroadcastEvent(EventSubscription::InputActiveStateChanged, "InputActiveStateChanged", eventData);
|
||||
}
|
||||
@ -135,6 +171,7 @@ void EventHandler::HandleInputActiveStateChanged(void *param, calldata_t *data)
|
||||
* When an input is showing, it means it's being shown by the preview or a dialog.
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
* @dataField videoShowing | Boolean | Whether the input is showing
|
||||
*
|
||||
* @eventType InputShowStateChanged
|
||||
@ -161,6 +198,7 @@ void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventData["videoShowing"] = obs_source_showing(source);
|
||||
eventHandler->BroadcastEvent(EventSubscription::InputShowStateChanged, "InputShowStateChanged", eventData);
|
||||
}
|
||||
@ -169,6 +207,7 @@ void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data)
|
||||
* An input's mute state has changed.
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
* @dataField inputMuted | Boolean | Whether the input is muted
|
||||
*
|
||||
* @eventType InputMuteStateChanged
|
||||
@ -192,6 +231,7 @@ void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventData["inputMuted"] = obs_source_muted(source);
|
||||
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputMuteStateChanged", eventData);
|
||||
}
|
||||
@ -200,6 +240,7 @@ void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data)
|
||||
* An input's volume level has changed.
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
* @dataField inputVolumeMul | Number | New volume level multiplier
|
||||
* @dataField inputVolumeDb | Number | New volume level in dB
|
||||
*
|
||||
@ -231,6 +272,7 @@ void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventData["inputVolumeMul"] = inputVolumeMul;
|
||||
eventData["inputVolumeDb"] = inputVolumeDb;
|
||||
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputVolumeChanged", eventData);
|
||||
@ -239,7 +281,8 @@ void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data)
|
||||
/**
|
||||
* The audio balance value of an input has changed.
|
||||
*
|
||||
* @dataField inputName | String | Name of the affected input
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
* @dataField inputAudioBalance | Number | New audio balance value of the input
|
||||
*
|
||||
* @eventType InputAudioBalanceChanged
|
||||
@ -265,6 +308,7 @@ void EventHandler::HandleInputAudioBalanceChanged(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventData["inputAudioBalance"] = inputAudioBalance;
|
||||
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioBalanceChanged", eventData);
|
||||
}
|
||||
@ -273,6 +317,7 @@ void EventHandler::HandleInputAudioBalanceChanged(void *param, calldata_t *data)
|
||||
* The sync offset of an input has changed.
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
* @dataField inputAudioSyncOffset | Number | New sync offset in milliseconds
|
||||
*
|
||||
* @eventType InputAudioSyncOffsetChanged
|
||||
@ -298,6 +343,7 @@ void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *da
|
||||
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventData["inputAudioSyncOffset"] = inputAudioSyncOffset / 1000000;
|
||||
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioSyncOffsetChanged", eventData);
|
||||
}
|
||||
@ -306,6 +352,7 @@ void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *da
|
||||
* The audio tracks of an input have changed.
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
* @dataField inputAudioTracks | Object | Object of audio tracks along with their associated enable states
|
||||
*
|
||||
* @eventType InputAudioTracksChanged
|
||||
@ -336,6 +383,7 @@ void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventData["inputAudioTracks"] = inputAudioTracks;
|
||||
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioTracksChanged", eventData);
|
||||
}
|
||||
@ -350,6 +398,7 @@ void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data)
|
||||
* - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT`
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
* @dataField monitorType | String | New monitor type of the input
|
||||
*
|
||||
* @eventType InputAudioMonitorTypeChanged
|
||||
@ -375,6 +424,7 @@ void EventHandler::HandleInputAudioMonitorTypeChanged(void *param, calldata_t *d
|
||||
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventData["monitorType"] = monitorType;
|
||||
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioMonitorTypeChanged", eventData);
|
||||
}
|
||||
|
@ -124,6 +124,7 @@ void EventHandler::SourceMediaPreviousMultiHandler(void *param, calldata_t *data
|
||||
* A media input has started playing.
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
*
|
||||
* @eventType MediaInputPlaybackStarted
|
||||
* @eventSubscription MediaInputs
|
||||
@ -146,6 +147,7 @@ void EventHandler::HandleMediaInputPlaybackStarted(void *param, calldata_t *data
|
||||
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventHandler->BroadcastEvent(EventSubscription::MediaInputs, "MediaInputPlaybackStarted", eventData);
|
||||
}
|
||||
|
||||
@ -153,6 +155,7 @@ void EventHandler::HandleMediaInputPlaybackStarted(void *param, calldata_t *data
|
||||
* A media input has finished playing.
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
*
|
||||
* @eventType MediaInputPlaybackEnded
|
||||
* @eventSubscription MediaInputs
|
||||
@ -175,6 +178,7 @@ void EventHandler::HandleMediaInputPlaybackEnded(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventHandler->BroadcastEvent(EventSubscription::MediaInputs, "MediaInputPlaybackEnded", eventData);
|
||||
}
|
||||
|
||||
@ -182,6 +186,7 @@ void EventHandler::HandleMediaInputPlaybackEnded(void *param, calldata_t *data)
|
||||
* An action has been performed on an input.
|
||||
*
|
||||
* @dataField inputName | String | Name of the input
|
||||
* @dataField inputUuid | String | UUID of the input
|
||||
* @dataField mediaAction | String | Action performed on the input. See `ObsMediaInputAction` enum
|
||||
*
|
||||
* @eventType MediaInputActionTriggered
|
||||
@ -196,6 +201,7 @@ void EventHandler::HandleMediaInputActionTriggered(obs_source_t *source, ObsMedi
|
||||
{
|
||||
json eventData;
|
||||
eventData["inputName"] = obs_source_get_name(source);
|
||||
eventData["inputUuid"] = obs_source_get_uuid(source);
|
||||
eventData["mediaAction"] = GetMediaInputActionString(action);
|
||||
BroadcastEvent(EventSubscription::MediaInputs, "MediaInputActionTriggered", eventData);
|
||||
}
|
||||
|
@ -87,6 +87,28 @@ void EventHandler::HandleRecordStateChanged(ObsOutputState state)
|
||||
BroadcastEvent(EventSubscription::Outputs, "RecordStateChanged", eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* The record output has started writing to a new file. For example, when a file split happens.
|
||||
*
|
||||
* @dataField newOutputPath | String | File name that the output has begun writing to
|
||||
*
|
||||
* @eventType RecordFileChanged
|
||||
* @eventSubscription Outputs
|
||||
* @complexity 2
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.5.0
|
||||
* @api events
|
||||
* @category outputs
|
||||
*/
|
||||
void EventHandler::HandleRecordFileChanged(void *param, calldata_t *data)
|
||||
{
|
||||
auto eventHandler = static_cast<EventHandler *>(param);
|
||||
|
||||
json eventData;
|
||||
eventData["newOutputPath"] = calldata_string(data, "next_file");
|
||||
eventHandler->BroadcastEvent(EventSubscription::Outputs, "RecordFileChanged", eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* The state of the replay buffer output has changed.
|
||||
*
|
||||
|
@ -23,7 +23,9 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
* A scene item has been created.
|
||||
*
|
||||
* @dataField sceneName | String | Name of the scene the item was added to
|
||||
* @dataField sceneUuid | String | UUID of the scene the item was added to
|
||||
* @dataField sourceName | String | Name of the underlying source (input/scene)
|
||||
* @dataField sourceUuid | String | UUID of the underlying source (input/scene)
|
||||
* @dataField sceneItemId | Number | Numeric ID of the scene item
|
||||
* @dataField sceneItemIndex | Number | Index position of the item
|
||||
*
|
||||
@ -49,7 +51,9 @@ void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
|
||||
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
|
||||
eventData["sourceName"] = obs_source_get_name(obs_sceneitem_get_source(sceneItem));
|
||||
eventData["sourceUuid"] = obs_source_get_uuid(obs_sceneitem_get_source(sceneItem));
|
||||
eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
|
||||
eventData["sceneItemIndex"] = obs_sceneitem_get_order_position(sceneItem);
|
||||
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemCreated", eventData);
|
||||
@ -61,7 +65,9 @@ void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data)
|
||||
* This event is not emitted when the scene the item is in is removed.
|
||||
*
|
||||
* @dataField sceneName | String | Name of the scene the item was removed from
|
||||
* @dataField sceneUuid | String | UUID of the scene the item was removed from
|
||||
* @dataField sourceName | String | Name of the underlying source (input/scene)
|
||||
* @dataField sourceUuid | String | UUID of the underlying source (input/scene)
|
||||
* @dataField sceneItemId | Number | Numeric ID of the scene item
|
||||
*
|
||||
* @eventType SceneItemRemoved
|
||||
@ -86,7 +92,9 @@ void EventHandler::HandleSceneItemRemoved(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
|
||||
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
|
||||
eventData["sourceName"] = obs_source_get_name(obs_sceneitem_get_source(sceneItem));
|
||||
eventData["sourceUuid"] = obs_source_get_uuid(obs_sceneitem_get_source(sceneItem));
|
||||
eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
|
||||
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemRemoved", eventData);
|
||||
}
|
||||
@ -95,6 +103,7 @@ void EventHandler::HandleSceneItemRemoved(void *param, calldata_t *data)
|
||||
* A scene's item list has been reindexed.
|
||||
*
|
||||
* @dataField sceneName | String | Name of the scene
|
||||
* @dataField sceneUuid | String | UUID of the scene
|
||||
* @dataField sceneItems | Array<Object> | Array of scene item objects
|
||||
*
|
||||
* @eventType SceneItemListReindexed
|
||||
@ -115,6 +124,7 @@ void EventHandler::HandleSceneItemListReindexed(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
|
||||
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
|
||||
eventData["sceneItems"] = Utils::Obs::ArrayHelper::GetSceneItemList(scene, true);
|
||||
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemListReindexed", eventData);
|
||||
}
|
||||
@ -123,6 +133,7 @@ void EventHandler::HandleSceneItemListReindexed(void *param, calldata_t *data)
|
||||
* A scene item's enable state has changed.
|
||||
*
|
||||
* @dataField sceneName | String | Name of the scene the item is in
|
||||
* @dataField sceneUuid | String | UUID of the scene the item is in
|
||||
* @dataField sceneItemId | Number | Numeric ID of the scene item
|
||||
* @dataField sceneItemEnabled | Boolean | Whether the scene item is enabled (visible)
|
||||
*
|
||||
@ -150,6 +161,7 @@ void EventHandler::HandleSceneItemEnableStateChanged(void *param, calldata_t *da
|
||||
|
||||
json eventData;
|
||||
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
|
||||
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
|
||||
eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
|
||||
eventData["sceneItemEnabled"] = sceneItemEnabled;
|
||||
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemEnableStateChanged", eventData);
|
||||
@ -159,6 +171,7 @@ void EventHandler::HandleSceneItemEnableStateChanged(void *param, calldata_t *da
|
||||
* A scene item's lock state has changed.
|
||||
*
|
||||
* @dataField sceneName | String | Name of the scene the item is in
|
||||
* @dataField sceneUuid | String | UUID of the scene the item is in
|
||||
* @dataField sceneItemId | Number | Numeric ID of the scene item
|
||||
* @dataField sceneItemLocked | Boolean | Whether the scene item is locked
|
||||
*
|
||||
@ -186,6 +199,7 @@ void EventHandler::HandleSceneItemLockStateChanged(void *param, calldata_t *data
|
||||
|
||||
json eventData;
|
||||
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
|
||||
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
|
||||
eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
|
||||
eventData["sceneItemLocked"] = sceneItemLocked;
|
||||
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemLockStateChanged", eventData);
|
||||
@ -195,6 +209,7 @@ void EventHandler::HandleSceneItemLockStateChanged(void *param, calldata_t *data
|
||||
* A scene item has been selected in the Ui.
|
||||
*
|
||||
* @dataField sceneName | String | Name of the scene the item is in
|
||||
* @dataField sceneUuid | String | UUID of the scene the item is in
|
||||
* @dataField sceneItemId | Number | Numeric ID of the scene item
|
||||
*
|
||||
* @eventType SceneItemSelected
|
||||
@ -219,6 +234,7 @@ void EventHandler::HandleSceneItemSelected(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
|
||||
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
|
||||
eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
|
||||
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemSelected", eventData);
|
||||
}
|
||||
@ -227,6 +243,7 @@ void EventHandler::HandleSceneItemSelected(void *param, calldata_t *data)
|
||||
* The transform/crop of a scene item has changed.
|
||||
*
|
||||
* @dataField sceneName | String | The name of the scene the item is in
|
||||
* @dataField sceneUuid | String | The UUID of the scene the item is in
|
||||
* @dataField sceneItemId | Number | Numeric ID of the scene item
|
||||
* @dataField sceneItemTransform | Object | New transform/crop info of the scene item
|
||||
*
|
||||
@ -255,6 +272,7 @@ void EventHandler::HandleSceneItemTransformChanged(void *param, calldata_t *data
|
||||
|
||||
json eventData;
|
||||
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
|
||||
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
|
||||
eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
|
||||
eventData["sceneItemTransform"] = Utils::Obs::ObjectHelper::GetSceneItemTransform(sceneItem);
|
||||
eventHandler->BroadcastEvent(EventSubscription::SceneItemTransformChanged, "SceneItemTransformChanged", eventData);
|
||||
|
@ -23,6 +23,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
* A new scene has been created.
|
||||
*
|
||||
* @dataField sceneName | String | Name of the new scene
|
||||
* @dataField sceneUuid | String | UUID of the new scene
|
||||
* @dataField isGroup | Boolean | Whether the new scene is a group
|
||||
*
|
||||
* @eventType SceneCreated
|
||||
@ -37,6 +38,7 @@ void EventHandler::HandleSceneCreated(obs_source_t *source)
|
||||
{
|
||||
json eventData;
|
||||
eventData["sceneName"] = obs_source_get_name(source);
|
||||
eventData["sceneUuid"] = obs_source_get_uuid(source);
|
||||
eventData["isGroup"] = obs_source_is_group(source);
|
||||
BroadcastEvent(EventSubscription::Scenes, "SceneCreated", eventData);
|
||||
}
|
||||
@ -45,6 +47,7 @@ void EventHandler::HandleSceneCreated(obs_source_t *source)
|
||||
* A scene has been removed.
|
||||
*
|
||||
* @dataField sceneName | String | Name of the removed scene
|
||||
* @dataField sceneUuid | String | UUID of the removed scene
|
||||
* @dataField isGroup | Boolean | Whether the scene was a group
|
||||
*
|
||||
* @eventType SceneRemoved
|
||||
@ -59,6 +62,7 @@ void EventHandler::HandleSceneRemoved(obs_source_t *source)
|
||||
{
|
||||
json eventData;
|
||||
eventData["sceneName"] = obs_source_get_name(source);
|
||||
eventData["sceneUuid"] = obs_source_get_uuid(source);
|
||||
eventData["isGroup"] = obs_source_is_group(source);
|
||||
BroadcastEvent(EventSubscription::Scenes, "SceneRemoved", eventData);
|
||||
}
|
||||
@ -66,6 +70,7 @@ void EventHandler::HandleSceneRemoved(obs_source_t *source)
|
||||
/**
|
||||
* The name of a scene has changed.
|
||||
*
|
||||
* @dataField sceneUuid | String | UUID of the scene
|
||||
* @dataField oldSceneName | String | Old name of the scene
|
||||
* @dataField sceneName | String | New name of the scene
|
||||
*
|
||||
@ -77,9 +82,10 @@ void EventHandler::HandleSceneRemoved(obs_source_t *source)
|
||||
* @api events
|
||||
* @category scenes
|
||||
*/
|
||||
void EventHandler::HandleSceneNameChanged(obs_source_t *, std::string oldSceneName, std::string sceneName)
|
||||
void EventHandler::HandleSceneNameChanged(obs_source_t *source, std::string oldSceneName, std::string sceneName)
|
||||
{
|
||||
json eventData;
|
||||
eventData["sceneUuid"] = obs_source_get_uuid(source);
|
||||
eventData["oldSceneName"] = oldSceneName;
|
||||
eventData["sceneName"] = sceneName;
|
||||
BroadcastEvent(EventSubscription::Scenes, "SceneNameChanged", eventData);
|
||||
@ -89,6 +95,7 @@ void EventHandler::HandleSceneNameChanged(obs_source_t *, std::string oldSceneNa
|
||||
* The current program scene has changed.
|
||||
*
|
||||
* @dataField sceneName | String | Name of the scene that was switched to
|
||||
* @dataField sceneUuid | String | UUID of the scene that was switched to
|
||||
*
|
||||
* @eventType CurrentProgramSceneChanged
|
||||
* @eventSubscription Scenes
|
||||
@ -104,6 +111,7 @@ void EventHandler::HandleCurrentProgramSceneChanged()
|
||||
|
||||
json eventData;
|
||||
eventData["sceneName"] = obs_source_get_name(currentScene);
|
||||
eventData["sceneUuid"] = obs_source_get_uuid(currentScene);
|
||||
BroadcastEvent(EventSubscription::Scenes, "CurrentProgramSceneChanged", eventData);
|
||||
}
|
||||
|
||||
@ -111,6 +119,7 @@ void EventHandler::HandleCurrentProgramSceneChanged()
|
||||
* The current preview scene has changed.
|
||||
*
|
||||
* @dataField sceneName | String | Name of the scene that was switched to
|
||||
* @dataField sceneUuid | String | UUID of the scene that was switched to
|
||||
*
|
||||
* @eventType CurrentPreviewSceneChanged
|
||||
* @eventSubscription Scenes
|
||||
@ -130,6 +139,7 @@ void EventHandler::HandleCurrentPreviewSceneChanged()
|
||||
|
||||
json eventData;
|
||||
eventData["sceneName"] = obs_source_get_name(currentPreviewScene);
|
||||
eventData["sceneUuid"] = obs_source_get_uuid(currentPreviewScene);
|
||||
BroadcastEvent(EventSubscription::Scenes, "CurrentPreviewSceneChanged", eventData);
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
* The current scene transition has changed.
|
||||
*
|
||||
* @dataField transitionName | String | Name of the new transition
|
||||
* @dataField transitionUuid | String | UUID of the new transition
|
||||
*
|
||||
* @eventType CurrentSceneTransitionChanged
|
||||
* @eventSubscription Transitions
|
||||
@ -38,6 +39,7 @@ void EventHandler::HandleCurrentSceneTransitionChanged()
|
||||
|
||||
json eventData;
|
||||
eventData["transitionName"] = obs_source_get_name(transition);
|
||||
eventData["transitionUuid"] = obs_source_get_uuid(transition);
|
||||
BroadcastEvent(EventSubscription::Transitions, "CurrentSceneTransitionChanged", eventData);
|
||||
}
|
||||
|
||||
@ -65,6 +67,7 @@ void EventHandler::HandleCurrentSceneTransitionDurationChanged()
|
||||
* A scene transition has started.
|
||||
*
|
||||
* @dataField transitionName | String | Scene transition name
|
||||
* @dataField transitionUuid | String | Scene transition UUID
|
||||
*
|
||||
* @eventType SceneTransitionStarted
|
||||
* @eventSubscription Transitions
|
||||
@ -84,6 +87,7 @@ void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["transitionName"] = obs_source_get_name(source);
|
||||
eventData["transitionUuid"] = obs_source_get_uuid(source);
|
||||
eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionStarted", eventData);
|
||||
}
|
||||
|
||||
@ -93,6 +97,7 @@ void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data)
|
||||
* Note: Does not appear to trigger when the transition is interrupted by the user.
|
||||
*
|
||||
* @dataField transitionName | String | Scene transition name
|
||||
* @dataField transitionUuid | String | Scene transition UUID
|
||||
*
|
||||
* @eventType SceneTransitionEnded
|
||||
* @eventSubscription Transitions
|
||||
@ -112,6 +117,7 @@ void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data)
|
||||
|
||||
json eventData;
|
||||
eventData["transitionName"] = obs_source_get_name(source);
|
||||
eventData["transitionUuid"] = obs_source_get_uuid(source);
|
||||
eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionEnded", eventData);
|
||||
}
|
||||
|
||||
@ -124,6 +130,7 @@ void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data)
|
||||
* Note: Appears to be called by every transition, regardless of relevance.
|
||||
*
|
||||
* @dataField transitionName | String | Scene transition name
|
||||
* @dataField transitionUuid | String | Scene transition UUID
|
||||
*
|
||||
* @eventType SceneTransitionVideoEnded
|
||||
* @eventSubscription Transitions
|
||||
@ -143,5 +150,6 @@ void EventHandler::HandleSceneTransitionVideoEnded(void *param, calldata_t *data
|
||||
|
||||
json eventData;
|
||||
eventData["transitionName"] = obs_source_get_name(source);
|
||||
eventData["transitionUuid"] = obs_source_get_uuid(source);
|
||||
eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionVideoEnded", eventData);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ void ConnectInfo::RefreshData()
|
||||
QString serverPassword;
|
||||
if (conf->AuthRequired) {
|
||||
ui->copyServerPasswordButton->setEnabled(true);
|
||||
serverPassword = QUrl::toPercentEncoding(conf->ServerPassword);
|
||||
serverPassword = QUrl::toPercentEncoding(QString::fromStdString(conf->ServerPassword));
|
||||
} else {
|
||||
ui->copyServerPasswordButton->setEnabled(false);
|
||||
serverPassword = obs_module_text("OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText");
|
||||
|
@ -123,7 +123,7 @@ void SettingsDialog::RefreshData()
|
||||
ui->enableDebugLoggingCheckBox->setChecked(conf->DebugEnabled);
|
||||
ui->serverPortSpinBox->setValue(conf->ServerPort);
|
||||
ui->enableAuthenticationCheckBox->setChecked(conf->AuthRequired);
|
||||
ui->serverPasswordLineEdit->setText(conf->ServerPassword);
|
||||
ui->serverPasswordLineEdit->setText(QString::fromStdString(conf->ServerPassword));
|
||||
|
||||
ui->serverPasswordLineEdit->setEnabled(conf->AuthRequired);
|
||||
ui->generatePasswordButton->setEnabled(conf->AuthRequired);
|
||||
@ -158,7 +158,7 @@ void SettingsDialog::SaveFormData()
|
||||
}
|
||||
|
||||
// Show a confirmation box to the user if they attempt to provide their own password
|
||||
if (passwordManuallyEdited && (conf->ServerPassword != ui->serverPasswordLineEdit->text())) {
|
||||
if (passwordManuallyEdited && (conf->ServerPassword != ui->serverPasswordLineEdit->text().toStdString())) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(obs_module_text("OBSWebSocket.Settings.Save.UserPasswordWarningTitle"));
|
||||
msgBox.setText(obs_module_text("OBSWebSocket.Settings.Save.UserPasswordWarningMessage"));
|
||||
@ -172,22 +172,22 @@ void SettingsDialog::SaveFormData()
|
||||
break;
|
||||
case QMessageBox::No:
|
||||
default:
|
||||
ui->serverPasswordLineEdit->setText(conf->ServerPassword);
|
||||
ui->serverPasswordLineEdit->setText(QString::fromStdString(conf->ServerPassword));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool needsRestart =
|
||||
(conf->ServerEnabled != ui->enableWebSocketServerCheckBox->isChecked()) ||
|
||||
(conf->ServerPort != ui->serverPortSpinBox->value()) ||
|
||||
(ui->enableAuthenticationCheckBox->isChecked() && conf->ServerPassword != ui->serverPasswordLineEdit->text());
|
||||
bool needsRestart = (conf->ServerEnabled != ui->enableWebSocketServerCheckBox->isChecked()) ||
|
||||
(conf->ServerPort != ui->serverPortSpinBox->value()) ||
|
||||
(ui->enableAuthenticationCheckBox->isChecked() &&
|
||||
conf->ServerPassword != ui->serverPasswordLineEdit->text().toStdString());
|
||||
|
||||
conf->ServerEnabled = ui->enableWebSocketServerCheckBox->isChecked();
|
||||
conf->AlertsEnabled = ui->enableSystemTrayAlertsCheckBox->isChecked();
|
||||
conf->DebugEnabled = ui->enableDebugLoggingCheckBox->isChecked();
|
||||
conf->ServerPort = ui->serverPortSpinBox->value();
|
||||
conf->AuthRequired = ui->enableAuthenticationCheckBox->isChecked();
|
||||
conf->ServerPassword = ui->serverPasswordLineEdit->text();
|
||||
conf->ServerPassword = ui->serverPasswordLineEdit->text().toStdString();
|
||||
|
||||
conf->Save();
|
||||
|
||||
|
@ -48,7 +48,9 @@ WebSocketApiPtr _webSocketApi;
|
||||
WebSocketServerPtr _webSocketServer;
|
||||
SettingsDialog *_settingsDialog = nullptr;
|
||||
|
||||
void WebSocketApiEventCallback(std::string vendorName, std::string eventType, obs_data_t *obsEventData);
|
||||
void OnWebSocketApiVendorEvent(std::string vendorName, std::string eventType, obs_data_t *obsEventData);
|
||||
void OnEvent(uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion);
|
||||
void OnObsReady(bool ready);
|
||||
|
||||
bool obs_module_load(void)
|
||||
{
|
||||
@ -60,19 +62,30 @@ bool obs_module_load(void)
|
||||
// Initialize the cpu stats
|
||||
_cpuUsageInfo = os_cpu_usage_info_start();
|
||||
|
||||
// Handle migrations
|
||||
if (!MigratePersistentData()) {
|
||||
os_cpu_usage_info_destroy(_cpuUsageInfo);
|
||||
return false;
|
||||
}
|
||||
json migratedConfig = MigrateGlobalConfigData();
|
||||
|
||||
// Create the config manager then load the parameters from storage
|
||||
_config = ConfigPtr(new Config());
|
||||
_config->Load();
|
||||
_config = std::make_shared<Config>();
|
||||
_config->Load(migratedConfig);
|
||||
|
||||
// Initialize the event handler
|
||||
_eventHandler = EventHandlerPtr(new EventHandler());
|
||||
_eventHandler = std::make_shared<EventHandler>();
|
||||
_eventHandler->SetEventCallback(OnEvent);
|
||||
_eventHandler->SetObsReadyCallback(OnObsReady);
|
||||
|
||||
// Initialize the plugin/script API
|
||||
_webSocketApi = WebSocketApiPtr(new WebSocketApi());
|
||||
_webSocketApi->SetEventCallback(WebSocketApiEventCallback);
|
||||
_webSocketApi = std::make_shared<WebSocketApi>();
|
||||
_webSocketApi->SetVendorEventCallback(OnWebSocketApiVendorEvent);
|
||||
|
||||
// Initialize the WebSocket server
|
||||
_webSocketServer = WebSocketServerPtr(new WebSocketServer());
|
||||
_webSocketServer = std::make_shared<WebSocketServer>();
|
||||
_webSocketServer->SetClientSubscriptionCallback(std::bind(&EventHandler::ProcessSubscriptionChange, _eventHandler.get(),
|
||||
std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
// Initialize the settings dialog
|
||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||
@ -90,12 +103,16 @@ bool obs_module_load(void)
|
||||
}
|
||||
|
||||
#ifdef PLUGIN_TESTS
|
||||
void test_call_request();
|
||||
void test_register_event_callback();
|
||||
void test_register_vendor();
|
||||
#endif
|
||||
|
||||
void obs_module_post_load(void)
|
||||
{
|
||||
#ifdef PLUGIN_TESTS
|
||||
test_call_request();
|
||||
test_register_event_callback();
|
||||
test_register_vendor();
|
||||
#endif
|
||||
|
||||
@ -116,17 +133,20 @@ void obs_module_unload(void)
|
||||
_webSocketServer->Stop();
|
||||
}
|
||||
|
||||
// Destroy the WebSocket server
|
||||
_webSocketServer.reset();
|
||||
// Release the WebSocket server
|
||||
_webSocketServer->SetClientSubscriptionCallback(nullptr);
|
||||
_webSocketServer = nullptr;
|
||||
|
||||
// Destroy the plugin/script api
|
||||
_webSocketApi.reset();
|
||||
// Release the plugin/script api
|
||||
_webSocketApi = nullptr;
|
||||
|
||||
// Destroy the event handler
|
||||
_eventHandler.reset();
|
||||
// Release the event handler
|
||||
_eventHandler->SetObsReadyCallback(nullptr);
|
||||
_eventHandler->SetEventCallback(nullptr);
|
||||
_eventHandler = nullptr;
|
||||
|
||||
// Destroy the config manager
|
||||
_config.reset();
|
||||
// Release the config manager
|
||||
_config = nullptr;
|
||||
|
||||
// Destroy the cpu stats
|
||||
os_cpu_usage_info_destroy(_cpuUsageInfo);
|
||||
@ -182,7 +202,7 @@ bool IsDebugEnabled()
|
||||
* @api events
|
||||
* @category general
|
||||
*/
|
||||
void WebSocketApiEventCallback(std::string vendorName, std::string eventType, obs_data_t *obsEventData)
|
||||
void OnWebSocketApiVendorEvent(std::string vendorName, std::string eventType, obs_data_t *obsEventData)
|
||||
{
|
||||
json eventData = Utils::Json::ObsDataToJson(obsEventData);
|
||||
|
||||
@ -194,13 +214,62 @@ void WebSocketApiEventCallback(std::string vendorName, std::string eventType, ob
|
||||
_webSocketServer->BroadcastEvent(EventSubscription::Vendors, "VendorEvent", broadcastEventData);
|
||||
}
|
||||
|
||||
// Sent from: EventHandler
|
||||
void OnEvent(uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion)
|
||||
{
|
||||
if (_webSocketServer)
|
||||
_webSocketServer->BroadcastEvent(requiredIntent, eventType, eventData, rpcVersion);
|
||||
if (_webSocketApi)
|
||||
_webSocketApi->BroadcastEvent(requiredIntent, eventType, eventData, rpcVersion);
|
||||
}
|
||||
|
||||
// Sent from: EventHandler
|
||||
void OnObsReady(bool ready)
|
||||
{
|
||||
if (_webSocketServer)
|
||||
_webSocketServer->SetObsReady(ready);
|
||||
if (_webSocketApi)
|
||||
_webSocketApi->SetObsReady(ready);
|
||||
}
|
||||
|
||||
#ifdef PLUGIN_TESTS
|
||||
void test_call_request()
|
||||
{
|
||||
blog(LOG_INFO, "[test_call_request] Testing obs-websocket plugin API request calling...");
|
||||
|
||||
struct obs_websocket_request_response *response = obs_websocket_call_request("GetVersion");
|
||||
if (response) {
|
||||
blog(LOG_INFO, "[test_call_request] Called GetVersion. Status Code: %u | Comment: %s | Response Data: %s",
|
||||
response->status_code, response->comment, response->response_data);
|
||||
obs_websocket_request_response_free(response);
|
||||
} else {
|
||||
blog(LOG_ERROR, "[test_call_request] Failed to call GetVersion request via obs-websocket plugin API!");
|
||||
}
|
||||
|
||||
blog(LOG_INFO, "[test_call_request] Test done.");
|
||||
}
|
||||
|
||||
static void test_event_cb(uint64_t eventIntent, const char *eventType, const char *eventData, void *priv_data)
|
||||
{
|
||||
blog(LOG_DEBUG, "[test_event_cb] New event! Type: %s | Data: %s", eventType, eventData);
|
||||
|
||||
UNUSED_PARAMETER(eventIntent);
|
||||
UNUSED_PARAMETER(priv_data);
|
||||
}
|
||||
|
||||
void test_register_event_callback()
|
||||
{
|
||||
blog(LOG_INFO, "[test_register_event_callback] Registering test event callback...");
|
||||
|
||||
if (!obs_websocket_register_event_callback(test_event_cb, nullptr))
|
||||
blog(LOG_ERROR, "[test_register_event_callback] Failed to register event callback!");
|
||||
|
||||
blog(LOG_INFO, "[test_register_event_callback] Test done.");
|
||||
}
|
||||
|
||||
static void test_vendor_request_cb(obs_data_t *requestData, obs_data_t *responseData, void *priv_data)
|
||||
{
|
||||
blog(LOG_INFO, "[test_vendor_request_cb] Request called!");
|
||||
|
||||
blog(LOG_INFO, "[test_vendor_request_cb] Request data: %s", obs_data_get_json(requestData));
|
||||
blog(LOG_INFO, "[test_vendor_request_cb] Request called! Request data: %s", obs_data_get_json(requestData));
|
||||
|
||||
// Set an item to the response data
|
||||
obs_data_set_string(responseData, "test", "pp");
|
||||
@ -211,34 +280,25 @@ static void test_vendor_request_cb(obs_data_t *requestData, obs_data_t *response
|
||||
|
||||
void test_register_vendor()
|
||||
{
|
||||
blog(LOG_INFO, "[test_register_vendor] Registering test vendor...");
|
||||
blog(LOG_INFO, "[test_register_vendor] Testing vendor registration...");
|
||||
|
||||
// Test plugin API version fetch
|
||||
uint apiVersion = obs_websocket_get_api_version();
|
||||
blog(LOG_INFO, "[test_register_vendor] obs-websocket plugin API version: %u", apiVersion);
|
||||
|
||||
// Test calling obs-websocket requests
|
||||
struct obs_websocket_request_response *response = obs_websocket_call_request("GetVersion");
|
||||
if (response) {
|
||||
blog(LOG_INFO, "[test_register_vendor] Called GetVersion. Status Code: %u | Comment: %s | Response Data: %s",
|
||||
response->status_code, response->comment, response->response_data);
|
||||
obs_websocket_request_response_free(response);
|
||||
}
|
||||
|
||||
// Test vendor creation
|
||||
auto vendor = obs_websocket_register_vendor("obs-websocket-test");
|
||||
if (!vendor) {
|
||||
blog(LOG_WARNING, "[test_register_vendor] Failed to create vendor!");
|
||||
blog(LOG_ERROR, "[test_register_vendor] Failed to create vendor!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Test vendor request registration
|
||||
if (!obs_websocket_vendor_register_request(vendor, "TestRequest", test_vendor_request_cb, vendor)) {
|
||||
blog(LOG_WARNING, "[test_register_vendor] Failed to register vendor request!");
|
||||
blog(LOG_ERROR, "[test_register_vendor] Failed to register vendor request!");
|
||||
return;
|
||||
}
|
||||
|
||||
blog(LOG_INFO, "[test_register_vendor] Post load completed.");
|
||||
blog(LOG_INFO, "[test_register_vendor] Test done.");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -26,6 +26,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
#include "utils/Obs.h"
|
||||
#include "plugin-macros.generated.h"
|
||||
|
||||
#define CURRENT_RPC_VERSION 1
|
||||
|
||||
struct Config;
|
||||
typedef std::shared_ptr<Config> ConfigPtr;
|
||||
|
||||
|
@ -37,7 +37,9 @@ struct SerialFrameBatch {
|
||||
std::condition_variable condition;
|
||||
|
||||
SerialFrameBatch(RequestHandler &requestHandler, json &variables, bool haltOnFailure)
|
||||
: requestHandler(requestHandler), variables(variables), haltOnFailure(haltOnFailure)
|
||||
: requestHandler(requestHandler),
|
||||
variables(variables),
|
||||
haltOnFailure(haltOnFailure)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -111,6 +111,7 @@ const std::unordered_map<std::string, RequestMethodHandler> RequestHandler::_han
|
||||
{"SetTBarPosition", &RequestHandler::SetTBarPosition},
|
||||
|
||||
// Filters
|
||||
{"GetSourceFilterKindList", &RequestHandler::GetSourceFilterKindList},
|
||||
{"GetSourceFilterList", &RequestHandler::GetSourceFilterList},
|
||||
{"GetSourceFilterDefaultSettings", &RequestHandler::GetSourceFilterDefaultSettings},
|
||||
{"CreateSourceFilter", &RequestHandler::CreateSourceFilter},
|
||||
@ -125,6 +126,7 @@ const std::unordered_map<std::string, RequestMethodHandler> RequestHandler::_han
|
||||
{"GetSceneItemList", &RequestHandler::GetSceneItemList},
|
||||
{"GetGroupSceneItemList", &RequestHandler::GetGroupSceneItemList},
|
||||
{"GetSceneItemId", &RequestHandler::GetSceneItemId},
|
||||
{"GetSceneItemSource", &RequestHandler::GetSceneItemSource},
|
||||
{"CreateSceneItem", &RequestHandler::CreateSceneItem},
|
||||
{"RemoveSceneItem", &RequestHandler::RemoveSceneItem},
|
||||
{"DuplicateSceneItem", &RequestHandler::DuplicateSceneItem},
|
||||
@ -175,6 +177,8 @@ const std::unordered_map<std::string, RequestMethodHandler> RequestHandler::_han
|
||||
{"ToggleRecordPause", &RequestHandler::ToggleRecordPause},
|
||||
{"PauseRecord", &RequestHandler::PauseRecord},
|
||||
{"ResumeRecord", &RequestHandler::ResumeRecord},
|
||||
{"SplitRecordFile", &RequestHandler::SplitRecordFile},
|
||||
{"CreateRecordChapter", &RequestHandler::CreateRecordChapter},
|
||||
|
||||
// Media Inputs
|
||||
{"GetMediaInputStatus", &RequestHandler::GetMediaInputStatus},
|
||||
|
@ -130,6 +130,7 @@ private:
|
||||
RequestResult SetTBarPosition(const Request &);
|
||||
|
||||
// Filters
|
||||
RequestResult GetSourceFilterKindList(const Request &);
|
||||
RequestResult GetSourceFilterList(const Request &);
|
||||
RequestResult GetSourceFilterDefaultSettings(const Request &);
|
||||
RequestResult CreateSourceFilter(const Request &);
|
||||
@ -144,6 +145,7 @@ private:
|
||||
RequestResult GetSceneItemList(const Request &);
|
||||
RequestResult GetGroupSceneItemList(const Request &);
|
||||
RequestResult GetSceneItemId(const Request &);
|
||||
RequestResult GetSceneItemSource(const Request &);
|
||||
RequestResult CreateSceneItem(const Request &);
|
||||
RequestResult RemoveSceneItem(const Request &);
|
||||
RequestResult DuplicateSceneItem(const Request &);
|
||||
@ -194,6 +196,8 @@ private:
|
||||
RequestResult ToggleRecordPause(const Request &);
|
||||
RequestResult PauseRecord(const Request &);
|
||||
RequestResult ResumeRecord(const Request &);
|
||||
RequestResult SplitRecordFile(const Request &);
|
||||
RequestResult CreateRecordChapter(const Request &);
|
||||
|
||||
// Media Inputs
|
||||
RequestResult GetMediaInputStatus(const Request &);
|
||||
|
@ -22,6 +22,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
|
||||
#include "RequestHandler.h"
|
||||
|
||||
#define GLOBAL_PERSISTENT_DATA_FILE_NAME "persistent_data.json"
|
||||
|
||||
/**
|
||||
* Gets the value of a "slot" from the selected persistent data realm.
|
||||
*
|
||||
@ -47,11 +49,11 @@ RequestResult RequestHandler::GetPersistentData(const Request &request)
|
||||
std::string realm = request.RequestData["realm"];
|
||||
std::string slotName = request.RequestData["slotName"];
|
||||
|
||||
std::string persistentDataPath = Utils::Obs::StringHelper::GetCurrentProfilePath();
|
||||
std::string persistentDataPath;
|
||||
if (realm == "OBS_WEBSOCKET_DATA_REALM_GLOBAL")
|
||||
persistentDataPath += "/../../../obsWebSocketPersistentData.json";
|
||||
persistentDataPath = Utils::Obs::StringHelper::GetModuleConfigPath(GLOBAL_PERSISTENT_DATA_FILE_NAME);
|
||||
else if (realm == "OBS_WEBSOCKET_DATA_REALM_PROFILE")
|
||||
persistentDataPath += "/obsWebSocketPersistentData.json";
|
||||
persistentDataPath = Utils::Obs::StringHelper::GetCurrentProfilePath() + "/obsWebSocketPersistentData.json";
|
||||
else
|
||||
return RequestResult::Error(RequestStatus::ResourceNotFound,
|
||||
"You have specified an invalid persistent data realm.");
|
||||
@ -92,16 +94,16 @@ RequestResult RequestHandler::SetPersistentData(const Request &request)
|
||||
std::string slotName = request.RequestData["slotName"];
|
||||
json slotValue = request.RequestData["slotValue"];
|
||||
|
||||
std::string persistentDataPath = Utils::Obs::StringHelper::GetCurrentProfilePath();
|
||||
std::string persistentDataPath;
|
||||
if (realm == "OBS_WEBSOCKET_DATA_REALM_GLOBAL")
|
||||
persistentDataPath += "/../../../obsWebSocketPersistentData.json";
|
||||
persistentDataPath = Utils::Obs::StringHelper::GetModuleConfigPath(GLOBAL_PERSISTENT_DATA_FILE_NAME);
|
||||
else if (realm == "OBS_WEBSOCKET_DATA_REALM_PROFILE")
|
||||
persistentDataPath += "/obsWebSocketPersistentData.json";
|
||||
persistentDataPath = Utils::Obs::StringHelper::GetCurrentProfilePath() + "/obsWebSocketPersistentData.json";
|
||||
else
|
||||
return RequestResult::Error(RequestStatus::ResourceNotFound,
|
||||
"You have specified an invalid persistent data realm.");
|
||||
|
||||
json persistentData = json::object();
|
||||
json persistentData;
|
||||
Utils::Json::GetJsonFileContent(persistentDataPath, persistentData);
|
||||
persistentData[slotName] = slotValue;
|
||||
if (!Utils::Json::SetJsonFileContent(persistentDataPath, persistentData))
|
||||
@ -198,10 +200,7 @@ RequestResult RequestHandler::CreateSceneCollection(const Request &request)
|
||||
if (std::find(sceneCollections.begin(), sceneCollections.end(), sceneCollectionName) != sceneCollections.end())
|
||||
return RequestResult::Error(RequestStatus::ResourceAlreadyExists);
|
||||
|
||||
QMainWindow *mainWindow = static_cast<QMainWindow *>(obs_frontend_get_main_window());
|
||||
bool success = false;
|
||||
QMetaObject::invokeMethod(mainWindow, "AddSceneCollection", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, success),
|
||||
Q_ARG(bool, true), Q_ARG(QString, QString::fromStdString(sceneCollectionName)));
|
||||
bool success = obs_frontend_add_scene_collection(sceneCollectionName.c_str());
|
||||
if (!success)
|
||||
return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Failed to create the scene collection.");
|
||||
|
||||
@ -599,9 +598,9 @@ RequestResult RequestHandler::SetStreamServiceSettings(const Request &request)
|
||||
|
||||
obs_service_update(currentStreamService, newStreamServiceSettings);
|
||||
} else {
|
||||
// TODO: This leaks memory. I have no idea why.
|
||||
OBSService newStreamService = obs_service_create(requestedStreamServiceType.c_str(), "obs_websocket_custom_service",
|
||||
requestedStreamServiceSettings, nullptr);
|
||||
OBSServiceAutoRelease newStreamService = obs_service_create(requestedStreamServiceType.c_str(),
|
||||
"obs_websocket_custom_service",
|
||||
requestedStreamServiceSettings, nullptr);
|
||||
// TODO: Check service type here, instead of relying on service creation to fail.
|
||||
if (!newStreamService)
|
||||
return RequestResult::Error(
|
||||
|
@ -19,10 +19,32 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
|
||||
#include "RequestHandler.h"
|
||||
|
||||
/**
|
||||
* Gets an array of all available source filter kinds.
|
||||
*
|
||||
* Similar to `GetInputKindList`
|
||||
*
|
||||
* @responseField sourceFilterKinds | Array<String> | Array of source filter kinds
|
||||
*
|
||||
* @requestType GetSourceFilterKindList
|
||||
* @complexity 2
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.4.0
|
||||
* @api requests
|
||||
* @category filters
|
||||
*/
|
||||
RequestResult RequestHandler::GetSourceFilterKindList(const Request &)
|
||||
{
|
||||
json responseData;
|
||||
responseData["sourceFilterKinds"] = Utils::Obs::ArrayHelper::GetFilterKindList();
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of all of a source's filters.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source
|
||||
* @requestField ?sourceName | String | Name of the source
|
||||
* @requestField ?sourceUuid | String | UUID of the source
|
||||
*
|
||||
* @responseField filters | Array<Object> | Array of filters
|
||||
*
|
||||
@ -37,7 +59,7 @@ RequestResult RequestHandler::GetSourceFilterList(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment);
|
||||
if (!source)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -85,7 +107,8 @@ RequestResult RequestHandler::GetSourceFilterDefaultSettings(const Request &requ
|
||||
/**
|
||||
* Creates a new filter, adding it to the specified source.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source to add the filter to
|
||||
* @requestField ?sourceName | String | Name of the source to add the filter to
|
||||
* @requestField ?sourceUuid | String | UUID of the source to add the filter to
|
||||
* @requestField filterName | String | Name of the new filter to be created
|
||||
* @requestField filterKind | String | The kind of filter to be created
|
||||
* @requestField ?filterSettings | Object | Settings object to initialize the filter with | Default settings used
|
||||
@ -102,7 +125,7 @@ RequestResult RequestHandler::CreateSourceFilter(const Request &request)
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment);
|
||||
if (!(source && request.ValidateString("filterName", statusCode, comment) &&
|
||||
request.ValidateString("filterKind", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
@ -138,8 +161,9 @@ RequestResult RequestHandler::CreateSourceFilter(const Request &request)
|
||||
/**
|
||||
* Removes a filter from a source.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source the filter is on
|
||||
* @requestField filterName | String | Name of the filter to remove
|
||||
* @requestField ?sourceName | String | Name of the source the filter is on
|
||||
* @requestField ?sourceUuid | String | UUID of the source the filter is on
|
||||
* @requestField filterName | String | Name of the filter to remove
|
||||
*
|
||||
* @requestType RemoveSourceFilter
|
||||
* @complexity 2
|
||||
@ -152,7 +176,7 @@ RequestResult RequestHandler::RemoveSourceFilter(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
|
||||
FilterPair pair = request.ValidateFilter(statusCode, comment);
|
||||
if (!pair.filter)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -164,7 +188,8 @@ RequestResult RequestHandler::RemoveSourceFilter(const Request &request)
|
||||
/**
|
||||
* Sets the name of a source filter (rename).
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source the filter is on
|
||||
* @requestField ?sourceName | String | Name of the source the filter is on
|
||||
* @requestField ?sourceUuid | String | UUID of the source the filter is on
|
||||
* @requestField filterName | String | Current name of the filter
|
||||
* @requestField newFilterName | String | New name for the filter
|
||||
*
|
||||
@ -179,7 +204,7 @@ RequestResult RequestHandler::SetSourceFilterName(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
|
||||
FilterPair pair = request.ValidateFilter(statusCode, comment);
|
||||
if (!pair.filter || !request.ValidateString("newFilterName", statusCode, comment))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -197,8 +222,9 @@ RequestResult RequestHandler::SetSourceFilterName(const Request &request)
|
||||
/**
|
||||
* Gets the info for a specific source filter.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source
|
||||
* @requestField filterName | String | Name of the filter
|
||||
* @requestField ?sourceName | String | Name of the source
|
||||
* @requestField ?sourceUuid | String | UUID of the source
|
||||
* @requestField filterName | String | Name of the filter
|
||||
*
|
||||
* @responseField filterEnabled | Boolean | Whether the filter is enabled
|
||||
* @responseField filterIndex | Number | Index of the filter in the list, beginning at 0
|
||||
@ -216,7 +242,7 @@ RequestResult RequestHandler::GetSourceFilter(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
|
||||
FilterPair pair = request.ValidateFilter(statusCode, comment);
|
||||
if (!pair.filter)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -236,7 +262,8 @@ RequestResult RequestHandler::GetSourceFilter(const Request &request)
|
||||
/**
|
||||
* Sets the index position of a filter on a source.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source the filter is on
|
||||
* @requestField ?sourceName | String | Name of the source the filter is on
|
||||
* @requestField ?sourceUuid | String | UUID of the source the filter is on
|
||||
* @requestField filterName | String | Name of the filter
|
||||
* @requestField filterIndex | Number | New index position of the filter | >= 0
|
||||
*
|
||||
@ -251,7 +278,7 @@ RequestResult RequestHandler::SetSourceFilterIndex(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
|
||||
FilterPair pair = request.ValidateFilter(statusCode, comment);
|
||||
if (!(pair.filter && request.ValidateNumber("filterIndex", statusCode, comment, 0, 8192)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -265,7 +292,8 @@ RequestResult RequestHandler::SetSourceFilterIndex(const Request &request)
|
||||
/**
|
||||
* Sets the settings of a source filter.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source the filter is on
|
||||
* @requestField ?sourceName | String | Name of the source the filter is on
|
||||
* @requestField ?sourceUuid | String | UUID of the source the filter is on
|
||||
* @requestField filterName | String | Name of the filter to set the settings of
|
||||
* @requestField filterSettings | Object | Object of settings to apply
|
||||
* @requestField ?overlay | Boolean | True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. | true
|
||||
@ -281,7 +309,7 @@ RequestResult RequestHandler::SetSourceFilterSettings(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
|
||||
FilterPair pair = request.ValidateFilter(statusCode, comment);
|
||||
if (!(pair.filter && request.ValidateObject("filterSettings", statusCode, comment, true)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -313,7 +341,8 @@ RequestResult RequestHandler::SetSourceFilterSettings(const Request &request)
|
||||
/**
|
||||
* Sets the enable state of a source filter.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source the filter is on
|
||||
* @requestField ?sourceName | String | Name of the source the filter is on
|
||||
* @requestField ?sourceUuid | String | UUID of the source the filter is on
|
||||
* @requestField filterName | String | Name of the filter
|
||||
* @requestField filterEnabled | Boolean | New enable state of the filter
|
||||
*
|
||||
@ -328,7 +357,7 @@ RequestResult RequestHandler::SetSourceFilterEnabled(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
|
||||
FilterPair pair = request.ValidateFilter(statusCode, comment);
|
||||
if (!(pair.filter && request.ValidateBoolean("filterEnabled", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
|
@ -211,12 +211,14 @@ RequestResult RequestHandler::CallVendorRequest(const Request &request)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of all hotkey names in OBS
|
||||
* Gets an array of all hotkey names in OBS.
|
||||
*
|
||||
* Note: Hotkey functionality in obs-websocket comes as-is, and we do not guarantee support if things are broken. In 9/10 usages of hotkey requests, there exists a better, more reliable method via other requests.
|
||||
*
|
||||
* @responseField hotkeys | Array<String> | Array of hotkey names
|
||||
*
|
||||
* @requestType GetHotkeyList
|
||||
* @complexity 3
|
||||
* @complexity 4
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @category general
|
||||
@ -230,12 +232,15 @@ RequestResult RequestHandler::GetHotkeyList(const Request &)
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a hotkey using its name. See `GetHotkeyList`
|
||||
* Triggers a hotkey using its name. See `GetHotkeyList`.
|
||||
*
|
||||
* Note: Hotkey functionality in obs-websocket comes as-is, and we do not guarantee support if things are broken. In 9/10 usages of hotkey requests, there exists a better, more reliable method via other requests.
|
||||
*
|
||||
* @requestField hotkeyName | String | Name of the hotkey to trigger
|
||||
* @requestField ?contextName | String | Name of context of the hotkey to trigger
|
||||
*
|
||||
* @requestType TriggerHotkeyByName
|
||||
* @complexity 3
|
||||
* @complexity 4
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @category general
|
||||
@ -248,11 +253,20 @@ RequestResult RequestHandler::TriggerHotkeyByName(const Request &request)
|
||||
if (!request.ValidateString("hotkeyName", statusCode, comment))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
obs_hotkey_t *hotkey = Utils::Obs::SearchHelper::GetHotkeyByName(request.RequestData["hotkeyName"]);
|
||||
std::string contextName;
|
||||
if (request.Contains("contextName")) {
|
||||
if (!request.ValidateOptionalString("contextName", statusCode, comment))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
contextName = request.RequestData["contextName"];
|
||||
}
|
||||
|
||||
obs_hotkey_t *hotkey = Utils::Obs::SearchHelper::GetHotkeyByName(request.RequestData["hotkeyName"], contextName);
|
||||
if (!hotkey)
|
||||
return RequestResult::Error(RequestStatus::ResourceNotFound, "No hotkeys were found by that name.");
|
||||
|
||||
obs_hotkey_trigger_routed_callback(obs_hotkey_get_id(hotkey), true);
|
||||
obs_hotkey_trigger_routed_callback(obs_hotkey_get_id(hotkey), false);
|
||||
|
||||
return RequestResult::Success();
|
||||
}
|
||||
@ -260,6 +274,8 @@ RequestResult RequestHandler::TriggerHotkeyByName(const Request &request)
|
||||
/**
|
||||
* Triggers a hotkey using a sequence of keys.
|
||||
*
|
||||
* Note: Hotkey functionality in obs-websocket comes as-is, and we do not guarantee support if things are broken. In 9/10 usages of hotkey requests, there exists a better, more reliable method via other requests.
|
||||
*
|
||||
* @requestField ?keyId | String | The OBS key ID to use. See https://github.com/obsproject/obs-studio/blob/master/libobs/obs-hotkeys.h | Not pressed
|
||||
* @requestField ?keyModifiers | Object | Object containing key modifiers to apply | Ignored
|
||||
* @requestField ?keyModifiers.shift | Boolean | Press Shift | Not pressed
|
||||
|
@ -123,12 +123,14 @@ RequestResult RequestHandler::GetSpecialInputs(const Request &)
|
||||
/**
|
||||
* Creates a new input, adding it as a scene item to the specified scene.
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene to add the input to as a scene item
|
||||
* @requestField ?sceneName | String | Name of the scene to add the input to as a scene item
|
||||
* @requestField ?sceneUuid | String | UUID of the scene to add the input to as a scene item
|
||||
* @requestField inputName | String | Name of the new input to created
|
||||
* @requestField inputKind | String | The kind of input to be created
|
||||
* @requestField ?inputSettings | Object | Settings object to initialize the input with | Default settings used
|
||||
* @requestField ?sceneItemEnabled | Boolean | Whether to set the created scene item to enabled or disabled | True
|
||||
*
|
||||
* @responseField inputUuid | String | UUID of the newly created input
|
||||
* @responseField sceneItemId | Number | ID of the newly created scene item
|
||||
*
|
||||
* @requestType CreateInput
|
||||
@ -142,7 +144,7 @@ RequestResult RequestHandler::CreateInput(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease sceneSource = request.ValidateScene("sceneName", statusCode, comment);
|
||||
OBSSourceAutoRelease sceneSource = request.ValidateScene(statusCode, comment);
|
||||
if (!(sceneSource && request.ValidateString("inputName", statusCode, comment) &&
|
||||
request.ValidateString("inputKind", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
@ -185,6 +187,7 @@ RequestResult RequestHandler::CreateInput(const Request &request)
|
||||
return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Creation of the input or scene item failed.");
|
||||
|
||||
json responseData;
|
||||
responseData["inputUuid"] = obs_source_get_uuid(obs_sceneitem_get_source(sceneItem));
|
||||
responseData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
@ -194,7 +197,8 @@ RequestResult RequestHandler::CreateInput(const Request &request)
|
||||
*
|
||||
* Note: Will immediately remove all associated scene items.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to remove
|
||||
* @requestField ?inputName | String | Name of the input to remove
|
||||
* @requestField ?inputUuid | String | UUID of the input to remove
|
||||
*
|
||||
* @requestType RemoveInput
|
||||
* @complexity 2
|
||||
@ -207,7 +211,7 @@ RequestResult RequestHandler::RemoveInput(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -222,7 +226,8 @@ RequestResult RequestHandler::RemoveInput(const Request &request)
|
||||
/**
|
||||
* Sets the name of an input (rename).
|
||||
*
|
||||
* @requestField inputName | String | Current input name
|
||||
* @requestField ?inputName | String | Current input name
|
||||
* @requestField ?inputUuid | String | Current input UUID
|
||||
* @requestField newInputName | String | New name for the input
|
||||
*
|
||||
* @requestType SetInputName
|
||||
@ -236,7 +241,7 @@ RequestResult RequestHandler::SetInputName(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!(input && request.ValidateString("newInputName", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -292,7 +297,8 @@ RequestResult RequestHandler::GetInputDefaultSettings(const Request &request)
|
||||
*
|
||||
* Note: Does not include defaults. To create the entire settings object, overlay `inputSettings` over the `defaultInputSettings` provided by `GetInputDefaultSettings`.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to get the settings of
|
||||
* @requestField ?inputName | String | Name of the input to get the settings of
|
||||
* @requestField ?inputUuid | String | UUID of the input to get the settings of
|
||||
*
|
||||
* @responseField inputSettings | Object | Object of settings for the input
|
||||
* @responseField inputKind | String | The kind of the input
|
||||
@ -308,7 +314,7 @@ RequestResult RequestHandler::GetInputSettings(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -323,7 +329,8 @@ RequestResult RequestHandler::GetInputSettings(const Request &request)
|
||||
/**
|
||||
* Sets the settings of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to set the settings of
|
||||
* @requestField ?inputName | String | Name of the input to set the settings of
|
||||
* @requestField ?inputUuid | String | UUID of the input to set the settings of
|
||||
* @requestField inputSettings | Object | Object of settings to apply
|
||||
* @requestField ?overlay | Boolean | True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. | true
|
||||
*
|
||||
@ -338,7 +345,7 @@ RequestResult RequestHandler::SetInputSettings(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!(input && request.ValidateObject("inputSettings", statusCode, comment, true)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -373,7 +380,8 @@ RequestResult RequestHandler::SetInputSettings(const Request &request)
|
||||
/**
|
||||
* Gets the audio mute state of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of input to get the mute state of
|
||||
* @requestField ?inputName | String | Name of input to get the mute state of
|
||||
* @requestField ?inputUuid | String | UUID of input to get the mute state of
|
||||
*
|
||||
* @responseField inputMuted | Boolean | Whether the input is muted
|
||||
*
|
||||
@ -388,7 +396,7 @@ RequestResult RequestHandler::GetInputMute(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -403,7 +411,8 @@ RequestResult RequestHandler::GetInputMute(const Request &request)
|
||||
/**
|
||||
* Sets the audio mute state of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to set the mute state of
|
||||
* @requestField ?inputName | String | Name of the input to set the mute state of
|
||||
* @requestField ?inputUuid | String | UUID of the input to set the mute state of
|
||||
* @requestField inputMuted | Boolean | Whether to mute the input or not
|
||||
*
|
||||
* @requestType SetInputMute
|
||||
@ -417,7 +426,7 @@ RequestResult RequestHandler::SetInputMute(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!(input && request.ValidateBoolean("inputMuted", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -432,7 +441,8 @@ RequestResult RequestHandler::SetInputMute(const Request &request)
|
||||
/**
|
||||
* Toggles the audio mute state of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to toggle the mute state of
|
||||
* @requestField ?inputName | String | Name of the input to toggle the mute state of
|
||||
* @requestField ?inputUuid | String | UUID of the input to toggle the mute state of
|
||||
*
|
||||
* @responseField inputMuted | Boolean | Whether the input has been muted or unmuted
|
||||
*
|
||||
@ -447,7 +457,7 @@ RequestResult RequestHandler::ToggleInputMute(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -465,7 +475,8 @@ RequestResult RequestHandler::ToggleInputMute(const Request &request)
|
||||
/**
|
||||
* Gets the current volume setting of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to get the volume of
|
||||
* @requestField ?inputName | String | Name of the input to get the volume of
|
||||
* @requestField ?inputUuid | String | UUID of the input to get the volume of
|
||||
*
|
||||
* @responseField inputVolumeMul | Number | Volume setting in mul
|
||||
* @responseField inputVolumeDb | Number | Volume setting in dB
|
||||
@ -481,7 +492,7 @@ RequestResult RequestHandler::GetInputVolume(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -502,7 +513,8 @@ RequestResult RequestHandler::GetInputVolume(const Request &request)
|
||||
/**
|
||||
* Sets the volume setting of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to set the volume of
|
||||
* @requestField ?inputName | String | Name of the input to set the volume of
|
||||
* @requestField ?inputUuid | String | UUID of the input to set the volume of
|
||||
* @requestField ?inputVolumeMul | Number | Volume setting in mul | >= 0, <= 20 | `inputVolumeDb` should be specified
|
||||
* @requestField ?inputVolumeDb | Number | Volume setting in dB | >= -100, <= 26 | `inputVolumeMul` should be specified
|
||||
*
|
||||
@ -517,7 +529,7 @@ RequestResult RequestHandler::SetInputVolume(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -552,7 +564,8 @@ RequestResult RequestHandler::SetInputVolume(const Request &request)
|
||||
/**
|
||||
* Gets the audio balance of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to get the audio balance of
|
||||
* @requestField ?inputName | String | Name of the input to get the audio balance of
|
||||
* @requestField ?inputUuid | String | UUID of the input to get the audio balance of
|
||||
*
|
||||
* @responseField inputAudioBalance | Number | Audio balance value from 0.0-1.0
|
||||
*
|
||||
@ -567,7 +580,7 @@ RequestResult RequestHandler::GetInputAudioBalance(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -583,7 +596,8 @@ RequestResult RequestHandler::GetInputAudioBalance(const Request &request)
|
||||
/**
|
||||
* Sets the audio balance of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to set the audio balance of
|
||||
* @requestField ?inputName | String | Name of the input to set the audio balance of
|
||||
* @requestField ?inputUuid | String | UUID of the input to set the audio balance of
|
||||
* @requestField inputAudioBalance | Number | New audio balance value | >= 0.0, <= 1.0
|
||||
*
|
||||
* @requestType SetInputAudioBalance
|
||||
@ -597,7 +611,7 @@ RequestResult RequestHandler::SetInputAudioBalance(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!(input && request.ValidateNumber("inputAudioBalance", statusCode, comment, 0.0, 1.0)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -615,7 +629,8 @@ RequestResult RequestHandler::SetInputAudioBalance(const Request &request)
|
||||
*
|
||||
* Note: The audio sync offset can be negative too!
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to get the audio sync offset of
|
||||
* @requestField ?inputName | String | Name of the input to get the audio sync offset of
|
||||
* @requestField ?inputUuid | String | UUID of the input to get the audio sync offset of
|
||||
*
|
||||
* @responseField inputAudioSyncOffset | Number | Audio sync offset in milliseconds
|
||||
*
|
||||
@ -630,7 +645,7 @@ RequestResult RequestHandler::GetInputAudioSyncOffset(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -647,7 +662,8 @@ RequestResult RequestHandler::GetInputAudioSyncOffset(const Request &request)
|
||||
/**
|
||||
* Sets the audio sync offset of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to set the audio sync offset of
|
||||
* @requestField ?inputName | String | Name of the input to set the audio sync offset of
|
||||
* @requestField ?inputUuid | String | UUID of the input to set the audio sync offset of
|
||||
* @requestField inputAudioSyncOffset | Number | New audio sync offset in milliseconds | >= -950, <= 20000
|
||||
*
|
||||
* @requestType SetInputAudioSyncOffset
|
||||
@ -661,7 +677,7 @@ RequestResult RequestHandler::SetInputAudioSyncOffset(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!(input && request.ValidateNumber("inputAudioSyncOffset", statusCode, comment, -950, 20000)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -683,7 +699,8 @@ RequestResult RequestHandler::SetInputAudioSyncOffset(const Request &request)
|
||||
* - `OBS_MONITORING_TYPE_MONITOR_ONLY`
|
||||
* - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT`
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to get the audio monitor type of
|
||||
* @requestField ?inputName | String | Name of the input to get the audio monitor type of
|
||||
* @requestField ?inputUuid | String | UUID of the input to get the audio monitor type of
|
||||
*
|
||||
* @responseField monitorType | String | Audio monitor type
|
||||
*
|
||||
@ -698,7 +715,7 @@ RequestResult RequestHandler::GetInputAudioMonitorType(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -714,7 +731,8 @@ RequestResult RequestHandler::GetInputAudioMonitorType(const Request &request)
|
||||
/**
|
||||
* Sets the audio monitor type of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to set the audio monitor type of
|
||||
* @requestField ?inputName | String | Name of the input to set the audio monitor type of
|
||||
* @requestField ?inputUuid | String | UUID of the input to set the audio monitor type of
|
||||
* @requestField monitorType | String | Audio monitor type
|
||||
*
|
||||
* @requestType SetInputAudioMonitorType
|
||||
@ -728,7 +746,7 @@ RequestResult RequestHandler::SetInputAudioMonitorType(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!(input && request.ValidateString("monitorType", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -759,7 +777,8 @@ RequestResult RequestHandler::SetInputAudioMonitorType(const Request &request)
|
||||
/**
|
||||
* Gets the enable state of all audio tracks of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input
|
||||
* @requestField ?inputName | String | Name of the input
|
||||
* @requestField ?inputUuid | String | UUID of the input
|
||||
*
|
||||
* @responseField inputAudioTracks | Object | Object of audio tracks and associated enable states
|
||||
*
|
||||
@ -774,7 +793,7 @@ RequestResult RequestHandler::GetInputAudioTracks(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -797,7 +816,8 @@ RequestResult RequestHandler::GetInputAudioTracks(const Request &request)
|
||||
/**
|
||||
* Sets the enable state of audio tracks of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input
|
||||
* @requestField ?inputName | String | Name of the input
|
||||
* @requestField ?inputUuid | String | UUID of the input
|
||||
* @requestField inputAudioTracks | Object | Track settings to apply
|
||||
*
|
||||
* @requestType SetInputAudioTracks
|
||||
@ -811,7 +831,7 @@ RequestResult RequestHandler::SetInputAudioTracks(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input || !request.ValidateObject("inputAudioTracks", statusCode, comment))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -851,7 +871,8 @@ RequestResult RequestHandler::SetInputAudioTracks(const Request &request)
|
||||
*
|
||||
* Note: Use this in cases where an input provides a dynamic, selectable list of items. For example, display capture, where it provides a list of available displays.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input
|
||||
* @requestField ?inputName | String | Name of the input
|
||||
* @requestField ?inputUuid | String | UUID of the input
|
||||
* @requestField propertyName | String | Name of the list property to get the items of
|
||||
*
|
||||
* @responseField propertyItems | Array<Object> | Array of items in the list property
|
||||
@ -867,7 +888,7 @@ RequestResult RequestHandler::GetInputPropertiesListPropertyItems(const Request
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!(input && request.ValidateString("propertyName", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -895,7 +916,8 @@ RequestResult RequestHandler::GetInputPropertiesListPropertyItems(const Request
|
||||
*
|
||||
* Note: Use this in cases where there is a button in the properties of an input that cannot be accessed in any other way. For example, browser sources, where there is a refresh button.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input
|
||||
* @requestField ?inputName | String | Name of the input
|
||||
* @requestField ?inputUuid | String | UUID of the input
|
||||
* @requestField propertyName | String | Name of the button property to press
|
||||
*
|
||||
* @requestType PressInputPropertiesButton
|
||||
@ -909,7 +931,7 @@ RequestResult RequestHandler::PressInputPropertiesButton(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!(input && request.ValidateString("propertyName", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
|
@ -39,7 +39,8 @@ bool IsMediaTimeValid(obs_source_t *input)
|
||||
* - `OBS_MEDIA_STATE_ENDED`
|
||||
* - `OBS_MEDIA_STATE_ERROR`
|
||||
*
|
||||
* @requestField inputName | String | Name of the media input
|
||||
* @requestField ?inputName | String | Name of the media input
|
||||
* @requestField ?inputUuid | String | UUID of the media input
|
||||
*
|
||||
* @responseField mediaState | String | State of the media input
|
||||
* @responseField mediaDuration | Number | Total duration of the playing media in milliseconds. `null` if not playing
|
||||
@ -56,7 +57,7 @@ RequestResult RequestHandler::GetMediaInputStatus(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -80,7 +81,8 @@ RequestResult RequestHandler::GetMediaInputStatus(const Request &request)
|
||||
*
|
||||
* This request does not perform bounds checking of the cursor position.
|
||||
*
|
||||
* @requestField inputName | String | Name of the media input
|
||||
* @requestField ?inputName | String | Name of the media input
|
||||
* @requestField ?inputUuid | String | UUID of the media input
|
||||
* @requestField mediaCursor | Number | New cursor position to set | >= 0
|
||||
*
|
||||
* @requestType SetMediaInputCursor
|
||||
@ -94,7 +96,7 @@ RequestResult RequestHandler::SetMediaInputCursor(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!(input && request.ValidateNumber("mediaCursor", statusCode, comment, 0)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -115,7 +117,8 @@ RequestResult RequestHandler::SetMediaInputCursor(const Request &request)
|
||||
*
|
||||
* This request does not perform bounds checking of the cursor position.
|
||||
*
|
||||
* @requestField inputName | String | Name of the media input
|
||||
* @requestField ?inputName | String | Name of the media input
|
||||
* @requestField ?inputUuid | String | UUID of the media input
|
||||
* @requestField mediaCursorOffset | Number | Value to offset the current cursor position by | None
|
||||
*
|
||||
* @requestType OffsetMediaInputCursor
|
||||
@ -129,7 +132,7 @@ RequestResult RequestHandler::OffsetMediaInputCursor(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!(input && request.ValidateNumber("mediaCursorOffset", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -151,7 +154,8 @@ RequestResult RequestHandler::OffsetMediaInputCursor(const Request &request)
|
||||
/**
|
||||
* Triggers an action on a media input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the media input
|
||||
* @requestField ?inputName | String | Name of the media input
|
||||
* @requestField ?inputUuid | String | UUID of the media input
|
||||
* @requestField mediaAction | String | Identifier of the `ObsMediaInputAction` enum
|
||||
*
|
||||
* @requestType TriggerMediaInputAction
|
||||
@ -165,7 +169,7 @@ RequestResult RequestHandler::TriggerMediaInputAction(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!(input && request.ValidateString("mediaAction", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
|
@ -21,11 +21,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
|
||||
static bool VirtualCamAvailable()
|
||||
{
|
||||
OBSDataAutoRelease privateData = obs_get_private_data();
|
||||
if (!privateData)
|
||||
return false;
|
||||
|
||||
return obs_data_get_bool(privateData, "vcamEnabled");
|
||||
OBSOutputAutoRelease output = obs_frontend_get_virtualcam_output();
|
||||
return output != nullptr;
|
||||
}
|
||||
|
||||
static bool ReplayBufferAvailable()
|
||||
|
@ -54,6 +54,8 @@ RequestResult RequestHandler::GetRecordStatus(const Request &)
|
||||
/**
|
||||
* Toggles the status of the record output.
|
||||
*
|
||||
* @responseField outputActive | Boolean | The new active state of the output
|
||||
*
|
||||
* @requestType ToggleRecord
|
||||
* @complexity 1
|
||||
* @rpcVersion -1
|
||||
@ -187,3 +189,60 @@ RequestResult RequestHandler::ResumeRecord(const Request &)
|
||||
|
||||
return RequestResult::Success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the current file being recorded into a new file.
|
||||
*
|
||||
* @requestType SplitRecordFile
|
||||
* @complexity 2
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.5.0
|
||||
* @api requests
|
||||
* @category record
|
||||
*/
|
||||
RequestResult RequestHandler::SplitRecordFile(const Request &)
|
||||
{
|
||||
if (!obs_frontend_recording_active())
|
||||
return RequestResult::Error(RequestStatus::OutputNotRunning);
|
||||
|
||||
if (!obs_frontend_recording_split_file())
|
||||
return RequestResult::Error(RequestStatus::RequestProcessingFailed,
|
||||
"Verify that file splitting is enabled in the output settings.");
|
||||
|
||||
return RequestResult::Success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new chapter marker to the file currently being recorded.
|
||||
*
|
||||
* Note: As of OBS 30.2.0, the only file format supporting this feature is Hybrid MP4.
|
||||
*
|
||||
* @requestField ?chapterName | String | Name of the new chapter
|
||||
*
|
||||
* @requestType CreateRecordChapter
|
||||
* @complexity 2
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.5.0
|
||||
* @api requests
|
||||
* @category record
|
||||
*/
|
||||
RequestResult RequestHandler::CreateRecordChapter(const Request &request)
|
||||
{
|
||||
std::string chapterName;
|
||||
if (request.Contains("chapterName")) {
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
if (!request.ValidateOptionalString("chapterName", statusCode, comment))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
chapterName = request.RequestData["chapterName"];
|
||||
}
|
||||
|
||||
if (!obs_frontend_recording_active())
|
||||
return RequestResult::Error(RequestStatus::OutputNotRunning);
|
||||
|
||||
if (!obs_frontend_recording_add_chapter(chapterName.empty() ? nullptr : chapterName.c_str()))
|
||||
return RequestResult::Error(RequestStatus::RequestProcessingFailed,
|
||||
"Verify that the output being used supports chapter markers.");
|
||||
|
||||
return RequestResult::Success();
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
*
|
||||
* Scenes only
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene to get the items of
|
||||
* @requestField ?sceneName | String | Name of the scene to get the items of
|
||||
* @requestField ?sceneUuid | String | UUID of the scene to get the items of
|
||||
*
|
||||
* @responseField sceneItems | Array<Object> | Array of scene items in the scene
|
||||
*
|
||||
@ -39,7 +40,7 @@ RequestResult RequestHandler::GetSceneItemList(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
|
||||
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment);
|
||||
if (!scene)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -56,7 +57,8 @@ RequestResult RequestHandler::GetSceneItemList(const Request &request)
|
||||
*
|
||||
* Groups only
|
||||
*
|
||||
* @requestField sceneName | String | Name of the group to get the items of
|
||||
* @requestField ?sceneName | String | Name of the group to get the items of
|
||||
* @requestField ?sceneUuid | String | UUID of the group to get the items of
|
||||
*
|
||||
* @responseField sceneItems | Array<Object> | Array of scene items in the group
|
||||
*
|
||||
@ -71,7 +73,7 @@ RequestResult RequestHandler::GetGroupSceneItemList(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_GROUP_ONLY);
|
||||
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_GROUP_ONLY);
|
||||
if (!scene)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -86,7 +88,8 @@ RequestResult RequestHandler::GetGroupSceneItemList(const Request &request)
|
||||
*
|
||||
* Scenes and Groups
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene or group to search in
|
||||
* @requestField ?sceneName | String | Name of the scene or group to search in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene or group to search in
|
||||
* @requestField sourceName | String | Name of the source to find
|
||||
* @requestField ?searchOffset | Number | Number of matches to skip during search. >= 0 means first forward. -1 means last (top) item | >= -1 | 0
|
||||
*
|
||||
@ -103,9 +106,8 @@ RequestResult RequestHandler::GetSceneItemId(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneAutoRelease scene =
|
||||
request.ValidateScene2("sceneName", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!(scene && request.ValidateString("sourceName", statusCode, comment)))
|
||||
OBSSceneAutoRelease scene = request.ValidateScene2(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!(scene && request.ValidateString("sourceName", statusCode, comment))) // TODO: Source UUID support
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
std::string sourceName = request.RequestData["sourceName"];
|
||||
@ -128,13 +130,49 @@ RequestResult RequestHandler::GetSceneItemId(const Request &request)
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source associated with a scene item.
|
||||
*
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
*
|
||||
* @responseField sourceName | String | Name of the source associated with the scene item
|
||||
* @responseField sourceUuid | String | UUID of the source associated with the scene item
|
||||
*
|
||||
* @requestType GetSceneItemSource
|
||||
* @complexity 3
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.4.0
|
||||
* @api requests
|
||||
* @category scene items
|
||||
*/
|
||||
RequestResult RequestHandler::GetSceneItemSource(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem(statusCode, comment);
|
||||
if (!sceneItem)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
OBSSource source = obs_sceneitem_get_source(sceneItem);
|
||||
|
||||
json responseData;
|
||||
responseData["sourceName"] = obs_source_get_name(source);
|
||||
responseData["sourceUuid"] = obs_source_get_uuid(source);
|
||||
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new scene item using a source.
|
||||
*
|
||||
* Scenes only
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene to create the new item in
|
||||
* @requestField sourceName | String | Name of the source to add to the scene
|
||||
* @requestField ?sceneName | String | Name of the scene to create the new item in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene to create the new item in
|
||||
* @requestField ?sourceName | String | Name of the source to add to the scene
|
||||
* @requestField ?sourceUuid | String | UUID of the source to add to the scene
|
||||
* @requestField ?sceneItemEnabled | Boolean | Enable state to apply to the scene item on creation | True
|
||||
*
|
||||
* @responseField sceneItemId | Number | Numeric ID of the scene item
|
||||
@ -150,17 +188,17 @@ RequestResult RequestHandler::CreateSceneItem(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease sceneSource = request.ValidateScene("sceneName", statusCode, comment);
|
||||
OBSSourceAutoRelease sceneSource = request.ValidateScene(statusCode, comment);
|
||||
if (!sceneSource)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
OBSScene scene = obs_scene_from_source(sceneSource);
|
||||
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment);
|
||||
if (!source)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
if (request.RequestData["sceneName"] == request.RequestData["sourceName"])
|
||||
if (sceneSource == source)
|
||||
return RequestResult::Error(RequestStatus::CannotAct, "You cannot create scene item of a scene within itself.");
|
||||
|
||||
bool sceneItemEnabled = true;
|
||||
@ -185,7 +223,8 @@ RequestResult RequestHandler::CreateSceneItem(const Request &request)
|
||||
*
|
||||
* Scenes only
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
*
|
||||
* @requestType RemoveSceneItem
|
||||
@ -199,7 +238,7 @@ RequestResult RequestHandler::RemoveSceneItem(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment);
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem(statusCode, comment);
|
||||
if (!sceneItem)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -214,9 +253,11 @@ RequestResult RequestHandler::RemoveSceneItem(const Request &request)
|
||||
*
|
||||
* Scenes only
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
* @requestField ?destinationSceneName | String | Name of the scene to create the duplicated item in | `sceneName` is assumed
|
||||
* @requestField ?destinationSceneName | String | Name of the scene to create the duplicated item in | From scene is assumed
|
||||
* @requestField ?destinationSceneUuid | String | UUID of the scene to create the duplicated item in | From scene is assumed
|
||||
*
|
||||
* @responseField sceneItemId | Number | Numeric ID of the duplicated scene item
|
||||
*
|
||||
@ -231,16 +272,26 @@ RequestResult RequestHandler::DuplicateSceneItem(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment);
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem(statusCode, comment);
|
||||
if (!sceneItem)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
// Get destination scene
|
||||
obs_scene_t *destinationScene;
|
||||
if (request.Contains("destinationSceneName")) {
|
||||
destinationScene = request.ValidateScene2("destinationSceneName", statusCode, comment);
|
||||
if (!destinationScene)
|
||||
OBSSourceAutoRelease destinationSceneSource =
|
||||
request.ValidateSource("destinationSceneName", "destinationSceneUuid", statusCode, comment);
|
||||
if (!destinationSceneSource)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
// Reimplementation of ValidateScene2
|
||||
if (obs_source_get_type(destinationSceneSource) != OBS_SOURCE_TYPE_SCENE)
|
||||
return RequestResult::Error(RequestStatus::InvalidResourceType, "The specified source is not a scene.");
|
||||
if (obs_source_is_group(destinationSceneSource))
|
||||
return RequestResult::Error(RequestStatus::InvalidResourceType,
|
||||
"The specified source is not a scene. (Is group)");
|
||||
|
||||
destinationScene = obs_scene_get_ref(obs_scene_from_source(destinationSceneSource));
|
||||
} else {
|
||||
destinationScene = obs_scene_get_ref(obs_sceneitem_get_scene(sceneItem));
|
||||
if (!destinationScene)
|
||||
@ -258,7 +309,7 @@ RequestResult RequestHandler::DuplicateSceneItem(const Request &request)
|
||||
bool sceneItemEnabled = obs_sceneitem_visible(sceneItem);
|
||||
obs_transform_info sceneItemTransform;
|
||||
obs_sceneitem_crop sceneItemCrop;
|
||||
obs_sceneitem_get_info(sceneItem, &sceneItemTransform);
|
||||
obs_sceneitem_get_info2(sceneItem, &sceneItemTransform);
|
||||
obs_sceneitem_get_crop(sceneItem, &sceneItemCrop);
|
||||
|
||||
// Create the new item
|
||||
@ -279,7 +330,8 @@ RequestResult RequestHandler::DuplicateSceneItem(const Request &request)
|
||||
*
|
||||
* Scenes and Groups
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
*
|
||||
* @responseField sceneItemTransform | Object | Object containing scene item transform info
|
||||
@ -295,8 +347,8 @@ RequestResult RequestHandler::GetSceneItemTransform(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
|
||||
OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
OBSSceneItemAutoRelease sceneItem =
|
||||
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!sceneItem)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -309,7 +361,8 @@ RequestResult RequestHandler::GetSceneItemTransform(const Request &request)
|
||||
/**
|
||||
* Sets the transform and crop info of a scene item.
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
* @requestField sceneItemTransform | Object | Object containing scene item transform info to update
|
||||
*
|
||||
@ -324,8 +377,8 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
|
||||
OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
OBSSceneItemAutoRelease sceneItem =
|
||||
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!(sceneItem && request.ValidateObject("sceneItemTransform", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -336,7 +389,7 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request &request)
|
||||
bool cropChanged = false;
|
||||
obs_transform_info sceneItemTransform;
|
||||
obs_sceneitem_crop sceneItemCrop;
|
||||
obs_sceneitem_get_info(sceneItem, &sceneItemTransform);
|
||||
obs_sceneitem_get_info2(sceneItem, &sceneItemTransform);
|
||||
obs_sceneitem_get_crop(sceneItem, &sceneItemCrop);
|
||||
|
||||
OBSSource source = obs_sceneitem_get_source(sceneItem);
|
||||
@ -449,11 +502,18 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request &request)
|
||||
cropChanged = true;
|
||||
}
|
||||
|
||||
if (r.Contains("cropToBounds")) {
|
||||
if (!r.ValidateOptionalBoolean("cropToBounds", statusCode, comment))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
sceneItemTransform.crop_to_bounds = r.RequestData["cropToBounds"];
|
||||
transformChanged = true;
|
||||
}
|
||||
|
||||
if (!transformChanged && !cropChanged)
|
||||
return RequestResult::Error(RequestStatus::CannotAct, "You have not provided any valid transform changes.");
|
||||
|
||||
if (transformChanged)
|
||||
obs_sceneitem_set_info(sceneItem, &sceneItemTransform);
|
||||
obs_sceneitem_set_info2(sceneItem, &sceneItemTransform);
|
||||
|
||||
if (cropChanged)
|
||||
obs_sceneitem_set_crop(sceneItem, &sceneItemCrop);
|
||||
@ -466,7 +526,8 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request &request)
|
||||
*
|
||||
* Scenes and Groups
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
*
|
||||
* @responseField sceneItemEnabled | Boolean | Whether the scene item is enabled. `true` for enabled, `false` for disabled
|
||||
@ -482,8 +543,8 @@ RequestResult RequestHandler::GetSceneItemEnabled(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
|
||||
OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
OBSSceneItemAutoRelease sceneItem =
|
||||
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!sceneItem)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -498,7 +559,8 @@ RequestResult RequestHandler::GetSceneItemEnabled(const Request &request)
|
||||
*
|
||||
* Scenes and Groups
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
* @requestField sceneItemEnabled | Boolean | New enable state of the scene item
|
||||
*
|
||||
@ -513,8 +575,8 @@ RequestResult RequestHandler::SetSceneItemEnabled(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
|
||||
OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
OBSSceneItemAutoRelease sceneItem =
|
||||
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!(sceneItem && request.ValidateBoolean("sceneItemEnabled", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -530,7 +592,8 @@ RequestResult RequestHandler::SetSceneItemEnabled(const Request &request)
|
||||
*
|
||||
* Scenes and Groups
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
*
|
||||
* @responseField sceneItemLocked | Boolean | Whether the scene item is locked. `true` for locked, `false` for unlocked
|
||||
@ -546,8 +609,8 @@ RequestResult RequestHandler::GetSceneItemLocked(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
|
||||
OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
OBSSceneItemAutoRelease sceneItem =
|
||||
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!sceneItem)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -562,8 +625,9 @@ RequestResult RequestHandler::GetSceneItemLocked(const Request &request)
|
||||
*
|
||||
* Scenes and Group
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
* @requestField sceneItemLocked | Boolean | New lock state of the scene item
|
||||
*
|
||||
* @requestType SetSceneItemLocked
|
||||
@ -577,8 +641,8 @@ RequestResult RequestHandler::SetSceneItemLocked(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
|
||||
OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
OBSSceneItemAutoRelease sceneItem =
|
||||
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!(sceneItem && request.ValidateBoolean("sceneItemLocked", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -596,7 +660,8 @@ RequestResult RequestHandler::SetSceneItemLocked(const Request &request)
|
||||
*
|
||||
* Scenes and Groups
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
*
|
||||
* @responseField sceneItemIndex | Number | Index position of the scene item
|
||||
@ -612,8 +677,8 @@ RequestResult RequestHandler::GetSceneItemIndex(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
|
||||
OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
OBSSceneItemAutoRelease sceneItem =
|
||||
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!sceneItem)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -628,7 +693,8 @@ RequestResult RequestHandler::GetSceneItemIndex(const Request &request)
|
||||
*
|
||||
* Scenes and Groups
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
* @requestField sceneItemIndex | Number | New index position of the scene item | >= 0
|
||||
*
|
||||
@ -643,8 +709,8 @@ RequestResult RequestHandler::SetSceneItemIndex(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
|
||||
OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
OBSSceneItemAutoRelease sceneItem =
|
||||
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!(sceneItem && request.ValidateNumber("sceneItemIndex", statusCode, comment, 0, 8192)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -670,7 +736,8 @@ RequestResult RequestHandler::SetSceneItemIndex(const Request &request)
|
||||
*
|
||||
* Scenes and Groups
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
*
|
||||
* @responseField sceneItemBlendMode | String | Current blend mode
|
||||
@ -686,8 +753,8 @@ RequestResult RequestHandler::GetSceneItemBlendMode(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
|
||||
OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
OBSSceneItemAutoRelease sceneItem =
|
||||
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!sceneItem)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -704,7 +771,8 @@ RequestResult RequestHandler::GetSceneItemBlendMode(const Request &request)
|
||||
*
|
||||
* Scenes and Groups
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneName | String | Name of the scene the item is in
|
||||
* @requestField ?sceneUuid | String | UUID of the scene the item is in
|
||||
* @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0
|
||||
* @requestField sceneItemBlendMode | String | New blend mode
|
||||
*
|
||||
@ -719,8 +787,8 @@ RequestResult RequestHandler::SetSceneItemBlendMode(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
|
||||
OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
OBSSceneItemAutoRelease sceneItem =
|
||||
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!(sceneItem && request.ValidateString("sceneItemBlendMode", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -739,8 +807,8 @@ RequestResult RequestHandler::GetSceneItemPrivateSettings(const Request &request
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
|
||||
OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
OBSSceneItemAutoRelease sceneItem =
|
||||
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!sceneItem)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -757,8 +825,8 @@ RequestResult RequestHandler::SetSceneItemPrivateSettings(const Request &request
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
|
||||
OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
OBSSceneItemAutoRelease sceneItem =
|
||||
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||
if (!sceneItem || !request.ValidateObject("sceneItemSettings", statusCode, comment, true))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
|
@ -22,8 +22,10 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
/**
|
||||
* Gets an array of all scenes in OBS.
|
||||
*
|
||||
* @responseField currentProgramSceneName | String | Current program scene
|
||||
* @responseField currentPreviewSceneName | String | Current preview scene. `null` if not in studio mode
|
||||
* @responseField currentProgramSceneName | String | Current program scene name. Can be `null` if internal state desync
|
||||
* @responseField currentProgramSceneUuid | String | Current program scene UUID. Can be `null` if internal state desync
|
||||
* @responseField currentPreviewSceneName | String | Current preview scene name. `null` if not in studio mode
|
||||
* @responseField currentPreviewSceneUuid | String | Current preview scene UUID. `null` if not in studio mode
|
||||
* @responseField scenes | Array<Object> | Array of scenes
|
||||
*
|
||||
* @requestType GetSceneList
|
||||
@ -38,16 +40,22 @@ RequestResult RequestHandler::GetSceneList(const Request &)
|
||||
json responseData;
|
||||
|
||||
OBSSourceAutoRelease currentProgramScene = obs_frontend_get_current_scene();
|
||||
if (currentProgramScene)
|
||||
if (currentProgramScene) {
|
||||
responseData["currentProgramSceneName"] = obs_source_get_name(currentProgramScene);
|
||||
else
|
||||
responseData["currentProgramSceneUuid"] = obs_source_get_uuid(currentProgramScene);
|
||||
} else {
|
||||
responseData["currentProgramSceneName"] = nullptr;
|
||||
responseData["currentProgramSceneUuid"] = nullptr;
|
||||
}
|
||||
|
||||
OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene();
|
||||
if (currentPreviewScene)
|
||||
if (currentPreviewScene) {
|
||||
responseData["currentPreviewSceneName"] = obs_source_get_name(currentPreviewScene);
|
||||
else
|
||||
responseData["currentPreviewSceneUuid"] = obs_source_get_uuid(currentPreviewScene);
|
||||
} else {
|
||||
responseData["currentPreviewSceneName"] = nullptr;
|
||||
responseData["currentPreviewSceneUuid"] = nullptr;
|
||||
}
|
||||
|
||||
responseData["scenes"] = Utils::Obs::ArrayHelper::GetSceneList();
|
||||
|
||||
@ -80,7 +88,12 @@ RequestResult RequestHandler::GetGroupList(const Request &)
|
||||
/**
|
||||
* Gets the current program scene.
|
||||
*
|
||||
* @responseField currentProgramSceneName | String | Current program scene
|
||||
* Note: This request is slated to have the `currentProgram`-prefixed fields removed from in an upcoming RPC version.
|
||||
*
|
||||
* @responseField sceneName | String | Current program scene name
|
||||
* @responseField sceneUuid | String | Current program scene UUID
|
||||
* @responseField currentProgramSceneName | String | Current program scene name (Deprecated)
|
||||
* @responseField currentProgramSceneUuid | String | Current program scene UUID (Deprecated)
|
||||
*
|
||||
* @requestType GetCurrentProgramScene
|
||||
* @complexity 1
|
||||
@ -93,7 +106,8 @@ RequestResult RequestHandler::GetCurrentProgramScene(const Request &)
|
||||
{
|
||||
json responseData;
|
||||
OBSSourceAutoRelease currentProgramScene = obs_frontend_get_current_scene();
|
||||
responseData["currentProgramSceneName"] = obs_source_get_name(currentProgramScene);
|
||||
responseData["sceneName"] = responseData["currentProgramSceneName"] = obs_source_get_name(currentProgramScene);
|
||||
responseData["sceneUuid"] = responseData["currentProgramSceneUuid"] = obs_source_get_uuid(currentProgramScene);
|
||||
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
@ -101,7 +115,8 @@ RequestResult RequestHandler::GetCurrentProgramScene(const Request &)
|
||||
/**
|
||||
* Sets the current program scene.
|
||||
*
|
||||
* @requestField sceneName | String | Scene to set as the current program scene
|
||||
* @requestField ?sceneName | String | Scene name to set as the current program scene
|
||||
* @requestField ?sceneUuid | String | Scene UUID to set as the current program scene
|
||||
*
|
||||
* @requestType SetCurrentProgramScene
|
||||
* @complexity 1
|
||||
@ -114,7 +129,7 @@ RequestResult RequestHandler::SetCurrentProgramScene(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
|
||||
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment);
|
||||
if (!scene)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -128,7 +143,12 @@ RequestResult RequestHandler::SetCurrentProgramScene(const Request &request)
|
||||
*
|
||||
* Only available when studio mode is enabled.
|
||||
*
|
||||
* @responseField currentPreviewSceneName | String | Current preview scene
|
||||
* Note: This request is slated to have the `currentPreview`-prefixed fields removed from in an upcoming RPC version.
|
||||
*
|
||||
* @responseField sceneName | String | Current preview scene name
|
||||
* @responseField sceneUuid | String | Current preview scene UUID
|
||||
* @responseField currentPreviewSceneName | String | Current preview scene name
|
||||
* @responseField currentPreviewSceneUuid | String | Current preview scene UUID
|
||||
*
|
||||
* @requestType GetCurrentPreviewScene
|
||||
* @complexity 1
|
||||
@ -145,7 +165,8 @@ RequestResult RequestHandler::GetCurrentPreviewScene(const Request &)
|
||||
OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene();
|
||||
|
||||
json responseData;
|
||||
responseData["currentPreviewSceneName"] = obs_source_get_name(currentPreviewScene);
|
||||
responseData["sceneName"] = responseData["currentPreviewSceneName"] = obs_source_get_name(currentPreviewScene);
|
||||
responseData["sceneUuid"] = responseData["currentPreviewSceneUuid"] = obs_source_get_uuid(currentPreviewScene);
|
||||
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
@ -155,7 +176,8 @@ RequestResult RequestHandler::GetCurrentPreviewScene(const Request &)
|
||||
*
|
||||
* Only available when studio mode is enabled.
|
||||
*
|
||||
* @requestField sceneName | String | Scene to set as the current preview scene
|
||||
* @requestField ?sceneName | String | Scene name to set as the current preview scene
|
||||
* @requestField ?sceneUuid | String | Scene UUID to set as the current preview scene
|
||||
*
|
||||
* @requestType SetCurrentPreviewScene
|
||||
* @complexity 1
|
||||
@ -171,7 +193,7 @@ RequestResult RequestHandler::SetCurrentPreviewScene(const Request &request)
|
||||
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
|
||||
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment);
|
||||
if (!scene)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -185,6 +207,8 @@ RequestResult RequestHandler::SetCurrentPreviewScene(const Request &request)
|
||||
*
|
||||
* @requestField sceneName | String | Name for the new scene
|
||||
*
|
||||
* @responseField sceneUuid | String | UUID of the created scene
|
||||
*
|
||||
* @requestType CreateScene
|
||||
* @complexity 2
|
||||
* @rpcVersion -1
|
||||
@ -205,19 +229,21 @@ RequestResult RequestHandler::CreateScene(const Request &request)
|
||||
if (scene)
|
||||
return RequestResult::Error(RequestStatus::ResourceAlreadyExists, "A source already exists by that scene name.");
|
||||
|
||||
obs_scene_t *createdScene = obs_scene_create(sceneName.c_str());
|
||||
OBSSceneAutoRelease createdScene = obs_scene_create(sceneName.c_str());
|
||||
if (!createdScene)
|
||||
return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Failed to create the scene.");
|
||||
|
||||
obs_scene_release(createdScene);
|
||||
json responseData;
|
||||
responseData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(createdScene));
|
||||
|
||||
return RequestResult::Success();
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a scene from OBS.
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene to remove
|
||||
* @requestField ?sceneName | String | Name of the scene to remove
|
||||
* @requestField ?sceneUuid | String | UUID of the scene to remove
|
||||
*
|
||||
* @requestType RemoveScene
|
||||
* @complexity 2
|
||||
@ -230,7 +256,7 @@ RequestResult RequestHandler::RemoveScene(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
|
||||
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment);
|
||||
if (!scene)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -246,7 +272,8 @@ RequestResult RequestHandler::RemoveScene(const Request &request)
|
||||
/**
|
||||
* Sets the name of a scene (rename).
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene to be renamed
|
||||
* @requestField ?sceneName | String | Name of the scene to be renamed
|
||||
* @requestField ?sceneUuid | String | UUID of the scene to be renamed
|
||||
* @requestField newSceneName | String | New name for the scene
|
||||
*
|
||||
* @requestType SetSceneName
|
||||
@ -260,7 +287,7 @@ RequestResult RequestHandler::SetSceneName(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
|
||||
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment);
|
||||
if (!(scene && request.ValidateString("newSceneName", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -279,7 +306,10 @@ RequestResult RequestHandler::SetSceneName(const Request &request)
|
||||
/**
|
||||
* Gets the scene transition overridden for a scene.
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene
|
||||
* Note: A transition UUID response field is not currently able to be implemented as of 2024-1-18.
|
||||
*
|
||||
* @requestField ?sceneName | String | Name of the scene
|
||||
* @requestField ?sceneUuid | String | UUID of the scene
|
||||
*
|
||||
* @responseField transitionName | String | Name of the overridden scene transition, else `null`
|
||||
* @responseField transitionDuration | Number | Duration of the overridden scene transition, else `null`
|
||||
@ -295,7 +325,7 @@ RequestResult RequestHandler::GetSceneSceneTransitionOverride(const Request &req
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
|
||||
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment);
|
||||
if (!scene)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -319,7 +349,8 @@ RequestResult RequestHandler::GetSceneSceneTransitionOverride(const Request &req
|
||||
/**
|
||||
* Sets the scene transition overridden for a scene.
|
||||
*
|
||||
* @requestField sceneName | String | Name of the scene
|
||||
* @requestField ?sceneName | String | Name of the scene
|
||||
* @requestField ?sceneUuid | String | UUID of the scene
|
||||
* @requestField ?transitionName | String | Name of the scene transition to use as override. Specify `null` to remove | Unchanged
|
||||
* @requestField ?transitionDuration | Number | Duration to use for any overridden transition. Specify `null` to remove | >= 50, <= 20000 | Unchanged
|
||||
*
|
||||
@ -334,7 +365,7 @@ RequestResult RequestHandler::SetSceneSceneTransitionOverride(const Request &req
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
|
||||
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment);
|
||||
if (!scene)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
|
@ -28,8 +28,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
QImage TakeSourceScreenshot(obs_source_t *source, bool &success, uint32_t requestedWidth = 0, uint32_t requestedHeight = 0)
|
||||
{
|
||||
// Get info about the requested source
|
||||
const uint32_t sourceWidth = obs_source_get_base_width(source);
|
||||
const uint32_t sourceHeight = obs_source_get_base_height(source);
|
||||
const uint32_t sourceWidth = obs_source_get_width(source);
|
||||
const uint32_t sourceHeight = obs_source_get_height(source);
|
||||
const double sourceAspectRatio = ((double)sourceWidth / (double)sourceHeight);
|
||||
|
||||
uint32_t imgWidth = sourceWidth;
|
||||
@ -114,7 +114,8 @@ bool IsImageFormatValid(std::string format)
|
||||
*
|
||||
* **Compatible with inputs and scenes.**
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source to get the active state of
|
||||
* @requestField ?sourceName | String | Name of the source to get the active state of
|
||||
* @requestField ?sourceUuid | String | UUID of the source to get the active state of
|
||||
*
|
||||
* @responseField videoActive | Boolean | Whether the source is showing in Program
|
||||
* @responseField videoShowing | Boolean | Whether the source is showing in the UI (Preview, Projector, Properties)
|
||||
@ -130,7 +131,7 @@ RequestResult RequestHandler::GetSourceActive(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment);
|
||||
if (!source)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -151,7 +152,8 @@ RequestResult RequestHandler::GetSourceActive(const Request &request)
|
||||
*
|
||||
* **Compatible with inputs and scenes.**
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source to take a screenshot of
|
||||
* @requestField ?sourceName | String | Name of the source to take a screenshot of
|
||||
* @requestField ?sourceUuid | String | UUID of the source to take a screenshot of
|
||||
* @requestField imageFormat | String | Image compression format to use. Use `GetVersion` to get compatible image formats
|
||||
* @requestField ?imageWidth | Number | Width to scale the screenshot to | >= 8, <= 4096 | Source value is used
|
||||
* @requestField ?imageHeight | Number | Height to scale the screenshot to | >= 8, <= 4096 | Source value is used
|
||||
@ -170,7 +172,7 @@ RequestResult RequestHandler::GetSourceScreenshot(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment);
|
||||
if (!(source && request.ValidateString("imageFormat", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -238,15 +240,14 @@ RequestResult RequestHandler::GetSourceScreenshot(const Request &request)
|
||||
*
|
||||
* **Compatible with inputs and scenes.**
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source to take a screenshot of
|
||||
* @requestField ?sourceName | String | Name of the source to take a screenshot of
|
||||
* @requestField ?sourceUuid | String | UUID of the source to take a screenshot of
|
||||
* @requestField imageFormat | String | Image compression format to use. Use `GetVersion` to get compatible image formats
|
||||
* @requestField imageFilePath | String | Path to save the screenshot file to. Eg. `C:\Users\user\Desktop\screenshot.png`
|
||||
* @requestField ?imageWidth | Number | Width to scale the screenshot to | >= 8, <= 4096 | Source value is used
|
||||
* @requestField ?imageHeight | Number | Height to scale the screenshot to | >= 8, <= 4096 | Source value is used
|
||||
* @requestField ?imageCompressionQuality | Number | Compression quality to use. 0 for high compression, 100 for uncompressed. -1 to use "default" (whatever that means, idk) | >= -1, <= 100 | -1
|
||||
*
|
||||
* @responseField imageData | String | Base64-encoded screenshot
|
||||
*
|
||||
* @requestType SaveSourceScreenshot
|
||||
* @complexity 3
|
||||
* @rpcVersion -1
|
||||
@ -258,7 +259,7 @@ RequestResult RequestHandler::SaveSourceScreenshot(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment);
|
||||
if (!(source && request.ValidateString("imageFormat", statusCode, comment) &&
|
||||
request.ValidateString("imageFilePath", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
@ -321,7 +322,7 @@ RequestResult RequestHandler::GetSourcePrivateSettings(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment);
|
||||
if (!source)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -338,7 +339,7 @@ RequestResult RequestHandler::SetSourcePrivateSettings(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment);
|
||||
if (!source || !request.ValidateObject("sourceSettings", statusCode, comment, true))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
|
@ -44,12 +44,16 @@ RequestResult RequestHandler::GetStreamStatus(const Request &)
|
||||
|
||||
uint64_t outputDuration = Utils::Obs::NumberHelper::GetOutputDuration(streamOutput);
|
||||
|
||||
float outputCongestion = obs_output_get_congestion(streamOutput);
|
||||
if (std::isnan(outputCongestion)) // libobs does not handle NaN, so we're handling it here
|
||||
outputCongestion = 0.0f;
|
||||
|
||||
json responseData;
|
||||
responseData["outputActive"] = obs_output_active(streamOutput);
|
||||
responseData["outputReconnecting"] = obs_output_reconnecting(streamOutput);
|
||||
responseData["outputTimecode"] = Utils::Obs::StringHelper::DurationToTimecode(outputDuration);
|
||||
responseData["outputDuration"] = outputDuration;
|
||||
responseData["outputCongestion"] = obs_output_get_congestion(streamOutput);
|
||||
responseData["outputCongestion"] = outputCongestion;
|
||||
responseData["outputBytes"] = (uint64_t)obs_output_get_total_bytes(streamOutput);
|
||||
responseData["outputSkippedFrames"] = obs_output_get_frames_dropped(streamOutput);
|
||||
responseData["outputTotalFrames"] = obs_output_get_total_frames(streamOutput);
|
||||
|
@ -46,6 +46,7 @@ RequestResult RequestHandler::GetTransitionKindList(const Request &)
|
||||
* Gets an array of all scene transitions in OBS.
|
||||
*
|
||||
* @responseField currentSceneTransitionName | String | Name of the current scene transition. Can be null
|
||||
* @responseField currentSceneTransitionUuid | String | UUID of the current scene transition. Can be null
|
||||
* @responseField currentSceneTransitionKind | String | Kind of the current scene transition. Can be null
|
||||
* @responseField transitions | Array<Object> | Array of transitions
|
||||
*
|
||||
@ -63,9 +64,11 @@ RequestResult RequestHandler::GetSceneTransitionList(const Request &)
|
||||
OBSSourceAutoRelease transition = obs_frontend_get_current_transition();
|
||||
if (transition) {
|
||||
responseData["currentSceneTransitionName"] = obs_source_get_name(transition);
|
||||
responseData["currentSceneTransitionUuid"] = obs_source_get_uuid(transition);
|
||||
responseData["currentSceneTransitionKind"] = obs_source_get_id(transition);
|
||||
} else {
|
||||
responseData["currentSceneTransitionName"] = nullptr;
|
||||
responseData["currentSceneTransitionUuid"] = nullptr;
|
||||
responseData["currentSceneTransitionKind"] = nullptr;
|
||||
}
|
||||
|
||||
@ -78,6 +81,7 @@ RequestResult RequestHandler::GetSceneTransitionList(const Request &)
|
||||
* Gets information about the current scene transition.
|
||||
*
|
||||
* @responseField transitionName | String | Name of the transition
|
||||
* @responseField transitionUuid | String | UUID of the transition
|
||||
* @responseField transitionKind | String | Kind of the transition
|
||||
* @responseField transitionFixed | Boolean | Whether the transition uses a fixed (unconfigurable) duration
|
||||
* @responseField transitionDuration | Number | Configured transition duration in milliseconds. `null` if transition is fixed
|
||||
@ -100,6 +104,7 @@ RequestResult RequestHandler::GetCurrentSceneTransition(const Request &)
|
||||
|
||||
json responseData;
|
||||
responseData["transitionName"] = obs_source_get_name(transition);
|
||||
responseData["transitionUuid"] = obs_source_get_uuid(transition);
|
||||
responseData["transitionKind"] = obs_source_get_id(transition);
|
||||
|
||||
if (obs_transition_fixed(transition)) {
|
||||
|
@ -82,7 +82,8 @@ RequestResult RequestHandler::SetStudioModeEnabled(const Request &request)
|
||||
/**
|
||||
* Opens the properties dialog of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to open the dialog of
|
||||
* @requestField ?inputName | String | Name of the input to open the dialog of
|
||||
* @requestField ?inputUuid | String | UUID of the input to open the dialog of
|
||||
*
|
||||
* @requestType OpenInputPropertiesDialog
|
||||
* @complexity 1
|
||||
@ -95,7 +96,7 @@ RequestResult RequestHandler::OpenInputPropertiesDialog(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -107,7 +108,8 @@ RequestResult RequestHandler::OpenInputPropertiesDialog(const Request &request)
|
||||
/**
|
||||
* Opens the filters dialog of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to open the dialog of
|
||||
* @requestField ?inputName | String | Name of the input to open the dialog of
|
||||
* @requestField ?inputUuid | String | UUID of the input to open the dialog of
|
||||
*
|
||||
* @requestType OpenInputFiltersDialog
|
||||
* @complexity 1
|
||||
@ -120,7 +122,7 @@ RequestResult RequestHandler::OpenInputFiltersDialog(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -132,7 +134,8 @@ RequestResult RequestHandler::OpenInputFiltersDialog(const Request &request)
|
||||
/**
|
||||
* Opens the interact dialog of an input.
|
||||
*
|
||||
* @requestField inputName | String | Name of the input to open the dialog of
|
||||
* @requestField ?inputName | String | Name of the input to open the dialog of
|
||||
* @requestField ?inputUuid | String | UUID of the input to open the dialog of
|
||||
*
|
||||
* @requestType OpenInputInteractDialog
|
||||
* @complexity 1
|
||||
@ -145,7 +148,7 @@ RequestResult RequestHandler::OpenInputInteractDialog(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
|
||||
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment);
|
||||
if (!input)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
@ -262,7 +265,8 @@ RequestResult RequestHandler::OpenVideoMixProjector(const Request &request)
|
||||
*
|
||||
* Note: This request serves to provide feature parity with 4.x. It is very likely to be changed/deprecated in a future release.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source to open a projector for
|
||||
* @requestField ?sourceName | String | Name of the source to open a projector for
|
||||
* @requestField ?sourceUuid | String | UUID of the source to open a projector for
|
||||
* @requestField ?monitorIndex | Number | Monitor index, use `GetMonitorList` to obtain index | None | -1: Opens projector in windowed mode
|
||||
* @requestField ?projectorGeometry | String | Size/Position data for a windowed projector, in Qt Base64 encoded format. Mutually exclusive with `monitorIndex` | N/A
|
||||
*
|
||||
@ -277,7 +281,7 @@ RequestResult RequestHandler::OpenSourceProjector(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment);
|
||||
if (!source)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
|
@ -211,28 +211,41 @@ bool Request::ValidateArray(const std::string &keyName, RequestStatus::RequestSt
|
||||
return true;
|
||||
}
|
||||
|
||||
obs_source_t *Request::ValidateSource(const std::string &keyName, RequestStatus::RequestStatus &statusCode,
|
||||
std::string &comment) const
|
||||
obs_source_t *Request::ValidateSource(const std::string &nameKeyName, const std::string &uuidKeyName,
|
||||
RequestStatus::RequestStatus &statusCode, std::string &comment) const
|
||||
{
|
||||
if (!ValidateString(keyName, statusCode, comment))
|
||||
return nullptr;
|
||||
|
||||
std::string sourceName = RequestData[keyName];
|
||||
|
||||
obs_source_t *ret = obs_get_source_by_name(sourceName.c_str());
|
||||
if (!ret) {
|
||||
statusCode = RequestStatus::ResourceNotFound;
|
||||
comment = std::string("No source was found by the name of `") + sourceName + "`.";
|
||||
return nullptr;
|
||||
if (ValidateString(nameKeyName, statusCode, comment)) {
|
||||
std::string sourceName = RequestData[nameKeyName];
|
||||
obs_source_t *ret = obs_get_source_by_name(sourceName.c_str());
|
||||
if (!ret) {
|
||||
statusCode = RequestStatus::ResourceNotFound;
|
||||
comment = std::string("No source was found by the name of `") + sourceName + "`.";
|
||||
return nullptr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (ValidateString(uuidKeyName, statusCode, comment)) {
|
||||
std::string sourceUuid = RequestData[uuidKeyName];
|
||||
obs_source_t *ret = obs_get_source_by_uuid(sourceUuid.c_str());
|
||||
if (!ret) {
|
||||
statusCode = RequestStatus::ResourceNotFound;
|
||||
comment = std::string("No source was found by the UUID of `") + sourceUuid + "`.";
|
||||
return nullptr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
statusCode = RequestStatus::MissingRequestField;
|
||||
comment = std::string("Your request must contain at least one of the following fields: `") + nameKeyName + "` or `" +
|
||||
uuidKeyName + "`.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
obs_source_t *Request::ValidateScene(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
obs_source_t *Request::ValidateScene(RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
const ObsWebSocketSceneFilter filter) const
|
||||
{
|
||||
obs_source_t *ret = ValidateSource(keyName, statusCode, comment);
|
||||
obs_source_t *ret = ValidateSource("sceneName", "sceneUuid", statusCode, comment);
|
||||
if (!ret)
|
||||
return nullptr;
|
||||
|
||||
@ -259,10 +272,10 @@ obs_source_t *Request::ValidateScene(const std::string &keyName, RequestStatus::
|
||||
return ret;
|
||||
}
|
||||
|
||||
obs_scene_t *Request::ValidateScene2(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
obs_scene_t *Request::ValidateScene2(RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
const ObsWebSocketSceneFilter filter) const
|
||||
{
|
||||
OBSSourceAutoRelease sceneSource = ValidateSource(keyName, statusCode, comment);
|
||||
OBSSourceAutoRelease sceneSource = ValidateSource("sceneName", "sceneUuid", statusCode, comment);
|
||||
if (!sceneSource)
|
||||
return nullptr;
|
||||
|
||||
@ -290,10 +303,9 @@ obs_scene_t *Request::ValidateScene2(const std::string &keyName, RequestStatus::
|
||||
}
|
||||
}
|
||||
|
||||
obs_source_t *Request::ValidateInput(const std::string &keyName, RequestStatus::RequestStatus &statusCode,
|
||||
std::string &comment) const
|
||||
obs_source_t *Request::ValidateInput(RequestStatus::RequestStatus &statusCode, std::string &comment) const
|
||||
{
|
||||
obs_source_t *ret = ValidateSource(keyName, statusCode, comment);
|
||||
obs_source_t *ret = ValidateSource("inputName", "inputUuid", statusCode, comment);
|
||||
if (!ret)
|
||||
return nullptr;
|
||||
|
||||
@ -307,47 +319,46 @@ obs_source_t *Request::ValidateInput(const std::string &keyName, RequestStatus::
|
||||
return ret;
|
||||
}
|
||||
|
||||
FilterPair Request::ValidateFilter(const std::string &sourceKeyName, const std::string &filterKeyName,
|
||||
RequestStatus::RequestStatus &statusCode, std::string &comment) const
|
||||
FilterPair Request::ValidateFilter(RequestStatus::RequestStatus &statusCode, std::string &comment) const
|
||||
{
|
||||
obs_source_t *source = ValidateSource(sourceKeyName, statusCode, comment);
|
||||
obs_source_t *source = ValidateSource("sourceName", "sourceUuid", statusCode, comment);
|
||||
if (!source)
|
||||
return FilterPair{source, nullptr};
|
||||
|
||||
if (!ValidateString(filterKeyName, statusCode, comment))
|
||||
if (!ValidateString("filterName", statusCode, comment))
|
||||
return FilterPair{source, nullptr};
|
||||
|
||||
std::string filterName = RequestData[filterKeyName];
|
||||
std::string filterName = RequestData["filterName"];
|
||||
|
||||
obs_source_t *filter = obs_source_get_filter_by_name(source, filterName.c_str());
|
||||
if (!filter) {
|
||||
std::string sourceName = obs_source_get_name(source);
|
||||
statusCode = RequestStatus::ResourceNotFound;
|
||||
comment = std::string("No filter was found in the source `") + RequestData[sourceKeyName].get<std::string>() +
|
||||
"` with the name `" + filterName + "`.";
|
||||
comment = std::string("No filter was found in the source `") + sourceName + "` with the name `" + filterName + "`.";
|
||||
return FilterPair{source, nullptr};
|
||||
}
|
||||
|
||||
return FilterPair{source, filter};
|
||||
}
|
||||
|
||||
obs_sceneitem_t *Request::ValidateSceneItem(const std::string &sceneKeyName, const std::string &sceneItemIdKeyName,
|
||||
RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
obs_sceneitem_t *Request::ValidateSceneItem(RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
const ObsWebSocketSceneFilter filter) const
|
||||
{
|
||||
OBSSceneAutoRelease scene = ValidateScene2(sceneKeyName, statusCode, comment, filter);
|
||||
OBSSceneAutoRelease scene = ValidateScene2(statusCode, comment, filter);
|
||||
if (!scene)
|
||||
return nullptr;
|
||||
|
||||
if (!ValidateNumber(sceneItemIdKeyName, statusCode, comment, 0))
|
||||
if (!ValidateNumber("sceneItemId", statusCode, comment, 0))
|
||||
return nullptr;
|
||||
|
||||
int64_t sceneItemId = RequestData[sceneItemIdKeyName];
|
||||
int64_t sceneItemId = RequestData["sceneItemId"];
|
||||
|
||||
OBSSceneItem sceneItem = obs_scene_find_sceneitem_by_id(scene, sceneItemId);
|
||||
if (!sceneItem) {
|
||||
std::string sceneName = obs_source_get_name(obs_scene_get_source(scene));
|
||||
statusCode = RequestStatus::ResourceNotFound;
|
||||
comment = std::string("No scene items were found in scene `") + RequestData[sceneKeyName].get<std::string>() +
|
||||
"` with the ID `" + std::to_string(sceneItemId) + "`.";
|
||||
comment = std::string("No scene items were found in scene `") + sceneName + "` with the ID `" +
|
||||
std::to_string(sceneItemId) + "`.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -64,18 +64,15 @@ struct Request {
|
||||
const bool allowEmpty = false) const;
|
||||
|
||||
// All return values have incremented refcounts
|
||||
obs_source_t *ValidateSource(const std::string &keyName, RequestStatus::RequestStatus &statusCode,
|
||||
std::string &comment) const;
|
||||
obs_source_t *ValidateScene(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
obs_source_t *ValidateSource(const std::string &nameKeyName, const std::string &uuidKeyName,
|
||||
RequestStatus::RequestStatus &statusCode, std::string &comment) const;
|
||||
obs_source_t *ValidateScene(RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const;
|
||||
obs_scene_t *ValidateScene2(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
obs_scene_t *ValidateScene2(RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const;
|
||||
obs_source_t *ValidateInput(const std::string &keyName, RequestStatus::RequestStatus &statusCode,
|
||||
std::string &comment) const;
|
||||
FilterPair ValidateFilter(const std::string &sourceKeyName, const std::string &filterKeyName,
|
||||
RequestStatus::RequestStatus &statusCode, std::string &comment) const;
|
||||
obs_sceneitem_t *ValidateSceneItem(const std::string &sceneKeyName, const std::string &sceneItemIdKeyName,
|
||||
RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
obs_source_t *ValidateInput(RequestStatus::RequestStatus &statusCode, std::string &comment) const;
|
||||
FilterPair ValidateFilter(RequestStatus::RequestStatus &statusCode, std::string &comment) const;
|
||||
obs_sceneitem_t *ValidateSceneItem(RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const;
|
||||
obs_output_t *ValidateOutput(const std::string &keyName, RequestStatus::RequestStatus &statusCode,
|
||||
std::string &comment) const;
|
||||
|
@ -21,6 +21,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
RequestBatchRequest::RequestBatchRequest(const std::string &requestType, const json &requestData,
|
||||
RequestBatchExecutionType::RequestBatchExecutionType executionType,
|
||||
const json &inputVariables, const json &outputVariables)
|
||||
: Request(requestType, requestData, executionType), InputVariables(inputVariables), OutputVariables(outputVariables)
|
||||
: Request(requestType, requestData, executionType),
|
||||
InputVariables(inputVariables),
|
||||
OutputVariables(outputVariables)
|
||||
{
|
||||
}
|
||||
|
@ -20,7 +20,10 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
#include "RequestResult.h"
|
||||
|
||||
RequestResult::RequestResult(RequestStatus::RequestStatus statusCode, json responseData, std::string comment)
|
||||
: StatusCode(statusCode), ResponseData(responseData), Comment(comment), SleepFrames(0)
|
||||
: StatusCode(statusCode),
|
||||
ResponseData(responseData),
|
||||
Comment(comment),
|
||||
SleepFrames(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -77,5 +77,8 @@ namespace RequestBatchExecutionType {
|
||||
Parallel = 2,
|
||||
};
|
||||
|
||||
inline bool IsValid(int8_t executionType) { return executionType >= None && executionType <= Parallel; }
|
||||
inline bool IsValid(int8_t executionType)
|
||||
{
|
||||
return executionType >= None && executionType <= Parallel;
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,9 @@ You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "Json.h"
|
||||
#include "Platform.h"
|
||||
#include "plugin-macros.generated.h"
|
||||
|
||||
bool Utils::Json::JsonArrayIsValidObsArray(const json &j)
|
||||
@ -177,21 +178,43 @@ json Utils::Json::ObsDataToJson(obs_data_t *d, bool includeDefault)
|
||||
|
||||
bool Utils::Json::GetJsonFileContent(std::string fileName, json &content)
|
||||
{
|
||||
std::string textContent;
|
||||
if (!Utils::Platform::GetTextFileContent(fileName, textContent))
|
||||
std::ifstream f(fileName);
|
||||
if (!f.is_open())
|
||||
return false;
|
||||
|
||||
try {
|
||||
content = json::parse(textContent);
|
||||
content = json::parse(f);
|
||||
} catch (json::parse_error &e) {
|
||||
blog(LOG_WARNING, "Failed to decode content of JSON file `%s`. Error: %s", fileName.c_str(), e.what());
|
||||
blog(LOG_WARNING, "[Utils::Json::GetJsonFileContent] Failed to decode content of JSON file `%s`. Error: %s",
|
||||
fileName.c_str(), e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Utils::Json::SetJsonFileContent(std::string fileName, const json &content, bool createNew)
|
||||
bool Utils::Json::SetJsonFileContent(std::string fileName, const json &content, bool makeDirs)
|
||||
{
|
||||
std::string textContent = content.dump(2);
|
||||
return Utils::Platform::SetTextFileContent(fileName, textContent, createNew);
|
||||
if (makeDirs) {
|
||||
std::error_code ec;
|
||||
auto p = std::filesystem::path(fileName).parent_path();
|
||||
if (!ec && !std::filesystem::exists(p, ec))
|
||||
std::filesystem::create_directories(p, ec);
|
||||
if (ec) {
|
||||
blog(LOG_ERROR, "[Utils::Json::SetJsonFileContent] Failed to create path directories: %s",
|
||||
ec.message().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::ofstream f(fileName);
|
||||
if (!f.is_open()) {
|
||||
blog(LOG_ERROR, "[Utils::Json::SetJsonFileContent] Failed to open file `%s` for writing", fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set indent to 2 spaces, then dump content
|
||||
f << std::setw(2) << content;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -76,7 +76,10 @@ namespace Utils {
|
||||
obs_data_t *JsonToObsData(json j);
|
||||
json ObsDataToJson(obs_data_t *d, bool includeDefault = false);
|
||||
bool GetJsonFileContent(std::string fileName, json &content);
|
||||
bool SetJsonFileContent(std::string fileName, const json &content, bool createNew = true);
|
||||
static inline bool Contains(const json &j, std::string key) { return j.contains(key) && !j[key].is_null(); }
|
||||
bool SetJsonFileContent(std::string fileName, const json &content, bool makeDirs = true);
|
||||
static inline bool Contains(const json &j, std::string key)
|
||||
{
|
||||
return j.contains(key) && !j[key].is_null();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,36 +29,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
inline void ___properties_dummy_addref(obs_properties_t *) {}
|
||||
using OBSPropertiesAutoDestroy = OBSRef<obs_properties_t *, ___properties_dummy_addref, obs_properties_destroy>;
|
||||
|
||||
#if !defined(OBS_AUTORELEASE)
|
||||
inline void ___source_dummy_addref(obs_source_t *) {}
|
||||
inline void ___scene_dummy_addref(obs_scene_t *) {}
|
||||
inline void ___sceneitem_dummy_addref(obs_sceneitem_t *) {}
|
||||
inline void ___data_dummy_addref(obs_data_t *) {}
|
||||
inline void ___data_array_dummy_addref(obs_data_array_t *) {}
|
||||
inline void ___output_dummy_addref(obs_output_t *) {}
|
||||
inline void ___encoder_dummy_addref(obs_encoder_t *) {}
|
||||
inline void ___service_dummy_addref(obs_service_t *) {}
|
||||
|
||||
inline void ___weak_source_dummy_addref(obs_weak_source_t *) {}
|
||||
inline void ___weak_output_dummy_addref(obs_weak_output_t *) {}
|
||||
inline void ___weak_encoder_dummy_addref(obs_weak_encoder_t *) {}
|
||||
inline void ___weak_service_dummy_addref(obs_weak_service_t *) {}
|
||||
|
||||
using OBSSourceAutoRelease = OBSRef<obs_source_t *, ___source_dummy_addref, obs_source_release>;
|
||||
using OBSSceneAutoRelease = OBSRef<obs_scene_t *, ___scene_dummy_addref, obs_scene_release>;
|
||||
using OBSSceneItemAutoRelease = OBSRef<obs_sceneitem_t *, ___sceneitem_dummy_addref, obs_sceneitem_release>;
|
||||
using OBSDataAutoRelease = OBSRef<obs_data_t *, ___data_dummy_addref, obs_data_release>;
|
||||
using OBSDataArrayAutoRelease = OBSRef<obs_data_array_t *, ___data_array_dummy_addref, obs_data_array_release>;
|
||||
using OBSOutputAutoRelease = OBSRef<obs_output_t *, ___output_dummy_addref, obs_output_release>;
|
||||
using OBSEncoderAutoRelease = OBSRef<obs_encoder_t *, ___encoder_dummy_addref, obs_encoder_release>;
|
||||
using OBSServiceAutoRelease = OBSRef<obs_service_t *, ___service_dummy_addref, obs_service_release>;
|
||||
|
||||
using OBSWeakSourceAutoRelease = OBSRef<obs_weak_source_t *, ___weak_source_dummy_addref, obs_weak_source_release>;
|
||||
using OBSWeakOutputAutoRelease = OBSRef<obs_weak_output_t *, ___weak_output_dummy_addref, obs_weak_output_release>;
|
||||
using OBSWeakEncoderAutoRelease = OBSRef<obs_weak_encoder_t *, ___weak_encoder_dummy_addref, obs_weak_encoder_release>;
|
||||
using OBSWeakServiceAutoRelease = OBSRef<obs_weak_service_t *, ___weak_service_dummy_addref, obs_weak_service_release>;
|
||||
#endif
|
||||
|
||||
template<typename T> T *GetCalldataPointer(const calldata_t *data, const char *name)
|
||||
{
|
||||
void *ptr = nullptr;
|
||||
@ -72,7 +42,7 @@ enum ObsOutputState {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_UNKNOWN
|
||||
* @enumType ObsOutputState
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -82,7 +52,7 @@ enum ObsOutputState {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_STARTING
|
||||
* @enumType ObsOutputState
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -92,7 +62,7 @@ enum ObsOutputState {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_STARTED
|
||||
* @enumType ObsOutputState
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -102,7 +72,7 @@ enum ObsOutputState {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_STOPPING
|
||||
* @enumType ObsOutputState
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -112,7 +82,7 @@ enum ObsOutputState {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_STOPPED
|
||||
* @enumType ObsOutputState
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -122,7 +92,7 @@ enum ObsOutputState {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_RECONNECTING
|
||||
* @enumType ObsOutputState
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -132,7 +102,7 @@ enum ObsOutputState {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_RECONNECTED
|
||||
* @enumType ObsOutputState
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.1.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -142,7 +112,7 @@ enum ObsOutputState {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_PAUSED
|
||||
* @enumType ObsOutputState
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.1.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -152,7 +122,7 @@ enum ObsOutputState {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_RESUMED
|
||||
* @enumType ObsOutputState
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -176,7 +146,7 @@ enum ObsMediaInputAction {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE
|
||||
* @enumType ObsMediaInputAction
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -186,7 +156,7 @@ enum ObsMediaInputAction {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY
|
||||
* @enumType ObsMediaInputAction
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -196,7 +166,7 @@ enum ObsMediaInputAction {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE
|
||||
* @enumType ObsMediaInputAction
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -206,7 +176,7 @@ enum ObsMediaInputAction {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP
|
||||
* @enumType ObsMediaInputAction
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -216,7 +186,7 @@ enum ObsMediaInputAction {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART
|
||||
* @enumType ObsMediaInputAction
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -226,7 +196,7 @@ enum ObsMediaInputAction {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT
|
||||
* @enumType ObsMediaInputAction
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -236,7 +206,7 @@ enum ObsMediaInputAction {
|
||||
*
|
||||
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS
|
||||
* @enumType ObsMediaInputAction
|
||||
* @rpcVersion 1
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
@ -257,6 +227,7 @@ namespace Utils {
|
||||
namespace Obs {
|
||||
namespace StringHelper {
|
||||
std::string GetObsVersion();
|
||||
std::string GetModuleConfigPath(std::string fileName);
|
||||
std::string GetCurrentSceneCollection();
|
||||
std::string GetCurrentProfile();
|
||||
std::string GetCurrentProfilePath();
|
||||
@ -297,7 +268,7 @@ namespace Utils {
|
||||
}
|
||||
|
||||
namespace SearchHelper {
|
||||
obs_hotkey_t *GetHotkeyByName(std::string name);
|
||||
obs_hotkey_t *GetHotkeyByName(std::string name, std::string context);
|
||||
obs_source_t *GetSceneTransitionByName(std::string name); // Increments source ref. Use OBSSourceAutoRelease
|
||||
obs_sceneitem_t *GetSceneItemByName(obs_scene_t *scene, std::string name,
|
||||
int offset = 0); // Increments ref. Use OBSSceneItemAutoRelease
|
||||
|
@ -33,7 +33,7 @@ static void CreateSceneItemHelper(void *_data, obs_scene_t *scene)
|
||||
data->sceneItem = obs_scene_add(scene, data->source);
|
||||
|
||||
if (data->sceneItemTransform)
|
||||
obs_sceneitem_set_info(data->sceneItem, data->sceneItemTransform);
|
||||
obs_sceneitem_set_info2(data->sceneItem, data->sceneItemTransform);
|
||||
|
||||
if (data->sceneItemCrop)
|
||||
obs_sceneitem_set_crop(data->sceneItem, data->sceneItemCrop);
|
||||
|
@ -96,6 +96,7 @@ std::vector<json> Utils::Obs::ArrayHelper::GetSceneList()
|
||||
|
||||
json sceneJson;
|
||||
sceneJson["sceneName"] = obs_source_get_name(scene);
|
||||
sceneJson["sceneUuid"] = obs_source_get_uuid(scene);
|
||||
sceneJson["sceneIndex"] = sceneList.sources.num - i - 1;
|
||||
|
||||
ret.push_back(sceneJson);
|
||||
@ -150,6 +151,7 @@ std::vector<json> Utils::Obs::ArrayHelper::GetSceneItemList(obs_scene_t *scene,
|
||||
item["sceneItemBlendMode"] = obs_sceneitem_get_blending_mode(sceneItem);
|
||||
OBSSource itemSource = obs_sceneitem_get_source(sceneItem);
|
||||
item["sourceName"] = obs_source_get_name(itemSource);
|
||||
item["sourceUuid"] = obs_source_get_uuid(itemSource);
|
||||
item["sourceType"] = obs_source_get_type(itemSource);
|
||||
if (obs_source_get_type(itemSource) == OBS_SOURCE_TYPE_INPUT)
|
||||
item["inputKind"] = obs_source_get_id(itemSource);
|
||||
@ -195,6 +197,7 @@ std::vector<json> Utils::Obs::ArrayHelper::GetInputList(std::string inputKind)
|
||||
|
||||
json inputJson;
|
||||
inputJson["inputName"] = obs_source_get_name(input);
|
||||
inputJson["inputUuid"] = obs_source_get_uuid(input);
|
||||
inputJson["inputKind"] = inputKind;
|
||||
inputJson["unversionedInputKind"] = obs_source_get_unversioned_id(input);
|
||||
|
||||
@ -281,6 +284,7 @@ std::vector<json> Utils::Obs::ArrayHelper::GetSceneTransitionList()
|
||||
obs_source_t *transition = transitionList.sources.array[i];
|
||||
json transitionJson;
|
||||
transitionJson["transitionName"] = obs_source_get_name(transition);
|
||||
transitionJson["transitionUuid"] = obs_source_get_uuid(transition);
|
||||
transitionJson["transitionKind"] = obs_source_get_id(transition);
|
||||
transitionJson["transitionFixed"] = obs_transition_fixed(transition);
|
||||
transitionJson["transitionConfigurable"] = obs_source_configurable(transition);
|
||||
|
@ -50,7 +50,7 @@ json Utils::Obs::ObjectHelper::GetSceneItemTransform(obs_sceneitem_t *item)
|
||||
|
||||
obs_transform_info osi;
|
||||
obs_sceneitem_crop crop;
|
||||
obs_sceneitem_get_info(item, &osi);
|
||||
obs_sceneitem_get_info2(item, &osi);
|
||||
obs_sceneitem_get_crop(item, &crop);
|
||||
|
||||
OBSSource source = obs_sceneitem_get_source(item);
|
||||
@ -83,5 +83,7 @@ json Utils::Obs::ObjectHelper::GetSceneItemTransform(obs_sceneitem_t *item)
|
||||
ret["cropTop"] = (int)crop.top;
|
||||
ret["cropBottom"] = (int)crop.bottom;
|
||||
|
||||
ret["cropToBounds"] = osi.crop_to_bounds;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
#include "Obs.h"
|
||||
#include "plugin-macros.generated.h"
|
||||
|
||||
obs_hotkey_t *Utils::Obs::SearchHelper::GetHotkeyByName(std::string name)
|
||||
obs_hotkey_t *Utils::Obs::SearchHelper::GetHotkeyByName(std::string name, std::string context)
|
||||
{
|
||||
if (name.empty())
|
||||
return nullptr;
|
||||
@ -27,8 +27,50 @@ obs_hotkey_t *Utils::Obs::SearchHelper::GetHotkeyByName(std::string name)
|
||||
auto hotkeys = ArrayHelper::GetHotkeyList();
|
||||
|
||||
for (auto hotkey : hotkeys) {
|
||||
if (obs_hotkey_get_name(hotkey) == name)
|
||||
if (obs_hotkey_get_name(hotkey) != name)
|
||||
continue;
|
||||
|
||||
if (context.empty())
|
||||
return hotkey;
|
||||
|
||||
auto type = obs_hotkey_get_registerer_type(hotkey);
|
||||
if (type == OBS_HOTKEY_REGISTERER_SOURCE) {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_weak_source_get_source((obs_weak_source_t *)obs_hotkey_get_registerer(hotkey));
|
||||
if (!source)
|
||||
continue;
|
||||
|
||||
if (context != obs_source_get_name(source))
|
||||
continue;
|
||||
|
||||
} else if (type == OBS_HOTKEY_REGISTERER_OUTPUT) {
|
||||
OBSOutputAutoRelease output =
|
||||
obs_weak_output_get_output((obs_weak_output_t *)obs_hotkey_get_registerer(hotkey));
|
||||
if (!output)
|
||||
continue;
|
||||
|
||||
if (context != obs_output_get_name(output))
|
||||
continue;
|
||||
|
||||
} else if (type == OBS_HOTKEY_REGISTERER_ENCODER) {
|
||||
OBSEncoderAutoRelease encoder =
|
||||
obs_weak_encoder_get_encoder((obs_weak_encoder_t *)obs_hotkey_get_registerer(hotkey));
|
||||
if (!encoder)
|
||||
continue;
|
||||
|
||||
if (context != obs_encoder_get_name(encoder))
|
||||
continue;
|
||||
|
||||
} else if (type == OBS_HOTKEY_REGISTERER_SERVICE) {
|
||||
OBSServiceAutoRelease service =
|
||||
obs_weak_service_get_service((obs_weak_service_t *)obs_hotkey_get_registerer(hotkey));
|
||||
if (!service)
|
||||
continue;
|
||||
|
||||
if (context != obs_service_get_name(service))
|
||||
continue;
|
||||
}
|
||||
return hotkey;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -20,13 +20,13 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
#include <inttypes.h>
|
||||
#include <QString>
|
||||
|
||||
#include <obs-module.h>
|
||||
|
||||
#include <util/util.hpp>
|
||||
|
||||
#include "Obs.h"
|
||||
#include "plugin-macros.generated.h"
|
||||
|
||||
#define CASE(x) \
|
||||
case x: \
|
||||
return #x;
|
||||
|
||||
std::string Utils::Obs::StringHelper::GetObsVersion()
|
||||
{
|
||||
uint32_t version = obs_get_version();
|
||||
@ -40,36 +40,34 @@ std::string Utils::Obs::StringHelper::GetObsVersion()
|
||||
return combined.toStdString();
|
||||
}
|
||||
|
||||
std::string Utils::Obs::StringHelper::GetModuleConfigPath(std::string fileName)
|
||||
{
|
||||
BPtr<char> configPath = obs_module_config_path(fileName.c_str());
|
||||
return std::string(configPath.Get());
|
||||
}
|
||||
|
||||
std::string Utils::Obs::StringHelper::GetCurrentSceneCollection()
|
||||
{
|
||||
char *sceneCollectionName = obs_frontend_get_current_scene_collection();
|
||||
std::string ret = sceneCollectionName;
|
||||
bfree(sceneCollectionName);
|
||||
return ret;
|
||||
BPtr<char> sceneCollectionName = obs_frontend_get_current_scene_collection();
|
||||
return std::string(sceneCollectionName.Get());
|
||||
}
|
||||
|
||||
std::string Utils::Obs::StringHelper::GetCurrentProfile()
|
||||
{
|
||||
char *profileName = obs_frontend_get_current_profile();
|
||||
std::string ret = profileName;
|
||||
bfree(profileName);
|
||||
return ret;
|
||||
BPtr<char> profileName = obs_frontend_get_current_profile();
|
||||
return std::string(profileName.Get());
|
||||
}
|
||||
|
||||
std::string Utils::Obs::StringHelper::GetCurrentProfilePath()
|
||||
{
|
||||
char *profilePath = obs_frontend_get_current_profile_path();
|
||||
std::string ret = profilePath;
|
||||
bfree(profilePath);
|
||||
return ret;
|
||||
BPtr<char> profilePath = obs_frontend_get_current_profile_path();
|
||||
return std::string(profilePath.Get());
|
||||
}
|
||||
|
||||
std::string Utils::Obs::StringHelper::GetCurrentRecordOutputPath()
|
||||
{
|
||||
char *recordOutputPath = obs_frontend_get_current_record_output_path();
|
||||
std::string ret = recordOutputPath;
|
||||
bfree(recordOutputPath);
|
||||
return ret;
|
||||
BPtr<char> recordOutputPath = obs_frontend_get_current_record_output_path();
|
||||
return std::string(recordOutputPath.Get());
|
||||
}
|
||||
|
||||
std::string Utils::Obs::StringHelper::GetLastRecordFileName()
|
||||
@ -94,18 +92,14 @@ std::string Utils::Obs::StringHelper::GetLastRecordFileName()
|
||||
|
||||
std::string Utils::Obs::StringHelper::GetLastReplayBufferFileName()
|
||||
{
|
||||
char *replayBufferPath = obs_frontend_get_last_replay();
|
||||
std::string ret = replayBufferPath;
|
||||
bfree(replayBufferPath);
|
||||
return ret;
|
||||
BPtr<char> replayBufferPath = obs_frontend_get_last_replay();
|
||||
return std::string(replayBufferPath.Get());
|
||||
}
|
||||
|
||||
std::string Utils::Obs::StringHelper::GetLastScreenshotFileName()
|
||||
{
|
||||
char *screenshotPath = obs_frontend_get_last_screenshot();
|
||||
std::string ret = screenshotPath;
|
||||
bfree(screenshotPath);
|
||||
return ret;
|
||||
BPtr<char> screenshotPath = obs_frontend_get_last_screenshot();
|
||||
return std::string(screenshotPath.Get());
|
||||
}
|
||||
|
||||
std::string Utils::Obs::StringHelper::DurationToTimecode(uint64_t ms)
|
||||
|
@ -93,6 +93,7 @@ json Utils::Obs::VolumeMeter::Meter::GetMeterData()
|
||||
l.unlock();
|
||||
|
||||
ret["inputName"] = obs_source_get_name(input);
|
||||
ret["inputUuid"] = obs_source_get_uuid(input);
|
||||
ret["inputLevelsMul"] = levels;
|
||||
|
||||
return ret;
|
||||
@ -237,7 +238,9 @@ void Utils::Obs::VolumeMeter::Meter::InputVolumeCallback(void *priv_data, callda
|
||||
}
|
||||
|
||||
Utils::Obs::VolumeMeter::Handler::Handler(UpdateCallback cb, uint64_t updatePeriod)
|
||||
: _updateCallback(cb), _updatePeriod(updatePeriod), _running(false)
|
||||
: _updateCallback(cb),
|
||||
_updatePeriod(updatePeriod),
|
||||
_running(false)
|
||||
{
|
||||
signal_handler_t *sh = obs_get_signal_handler();
|
||||
if (!sh)
|
||||
|
@ -21,7 +21,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
#include <QCommandLineParser>
|
||||
#include <QNetworkInterface>
|
||||
#include <QHostAddress>
|
||||
#include <QFile>
|
||||
#include <obs-frontend-api.h>
|
||||
|
||||
#include "Platform.h"
|
||||
@ -116,36 +115,13 @@ void Utils::Platform::SendTrayNotification(QSystemTrayIcon::MessageIcon icon, QS
|
||||
obs_queue_task(
|
||||
OBS_TASK_UI,
|
||||
[](void *param) {
|
||||
void *systemTrayPtr = obs_frontend_get_system_tray();
|
||||
auto systemTray = static_cast<QSystemTrayIcon *>(systemTrayPtr);
|
||||
|
||||
auto notification = static_cast<SystemTrayNotification *>(param);
|
||||
systemTray->showMessage(notification->title, notification->body, notification->icon);
|
||||
void *systemTrayPtr = obs_frontend_get_system_tray();
|
||||
if (systemTrayPtr) {
|
||||
auto systemTray = static_cast<QSystemTrayIcon *>(systemTrayPtr);
|
||||
systemTray->showMessage(notification->title, notification->body, notification->icon);
|
||||
}
|
||||
delete notification;
|
||||
},
|
||||
(void *)notification, false);
|
||||
}
|
||||
|
||||
bool Utils::Platform::GetTextFileContent(std::string fileName, std::string &content)
|
||||
{
|
||||
QFile f(QString::fromStdString(fileName));
|
||||
if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
return false;
|
||||
|
||||
content = f.readAll().toStdString();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Utils::Platform::SetTextFileContent(std::string fileName, std::string content, bool createNew)
|
||||
{
|
||||
if (!createNew && !QFile::exists(QString::fromStdString(fileName)))
|
||||
return false;
|
||||
|
||||
QFile f(QString::fromStdString(fileName));
|
||||
if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
return false;
|
||||
|
||||
QTextStream out(&f);
|
||||
out << content.c_str();
|
||||
return true;
|
||||
}
|
||||
|
@ -29,7 +29,5 @@ namespace Utils {
|
||||
QString GetCommandLineArgument(QString arg);
|
||||
bool GetCommandLineFlagSet(QString arg);
|
||||
void SendTrayNotification(QSystemTrayIcon::MessageIcon icon, QString title, QString body);
|
||||
bool GetTextFileContent(std::string fileName, std::string &content);
|
||||
bool SetTextFileContent(std::string filePath, std::string content, bool createNew = true);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
#include <obs-frontend-api.h>
|
||||
|
||||
#include "WebSocketServer.h"
|
||||
#include "../eventhandler/EventHandler.h"
|
||||
#include "../obs-websocket.h"
|
||||
#include "../Config.h"
|
||||
#include "../utils/Crypto.h"
|
||||
@ -47,23 +46,10 @@ WebSocketServer::WebSocketServer() : QObject(nullptr)
|
||||
_server.set_close_handler(websocketpp::lib::bind(&WebSocketServer::onClose, this, websocketpp::lib::placeholders::_1));
|
||||
_server.set_message_handler(websocketpp::lib::bind(&WebSocketServer::onMessage, this, websocketpp::lib::placeholders::_1,
|
||||
websocketpp::lib::placeholders::_2));
|
||||
|
||||
auto eventHandler = GetEventHandler();
|
||||
if (eventHandler) {
|
||||
eventHandler->SetBroadcastCallback(std::bind(&WebSocketServer::BroadcastEvent, this, std::placeholders::_1,
|
||||
std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
eventHandler->SetObsReadyCallback(std::bind(&WebSocketServer::onObsReady, this, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
|
||||
WebSocketServer::~WebSocketServer()
|
||||
{
|
||||
auto eventHandler = GetEventHandler();
|
||||
if (eventHandler) {
|
||||
eventHandler->SetObsReadyCallback(nullptr);
|
||||
eventHandler->SetBroadcastCallback(nullptr);
|
||||
}
|
||||
|
||||
if (_server.is_listening())
|
||||
Stop();
|
||||
}
|
||||
@ -97,7 +83,7 @@ void WebSocketServer::Start()
|
||||
}
|
||||
|
||||
_authenticationSalt = Utils::Crypto::GenerateSalt();
|
||||
_authenticationSecret = Utils::Crypto::GenerateSecret(conf->ServerPassword.toStdString(), _authenticationSalt);
|
||||
_authenticationSecret = Utils::Crypto::GenerateSecret(conf->ServerPassword, _authenticationSalt);
|
||||
|
||||
// Set log levels if debug is enabled
|
||||
if (IsDebugEnabled()) {
|
||||
@ -215,11 +201,6 @@ std::vector<WebSocketServer::WebSocketSessionState> WebSocketServer::GetWebSocke
|
||||
return webSocketSessions;
|
||||
}
|
||||
|
||||
void WebSocketServer::onObsReady(bool ready)
|
||||
{
|
||||
_obsReady = ready;
|
||||
}
|
||||
|
||||
bool WebSocketServer::onValidate(websocketpp::connection_hdl hdl)
|
||||
{
|
||||
auto conn = _server.get_con_from_hdl(hdl);
|
||||
@ -327,11 +308,9 @@ void WebSocketServer::onClose(websocketpp::connection_hdl hdl)
|
||||
_sessions.erase(hdl);
|
||||
lock.unlock();
|
||||
|
||||
// If client was identified, decrement appropriate refs in eventhandler.
|
||||
if (isIdentified) {
|
||||
auto eventHandler = GetEventHandler();
|
||||
eventHandler->ProcessUnsubscription(eventSubscriptions);
|
||||
}
|
||||
// If client was identified, announce unsubscription
|
||||
if (isIdentified && _clientSubscriptionCallback)
|
||||
_clientSubscriptionCallback(false, eventSubscriptions);
|
||||
|
||||
// Build SessionState object for signal
|
||||
WebSocketSessionState state;
|
||||
|
@ -30,8 +30,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
#include "rpc/WebSocketSession.h"
|
||||
#include "types/WebSocketCloseCode.h"
|
||||
#include "types/WebSocketOpCode.h"
|
||||
#include "../utils/Json.h"
|
||||
#include "../requesthandler/rpc/Request.h"
|
||||
#include "../utils/Json.h"
|
||||
#include "plugin-macros.generated.h"
|
||||
|
||||
class WebSocketServer : QObject {
|
||||
@ -57,12 +57,14 @@ public:
|
||||
void InvalidateSession(websocketpp::connection_hdl hdl);
|
||||
void BroadcastEvent(uint64_t requiredIntent, const std::string &eventType, const json &eventData = nullptr,
|
||||
uint8_t rpcVersion = 0);
|
||||
|
||||
bool IsListening() { return _server.is_listening(); }
|
||||
|
||||
inline void SetObsReady(bool ready) { _obsReady = ready; }
|
||||
inline bool IsListening() { return _server.is_listening(); }
|
||||
std::vector<WebSocketSessionState> GetWebSocketSessions();
|
||||
inline QThreadPool *GetThreadPool() { return &_threadPool; }
|
||||
|
||||
QThreadPool *GetThreadPool() { return &_threadPool; }
|
||||
// Callback for when a client subscribes or unsubscribes. `true` for sub, `false` for unsub
|
||||
typedef std::function<void(bool, uint64_t)> ClientSubscriptionCallback; // bool type, uint64_t eventSubscriptions
|
||||
inline void SetClientSubscriptionCallback(ClientSubscriptionCallback cb) { _clientSubscriptionCallback = cb; }
|
||||
|
||||
signals:
|
||||
void ClientConnected(WebSocketSessionState state);
|
||||
@ -77,7 +79,6 @@ private:
|
||||
|
||||
void ServerRunner();
|
||||
|
||||
void onObsReady(bool loaded);
|
||||
bool onValidate(websocketpp::connection_hdl hdl);
|
||||
void onOpen(websocketpp::connection_hdl hdl);
|
||||
void onClose(websocketpp::connection_hdl hdl);
|
||||
@ -98,4 +99,6 @@ private:
|
||||
std::map<websocketpp::connection_hdl, SessionPtr, std::owner_less<websocketpp::connection_hdl>> _sessions;
|
||||
|
||||
std::atomic<bool> _obsReady = false;
|
||||
|
||||
ClientSubscriptionCallback _clientSubscriptionCallback;
|
||||
};
|
||||
|
@ -23,7 +23,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
#include "WebSocketServer.h"
|
||||
#include "../requesthandler/RequestHandler.h"
|
||||
#include "../requesthandler/RequestBatchHandler.h"
|
||||
#include "../eventhandler/EventHandler.h"
|
||||
#include "../obs-websocket.h"
|
||||
#include "../Config.h"
|
||||
#include "../utils/Crypto.h"
|
||||
@ -32,7 +31,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
|
||||
static bool IsSupportedRpcVersion(uint8_t requestedVersion)
|
||||
{
|
||||
return (requestedVersion == 1);
|
||||
return (requestedVersion == CURRENT_RPC_VERSION);
|
||||
}
|
||||
|
||||
static json ConstructRequestResult(RequestResult requestResult, const json &requestJson)
|
||||
@ -149,9 +148,9 @@ void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::Proces
|
||||
if (ret.closeCode != WebSocketCloseCode::DontClose)
|
||||
return;
|
||||
|
||||
// Increment refs for event subscriptions
|
||||
auto eventHandler = GetEventHandler();
|
||||
eventHandler->ProcessSubscription(session->EventSubscriptions());
|
||||
// Announce subscribe
|
||||
if (_clientSubscriptionCallback)
|
||||
_clientSubscriptionCallback(true, session->EventSubscriptions());
|
||||
|
||||
// Mark session as identified
|
||||
session->SetIsIdentified(true);
|
||||
@ -172,16 +171,17 @@ void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::Proces
|
||||
case WebSocketOpCode::Reidentify: { // Reidentify
|
||||
std::unique_lock<std::mutex> sessionLock(session->OperationMutex);
|
||||
|
||||
// Decrement refs for current subscriptions
|
||||
auto eventHandler = GetEventHandler();
|
||||
eventHandler->ProcessUnsubscription(session->EventSubscriptions());
|
||||
// Announce unsubscribe
|
||||
if (_clientSubscriptionCallback)
|
||||
_clientSubscriptionCallback(false, session->EventSubscriptions());
|
||||
|
||||
SetSessionParameters(session, ret, payloadData);
|
||||
if (ret.closeCode != WebSocketCloseCode::DontClose)
|
||||
return;
|
||||
|
||||
// Increment refs for new subscriptions
|
||||
eventHandler->ProcessSubscription(session->EventSubscriptions());
|
||||
// Announce subscribe
|
||||
if (_clientSubscriptionCallback)
|
||||
_clientSubscriptionCallback(true, session->EventSubscriptions());
|
||||
|
||||
ret.result["op"] = WebSocketOpCode::Identified;
|
||||
ret.result["d"]["negotiatedRpcVersion"] = session->RpcVersion();
|
||||
|
@ -122,5 +122,8 @@ namespace WebSocketOpCode {
|
||||
RequestBatchResponse = 9,
|
||||
};
|
||||
|
||||
inline bool IsValid(uint8_t opCode) { return opCode >= Hello && opCode <= RequestBatchResponse; }
|
||||
inline bool IsValid(uint8_t opCode)
|
||||
{
|
||||
return opCode >= Hello && opCode <= RequestBatchResponse;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user