Compare commits

..

No commits in common. "master" and "5.3.2" have entirely different histories.

82 changed files with 963 additions and 3096 deletions

View File

@ -1,6 +1,6 @@
# please use clang-format version 16 or later # please use clang-format version 8 or later
Standard: c++17 Standard: Cpp11
AccessModifierOffset: -8 AccessModifierOffset: -8
AlignAfterOpenBracket: Align AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false AlignConsecutiveAssignments: false
@ -8,14 +8,14 @@ AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left AlignEscapedNewlines: Left
AlignOperands: true AlignOperands: true
AlignTrailingComments: true AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false #AllowAllArgumentsOnNextLine: false # requires clang-format 9
AllowAllConstructorInitializersOnNextLine: false #AllowAllConstructorInitializersOnNextLine: false # requires clang-format 9
AllowAllParametersOfDeclarationOnNextLine: false AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: Inline #AllowShortLambdasOnASingleLine: Inline # requires clang-format 9
AllowShortLoopsOnASingleLine: false AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None AlwaysBreakAfterReturnType: None
@ -57,7 +57,6 @@ ForEachMacros:
- 'json_object_foreach' - 'json_object_foreach'
- 'json_object_foreach_safe' - 'json_object_foreach_safe'
- 'json_array_foreach' - 'json_array_foreach'
- 'HASH_ITER'
IncludeBlocks: Preserve IncludeBlocks: Preserve
IndentCaseLabels: false IndentCaseLabels: false
IndentPPDirectives: None IndentPPDirectives: None
@ -66,7 +65,7 @@ IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
NamespaceIndentation: All NamespaceIndentation: All
ObjCBinPackProtocolList: Auto #ObjCBinPackProtocolList: Auto # requires clang-format 7
ObjCBlockIndentWidth: 8 ObjCBlockIndentWidth: 8
ObjCSpaceAfterProperty: true ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true ObjCSpaceBeforeProtocolList: true
@ -84,13 +83,13 @@ ReflowComments: false
SortIncludes: false SortIncludes: false
SortUsingDeclarations: false SortUsingDeclarations: false
SpaceAfterCStyleCast: false SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false #SpaceAfterLogicalNot: false # requires clang-format 9
SpaceAfterTemplateKeyword: false SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true
SpaceBeforeCtorInitializerColon: true #SpaceBeforeCtorInitializerColon: true # requires clang-format 7
SpaceBeforeInheritanceColon: true #SpaceBeforeInheritanceColon: true # requires clang-format 7
SpaceBeforeParens: ControlStatements SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true #SpaceBeforeRangeBasedForLoopColon: true # requires clang-format 7
SpaceInEmptyParentheses: false SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1 SpacesBeforeTrailingComments: 1
SpacesInAngles: false SpacesInAngles: false
@ -98,111 +97,11 @@ SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false SpacesInContainerLiterals: false
SpacesInParentheses: false SpacesInParentheses: false
SpacesInSquareBrackets: false SpacesInSquareBrackets: false
StatementMacros: #StatementMacros: # requires clang-format 8
- 'Q_OBJECT' # - 'Q_OBJECT'
TabWidth: 8 TabWidth: 8
TypenameMacros: #TypenameMacros: # requires clang-format 9
- 'DARRAY' # - 'DARRAY'
UseTab: ForContinuationAndIndentation UseTab: ForContinuationAndIndentation
--- ---
Language: ObjC 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

View File

@ -11,7 +11,7 @@ jobs:
if: github.repository_owner == 'obsproject' if: github.repository_owner == 'obsproject'
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
fetch-depth: 100 fetch-depth: 100
- name: Upload US English Language Files 🇺🇸 - name: Upload US English Language Files 🇺🇸

View File

@ -18,7 +18,7 @@ jobs:
IS_CI: "true" IS_CI: "true"
steps: steps:
- name: 'Checkout' - name: 'Checkout'
uses: actions/checkout@v4 uses: actions/checkout@v2
with: with:
path: ${{ github.workspace }}/obs-websocket path: ${{ github.workspace }}/obs-websocket
- name: 'Generate docs' - name: 'Generate docs'

View File

@ -15,7 +15,7 @@ jobs:
if: contains(github.event.head_commit.message, '[skip ci]') != true if: contains(github.event.head_commit.message, '[skip ci]') != true
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v2
- name: Generate docs - name: Generate docs
run: cd docs && ./build_docs.sh run: cd docs && ./build_docs.sh
- name: Run markdownlint-cli - name: Run markdownlint-cli

View File

@ -2,11 +2,9 @@ cmake_minimum_required(VERSION 3.16...3.25)
legacy_check() legacy_check()
set(obs-websocket_VERSION 5.5.2) set(obs-websocket_VERSION 5.3.2)
set(OBS_WEBSOCKET_RPC_VERSION 1) set(OBS_WEBSOCKET_RPC_VERSION 1)
include(cmake/obs-websocket-api.cmake)
option(ENABLE_WEBSOCKET "Enable building OBS with websocket plugin" ON) option(ENABLE_WEBSOCKET "Enable building OBS with websocket plugin" ON)
if(NOT ENABLE_WEBSOCKET) if(NOT ENABLE_WEBSOCKET)
target_disable(obs-websocket) target_disable(obs-websocket)
@ -14,7 +12,7 @@ if(NOT ENABLE_WEBSOCKET)
endif() endif()
# Find Qt # Find Qt
find_package(Qt6 REQUIRED Core Widgets Svg Network) find_qt(COMPONENTS Core Widgets Svg Network)
# Find nlohmann JSON # Find nlohmann JSON
find_package(nlohmann_json 3 REQUIRED) find_package(nlohmann_json 3 REQUIRED)
@ -33,52 +31,51 @@ find_package(Asio 1.12.1 REQUIRED)
add_library(obs-websocket MODULE) add_library(obs-websocket MODULE)
add_library(OBS::websocket ALIAS obs-websocket) add_library(OBS::websocket ALIAS obs-websocket)
target_sources(obs-websocket PRIVATE)
target_sources( target_sources(
obs-websocket obs-websocket
PRIVATE # cmake-format: sortable PRIVATE src/obs-websocket.cpp
src/obs-websocket.h
src/Config.cpp src/Config.cpp
src/Config.h src/Config.h
lib/obs-websocket-api.h
src/forms/ConnectInfo.cpp src/forms/ConnectInfo.cpp
src/forms/ConnectInfo.h src/forms/ConnectInfo.h
src/forms/resources.qrc src/forms/resources.qrc
src/forms/SettingsDialog.cpp src/forms/SettingsDialog.cpp
src/forms/SettingsDialog.h src/forms/SettingsDialog.h
src/obs-websocket.cpp
src/obs-websocket.h
src/WebSocketApi.cpp src/WebSocketApi.cpp
src/WebSocketApi.h) src/WebSocketApi.h)
target_sources( target_sources(
obs-websocket obs-websocket
PRIVATE # cmake-format: sortable PRIVATE src/websocketserver/WebSocketServer.cpp
src/websocketserver/WebSocketServer_Protocol.cpp
src/websocketserver/WebSocketServer.h
src/websocketserver/rpc/WebSocketSession.h src/websocketserver/rpc/WebSocketSession.h
src/websocketserver/types/WebSocketCloseCode.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( target_sources(
obs-websocket obs-websocket
PRIVATE # cmake-format: sortable PRIVATE src/eventhandler/EventHandler.cpp
src/eventhandler/EventHandler.cpp
src/eventhandler/EventHandler.h src/eventhandler/EventHandler.h
src/eventhandler/EventHandler_Config.cpp src/eventhandler/EventHandler_Config.cpp
src/eventhandler/EventHandler_Filters.cpp
src/eventhandler/EventHandler_General.cpp src/eventhandler/EventHandler_General.cpp
src/eventhandler/EventHandler_Filters.cpp
src/eventhandler/EventHandler_Inputs.cpp src/eventhandler/EventHandler_Inputs.cpp
src/eventhandler/EventHandler_MediaInputs.cpp src/eventhandler/EventHandler_MediaInputs.cpp
src/eventhandler/EventHandler_Outputs.cpp src/eventhandler/EventHandler_Outputs.cpp
src/eventhandler/EventHandler_SceneItems.cpp
src/eventhandler/EventHandler_Scenes.cpp src/eventhandler/EventHandler_Scenes.cpp
src/eventhandler/EventHandler_SceneItems.cpp
src/eventhandler/EventHandler_Transitions.cpp src/eventhandler/EventHandler_Transitions.cpp
src/eventhandler/EventHandler_Ui.cpp src/eventhandler/EventHandler_Ui.cpp
src/eventhandler/types/EventSubscription.h) src/eventhandler/types/EventSubscription.h)
target_sources( target_sources(
obs-websocket obs-websocket
PRIVATE # cmake-format: sortable PRIVATE src/requesthandler/RequestBatchHandler.cpp
src/requesthandler/RequestBatchHandler.cpp
src/requesthandler/RequestBatchHandler.h src/requesthandler/RequestBatchHandler.h
src/requesthandler/RequestHandler.cpp src/requesthandler/RequestHandler.cpp
src/requesthandler/RequestHandler.h src/requesthandler/RequestHandler.h
@ -88,10 +85,10 @@ target_sources(
src/requesthandler/RequestHandler_Inputs.cpp src/requesthandler/RequestHandler_Inputs.cpp
src/requesthandler/RequestHandler_MediaInputs.cpp src/requesthandler/RequestHandler_MediaInputs.cpp
src/requesthandler/RequestHandler_Outputs.cpp src/requesthandler/RequestHandler_Outputs.cpp
src/requesthandler/RequestHandler_Record.cpp
src/requesthandler/RequestHandler_SceneItems.cpp
src/requesthandler/RequestHandler_Scenes.cpp
src/requesthandler/RequestHandler_Sources.cpp src/requesthandler/RequestHandler_Sources.cpp
src/requesthandler/RequestHandler_Record.cpp
src/requesthandler/RequestHandler_Scenes.cpp
src/requesthandler/RequestHandler_SceneItems.cpp
src/requesthandler/RequestHandler_Stream.cpp src/requesthandler/RequestHandler_Stream.cpp
src/requesthandler/RequestHandler_Transitions.cpp src/requesthandler/RequestHandler_Transitions.cpp
src/requesthandler/RequestHandler_Ui.cpp src/requesthandler/RequestHandler_Ui.cpp
@ -101,13 +98,12 @@ target_sources(
src/requesthandler/rpc/RequestBatchRequest.h src/requesthandler/rpc/RequestBatchRequest.h
src/requesthandler/rpc/RequestResult.cpp src/requesthandler/rpc/RequestResult.cpp
src/requesthandler/rpc/RequestResult.h src/requesthandler/rpc/RequestResult.h
src/requesthandler/types/RequestBatchExecutionType.h src/requesthandler/types/RequestStatus.h
src/requesthandler/types/RequestStatus.h) src/requesthandler/types/RequestBatchExecutionType.h)
target_sources( target_sources(
obs-websocket obs-websocket
PRIVATE # cmake-format: sortable PRIVATE src/utils/Compat.cpp
src/utils/Compat.cpp
src/utils/Compat.h src/utils/Compat.h
src/utils/Crypto.cpp src/utils/Crypto.cpp
src/utils/Crypto.h src/utils/Crypto.h
@ -119,8 +115,8 @@ target_sources(
src/utils/Obs_ArrayHelper.cpp src/utils/Obs_ArrayHelper.cpp
src/utils/Obs_NumberHelper.cpp src/utils/Obs_NumberHelper.cpp
src/utils/Obs_ObjectHelper.cpp src/utils/Obs_ObjectHelper.cpp
src/utils/Obs_SearchHelper.cpp
src/utils/Obs_StringHelper.cpp src/utils/Obs_StringHelper.cpp
src/utils/Obs_SearchHelper.cpp
src/utils/Obs_VolumeMeter.cpp src/utils/Obs_VolumeMeter.cpp
src/utils/Obs_VolumeMeter.h src/utils/Obs_VolumeMeter.h
src/utils/Obs_VolumeMeter_Helpers.h src/utils/Obs_VolumeMeter_Helpers.h
@ -137,27 +133,19 @@ target_compile_definitions(
target_compile_options( target_compile_options(
obs-websocket obs-websocket
PRIVATE $<$<PLATFORM_ID:Windows>:/wd4267> PRIVATE
$<$<PLATFORM_ID:Windows>:/wd4267>
$<$<PLATFORM_ID:Windows>:/wd4996> $<$<PLATFORM_ID:Windows>:/wd4996>
$<$<COMPILE_LANG_AND_ID:CXX,GNU,AppleClang,Clang>:-Wall> $<$<PLATFORM_ID:Darwin,Linux,FreeBSD>:-Wall>
$<$<COMPILE_LANG_AND_ID:CXX,GNU,AppleClang,Clang>:-Wno-error=float-conversion> $<$<COMPILE_LANG_AND_ID:CXX,GNU,AppleClang,Clang>:-Wno-error=float-conversion;-Wno-error=shadow>
$<$<COMPILE_LANG_AND_ID:CXX,GNU,AppleClang,Clang>:-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,GNU>:-Wno-error=format-overflow> $<$<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>
$<$<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( target_link_libraries(
obs-websocket obs-websocket
PRIVATE OBS::libobs PRIVATE OBS::libobs
OBS::frontend-api OBS::frontend-api
OBS::websocket-api
Qt::Core Qt::Core
Qt::Widgets Qt::Widgets
Qt::Svg Qt::Svg
@ -167,8 +155,6 @@ target_link_libraries(
Asio::Asio Asio::Asio
qrcodegencpp::qrcodegencpp) qrcodegencpp::qrcodegencpp)
target_link_options(obs-websocket PRIVATE $<$<PLATFORM_ID:Windows>:/IGNORE:4099>)
set_target_properties_obs( set_target_properties_obs(
obs-websocket obs-websocket
PROPERTIES FOLDER plugins PROPERTIES FOLDER plugins
@ -182,4 +168,6 @@ if(OS_WINDOWS)
TARGET obs-websocket TARGET obs-websocket
APPEND APPEND
PROPERTY AUTORCC_OPTIONS --format-version 1) PROPERTY AUTORCC_OPTIONS --format-version 1)
target_link_options(obs-websocket PRIVATE /IGNORE:4099)
endif() endif()

View File

@ -41,8 +41,6 @@ It is **highly recommended** to keep obs-websocket protected with a password aga
- [Aitum](https://aitum.tv/) - [Aitum](https://aitum.tv/)
- [Kruiz Control](https://github.com/Kruiser8/Kruiz-Control) - [Kruiz Control](https://github.com/Kruiser8/Kruiz-Control)
- [Bitfocus Companion Module](https://bitfocus.io/companion/) - [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) ### Client libraries (for developers)
@ -51,7 +49,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.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 - 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 - Rust: [obws](https://github.com/dnaka91/obws) by dnaka91
- Godot 4.0.x: [obs-websocket-gd](https://github.com/you-win/obs-websocket-gd) by you-win - Godot 3.4.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 - 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) - 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 - Go: [goobs](https://github.com/andreykaipov/goobs) by andreykaipov

View File

@ -1,23 +1,8 @@
project(obs-websocket VERSION 5.5.2) project(obs-websocket VERSION 5.3.2)
set(OBS_WEBSOCKET_RPC_VERSION 1) set(OBS_WEBSOCKET_RPC_VERSION 1)
option(ENABLE_WEBSOCKET "Enable building OBS with websocket plugin" ON) 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) if(NOT ENABLE_WEBSOCKET OR NOT ENABLE_UI)
message(STATUS "OBS: DISABLED obs-websocket") message(STATUS "OBS: DISABLED obs-websocket")
return() return()
@ -71,6 +56,7 @@ target_sources(
src/obs-websocket.h src/obs-websocket.h
src/Config.cpp src/Config.cpp
src/Config.h src/Config.h
lib/obs-websocket-api.h
src/forms/SettingsDialog.cpp src/forms/SettingsDialog.cpp
src/forms/SettingsDialog.h src/forms/SettingsDialog.h
src/forms/ConnectInfo.cpp src/forms/ConnectInfo.cpp
@ -147,7 +133,6 @@ target_link_libraries(
obs-websocket obs-websocket
PRIVATE OBS::libobs PRIVATE OBS::libobs
OBS::frontend-api OBS::frontend-api
OBS::websocket-api
Qt::Core Qt::Core
Qt::Widgets Qt::Widgets
Qt::Svg Qt::Svg

View File

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

View File

@ -1,8 +0,0 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
find_dependency(libobs REQUIRED)
include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
check_required_components("@PROJECT_NAME@")

View File

@ -1,35 +1,9 @@
OBSWebSocket.Plugin.Description="Afstandbeheer van OBS deur WebSocket"
OBSWebSocket.Settings.DialogTitle="WebSocket-bedienerinstellings"
OBSWebSocket.Settings.PluginSettingsTitle="Inpropinstellings"
OBSWebSocket.Settings.ServerEnable="Aktiveer WebSocket-diens"
OBSWebSocket.Settings.ServerSettingsTitle="Bedienerinstellings" OBSWebSocket.Settings.ServerSettingsTitle="Bedienerinstellings"
OBSWebSocket.Settings.Password="Bedienerwagwoord" OBSWebSocket.Settings.Password="Bedienerwagwoord"
OBSWebSocket.Settings.GeneratePassword="Genereer wagwoord" OBSWebSocket.Settings.GeneratePassword="Genereer wagwoord"
OBSWebSocket.Settings.ServerPort="Bedienerpoort" OBSWebSocket.Settings.ServerPort="Bedienerpoort"
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."
OBSWebSocket.SessionTable.Title="Gekoppelde WebSocket-sessies"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Afstandsadres"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Sessieduur"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Boodskappe In/Uit"
OBSWebSocket.SessionTable.IdentifiedTitle="Geïdentifiseer" OBSWebSocket.SessionTable.IdentifiedTitle="Geïdentifiseer"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Verwyder?"
OBSWebSocket.SessionTable.KickButtonText="Verwyder"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket-verbindingsinligting"
OBSWebSocket.ConnectInfo.CopyText="Kopieer" OBSWebSocket.ConnectInfo.CopyText="Kopieer"
OBSWebSocket.ConnectInfo.ServerIp="Bediener-IP (beste skatting)" OBSWebSocket.ConnectInfo.ServerIp="Bediener-IP (beste skatting)"
OBSWebSocket.ConnectInfo.ServerPort="Bedienerpoort" OBSWebSocket.ConnectInfo.ServerPort="Bedienerpoort"
OBSWebSocket.ConnectInfo.ServerPassword="Bedienerwagwoord" OBSWebSocket.ConnectInfo.ServerPassword="Bedienerwagwoord"
OBSWebSocket.ConnectInfo.QrTitle="Koppel QR"
OBSWebSocket.TrayNotification.Identified.Title="Nuwe WebSocket-koppeling"
OBSWebSocket.TrayNotification.Identified.Body="Kliënt %1 geïdentifiseer."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket-waarmerkfout"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Kliënt %1 kon nie waarmerk nie."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket-kliënt is ontkoppel"
OBSWebSocket.TrayNotification.Disconnected.Body="Kliënt %1 is ontkoppel."

View File

@ -1,41 +0,0 @@
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 адключаны."

View File

@ -1,5 +1,4 @@
OBSWebSocket.Plugin.Description="Fjernstyring af OBS Studio via WebSocket" OBSWebSocket.Plugin.Description="Fjernstyring af OBS Studio via WebSocket"
OBSWebSocket.Settings.DialogTitle="WebSocket-serverindstillinger"
OBSWebSocket.Settings.PluginSettingsTitle="Plugin-indstillinger" OBSWebSocket.Settings.PluginSettingsTitle="Plugin-indstillinger"
OBSWebSocket.Settings.ServerEnable="Aktivér WebSocket-server" OBSWebSocket.Settings.ServerEnable="Aktivér WebSocket-server"
OBSWebSocket.Settings.AlertsEnable="Aktivér Systembakke Alarmer" OBSWebSocket.Settings.AlertsEnable="Aktivér Systembakke Alarmer"

View File

@ -4,7 +4,7 @@ OBSWebSocket.Settings.PluginSettingsTitle="Plugineinstellungen"
OBSWebSocket.Settings.ServerEnable="WebSocket-Server aktivieren" OBSWebSocket.Settings.ServerEnable="WebSocket-Server aktivieren"
OBSWebSocket.Settings.AlertsEnable="Warnungen im Infobereich aktivieren" OBSWebSocket.Settings.AlertsEnable="Warnungen im Infobereich aktivieren"
OBSWebSocket.Settings.DebugEnable="Debug-Logging aktivieren" OBSWebSocket.Settings.DebugEnable="Debug-Logging aktivieren"
OBSWebSocket.Settings.DebugEnableHoverText="Aktiviert Debug-Logging für die aktuelle OBS-Instanz.\nVerwenden Sie „--websocket_debug“, damit die Option beim Starten aktiviert wird." OBSWebSocket.Settings.DebugEnableHoverText="Aktiviert Debug-Logging für die aktuelle OBS-Instanz.\nVerwenden Sie „--websocket_debug“, damit die Option beim Laden aktiviert wird."
OBSWebSocket.Settings.ServerSettingsTitle="Servereinstellungen" OBSWebSocket.Settings.ServerSettingsTitle="Servereinstellungen"
OBSWebSocket.Settings.AuthRequired="Authentifizierung aktivieren" OBSWebSocket.Settings.AuthRequired="Authentifizierung aktivieren"
OBSWebSocket.Settings.Password="Serverpasswort" OBSWebSocket.Settings.Password="Serverpasswort"
@ -28,7 +28,7 @@ OBSWebSocket.SessionTable.KickButtonColumnTitle="Entfernen?"
OBSWebSocket.SessionTable.KickButtonText="Entfernen" OBSWebSocket.SessionTable.KickButtonText="Entfernen"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket-Verbindungsinformationen" OBSWebSocket.ConnectInfo.DialogTitle="WebSocket-Verbindungsinformationen"
OBSWebSocket.ConnectInfo.CopyText="Kopieren" OBSWebSocket.ConnectInfo.CopyText="Kopieren"
OBSWebSocket.ConnectInfo.ServerIp="Server-IP (Geschätzt)" OBSWebSocket.ConnectInfo.ServerIp="Server-IP (geschätzt)"
OBSWebSocket.ConnectInfo.ServerPort="Serverport" OBSWebSocket.ConnectInfo.ServerPort="Serverport"
OBSWebSocket.ConnectInfo.ServerPassword="Serverpasswort" OBSWebSocket.ConnectInfo.ServerPassword="Serverpasswort"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="Authentifizierung deaktiviert" OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="Authentifizierung deaktiviert"

View File

@ -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.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.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.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(e) de vouloir utiliser votre propre mot de passe ?" OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Êtes-vous sûr de vouloir utiliser votre propre mot de passe ?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Erreur : Configuration invalide" OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Erreur : Configuration invalide"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Vous devez utiliser un mot de passe de 6 caractères ou plus." OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Vous devez utiliser un mot de passe d'au moins 6 caractères"
OBSWebSocket.SessionTable.Title="Sessions WebSocket connectées" OBSWebSocket.SessionTable.Title="Sessions WebSocket connectées"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Adresse distante" OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Adresse distante"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Durée de session" OBSWebSocket.SessionTable.SessionDurationColumnTitle="Durée de session"
@ -30,7 +30,7 @@ OBSWebSocket.ConnectInfo.DialogTitle="Informations de connexion WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Copier" OBSWebSocket.ConnectInfo.CopyText="Copier"
OBSWebSocket.ConnectInfo.ServerIp="IP du serveur (meilleure estimation)" OBSWebSocket.ConnectInfo.ServerIp="IP du serveur (meilleure estimation)"
OBSWebSocket.ConnectInfo.ServerPort="Port serveur" OBSWebSocket.ConnectInfo.ServerPort="Port serveur"
OBSWebSocket.ConnectInfo.ServerPassword="Mot de passe du serveur" OBSWebSocket.ConnectInfo.ServerPassword="Mot de passe serveur"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Authentification désactivée]" OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Authentification désactivée]"
OBSWebSocket.ConnectInfo.QrTitle="QR code de connexion" OBSWebSocket.ConnectInfo.QrTitle="QR code de connexion"
OBSWebSocket.TrayNotification.Identified.Title="Nouvelle connexion WebSocket" OBSWebSocket.TrayNotification.Identified.Title="Nouvelle connexion WebSocket"

View File

@ -1,10 +1 @@
OBSWebSocket.Settings.DialogTitle="Postavke servera WebSocket" OBSWebSocket.Settings.DialogTitle="Postavke servera WebSocket"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Pogreška: Neispravna konfiguracija"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Lozinka mora sadržavati barem 6 znakova."
OBSWebSocket.SessionTable.Title="Spojene sesije WebSocketa"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Udaljena adresa"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Trajanje sesije"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Ulaz/izlaz poruka"
OBSWebSocket.ConnectInfo.CopyText="Kopiraj"
OBSWebSocket.ConnectInfo.ServerPort="Vrata servera"
OBSWebSocket.ConnectInfo.ServerPassword="Lozinka servera"

View File

@ -8,7 +8,7 @@ OBSWebSocket.Settings.DebugEnableHoverText="Aktifkan pencatatan awakutu untuk pe
OBSWebSocket.Settings.ServerSettingsTitle="Pengaturan Server" OBSWebSocket.Settings.ServerSettingsTitle="Pengaturan Server"
OBSWebSocket.Settings.AuthRequired="Aktifkan Autentikasi" OBSWebSocket.Settings.AuthRequired="Aktifkan Autentikasi"
OBSWebSocket.Settings.Password="Kata Sandi Server" OBSWebSocket.Settings.Password="Kata Sandi Server"
OBSWebSocket.Settings.GeneratePassword="Buat Kata Sandi" OBSWebSocket.Settings.GeneratePassword="Ciptakan Kata Sandi"
OBSWebSocket.Settings.ServerPort="Port Server" OBSWebSocket.Settings.ServerPort="Port Server"
OBSWebSocket.Settings.ShowConnectInfo="Tampilkan Informasi Koneksi" OBSWebSocket.Settings.ShowConnectInfo="Tampilkan Informasi Koneksi"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Peringatan: Saat Ini Siaran Langsung" 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.ShowConnectInfoWarningInfoText="Anda yakin ingin melihat informasi koneksi Anda?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Peringatan: Potensi Masalah Keamanan" 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.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="Apakah Anda yakin ingin menggunakan kata sandi sendiri?" OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Anda yakin ingin menggunakan kata sandi Anda sendiri?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Galat: Konfigurasi Tidak Berlaku" OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Galat: Konfigurasi Tidak Berlaku"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Anda harus menggunakan kata sandi yang minimal 6 karakter atau lebih." OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Anda harus menggunakan kata sandi yang minimal 6 karakter atau lebih."
OBSWebSocket.SessionTable.Title="Sesi WebSocket yang Terhubung" OBSWebSocket.SessionTable.Title="Sesi WebSocket yang Terhubung"

View File

@ -1,5 +1,4 @@
OBSWebSocket.Plugin.Description="Kawalan-jauh OBS Studio melalui WebSocket" OBSWebSocket.Plugin.Description="Kawalan-jauh OBS Studio melalui WebSocket"
OBSWebSocket.Settings.DialogTitle="Tetapan Pelayan WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Tetapan Pemalam" OBSWebSocket.Settings.PluginSettingsTitle="Tetapan Pemalam"
OBSWebSocket.Settings.ServerEnable="Benarkan pelayan WebSocket" OBSWebSocket.Settings.ServerEnable="Benarkan pelayan WebSocket"
OBSWebSocket.Settings.AlertsEnable="Benarkan Amaran Talam Sistem" OBSWebSocket.Settings.AlertsEnable="Benarkan Amaran Talam Sistem"

View File

@ -1,25 +1,2 @@
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.Password="Server Passord"
OBSWebSocket.Settings.GeneratePassword="Generer 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."

View File

@ -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.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.UserPasswordWarningInfoText="Czy na pewno chcesz użyć własnego hasła?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Błąd: Nieprawidłowa konfiguracja" OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Błąd: Nieprawidłowa konfiguracja"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Hasło musi zawierać 6 lub więcej znaków." OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Musisz użyć hasła, które ma 6 lub więcej znaków."
OBSWebSocket.SessionTable.Title="Podłączone sesje WebSocket" OBSWebSocket.SessionTable.Title="Podłączone sesje WebSocket"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Adres zdalny" OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Adres zdalny"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Czas trwania sesji" OBSWebSocket.SessionTable.SessionDurationColumnTitle="Czas trwania sesji"

View File

@ -1,18 +1,18 @@
OBSWebSocket.Plugin.Description="Control de la distanță pentru OBS Studio prin WebSocket" OBSWebSocket.Plugin.Description="Control de la distanță pentru OBS Studio prin WebSocket"
OBSWebSocket.Settings.DialogTitle="Setări pentru serverul WebSocket" OBSWebSocket.Settings.DialogTitle="Setări ale server-ului WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Setări pentru plugin" OBSWebSocket.Settings.PluginSettingsTitle="Setări pentru plugin"
OBSWebSocket.Settings.ServerEnable="Activează serverul WebSocket" OBSWebSocket.Settings.ServerEnable="Activează serverul WebSocket"
OBSWebSocket.Settings.AlertsEnable="Activează alertele din bara de sistem" OBSWebSocket.Settings.AlertsEnable="Activează alertele din bara de sistem"
OBSWebSocket.Settings.DebugEnable="Activează jurnalizarea pentru depanare" OBSWebSocket.Settings.DebugEnable="Activează jurnalizarea de depanare"
OBSWebSocket.Settings.DebugEnableHoverText="Activează jurnalizarea pentru depanare în cazul instanței actuale de OBS. Nu persistă la încărcare.\nFolosește --websocket_debug pentru a activa la încărcare." OBSWebSocket.Settings.DebugEnableHoverText="Activează jurnalizarea de depanare pentru instanța actuală de OBS. Nu persistă la încărcare.\nFolosește --websocket_debug pentru a activa la încărcare."
OBSWebSocket.Settings.ServerSettingsTitle="Setări pentru server" OBSWebSocket.Settings.ServerSettingsTitle="Setări server"
OBSWebSocket.Settings.AuthRequired="Activează autentificarea" OBSWebSocket.Settings.AuthRequired="Activează autentificarea"
OBSWebSocket.Settings.Password="Parola serverului" OBSWebSocket.Settings.Password="Parola serverului"
OBSWebSocket.Settings.GeneratePassword="Generează parola" OBSWebSocket.Settings.GeneratePassword="Generează parola"
OBSWebSocket.Settings.ServerPort="Portul serverului" OBSWebSocket.Settings.ServerPort="Portul serverului"
OBSWebSocket.Settings.ShowConnectInfo="Afișează informațiile conexiunii" OBSWebSocket.Settings.ShowConnectInfo="Afișează informațiile de conectare"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Avertisment: În prezent în direct" OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Avertisment: În prezent în direct"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Se pare că un output (stream, înregistrare etc.) este activ în prezent." OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Se pare că un output (transmisiune, înregistrare etc.) este activ în prezent."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Sigur vrei să afișezi informațiile de conectare?" 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.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." OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket stochează parola serverului ca text simplu. Este foarte recomandat să folosiți o parolă generată de obs-websocket."
@ -24,17 +24,17 @@ OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Adresă la distanță"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Durata sesiunii" OBSWebSocket.SessionTable.SessionDurationColumnTitle="Durata sesiunii"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Mesaje de intrare/ieșire" OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Mesaje de intrare/ieșire"
OBSWebSocket.SessionTable.IdentifiedTitle="Identificat" OBSWebSocket.SessionTable.IdentifiedTitle="Identificat"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Înlături?" OBSWebSocket.SessionTable.KickButtonColumnTitle="Înlătură?"
OBSWebSocket.SessionTable.KickButtonText="Înlătură" OBSWebSocket.SessionTable.KickButtonText="Înlătură"
OBSWebSocket.ConnectInfo.DialogTitle="Informațiile conexiunii WebSocket" OBSWebSocket.ConnectInfo.DialogTitle="Informații de conectare WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Copiază" OBSWebSocket.ConnectInfo.CopyText="Copiază"
OBSWebSocket.ConnectInfo.ServerIp="IP-ul serverului (cea mai bună presupunere)" OBSWebSocket.ConnectInfo.ServerIp="IP-ul serverului (cea mai bună presupunere)"
OBSWebSocket.ConnectInfo.ServerPort="Portul serverului" OBSWebSocket.ConnectInfo.ServerPort="Portul serverului"
OBSWebSocket.ConnectInfo.ServerPassword="Parola serverului" OBSWebSocket.ConnectInfo.ServerPassword="Parola serverului"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autentificare dezactivată]" OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autentificare dezactivată]"
OBSWebSocket.ConnectInfo.QrTitle="QR de conectare" OBSWebSocket.ConnectInfo.QrTitle="Conectare QR"
OBSWebSocket.TrayNotification.Identified.Title="O nouă conexiune WebSocket" OBSWebSocket.TrayNotification.Identified.Title="O nouă conexiune WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Clientul %1 identificat." OBSWebSocket.TrayNotification.Identified.Body="Client %1 identificat."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Eroare de autentificare WebSocket" OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Eroare de autentificare WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Client %1 nu a reușit să se autentifice." OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Client %1 nu a reușit să se autentifice."
OBSWebSocket.TrayNotification.Disconnected.Title="Client WebSocket deconectat" OBSWebSocket.TrayNotification.Disconnected.Title="Client WebSocket deconectat"

View File

@ -6,13 +6,13 @@ OBSWebSocket.Settings.AlertsEnable="Включить оповещения в т
OBSWebSocket.Settings.DebugEnable="Включить отладочный журнал" OBSWebSocket.Settings.DebugEnable="Включить отладочный журнал"
OBSWebSocket.Settings.DebugEnableHoverText="Включает ведение журнала отладки для текущего экземпляра OBS. Не сохраняется при запуске.\nИспользуйте --websocket_debug для включения при запуске." OBSWebSocket.Settings.DebugEnableHoverText="Включает ведение журнала отладки для текущего экземпляра OBS. Не сохраняется при запуске.\nИспользуйте --websocket_debug для включения при запуске."
OBSWebSocket.Settings.ServerSettingsTitle="Настройки сервера" OBSWebSocket.Settings.ServerSettingsTitle="Настройки сервера"
OBSWebSocket.Settings.AuthRequired="Включить вход в аккаунт" OBSWebSocket.Settings.AuthRequired="Включить аутентификацию"
OBSWebSocket.Settings.Password="Пароль сервера" OBSWebSocket.Settings.Password="Пароль сервера"
OBSWebSocket.Settings.GeneratePassword="Создать пароль" OBSWebSocket.Settings.GeneratePassword="Сгенерировать пароль"
OBSWebSocket.Settings.ServerPort="Порт сервера" OBSWebSocket.Settings.ServerPort="Порт сервера"
OBSWebSocket.Settings.ShowConnectInfo="Показать сведения о подключении" OBSWebSocket.Settings.ShowConnectInfo="Показать сведения о подключении"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Предупреждение: Сейчас в эфире" OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Предупреждение: Сейчас в эфире"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Похоже, что вывод (поток, запись и т. д.) в настоящее время уже выбран." OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Похоже, что вывод (поток, запись и т. д.) в настоящее время активен."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Уверены, что хотите показать ваши сведения о подключении?" OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Уверены, что хотите показать ваши сведения о подключении?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Предупреждение: Потенциальная проблема безопасности" OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Предупреждение: Потенциальная проблема безопасности"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket хранит пароль сервера в виде обычного текста. Настоятельно рекомендуется использовать пароль, сгенерированный obs-websock." OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket хранит пароль сервера в виде обычного текста. Настоятельно рекомендуется использовать пароль, сгенерированный obs-websock."
@ -28,14 +28,14 @@ OBSWebSocket.SessionTable.KickButtonColumnTitle="Выгнать?"
OBSWebSocket.SessionTable.KickButtonText="Выгнать" OBSWebSocket.SessionTable.KickButtonText="Выгнать"
OBSWebSocket.ConnectInfo.DialogTitle="Сведения о подключении WebSocket" OBSWebSocket.ConnectInfo.DialogTitle="Сведения о подключении WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Копировать" OBSWebSocket.ConnectInfo.CopyText="Копировать"
OBSWebSocket.ConnectInfo.ServerIp="IP сервера (вероятный)" OBSWebSocket.ConnectInfo.ServerIp="IP сервера (лучшая догадка)"
OBSWebSocket.ConnectInfo.ServerPort="Порт сервера" OBSWebSocket.ConnectInfo.ServerPort="Порт сервера"
OBSWebSocket.ConnectInfo.ServerPassword="Пароль сервера" OBSWebSocket.ConnectInfo.ServerPassword="Пароль сервера"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Вход отключён]" OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Авторизация отключена]"
OBSWebSocket.ConnectInfo.QrTitle="QR-код подключения" OBSWebSocket.ConnectInfo.QrTitle="QR-код подключения"
OBSWebSocket.TrayNotification.Identified.Title="Новое подключение WebSocket" OBSWebSocket.TrayNotification.Identified.Title="Новое подключение WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Клиент %1 распознан." OBSWebSocket.TrayNotification.Identified.Body="Клиент %1 распознан."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Ошибка входа WebSocket" OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Ошибка аутентификации WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Клиент %1 не смог войти." OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Клиент %1 не смог аутентифицироваться."
OBSWebSocket.TrayNotification.Disconnected.Title="Клиент WebSocket отключился" OBSWebSocket.TrayNotification.Disconnected.Title="Клиент WebSocket отключился"
OBSWebSocket.TrayNotification.Disconnected.Body="Клиент %1 отключился." OBSWebSocket.TrayNotification.Disconnected.Body="Клиент %1 отключился."

View File

@ -1,6 +1,6 @@
OBSWebSocket.Plugin.Description="Fjärrkontroll av OBS Studio via WebSocket" OBSWebSocket.Plugin.Description="Fjärrkontroll av OBS Studio via WebSocket"
OBSWebSocket.Settings.DialogTitle="WebSocket-serverinställningar" OBSWebSocket.Settings.DialogTitle="WebSocket-serverinställningar"
OBSWebSocket.Settings.PluginSettingsTitle="Insticksprogramsinställningar" OBSWebSocket.Settings.PluginSettingsTitle="Insticksmodulsinställningar"
OBSWebSocket.Settings.ServerEnable="Aktivera WebSocket-server" OBSWebSocket.Settings.ServerEnable="Aktivera WebSocket-server"
OBSWebSocket.Settings.AlertsEnable="Aktivera systemfältsmeddelanden" OBSWebSocket.Settings.AlertsEnable="Aktivera systemfältsmeddelanden"
OBSWebSocket.Settings.DebugEnable="Aktivera felsökningsloggning" OBSWebSocket.Settings.DebugEnable="Aktivera felsökningsloggning"
@ -11,7 +11,7 @@ OBSWebSocket.Settings.Password="Serverlösenord"
OBSWebSocket.Settings.GeneratePassword="Generera lösenord" OBSWebSocket.Settings.GeneratePassword="Generera lösenord"
OBSWebSocket.Settings.ServerPort="Serverport" OBSWebSocket.Settings.ServerPort="Serverport"
OBSWebSocket.Settings.ShowConnectInfo="Visa anslutningsinformation" OBSWebSocket.Settings.ShowConnectInfo="Visa anslutningsinformation"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Varning: Direktsändning pågår" OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Varning: Sänder för närvarande"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Det verkar som om en utmatning (ström, inspelning, etc.) är för närvarande aktiv." 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.ShowConnectInfoWarningInfoText="Är du säker på att du vill visa din anslutningsinformation?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Varning: Potentiellt säkerhetsproblem" OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Varning: Potentiellt säkerhetsproblem"

View File

@ -29,7 +29,7 @@ OBSWebSocket.SessionTable.KickButtonText="Çıkar"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket Bağlanma Bilgileri" OBSWebSocket.ConnectInfo.DialogTitle="WebSocket Bağlanma Bilgileri"
OBSWebSocket.ConnectInfo.CopyText="Kopyala" OBSWebSocket.ConnectInfo.CopyText="Kopyala"
OBSWebSocket.ConnectInfo.ServerIp="Sunucu IP (En İyi Tahmin)" OBSWebSocket.ConnectInfo.ServerIp="Sunucu IP (En İyi Tahmin)"
OBSWebSocket.ConnectInfo.ServerPort="Sunucu Portu" OBSWebSocket.ConnectInfo.ServerPort="Sunucu Kapısı"
OBSWebSocket.ConnectInfo.ServerPassword="Sunucu Parolası" OBSWebSocket.ConnectInfo.ServerPassword="Sunucu Parolası"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Doğrulama Devre Dışı]" OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Doğrulama Devre Dışı]"
OBSWebSocket.ConnectInfo.QrTitle="Kare Kod ile Bağlan" OBSWebSocket.ConnectInfo.QrTitle="Kare Kod ile Bağlan"

View File

@ -1,9 +0,0 @@
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="Сервер серсүзе"

View File

@ -1,2 +0,0 @@
OBSWebSocket.Settings.GeneratePassword="ئىم ھاسىللا"
OBSWebSocket.ConnectInfo.CopyText="كۆچۈر"

View File

@ -1,5 +1,5 @@
# obs-websocket 5.x.x Protocol # obs-websocket 5.1.0 Protocol
## Main Table of Contents ## Main Table of Contents

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <obs.h> #include <obs.h>
#define OBS_WEBSOCKET_API_VERSION 3 #define OBS_WEBSOCKET_API_VERSION 2
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -30,7 +30,6 @@ extern "C" {
typedef void *obs_websocket_vendor; typedef void *obs_websocket_vendor;
typedef void (*obs_websocket_request_callback_function)(obs_data_t *, obs_data_t *, void *); typedef void (*obs_websocket_request_callback_function)(obs_data_t *, obs_data_t *, void *);
typedef void (*obs_websocket_event_callback_function)(uint64_t, const char *, const char *, void *);
struct obs_websocket_request_response { struct obs_websocket_request_response {
unsigned int status_code; unsigned int status_code;
@ -45,12 +44,7 @@ struct obs_websocket_request_callback {
void *priv_data; void *priv_data;
}; };
struct obs_websocket_event_callback { inline proc_handler_t *_ph;
obs_websocket_event_callback_function callback;
void *priv_data;
};
static proc_handler_t *_ph;
/* ==================== INTERNAL API FUNCTIONS ==================== */ /* ==================== INTERNAL API FUNCTIONS ==================== */
@ -59,7 +53,7 @@ static inline proc_handler_t *obs_websocket_get_ph(void)
proc_handler_t *global_ph = obs_get_proc_handler(); proc_handler_t *global_ph = obs_get_proc_handler();
assert(global_ph != NULL); assert(global_ph != NULL);
calldata_t cd = {0, 0, 0, 0}; calldata_t cd = {0};
if (!proc_handler_call(global_ph, "obs_websocket_api_get_ph", &cd)) if (!proc_handler_call(global_ph, "obs_websocket_api_get_ph", &cd))
blog(LOG_DEBUG, "Unable to fetch obs-websocket proc handler object. obs-websocket not installed?"); blog(LOG_DEBUG, "Unable to fetch obs-websocket proc handler object. obs-websocket not installed?");
proc_handler_t *ret = (proc_handler_t *)calldata_ptr(&cd, "ph"); proc_handler_t *ret = (proc_handler_t *)calldata_ptr(&cd, "ph");
@ -97,7 +91,7 @@ static inline unsigned int obs_websocket_get_api_version(void)
if (!obs_websocket_ensure_ph()) if (!obs_websocket_ensure_ph())
return 0; return 0;
calldata_t cd = {0, 0, 0, 0}; calldata_t cd = {0};
if (!proc_handler_call(_ph, "get_api_version", &cd)) if (!proc_handler_call(_ph, "get_api_version", &cd))
return 1; // API v1 does not include get_api_version return 1; // API v1 does not include get_api_version
@ -110,11 +104,7 @@ static inline unsigned int obs_websocket_get_api_version(void)
} }
// Calls an obs-websocket request. Free response with `obs_websocket_request_response_free()` // Calls an obs-websocket request. Free response with `obs_websocket_request_response_free()`
static inline struct obs_websocket_request_response *obs_websocket_call_request(const char *request_type, obs_data_t *request_data static inline obs_websocket_request_response *obs_websocket_call_request(const char *request_type, obs_data_t *request_data = NULL)
#ifdef __cplusplus
= NULL
#endif
)
{ {
if (!obs_websocket_ensure_ph()) if (!obs_websocket_ensure_ph())
return NULL; return NULL;
@ -123,13 +113,14 @@ static inline struct obs_websocket_request_response *obs_websocket_call_request(
if (request_data) if (request_data)
request_data_string = obs_data_get_json(request_data); request_data_string = obs_data_get_json(request_data);
calldata_t cd = {0, 0, 0, 0}; calldata_t cd = {0};
calldata_set_string(&cd, "request_type", request_type); calldata_set_string(&cd, "request_type", request_type);
calldata_set_string(&cd, "request_data", request_data_string); calldata_set_string(&cd, "request_data", request_data_string);
proc_handler_call(_ph, "call_request", &cd); proc_handler_call(_ph, "call_request", &cd);
struct obs_websocket_request_response *ret = (struct obs_websocket_request_response *)calldata_ptr(&cd, "response"); auto ret = (struct obs_websocket_request_response *)calldata_ptr(&cd, "response");
calldata_free(&cd); calldata_free(&cd);
@ -149,46 +140,6 @@ static inline void obs_websocket_request_response_free(struct obs_websocket_requ
bfree(response); 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 ==================== */ /* ==================== VENDOR API FUNCTIONS ==================== */
// ALWAYS CALL ONLY VIA `obs_module_post_load()` CALLBACK! // ALWAYS CALL ONLY VIA `obs_module_post_load()` CALLBACK!
@ -198,7 +149,8 @@ static inline obs_websocket_vendor obs_websocket_register_vendor(const char *ven
if (!obs_websocket_ensure_ph()) if (!obs_websocket_ensure_ph())
return NULL; return NULL;
calldata_t cd = {0, 0, 0, 0}; calldata_t cd = {0};
calldata_set_string(&cd, "name", vendor_name); calldata_set_string(&cd, "name", vendor_name);
proc_handler_call(_ph, "vendor_register", &cd); proc_handler_call(_ph, "vendor_register", &cd);
@ -212,9 +164,12 @@ 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, 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) obs_websocket_request_callback_function request_callback, void *priv_data)
{ {
struct obs_websocket_request_callback cb = {request_callback, priv_data}; calldata_t cd = {0};
struct obs_websocket_request_callback cb = {};
cb.callback = request_callback;
cb.priv_data = priv_data;
calldata_t cd = {0, 0, 0, 0};
calldata_set_string(&cd, "type", request_type); calldata_set_string(&cd, "type", request_type);
calldata_set_ptr(&cd, "callback", &cb); calldata_set_ptr(&cd, "callback", &cb);
@ -227,7 +182,8 @@ static inline bool obs_websocket_vendor_register_request(obs_websocket_vendor ve
// Unregisters an existing vendor request // Unregisters an existing vendor request
static inline bool obs_websocket_vendor_unregister_request(obs_websocket_vendor vendor, const char *request_type) static inline bool obs_websocket_vendor_unregister_request(obs_websocket_vendor vendor, const char *request_type)
{ {
calldata_t cd = {0, 0, 0, 0}; calldata_t cd = {0};
calldata_set_string(&cd, "type", request_type); calldata_set_string(&cd, "type", request_type);
bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_unregister", &cd); bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_unregister", &cd);
@ -240,7 +196,8 @@ static inline bool obs_websocket_vendor_unregister_request(obs_websocket_vendor
// Emits an event under the vendor's name // Emits an event under the vendor's name
static inline bool obs_websocket_vendor_emit_event(obs_websocket_vendor vendor, const char *event_name, obs_data_t *event_data) static inline bool obs_websocket_vendor_emit_event(obs_websocket_vendor vendor, const char *event_name, obs_data_t *event_data)
{ {
calldata_t cd = {0, 0, 0, 0}; calldata_t cd = {0};
calldata_set_string(&cd, "type", event_name); calldata_set_string(&cd, "type", event_name);
calldata_set_ptr(&cd, "data", (void *)event_data); calldata_set_ptr(&cd, "data", (void *)event_data);

View File

@ -17,80 +17,60 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see <https://www.gnu.org/licenses/> with this program. If not, see <https://www.gnu.org/licenses/>
*/ */
#include <filesystem>
#include <obs-frontend-api.h> #include <obs-frontend-api.h>
#include "Config.h" #include "Config.h"
#include "utils/Crypto.h" #include "utils/Crypto.h"
#include "utils/Platform.h" #include "utils/Platform.h"
#include "utils/Obs.h"
#define CONFIG_SECTION_NAME "OBSWebSocket" #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 CONFIG_FILE_NAME "config.json" #define PARAM_FIRSTLOAD "FirstLoad"
#define PARAM_FIRSTLOAD "first_load" #define PARAM_ENABLED "ServerEnabled"
#define PARAM_ENABLED "server_enabled" #define PARAM_PORT "ServerPort"
#define PARAM_PORT "server_port" #define PARAM_ALERTS "AlertsEnabled"
#define PARAM_ALERTS "alerts_enabled" #define PARAM_AUTHREQUIRED "AuthRequired"
#define PARAM_AUTHREQUIRED "auth_required" #define PARAM_PASSWORD "ServerPassword"
#define PARAM_PASSWORD "server_password"
#define CMDLINE_WEBSOCKET_PORT "websocket_port" #define CMDLINE_WEBSOCKET_PORT "websocket_port"
#define CMDLINE_WEBSOCKET_IPV4_ONLY "websocket_ipv4_only" #define CMDLINE_WEBSOCKET_IPV4_ONLY "websocket_ipv4_only"
#define CMDLINE_WEBSOCKET_PASSWORD "websocket_password" #define CMDLINE_WEBSOCKET_PASSWORD "websocket_password"
#define CMDLINE_WEBSOCKET_DEBUG "websocket_debug" #define CMDLINE_WEBSOCKET_DEBUG "websocket_debug"
void Config::Load(json config) Config::Config()
{ {
// Only load from plugin config directory if there hasn't been a migration SetDefaultsToGlobalStore();
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 void Config::Load()
{
config_t *obsConfig = GetConfigStore();
if (!obsConfig) {
blog(LOG_ERROR, "[Config::Load] Unable to fetch OBS config!");
return;
} }
if (!config.is_object()) { FirstLoad = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD);
blog(LOG_INFO, "[Config::Load] Existing configuration not found, using defaults."); ServerEnabled = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED);
config = json::object(); 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);
if (config.contains(PARAM_FIRSTLOAD) && config[PARAM_FIRSTLOAD].is_boolean()) ServerPassword = config_get_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD);
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, // Set server password and save it to the config before processing overrides,
// so that there is always a true configured password regardless of if // so that there is always a true configured password regardless of if
// future loads use the override flag. // future loads use the override flag.
if (FirstLoad) { if (FirstLoad) {
FirstLoad = false; FirstLoad = false;
if (ServerPassword.empty()) { if (ServerPassword.isEmpty()) {
blog(LOG_INFO, "[Config::Load] (FirstLoad) Generating new server password."); blog(LOG_INFO, "[Config::Load] (FirstLoad) Generating new server password.");
ServerPassword = Utils::Crypto::GeneratePassword(); ServerPassword = QString::fromStdString(Utils::Crypto::GeneratePassword());
} else { } else {
blog(LOG_INFO, "[Config::Load] (FirstLoad) Not generating new password since one is already configured."); blog(LOG_INFO, "[Config::Load] (FirstLoad) Not generating new password since one is already configured.");
} }
Save(); Save();
} }
// If there are migrated settings, write them to disk before processing arguments.
if (!config.empty())
Save();
// Process `--websocket_port` override // Process `--websocket_port` override
QString portArgument = Utils::Platform::GetCommandLineArgument(CMDLINE_WEBSOCKET_PORT); QString portArgument = Utils::Platform::GetCommandLineArgument(CMDLINE_WEBSOCKET_PORT);
if (portArgument != "") { if (portArgument != "") {
@ -117,7 +97,7 @@ void Config::Load(json config)
blog(LOG_INFO, "[Config::Load] --websocket_password passed. Overriding WebSocket password."); blog(LOG_INFO, "[Config::Load] --websocket_password passed. Overriding WebSocket password.");
PasswordOverridden = true; PasswordOverridden = true;
AuthRequired = true; AuthRequired = true;
ServerPassword = passwordArgument.toStdString(); ServerPassword = passwordArgument;
} }
// Process `--websocket_debug` override // Process `--websocket_debug` override
@ -130,98 +110,43 @@ void Config::Load(json config)
void Config::Save() void Config::Save()
{ {
json config; config_t *obsConfig = GetConfigStore();
if (!obsConfig) {
blog(LOG_ERROR, "[Config::Save] Unable to fetch OBS config!");
return;
}
std::string configFilePath = Utils::Obs::StringHelper::GetModuleConfigPath(CONFIG_FILE_NAME); config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD, FirstLoad);
Utils::Json::GetJsonFileContent(configFilePath, config); // Fetch the existing config, which may not exist config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED, ServerEnabled);
if (!PortOverridden) {
config[PARAM_FIRSTLOAD] = FirstLoad.load(); config_set_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, ServerPort);
config[PARAM_ENABLED] = ServerEnabled.load(); }
if (!PortOverridden) config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, AlertsEnabled);
config[PARAM_PORT] = ServerPort.load();
config[PARAM_ALERTS] = AlertsEnabled.load();
if (!PasswordOverridden) { if (!PasswordOverridden) {
config[PARAM_AUTHREQUIRED] = AuthRequired.load(); config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired);
config[PARAM_PASSWORD] = ServerPassword; config_set_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD, QT_TO_UTF8(ServerPassword));
} }
if (Utils::Json::SetJsonFileContent(configFilePath, config)) config_save(obsConfig);
blog(LOG_DEBUG, "[Config::Save] Saved config.");
else
blog(LOG_ERROR, "[Config::Save] Failed to write config file!");
} }
// Finds any old values in global.ini and removes them, then returns the values as JSON void Config::SetDefaultsToGlobalStore()
json MigrateGlobalConfigData()
{ {
// Get existing global config config_t *obsConfig = GetConfigStore();
config_t *config = obs_frontend_get_global_config(); if (!obsConfig) {
json ret; blog(LOG_ERROR, "[Config::SetDefaultsToGlobalStore] Unable to fetch OBS config!");
return;
// 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);
} }
if (!ret.is_null()) { config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD, FirstLoad);
blog(LOG_INFO, "[MigrateGlobalConfigData] Some configurations have been migrated from old config"); config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED, ServerEnabled);
config_save(config); 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);
return ret; config_set_default_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD, QT_TO_UTF8(ServerPassword));
} }
// Migration from storing persistent data in obsWebSocketPersistentData.json to the module config directory config_t *Config::GetConfigStore()
// This will overwrite any persistent data in the destination. People doing manual OBS config modification be warned!
bool MigratePersistentData()
{ {
std::error_code ec; return obs_frontend_get_global_config();
// 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;
} }

View File

@ -23,12 +23,14 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <QString> #include <QString>
#include <util/config-file.h> #include <util/config-file.h>
#include "utils/Json.h"
#include "plugin-macros.generated.h" #include "plugin-macros.generated.h"
struct Config { struct Config {
void Load(json config = nullptr); Config();
void Load();
void Save(); void Save();
void SetDefaultsToGlobalStore();
static config_t *GetConfigStore();
std::atomic<bool> PortOverridden = false; std::atomic<bool> PortOverridden = false;
std::atomic<bool> PasswordOverridden = false; std::atomic<bool> PasswordOverridden = false;
@ -40,8 +42,5 @@ struct Config {
std::atomic<bool> DebugEnabled = false; std::atomic<bool> DebugEnabled = false;
std::atomic<bool> AlertsEnabled = false; std::atomic<bool> AlertsEnabled = false;
std::atomic<bool> AuthRequired = true; std::atomic<bool> AuthRequired = true;
std::string ServerPassword; QString ServerPassword;
}; };
json MigrateGlobalConfigData();
bool MigratePersistentData();

View File

@ -18,6 +18,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "WebSocketApi.h" #include "WebSocketApi.h"
#include "requesthandler/RequestHandler.h" #include "requesthandler/RequestHandler.h"
#include "obs-websocket.h"
#include "utils/Json.h" #include "utils/Json.h"
#define RETURN_STATUS(status) \ #define RETURN_STATUS(status) \
@ -47,19 +48,14 @@ WebSocketApi::WebSocketApi()
proc_handler_add(_procHandler, "bool get_api_version(out int version)", &get_api_version, nullptr); 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)", proc_handler_add(_procHandler, "bool call_request(in string request_type, in string request_data, out ptr response)",
&call_request, this); &call_request, nullptr);
proc_handler_add(_procHandler, "bool register_event_callback(in ptr callback, out bool success)", &register_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_register(in string name, out ptr vendor)", &vendor_register_cb, this);
proc_handler_add(_procHandler, proc_handler_add(_procHandler, "bool vendor_request_register(in ptr vendor, in string type, in ptr callback)",
"bool vendor_request_register(in ptr vendor, in string type, in ptr callback, out bool success)",
&vendor_request_register_cb, this); &vendor_request_register_cb, this);
proc_handler_add(_procHandler, "bool vendor_request_unregister(in ptr vendor, in string type, out bool success)", proc_handler_add(_procHandler, "bool vendor_request_unregister(in ptr vendor, in string type)",
&vendor_request_unregister_cb, this); &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)", proc_handler_add(_procHandler, "bool vendor_event_emit(in ptr vendor, in string type, in ptr data)", &vendor_event_emit_cb,
&vendor_event_emit_cb, this); this);
proc_handler_t *ph = obs_get_proc_handler(); proc_handler_t *ph = obs_get_proc_handler();
assert(ph != NULL); assert(ph != NULL);
@ -75,10 +71,6 @@ WebSocketApi::~WebSocketApi()
proc_handler_destroy(_procHandler); proc_handler_destroy(_procHandler);
size_t numEventCallbacks = _eventCallbacks.size();
_eventCallbacks.clear();
blog_debug("[WebSocketApi::~WebSocketApi] Deleted %ld event callbacks", numEventCallbacks);
for (auto vendor : _vendors) { for (auto vendor : _vendors) {
blog_debug("[WebSocketApi::~WebSocketApi] Deleting vendor: %s", vendor.first.c_str()); blog_debug("[WebSocketApi::~WebSocketApi] Deleting vendor: %s", vendor.first.c_str());
delete vendor.second; delete vendor.second;
@ -87,21 +79,9 @@ WebSocketApi::~WebSocketApi()
blog_debug("[WebSocketApi::~WebSocketApi] Finished."); blog_debug("[WebSocketApi::~WebSocketApi] Finished.");
} }
void WebSocketApi::BroadcastEvent(uint64_t requiredIntent, const std::string &eventType, const json &eventData, uint8_t rpcVersion) void WebSocketApi::SetEventCallback(EventCallback cb)
{ {
if (!_obsReady) _eventCallback = cb;
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, enum WebSocketApi::RequestReturnCode WebSocketApi::PerformVendorRequest(std::string vendorName, std::string requestType,
@ -146,27 +126,14 @@ void WebSocketApi::get_api_version(void *, calldata_t *cd)
RETURN_SUCCESS(); RETURN_SUCCESS();
} }
void WebSocketApi::call_request(void *priv_data, calldata_t *cd) void WebSocketApi::call_request(void *, 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_type = calldata_string(cd, "request_type");
const char *request_data = calldata_string(cd, "request_data"); const char *request_data = calldata_string(cd, "request_data");
if (!request_type) if (!request_type)
RETURN_FAILURE(); 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))); auto response = static_cast<obs_websocket_request_response *>(bzalloc(sizeof(struct obs_websocket_request_response)));
if (!response) if (!response)
RETURN_FAILURE(); RETURN_FAILURE();
@ -195,52 +162,6 @@ void WebSocketApi::call_request(void *priv_data, calldata_t *cd)
RETURN_SUCCESS(); 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) void WebSocketApi::vendor_register_cb(void *priv_data, calldata_t *cd)
{ {
auto c = static_cast<WebSocketApi *>(priv_data); auto c = static_cast<WebSocketApi *>(priv_data);
@ -251,7 +172,7 @@ void WebSocketApi::vendor_register_cb(void *priv_data, calldata_t *cd)
RETURN_FAILURE(); RETURN_FAILURE();
} }
// Theoretically doesn't need a mutex due to module load being single-thread, but it's good to be safe. // Theoretically doesn't need a mutex, but it's good to be safe.
std::unique_lock l(c->_mutex); std::unique_lock l(c->_mutex);
if (c->_vendors.count(vendorName)) { if (c->_vendors.count(vendorName)) {
@ -368,10 +289,10 @@ void WebSocketApi::vendor_event_emit_cb(void *priv_data, calldata_t *cd)
auto eventData = static_cast<obs_data_t *>(voidEventData); auto eventData = static_cast<obs_data_t *>(voidEventData);
if (!c->_vendorEventCallback) if (!c->_eventCallback)
RETURN_FAILURE(); RETURN_FAILURE();
c->_vendorEventCallback(v->_name, eventType, eventData); c->_eventCallback(v->_name, eventType, eventData);
RETURN_SUCCESS(); RETURN_SUCCESS();
} }

View File

@ -23,12 +23,9 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <map> #include <map>
#include <mutex> #include <mutex>
#include <shared_mutex> #include <shared_mutex>
#include <atomic>
#include <obs.h> #include <obs.h>
#include <obs-websocket-api.h>
#include "utils/Json.h" #include "../lib/obs-websocket-api.h"
#include "plugin-macros.generated.h"
class WebSocketApi { class WebSocketApi {
public: public:
@ -38,6 +35,8 @@ public:
NoVendorRequest, NoVendorRequest,
}; };
typedef std::function<void(std::string, std::string, obs_data_t *)> EventCallback;
struct Vendor { struct Vendor {
std::shared_mutex _mutex; std::shared_mutex _mutex;
std::string _name; std::string _name;
@ -46,44 +45,23 @@ public:
WebSocketApi(); WebSocketApi();
~WebSocketApi(); ~WebSocketApi();
void BroadcastEvent(uint64_t requiredIntent, const std::string &eventType, const json &eventData = nullptr,
uint8_t rpcVersion = 0); void SetEventCallback(EventCallback cb);
void SetObsReady(bool ready) { _obsReady = ready; }
enum RequestReturnCode PerformVendorRequest(std::string vendorName, std::string requestName, obs_data_t *requestData, enum RequestReturnCode PerformVendorRequest(std::string vendorName, std::string requestName, obs_data_t *requestData,
obs_data_t *responseData); 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_ph_cb(void *priv_data, calldata_t *cd);
static void get_api_version(void *, calldata_t *cd); static void get_api_version(void *, calldata_t *cd);
static void call_request(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_register_cb(void *priv_data, calldata_t *cd);
static void vendor_request_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_request_unregister_cb(void *priv_data, calldata_t *cd);
static void vendor_event_emit_cb(void *priv_data, calldata_t *cd); static void vendor_event_emit_cb(void *priv_data, calldata_t *cd);
private:
std::shared_mutex _mutex; std::shared_mutex _mutex;
EventCallback _eventCallback;
proc_handler_t *_procHandler; proc_handler_t *_procHandler;
std::map<std::string, Vendor *> _vendors; std::map<std::string, Vendor *> _vendors;
std::vector<obs_websocket_event_callback> _eventCallbacks;
std::atomic<bool> _obsReady = false;
VendorEventCallback _vendorEventCallback;
}; };

View File

@ -27,11 +27,10 @@ EventHandler::EventHandler()
signal_handler_t *coreSignalHandler = obs_get_signal_handler(); signal_handler_t *coreSignalHandler = obs_get_signal_handler();
if (coreSignalHandler) { if (coreSignalHandler) {
coreSignals.emplace_back(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this); signal_handler_connect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this);
coreSignals.emplace_back(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this); signal_handler_connect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this);
coreSignals.emplace_back(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this); signal_handler_connect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this);
coreSignals.emplace_back(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this); signal_handler_connect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this);
coreSignals.emplace_back(coreSignalHandler, "source_update", SourceUpdatedMultiHandler, this);
} else { } else {
blog(LOG_ERROR, "[EventHandler::EventHandler] Unable to get libobs signal handler!"); blog(LOG_ERROR, "[EventHandler::EventHandler] Unable to get libobs signal handler!");
} }
@ -45,34 +44,36 @@ EventHandler::~EventHandler()
obs_frontend_remove_event_callback(OnFrontendEvent, this); obs_frontend_remove_event_callback(OnFrontendEvent, this);
coreSignals.clear(); signal_handler_t *coreSignalHandler = obs_get_signal_handler();
if (coreSignalHandler) {
// Revoke callbacks of all inputs and scenes, in case some still have our callbacks attached signal_handler_disconnect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this);
auto enumInputs = [](void *param, obs_source_t *source) { signal_handler_disconnect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this);
auto eventHandler = static_cast<EventHandler *>(param); signal_handler_disconnect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this);
eventHandler->DisconnectSourceSignals(source); signal_handler_disconnect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this);
return true; } else {
}; blog(LOG_ERROR, "[EventHandler::~EventHandler] Unable to get libobs signal handler!");
obs_enum_sources(enumInputs, this); }
auto enumScenes = [](void *param, obs_source_t *source) {
auto eventHandler = static_cast<EventHandler *>(param);
eventHandler->DisconnectSourceSignals(source);
return true;
};
obs_enum_scenes(enumScenes, this);
blog_debug("[EventHandler::~EventHandler] Finished."); blog_debug("[EventHandler::~EventHandler] Finished.");
} }
// Function to increment or decrement refcounts for high volume event subscriptions void EventHandler::SetBroadcastCallback(EventHandler::BroadcastCallback cb)
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 (type) {
if ((eventSubscriptions & EventSubscription::InputVolumeMeters) != 0) { if ((eventSubscriptions & EventSubscription::InputVolumeMeters) != 0) {
if (_inputVolumeMetersRef.fetch_add(1) == 0) { if (_inputVolumeMetersRef.fetch_add(1) == 0) {
if (_inputVolumeMetersHandler) if (_inputVolumeMetersHandler)
blog(LOG_WARNING, blog(LOG_WARNING, "[EventHandler::ProcessSubscription] Input volume meter handler already exists!");
"[EventHandler::ProcessSubscription] Input volume meter handler already exists!");
else else
_inputVolumeMetersHandler = std::make_unique<Utils::Obs::VolumeMeter::Handler>( _inputVolumeMetersHandler = std::make_unique<Utils::Obs::VolumeMeter::Handler>(
std::bind(&EventHandler::HandleInputVolumeMeters, this, std::placeholders::_1)); std::bind(&EventHandler::HandleInputVolumeMeters, this, std::placeholders::_1));
@ -84,7 +85,11 @@ void EventHandler::ProcessSubscriptionChange(bool type, uint64_t eventSubscripti
_inputShowStateChangedRef++; _inputShowStateChangedRef++;
if ((eventSubscriptions & EventSubscription::SceneItemTransformChanged) != 0) if ((eventSubscriptions & EventSubscription::SceneItemTransformChanged) != 0)
_sceneItemTransformChangedRef++; _sceneItemTransformChangedRef++;
} else { }
// Function to decrement refcounts for high volume event subscriptions
void EventHandler::ProcessUnsubscription(uint64_t eventSubscriptions)
{
if ((eventSubscriptions & EventSubscription::InputVolumeMeters) != 0) { if ((eventSubscriptions & EventSubscription::InputVolumeMeters) != 0) {
if (_inputVolumeMetersRef.fetch_sub(1) == 1) if (_inputVolumeMetersRef.fetch_sub(1) == 1)
_inputVolumeMetersHandler.reset(); _inputVolumeMetersHandler.reset();
@ -95,16 +100,15 @@ void EventHandler::ProcessSubscriptionChange(bool type, uint64_t eventSubscripti
_inputShowStateChangedRef--; _inputShowStateChangedRef--;
if ((eventSubscriptions & EventSubscription::SceneItemTransformChanged) != 0) if ((eventSubscriptions & EventSubscription::SceneItemTransformChanged) != 0)
_sceneItemTransformChangedRef--; _sceneItemTransformChangedRef--;
}
} }
// Function required in order to use default arguments // Function required in order to use default arguments
void EventHandler::BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion) void EventHandler::BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion)
{ {
if (!_eventCallback) if (!_broadcastCallback)
return; return;
_eventCallback(requiredIntent, eventType, eventData, rpcVersion); _broadcastCallback(requiredIntent, eventType, eventData, rpcVersion);
} }
// Connect source signals for Inputs, Scenes, and Transitions. Filters are automatically connected. // Connect source signals for Inputs, Scenes, and Transitions. Filters are automatically connected.
@ -369,21 +373,12 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_
break; break;
case OBS_FRONTEND_EVENT_RECORDING_STARTED: case OBS_FRONTEND_EVENT_RECORDING_STARTED:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_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; break;
case OBS_FRONTEND_EVENT_RECORDING_STOPPING: case OBS_FRONTEND_EVENT_RECORDING_STOPPING:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING); eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING);
break; break;
case OBS_FRONTEND_EVENT_RECORDING_STOPPED: case OBS_FRONTEND_EVENT_RECORDING_STOPPED:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED); eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED);
eventHandler->recordFileChangedSignal.Disconnect();
break; break;
case OBS_FRONTEND_EVENT_RECORDING_PAUSED: case OBS_FRONTEND_EVENT_RECORDING_PAUSED:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_PAUSED); eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_PAUSED);
@ -579,26 +574,6 @@ 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 *) void EventHandler::StreamOutputReconnectHandler(void *param, calldata_t *)
{ {
auto eventHandler = static_cast<EventHandler *>(param); auto eventHandler = static_cast<EventHandler *>(param);

View File

@ -34,26 +34,21 @@ public:
EventHandler(); EventHandler();
~EventHandler(); ~EventHandler();
void ProcessSubscriptionChange(bool type, uint64_t eventSubscriptions);
// Callback when an event fires
typedef std::function<void(uint64_t, std::string, json, uint8_t)> typedef std::function<void(uint64_t, std::string, json, uint8_t)>
EventCallback; // uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion BroadcastCallback; // uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion
inline void SetEventCallback(EventCallback cb) { _eventCallback = cb; } void SetBroadcastCallback(BroadcastCallback cb);
// Callback when OBS becomes ready or non-ready
typedef std::function<void(bool)> ObsReadyCallback; // bool ready typedef std::function<void(bool)> ObsReadyCallback; // bool ready
inline void SetObsReadyCallback(ObsReadyCallback cb) { _obsReadyCallback = cb; } void SetObsReadyCallback(ObsReadyCallback cb);
void ProcessSubscription(uint64_t eventSubscriptions);
void ProcessUnsubscription(uint64_t eventSubscriptions);
private: private:
EventCallback _eventCallback; BroadcastCallback _broadcastCallback;
ObsReadyCallback _obsReadyCallback; ObsReadyCallback _obsReadyCallback;
std::atomic<bool> _obsReady = false; std::atomic<bool> _obsReady = false;
std::vector<OBSSignal> coreSignals;
OBSSignal recordFileChangedSignal;
std::unique_ptr<Utils::Obs::VolumeMeter::Handler> _inputVolumeMetersHandler; std::unique_ptr<Utils::Obs::VolumeMeter::Handler> _inputVolumeMetersHandler;
std::atomic<uint64_t> _inputVolumeMetersRef = 0; std::atomic<uint64_t> _inputVolumeMetersRef = 0;
std::atomic<uint64_t> _inputActiveStateChangedRef = 0; std::atomic<uint64_t> _inputActiveStateChangedRef = 0;
@ -74,10 +69,9 @@ private:
static void SourceCreatedMultiHandler(void *param, calldata_t *data); static void SourceCreatedMultiHandler(void *param, calldata_t *data);
static void SourceDestroyedMultiHandler(void *param, calldata_t *data); static void SourceDestroyedMultiHandler(void *param, calldata_t *data);
static void SourceRemovedMultiHandler(void *param, calldata_t *data); static void SourceRemovedMultiHandler(void *param, calldata_t *data);
static void SourceRenamedMultiHandler(void *param, calldata_t *data);
static void SourceUpdatedMultiHandler(void *param, calldata_t *data);
// Signal handler: media sources // Signal handler: source
static void SourceRenamedMultiHandler(void *param, calldata_t *data);
static void SourceMediaPauseMultiHandler(void *param, calldata_t *data); static void SourceMediaPauseMultiHandler(void *param, calldata_t *data);
static void SourceMediaPlayMultiHandler(void *param, calldata_t *data); static void SourceMediaPlayMultiHandler(void *param, calldata_t *data);
static void SourceMediaRestartMultiHandler(void *param, calldata_t *data); static void SourceMediaRestartMultiHandler(void *param, calldata_t *data);
@ -112,7 +106,7 @@ private:
void HandleInputCreated(obs_source_t *source); void HandleInputCreated(obs_source_t *source);
void HandleInputRemoved(obs_source_t *source); void HandleInputRemoved(obs_source_t *source);
void HandleInputNameChanged(obs_source_t *source, std::string oldInputName, std::string inputName); void HandleInputNameChanged(obs_source_t *source, std::string oldInputName, std::string inputName);
void HandleInputSettingsChanged(obs_source_t *source); void HandleInputVolumeMeters(std::vector<json> inputs); // AudioMeter::Handler callback
static void HandleInputActiveStateChanged(void *param, static void HandleInputActiveStateChanged(void *param,
calldata_t *data); // Direct callback calldata_t *data); // Direct callback
static void HandleInputShowStateChanged(void *param, static void HandleInputShowStateChanged(void *param,
@ -129,7 +123,6 @@ private:
calldata_t *data); // Direct callback calldata_t *data); // Direct callback
static void HandleInputAudioMonitorTypeChanged(void *param, static void HandleInputAudioMonitorTypeChanged(void *param,
calldata_t *data); // Direct callback calldata_t *data); // Direct callback
void HandleInputVolumeMeters(std::vector<json> inputs); // AudioMeter::Handler callback
// Transitions // Transitions
void HandleCurrentSceneTransitionChanged(); void HandleCurrentSceneTransitionChanged();
@ -152,13 +145,11 @@ private:
void HandleSourceFilterRemoved(obs_source_t *source, obs_source_t *filter); void HandleSourceFilterRemoved(obs_source_t *source, obs_source_t *filter);
static void HandleSourceFilterNameChanged(void *param, 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 static void HandleSourceFilterEnableStateChanged(void *param, calldata_t *data); // Direct callback
// Outputs // Outputs
void HandleStreamStateChanged(ObsOutputState state); void HandleStreamStateChanged(ObsOutputState state);
void HandleRecordStateChanged(ObsOutputState state); void HandleRecordStateChanged(ObsOutputState state);
static void HandleRecordFileChanged(void *param, calldata_t *data); // Direct callback
void HandleReplayBufferStateChanged(ObsOutputState state); void HandleReplayBufferStateChanged(ObsOutputState state);
void HandleVirtualcamStateChanged(ObsOutputState state); void HandleVirtualcamStateChanged(ObsOutputState state);
void HandleReplayBufferSaved(); void HandleReplayBufferSaved();

View File

@ -163,32 +163,6 @@ void EventHandler::HandleSourceFilterNameChanged(void *param, calldata_t *data)
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterNameChanged", eventData); 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. * A source filter's enable state has changed.
* *

View File

@ -23,7 +23,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
* An input has been created. * An input has been created.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField inputKind | String | The kind of the input * @dataField inputKind | String | The kind of the input
* @dataField unversionedInputKind | String | The unversioned kind of input (aka no `_v2` stuff) * @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 * @dataField inputSettings | Object | The settings configured to the input when it was created
@ -45,7 +44,6 @@ void EventHandler::HandleInputCreated(obs_source_t *source)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputKind"] = inputKind; eventData["inputKind"] = inputKind;
eventData["unversionedInputKind"] = obs_source_get_unversioned_id(source); eventData["unversionedInputKind"] = obs_source_get_unversioned_id(source);
eventData["inputSettings"] = Utils::Json::ObsDataToJson(inputSettings); eventData["inputSettings"] = Utils::Json::ObsDataToJson(inputSettings);
@ -57,7 +55,6 @@ void EventHandler::HandleInputCreated(obs_source_t *source)
* An input has been removed. * An input has been removed.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* *
* @eventType InputRemoved * @eventType InputRemoved
* @eventSubscription Inputs * @eventSubscription Inputs
@ -71,14 +68,12 @@ void EventHandler::HandleInputRemoved(obs_source_t *source)
{ {
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
BroadcastEvent(EventSubscription::Inputs, "InputRemoved", eventData); BroadcastEvent(EventSubscription::Inputs, "InputRemoved", eventData);
} }
/** /**
* The name of an input has changed. * The name of an input has changed.
* *
* @dataField inputUuid | String | UUID of the input
* @dataField oldInputName | String | Old name of the input * @dataField oldInputName | String | Old name of the input
* @dataField inputName | String | New name of the input * @dataField inputName | String | New name of the input
* *
@ -90,50 +85,20 @@ void EventHandler::HandleInputRemoved(obs_source_t *source)
* @api events * @api events
* @category inputs * @category inputs
*/ */
void EventHandler::HandleInputNameChanged(obs_source_t *source, std::string oldInputName, std::string inputName) void EventHandler::HandleInputNameChanged(obs_source_t *, std::string oldInputName, std::string inputName)
{ {
json eventData; json eventData;
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["oldInputName"] = oldInputName; eventData["oldInputName"] = oldInputName;
eventData["inputName"] = inputName; eventData["inputName"] = inputName;
BroadcastEvent(EventSubscription::Inputs, "InputNameChanged", eventData); 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. * An input's active state has changed.
* *
* When an input is active, it means it's being shown by the program feed. * When an input is active, it means it's being shown by the program feed.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField videoActive | Boolean | Whether the input is active * @dataField videoActive | Boolean | Whether the input is active
* *
* @eventType InputActiveStateChanged * @eventType InputActiveStateChanged
@ -160,7 +125,6 @@ void EventHandler::HandleInputActiveStateChanged(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["videoActive"] = obs_source_active(source); eventData["videoActive"] = obs_source_active(source);
eventHandler->BroadcastEvent(EventSubscription::InputActiveStateChanged, "InputActiveStateChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::InputActiveStateChanged, "InputActiveStateChanged", eventData);
} }
@ -171,7 +135,6 @@ 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. * 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 inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField videoShowing | Boolean | Whether the input is showing * @dataField videoShowing | Boolean | Whether the input is showing
* *
* @eventType InputShowStateChanged * @eventType InputShowStateChanged
@ -198,7 +161,6 @@ void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["videoShowing"] = obs_source_showing(source); eventData["videoShowing"] = obs_source_showing(source);
eventHandler->BroadcastEvent(EventSubscription::InputShowStateChanged, "InputShowStateChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::InputShowStateChanged, "InputShowStateChanged", eventData);
} }
@ -207,7 +169,6 @@ void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data)
* An input's mute state has changed. * An input's mute state has changed.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField inputMuted | Boolean | Whether the input is muted * @dataField inputMuted | Boolean | Whether the input is muted
* *
* @eventType InputMuteStateChanged * @eventType InputMuteStateChanged
@ -231,7 +192,6 @@ void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputMuted"] = obs_source_muted(source); eventData["inputMuted"] = obs_source_muted(source);
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputMuteStateChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputMuteStateChanged", eventData);
} }
@ -240,7 +200,6 @@ void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data)
* An input's volume level has changed. * An input's volume level has changed.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField inputVolumeMul | Number | New volume level multiplier * @dataField inputVolumeMul | Number | New volume level multiplier
* @dataField inputVolumeDb | Number | New volume level in dB * @dataField inputVolumeDb | Number | New volume level in dB
* *
@ -272,7 +231,6 @@ void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputVolumeMul"] = inputVolumeMul; eventData["inputVolumeMul"] = inputVolumeMul;
eventData["inputVolumeDb"] = inputVolumeDb; eventData["inputVolumeDb"] = inputVolumeDb;
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputVolumeChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputVolumeChanged", eventData);
@ -281,8 +239,7 @@ void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data)
/** /**
* The audio balance value of an input has changed. * The audio balance value of an input has changed.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the affected input
* @dataField inputUuid | String | UUID of the input
* @dataField inputAudioBalance | Number | New audio balance value of the input * @dataField inputAudioBalance | Number | New audio balance value of the input
* *
* @eventType InputAudioBalanceChanged * @eventType InputAudioBalanceChanged
@ -308,7 +265,6 @@ void EventHandler::HandleInputAudioBalanceChanged(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputAudioBalance"] = inputAudioBalance; eventData["inputAudioBalance"] = inputAudioBalance;
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioBalanceChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioBalanceChanged", eventData);
} }
@ -317,7 +273,6 @@ void EventHandler::HandleInputAudioBalanceChanged(void *param, calldata_t *data)
* The sync offset of an input has changed. * The sync offset of an input has changed.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField inputAudioSyncOffset | Number | New sync offset in milliseconds * @dataField inputAudioSyncOffset | Number | New sync offset in milliseconds
* *
* @eventType InputAudioSyncOffsetChanged * @eventType InputAudioSyncOffsetChanged
@ -343,7 +298,6 @@ void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *da
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputAudioSyncOffset"] = inputAudioSyncOffset / 1000000; eventData["inputAudioSyncOffset"] = inputAudioSyncOffset / 1000000;
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioSyncOffsetChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioSyncOffsetChanged", eventData);
} }
@ -352,7 +306,6 @@ void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *da
* The audio tracks of an input have changed. * The audio tracks of an input have changed.
* *
* @dataField inputName | String | Name of the input * @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 * @dataField inputAudioTracks | Object | Object of audio tracks along with their associated enable states
* *
* @eventType InputAudioTracksChanged * @eventType InputAudioTracksChanged
@ -383,7 +336,6 @@ void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputAudioTracks"] = inputAudioTracks; eventData["inputAudioTracks"] = inputAudioTracks;
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioTracksChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioTracksChanged", eventData);
} }
@ -398,7 +350,6 @@ void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data)
* - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` * - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT`
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField monitorType | String | New monitor type of the input * @dataField monitorType | String | New monitor type of the input
* *
* @eventType InputAudioMonitorTypeChanged * @eventType InputAudioMonitorTypeChanged
@ -424,7 +375,6 @@ void EventHandler::HandleInputAudioMonitorTypeChanged(void *param, calldata_t *d
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["monitorType"] = monitorType; eventData["monitorType"] = monitorType;
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioMonitorTypeChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioMonitorTypeChanged", eventData);
} }

View File

@ -124,7 +124,6 @@ void EventHandler::SourceMediaPreviousMultiHandler(void *param, calldata_t *data
* A media input has started playing. * A media input has started playing.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* *
* @eventType MediaInputPlaybackStarted * @eventType MediaInputPlaybackStarted
* @eventSubscription MediaInputs * @eventSubscription MediaInputs
@ -147,7 +146,6 @@ void EventHandler::HandleMediaInputPlaybackStarted(void *param, calldata_t *data
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventHandler->BroadcastEvent(EventSubscription::MediaInputs, "MediaInputPlaybackStarted", eventData); eventHandler->BroadcastEvent(EventSubscription::MediaInputs, "MediaInputPlaybackStarted", eventData);
} }
@ -155,7 +153,6 @@ void EventHandler::HandleMediaInputPlaybackStarted(void *param, calldata_t *data
* A media input has finished playing. * A media input has finished playing.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* *
* @eventType MediaInputPlaybackEnded * @eventType MediaInputPlaybackEnded
* @eventSubscription MediaInputs * @eventSubscription MediaInputs
@ -178,7 +175,6 @@ void EventHandler::HandleMediaInputPlaybackEnded(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventHandler->BroadcastEvent(EventSubscription::MediaInputs, "MediaInputPlaybackEnded", eventData); eventHandler->BroadcastEvent(EventSubscription::MediaInputs, "MediaInputPlaybackEnded", eventData);
} }
@ -186,7 +182,6 @@ void EventHandler::HandleMediaInputPlaybackEnded(void *param, calldata_t *data)
* An action has been performed on an input. * An action has been performed on an input.
* *
* @dataField inputName | String | Name of the 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 * @dataField mediaAction | String | Action performed on the input. See `ObsMediaInputAction` enum
* *
* @eventType MediaInputActionTriggered * @eventType MediaInputActionTriggered
@ -201,7 +196,6 @@ void EventHandler::HandleMediaInputActionTriggered(obs_source_t *source, ObsMedi
{ {
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["mediaAction"] = GetMediaInputActionString(action); eventData["mediaAction"] = GetMediaInputActionString(action);
BroadcastEvent(EventSubscription::MediaInputs, "MediaInputActionTriggered", eventData); BroadcastEvent(EventSubscription::MediaInputs, "MediaInputActionTriggered", eventData);
} }

View File

@ -87,28 +87,6 @@ void EventHandler::HandleRecordStateChanged(ObsOutputState state)
BroadcastEvent(EventSubscription::Outputs, "RecordStateChanged", eventData); 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. * The state of the replay buffer output has changed.
* *

View File

@ -23,9 +23,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
* A scene item has been created. * A scene item has been created.
* *
* @dataField sceneName | String | Name of the scene the item was added to * @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 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 sceneItemId | Number | Numeric ID of the scene item
* @dataField sceneItemIndex | Number | Index position of the item * @dataField sceneItemIndex | Number | Index position of the item
* *
@ -51,9 +49,7 @@ void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data)
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); 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["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["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
eventData["sceneItemIndex"] = obs_sceneitem_get_order_position(sceneItem); eventData["sceneItemIndex"] = obs_sceneitem_get_order_position(sceneItem);
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemCreated", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemCreated", eventData);
@ -65,9 +61,7 @@ void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data)
* This event is not emitted when the scene the item is in is removed. * 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 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 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 sceneItemId | Number | Numeric ID of the scene item
* *
* @eventType SceneItemRemoved * @eventType SceneItemRemoved
@ -92,9 +86,7 @@ void EventHandler::HandleSceneItemRemoved(void *param, calldata_t *data)
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); 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["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["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemRemoved", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemRemoved", eventData);
} }
@ -103,7 +95,6 @@ void EventHandler::HandleSceneItemRemoved(void *param, calldata_t *data)
* A scene's item list has been reindexed. * A scene's item list has been reindexed.
* *
* @dataField sceneName | String | Name of the scene * @dataField sceneName | String | Name of the scene
* @dataField sceneUuid | String | UUID of the scene
* @dataField sceneItems | Array<Object> | Array of scene item objects * @dataField sceneItems | Array<Object> | Array of scene item objects
* *
* @eventType SceneItemListReindexed * @eventType SceneItemListReindexed
@ -124,7 +115,6 @@ void EventHandler::HandleSceneItemListReindexed(void *param, calldata_t *data)
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); 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); eventData["sceneItems"] = Utils::Obs::ArrayHelper::GetSceneItemList(scene, true);
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemListReindexed", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemListReindexed", eventData);
} }
@ -133,7 +123,6 @@ void EventHandler::HandleSceneItemListReindexed(void *param, calldata_t *data)
* A scene item's enable state has changed. * A scene item's enable state has changed.
* *
* @dataField sceneName | String | Name of the scene the item is in * @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 sceneItemId | Number | Numeric ID of the scene item
* @dataField sceneItemEnabled | Boolean | Whether the scene item is enabled (visible) * @dataField sceneItemEnabled | Boolean | Whether the scene item is enabled (visible)
* *
@ -161,7 +150,6 @@ void EventHandler::HandleSceneItemEnableStateChanged(void *param, calldata_t *da
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); 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["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
eventData["sceneItemEnabled"] = sceneItemEnabled; eventData["sceneItemEnabled"] = sceneItemEnabled;
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemEnableStateChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemEnableStateChanged", eventData);
@ -171,7 +159,6 @@ void EventHandler::HandleSceneItemEnableStateChanged(void *param, calldata_t *da
* A scene item's lock state has changed. * A scene item's lock state has changed.
* *
* @dataField sceneName | String | Name of the scene the item is in * @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 sceneItemId | Number | Numeric ID of the scene item
* @dataField sceneItemLocked | Boolean | Whether the scene item is locked * @dataField sceneItemLocked | Boolean | Whether the scene item is locked
* *
@ -199,7 +186,6 @@ void EventHandler::HandleSceneItemLockStateChanged(void *param, calldata_t *data
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); 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["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
eventData["sceneItemLocked"] = sceneItemLocked; eventData["sceneItemLocked"] = sceneItemLocked;
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemLockStateChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemLockStateChanged", eventData);
@ -209,7 +195,6 @@ void EventHandler::HandleSceneItemLockStateChanged(void *param, calldata_t *data
* A scene item has been selected in the Ui. * A scene item has been selected in the Ui.
* *
* @dataField sceneName | String | Name of the scene the item is in * @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 sceneItemId | Number | Numeric ID of the scene item
* *
* @eventType SceneItemSelected * @eventType SceneItemSelected
@ -234,7 +219,6 @@ void EventHandler::HandleSceneItemSelected(void *param, calldata_t *data)
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); 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["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemSelected", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemSelected", eventData);
} }
@ -243,7 +227,6 @@ void EventHandler::HandleSceneItemSelected(void *param, calldata_t *data)
* The transform/crop of a scene item has changed. * The transform/crop of a scene item has changed.
* *
* @dataField sceneName | String | The name of the scene the item is in * @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 sceneItemId | Number | Numeric ID of the scene item
* @dataField sceneItemTransform | Object | New transform/crop info of the scene item * @dataField sceneItemTransform | Object | New transform/crop info of the scene item
* *
@ -272,7 +255,6 @@ void EventHandler::HandleSceneItemTransformChanged(void *param, calldata_t *data
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); 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["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
eventData["sceneItemTransform"] = Utils::Obs::ObjectHelper::GetSceneItemTransform(sceneItem); eventData["sceneItemTransform"] = Utils::Obs::ObjectHelper::GetSceneItemTransform(sceneItem);
eventHandler->BroadcastEvent(EventSubscription::SceneItemTransformChanged, "SceneItemTransformChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItemTransformChanged, "SceneItemTransformChanged", eventData);

View File

@ -23,7 +23,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
* A new scene has been created. * A new scene has been created.
* *
* @dataField sceneName | String | Name of the new scene * @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 * @dataField isGroup | Boolean | Whether the new scene is a group
* *
* @eventType SceneCreated * @eventType SceneCreated
@ -38,7 +37,6 @@ void EventHandler::HandleSceneCreated(obs_source_t *source)
{ {
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(source); eventData["sceneName"] = obs_source_get_name(source);
eventData["sceneUuid"] = obs_source_get_uuid(source);
eventData["isGroup"] = obs_source_is_group(source); eventData["isGroup"] = obs_source_is_group(source);
BroadcastEvent(EventSubscription::Scenes, "SceneCreated", eventData); BroadcastEvent(EventSubscription::Scenes, "SceneCreated", eventData);
} }
@ -47,7 +45,6 @@ void EventHandler::HandleSceneCreated(obs_source_t *source)
* A scene has been removed. * A scene has been removed.
* *
* @dataField sceneName | String | Name of the removed scene * @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 * @dataField isGroup | Boolean | Whether the scene was a group
* *
* @eventType SceneRemoved * @eventType SceneRemoved
@ -62,7 +59,6 @@ void EventHandler::HandleSceneRemoved(obs_source_t *source)
{ {
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(source); eventData["sceneName"] = obs_source_get_name(source);
eventData["sceneUuid"] = obs_source_get_uuid(source);
eventData["isGroup"] = obs_source_is_group(source); eventData["isGroup"] = obs_source_is_group(source);
BroadcastEvent(EventSubscription::Scenes, "SceneRemoved", eventData); BroadcastEvent(EventSubscription::Scenes, "SceneRemoved", eventData);
} }
@ -70,7 +66,6 @@ void EventHandler::HandleSceneRemoved(obs_source_t *source)
/** /**
* The name of a scene has changed. * The name of a scene has changed.
* *
* @dataField sceneUuid | String | UUID of the scene
* @dataField oldSceneName | String | Old name of the scene * @dataField oldSceneName | String | Old name of the scene
* @dataField sceneName | String | New name of the scene * @dataField sceneName | String | New name of the scene
* *
@ -82,10 +77,9 @@ void EventHandler::HandleSceneRemoved(obs_source_t *source)
* @api events * @api events
* @category scenes * @category scenes
*/ */
void EventHandler::HandleSceneNameChanged(obs_source_t *source, std::string oldSceneName, std::string sceneName) void EventHandler::HandleSceneNameChanged(obs_source_t *, std::string oldSceneName, std::string sceneName)
{ {
json eventData; json eventData;
eventData["sceneUuid"] = obs_source_get_uuid(source);
eventData["oldSceneName"] = oldSceneName; eventData["oldSceneName"] = oldSceneName;
eventData["sceneName"] = sceneName; eventData["sceneName"] = sceneName;
BroadcastEvent(EventSubscription::Scenes, "SceneNameChanged", eventData); BroadcastEvent(EventSubscription::Scenes, "SceneNameChanged", eventData);
@ -95,7 +89,6 @@ void EventHandler::HandleSceneNameChanged(obs_source_t *source, std::string oldS
* The current program scene has changed. * The current program scene has changed.
* *
* @dataField sceneName | String | Name of the scene that was switched to * @dataField sceneName | String | Name of the scene that was switched to
* @dataField sceneUuid | String | UUID of the scene that was switched to
* *
* @eventType CurrentProgramSceneChanged * @eventType CurrentProgramSceneChanged
* @eventSubscription Scenes * @eventSubscription Scenes
@ -111,7 +104,6 @@ void EventHandler::HandleCurrentProgramSceneChanged()
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(currentScene); eventData["sceneName"] = obs_source_get_name(currentScene);
eventData["sceneUuid"] = obs_source_get_uuid(currentScene);
BroadcastEvent(EventSubscription::Scenes, "CurrentProgramSceneChanged", eventData); BroadcastEvent(EventSubscription::Scenes, "CurrentProgramSceneChanged", eventData);
} }
@ -119,7 +111,6 @@ void EventHandler::HandleCurrentProgramSceneChanged()
* The current preview scene has changed. * The current preview scene has changed.
* *
* @dataField sceneName | String | Name of the scene that was switched to * @dataField sceneName | String | Name of the scene that was switched to
* @dataField sceneUuid | String | UUID of the scene that was switched to
* *
* @eventType CurrentPreviewSceneChanged * @eventType CurrentPreviewSceneChanged
* @eventSubscription Scenes * @eventSubscription Scenes
@ -139,7 +130,6 @@ void EventHandler::HandleCurrentPreviewSceneChanged()
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(currentPreviewScene); eventData["sceneName"] = obs_source_get_name(currentPreviewScene);
eventData["sceneUuid"] = obs_source_get_uuid(currentPreviewScene);
BroadcastEvent(EventSubscription::Scenes, "CurrentPreviewSceneChanged", eventData); BroadcastEvent(EventSubscription::Scenes, "CurrentPreviewSceneChanged", eventData);
} }

View File

@ -23,7 +23,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
* The current scene transition has changed. * The current scene transition has changed.
* *
* @dataField transitionName | String | Name of the new transition * @dataField transitionName | String | Name of the new transition
* @dataField transitionUuid | String | UUID of the new transition
* *
* @eventType CurrentSceneTransitionChanged * @eventType CurrentSceneTransitionChanged
* @eventSubscription Transitions * @eventSubscription Transitions
@ -39,7 +38,6 @@ void EventHandler::HandleCurrentSceneTransitionChanged()
json eventData; json eventData;
eventData["transitionName"] = obs_source_get_name(transition); eventData["transitionName"] = obs_source_get_name(transition);
eventData["transitionUuid"] = obs_source_get_uuid(transition);
BroadcastEvent(EventSubscription::Transitions, "CurrentSceneTransitionChanged", eventData); BroadcastEvent(EventSubscription::Transitions, "CurrentSceneTransitionChanged", eventData);
} }
@ -67,7 +65,6 @@ void EventHandler::HandleCurrentSceneTransitionDurationChanged()
* A scene transition has started. * A scene transition has started.
* *
* @dataField transitionName | String | Scene transition name * @dataField transitionName | String | Scene transition name
* @dataField transitionUuid | String | Scene transition UUID
* *
* @eventType SceneTransitionStarted * @eventType SceneTransitionStarted
* @eventSubscription Transitions * @eventSubscription Transitions
@ -87,7 +84,6 @@ void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data)
json eventData; json eventData;
eventData["transitionName"] = obs_source_get_name(source); eventData["transitionName"] = obs_source_get_name(source);
eventData["transitionUuid"] = obs_source_get_uuid(source);
eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionStarted", eventData); eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionStarted", eventData);
} }
@ -97,7 +93,6 @@ void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data)
* Note: Does not appear to trigger when the transition is interrupted by the user. * Note: Does not appear to trigger when the transition is interrupted by the user.
* *
* @dataField transitionName | String | Scene transition name * @dataField transitionName | String | Scene transition name
* @dataField transitionUuid | String | Scene transition UUID
* *
* @eventType SceneTransitionEnded * @eventType SceneTransitionEnded
* @eventSubscription Transitions * @eventSubscription Transitions
@ -117,7 +112,6 @@ void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data)
json eventData; json eventData;
eventData["transitionName"] = obs_source_get_name(source); eventData["transitionName"] = obs_source_get_name(source);
eventData["transitionUuid"] = obs_source_get_uuid(source);
eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionEnded", eventData); eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionEnded", eventData);
} }
@ -130,7 +124,6 @@ void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data)
* Note: Appears to be called by every transition, regardless of relevance. * Note: Appears to be called by every transition, regardless of relevance.
* *
* @dataField transitionName | String | Scene transition name * @dataField transitionName | String | Scene transition name
* @dataField transitionUuid | String | Scene transition UUID
* *
* @eventType SceneTransitionVideoEnded * @eventType SceneTransitionVideoEnded
* @eventSubscription Transitions * @eventSubscription Transitions
@ -150,6 +143,5 @@ void EventHandler::HandleSceneTransitionVideoEnded(void *param, calldata_t *data
json eventData; json eventData;
eventData["transitionName"] = obs_source_get_name(source); eventData["transitionName"] = obs_source_get_name(source);
eventData["transitionUuid"] = obs_source_get_uuid(source);
eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionVideoEnded", eventData); eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionVideoEnded", eventData);
} }

View File

@ -64,7 +64,7 @@ void ConnectInfo::RefreshData()
QString serverPassword; QString serverPassword;
if (conf->AuthRequired) { if (conf->AuthRequired) {
ui->copyServerPasswordButton->setEnabled(true); ui->copyServerPasswordButton->setEnabled(true);
serverPassword = QUrl::toPercentEncoding(QString::fromStdString(conf->ServerPassword)); serverPassword = QUrl::toPercentEncoding(conf->ServerPassword);
} else { } else {
ui->copyServerPasswordButton->setEnabled(false); ui->copyServerPasswordButton->setEnabled(false);
serverPassword = obs_module_text("OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText"); serverPassword = obs_module_text("OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText");

View File

@ -123,7 +123,7 @@ void SettingsDialog::RefreshData()
ui->enableDebugLoggingCheckBox->setChecked(conf->DebugEnabled); ui->enableDebugLoggingCheckBox->setChecked(conf->DebugEnabled);
ui->serverPortSpinBox->setValue(conf->ServerPort); ui->serverPortSpinBox->setValue(conf->ServerPort);
ui->enableAuthenticationCheckBox->setChecked(conf->AuthRequired); ui->enableAuthenticationCheckBox->setChecked(conf->AuthRequired);
ui->serverPasswordLineEdit->setText(QString::fromStdString(conf->ServerPassword)); ui->serverPasswordLineEdit->setText(conf->ServerPassword);
ui->serverPasswordLineEdit->setEnabled(conf->AuthRequired); ui->serverPasswordLineEdit->setEnabled(conf->AuthRequired);
ui->generatePasswordButton->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 // Show a confirmation box to the user if they attempt to provide their own password
if (passwordManuallyEdited && (conf->ServerPassword != ui->serverPasswordLineEdit->text().toStdString())) { if (passwordManuallyEdited && (conf->ServerPassword != ui->serverPasswordLineEdit->text())) {
QMessageBox msgBox; QMessageBox msgBox;
msgBox.setWindowTitle(obs_module_text("OBSWebSocket.Settings.Save.UserPasswordWarningTitle")); msgBox.setWindowTitle(obs_module_text("OBSWebSocket.Settings.Save.UserPasswordWarningTitle"));
msgBox.setText(obs_module_text("OBSWebSocket.Settings.Save.UserPasswordWarningMessage")); msgBox.setText(obs_module_text("OBSWebSocket.Settings.Save.UserPasswordWarningMessage"));
@ -172,22 +172,22 @@ void SettingsDialog::SaveFormData()
break; break;
case QMessageBox::No: case QMessageBox::No:
default: default:
ui->serverPasswordLineEdit->setText(QString::fromStdString(conf->ServerPassword)); ui->serverPasswordLineEdit->setText(conf->ServerPassword);
return; return;
} }
} }
bool needsRestart = (conf->ServerEnabled != ui->enableWebSocketServerCheckBox->isChecked()) || bool needsRestart =
(conf->ServerEnabled != ui->enableWebSocketServerCheckBox->isChecked()) ||
(conf->ServerPort != ui->serverPortSpinBox->value()) || (conf->ServerPort != ui->serverPortSpinBox->value()) ||
(ui->enableAuthenticationCheckBox->isChecked() && (ui->enableAuthenticationCheckBox->isChecked() && conf->ServerPassword != ui->serverPasswordLineEdit->text());
conf->ServerPassword != ui->serverPasswordLineEdit->text().toStdString());
conf->ServerEnabled = ui->enableWebSocketServerCheckBox->isChecked(); conf->ServerEnabled = ui->enableWebSocketServerCheckBox->isChecked();
conf->AlertsEnabled = ui->enableSystemTrayAlertsCheckBox->isChecked(); conf->AlertsEnabled = ui->enableSystemTrayAlertsCheckBox->isChecked();
conf->DebugEnabled = ui->enableDebugLoggingCheckBox->isChecked(); conf->DebugEnabled = ui->enableDebugLoggingCheckBox->isChecked();
conf->ServerPort = ui->serverPortSpinBox->value(); conf->ServerPort = ui->serverPortSpinBox->value();
conf->AuthRequired = ui->enableAuthenticationCheckBox->isChecked(); conf->AuthRequired = ui->enableAuthenticationCheckBox->isChecked();
conf->ServerPassword = ui->serverPasswordLineEdit->text().toStdString(); conf->ServerPassword = ui->serverPasswordLineEdit->text();
conf->Save(); conf->Save();

View File

@ -48,9 +48,7 @@ WebSocketApiPtr _webSocketApi;
WebSocketServerPtr _webSocketServer; WebSocketServerPtr _webSocketServer;
SettingsDialog *_settingsDialog = nullptr; SettingsDialog *_settingsDialog = nullptr;
void OnWebSocketApiVendorEvent(std::string vendorName, std::string eventType, obs_data_t *obsEventData); void WebSocketApiEventCallback(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) bool obs_module_load(void)
{ {
@ -62,30 +60,19 @@ bool obs_module_load(void)
// Initialize the cpu stats // Initialize the cpu stats
_cpuUsageInfo = os_cpu_usage_info_start(); _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 // Create the config manager then load the parameters from storage
_config = std::make_shared<Config>(); _config = ConfigPtr(new Config());
_config->Load(migratedConfig); _config->Load();
// Initialize the event handler // Initialize the event handler
_eventHandler = std::make_shared<EventHandler>(); _eventHandler = EventHandlerPtr(new EventHandler());
_eventHandler->SetEventCallback(OnEvent);
_eventHandler->SetObsReadyCallback(OnObsReady);
// Initialize the plugin/script API // Initialize the plugin/script API
_webSocketApi = std::make_shared<WebSocketApi>(); _webSocketApi = WebSocketApiPtr(new WebSocketApi());
_webSocketApi->SetVendorEventCallback(OnWebSocketApiVendorEvent); _webSocketApi->SetEventCallback(WebSocketApiEventCallback);
// Initialize the WebSocket server // Initialize the WebSocket server
_webSocketServer = std::make_shared<WebSocketServer>(); _webSocketServer = WebSocketServerPtr(new WebSocketServer());
_webSocketServer->SetClientSubscriptionCallback(std::bind(&EventHandler::ProcessSubscriptionChange, _eventHandler.get(),
std::placeholders::_1, std::placeholders::_2));
// Initialize the settings dialog // Initialize the settings dialog
obs_frontend_push_ui_translation(obs_module_get_string); obs_frontend_push_ui_translation(obs_module_get_string);
@ -103,16 +90,12 @@ bool obs_module_load(void)
} }
#ifdef PLUGIN_TESTS #ifdef PLUGIN_TESTS
void test_call_request();
void test_register_event_callback();
void test_register_vendor(); void test_register_vendor();
#endif #endif
void obs_module_post_load(void) void obs_module_post_load(void)
{ {
#ifdef PLUGIN_TESTS #ifdef PLUGIN_TESTS
test_call_request();
test_register_event_callback();
test_register_vendor(); test_register_vendor();
#endif #endif
@ -133,20 +116,17 @@ void obs_module_unload(void)
_webSocketServer->Stop(); _webSocketServer->Stop();
} }
// Release the WebSocket server // Destroy the WebSocket server
_webSocketServer->SetClientSubscriptionCallback(nullptr); _webSocketServer.reset();
_webSocketServer = nullptr;
// Release the plugin/script api // Destroy the plugin/script api
_webSocketApi = nullptr; _webSocketApi.reset();
// Release the event handler // Destroy the event handler
_eventHandler->SetObsReadyCallback(nullptr); _eventHandler.reset();
_eventHandler->SetEventCallback(nullptr);
_eventHandler = nullptr;
// Release the config manager // Destroy the config manager
_config = nullptr; _config.reset();
// Destroy the cpu stats // Destroy the cpu stats
os_cpu_usage_info_destroy(_cpuUsageInfo); os_cpu_usage_info_destroy(_cpuUsageInfo);
@ -202,7 +182,7 @@ bool IsDebugEnabled()
* @api events * @api events
* @category general * @category general
*/ */
void OnWebSocketApiVendorEvent(std::string vendorName, std::string eventType, obs_data_t *obsEventData) void WebSocketApiEventCallback(std::string vendorName, std::string eventType, obs_data_t *obsEventData)
{ {
json eventData = Utils::Json::ObsDataToJson(obsEventData); json eventData = Utils::Json::ObsDataToJson(obsEventData);
@ -214,62 +194,13 @@ void OnWebSocketApiVendorEvent(std::string vendorName, std::string eventType, ob
_webSocketServer->BroadcastEvent(EventSubscription::Vendors, "VendorEvent", broadcastEventData); _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 #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) 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! Request data: %s", obs_data_get_json(requestData)); blog(LOG_INFO, "[test_vendor_request_cb] Request called!");
blog(LOG_INFO, "[test_vendor_request_cb] Request data: %s", obs_data_get_json(requestData));
// Set an item to the response data // Set an item to the response data
obs_data_set_string(responseData, "test", "pp"); obs_data_set_string(responseData, "test", "pp");
@ -280,25 +211,34 @@ static void test_vendor_request_cb(obs_data_t *requestData, obs_data_t *response
void test_register_vendor() void test_register_vendor()
{ {
blog(LOG_INFO, "[test_register_vendor] Testing vendor registration..."); blog(LOG_INFO, "[test_register_vendor] Registering test vendor...");
// Test plugin API version fetch // Test plugin API version fetch
uint apiVersion = obs_websocket_get_api_version(); uint apiVersion = obs_websocket_get_api_version();
blog(LOG_INFO, "[test_register_vendor] obs-websocket plugin API version: %u", apiVersion); 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 // Test vendor creation
auto vendor = obs_websocket_register_vendor("obs-websocket-test"); auto vendor = obs_websocket_register_vendor("obs-websocket-test");
if (!vendor) { if (!vendor) {
blog(LOG_ERROR, "[test_register_vendor] Failed to create vendor!"); blog(LOG_WARNING, "[test_register_vendor] Failed to create vendor!");
return; return;
} }
// Test vendor request registration // Test vendor request registration
if (!obs_websocket_vendor_register_request(vendor, "TestRequest", test_vendor_request_cb, vendor)) { if (!obs_websocket_vendor_register_request(vendor, "TestRequest", test_vendor_request_cb, vendor)) {
blog(LOG_ERROR, "[test_register_vendor] Failed to register vendor request!"); blog(LOG_WARNING, "[test_register_vendor] Failed to register vendor request!");
return; return;
} }
blog(LOG_INFO, "[test_register_vendor] Test done."); blog(LOG_INFO, "[test_register_vendor] Post load completed.");
} }
#endif #endif

View File

@ -26,8 +26,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "utils/Obs.h" #include "utils/Obs.h"
#include "plugin-macros.generated.h" #include "plugin-macros.generated.h"
#define CURRENT_RPC_VERSION 1
struct Config; struct Config;
typedef std::shared_ptr<Config> ConfigPtr; typedef std::shared_ptr<Config> ConfigPtr;

View File

@ -37,9 +37,7 @@ struct SerialFrameBatch {
std::condition_variable condition; std::condition_variable condition;
SerialFrameBatch(RequestHandler &requestHandler, json &variables, bool haltOnFailure) SerialFrameBatch(RequestHandler &requestHandler, json &variables, bool haltOnFailure)
: requestHandler(requestHandler), : requestHandler(requestHandler), variables(variables), haltOnFailure(haltOnFailure)
variables(variables),
haltOnFailure(haltOnFailure)
{ {
} }
}; };

View File

@ -111,7 +111,6 @@ const std::unordered_map<std::string, RequestMethodHandler> RequestHandler::_han
{"SetTBarPosition", &RequestHandler::SetTBarPosition}, {"SetTBarPosition", &RequestHandler::SetTBarPosition},
// Filters // Filters
{"GetSourceFilterKindList", &RequestHandler::GetSourceFilterKindList},
{"GetSourceFilterList", &RequestHandler::GetSourceFilterList}, {"GetSourceFilterList", &RequestHandler::GetSourceFilterList},
{"GetSourceFilterDefaultSettings", &RequestHandler::GetSourceFilterDefaultSettings}, {"GetSourceFilterDefaultSettings", &RequestHandler::GetSourceFilterDefaultSettings},
{"CreateSourceFilter", &RequestHandler::CreateSourceFilter}, {"CreateSourceFilter", &RequestHandler::CreateSourceFilter},
@ -126,7 +125,6 @@ const std::unordered_map<std::string, RequestMethodHandler> RequestHandler::_han
{"GetSceneItemList", &RequestHandler::GetSceneItemList}, {"GetSceneItemList", &RequestHandler::GetSceneItemList},
{"GetGroupSceneItemList", &RequestHandler::GetGroupSceneItemList}, {"GetGroupSceneItemList", &RequestHandler::GetGroupSceneItemList},
{"GetSceneItemId", &RequestHandler::GetSceneItemId}, {"GetSceneItemId", &RequestHandler::GetSceneItemId},
{"GetSceneItemSource", &RequestHandler::GetSceneItemSource},
{"CreateSceneItem", &RequestHandler::CreateSceneItem}, {"CreateSceneItem", &RequestHandler::CreateSceneItem},
{"RemoveSceneItem", &RequestHandler::RemoveSceneItem}, {"RemoveSceneItem", &RequestHandler::RemoveSceneItem},
{"DuplicateSceneItem", &RequestHandler::DuplicateSceneItem}, {"DuplicateSceneItem", &RequestHandler::DuplicateSceneItem},
@ -177,8 +175,6 @@ const std::unordered_map<std::string, RequestMethodHandler> RequestHandler::_han
{"ToggleRecordPause", &RequestHandler::ToggleRecordPause}, {"ToggleRecordPause", &RequestHandler::ToggleRecordPause},
{"PauseRecord", &RequestHandler::PauseRecord}, {"PauseRecord", &RequestHandler::PauseRecord},
{"ResumeRecord", &RequestHandler::ResumeRecord}, {"ResumeRecord", &RequestHandler::ResumeRecord},
{"SplitRecordFile", &RequestHandler::SplitRecordFile},
{"CreateRecordChapter", &RequestHandler::CreateRecordChapter},
// Media Inputs // Media Inputs
{"GetMediaInputStatus", &RequestHandler::GetMediaInputStatus}, {"GetMediaInputStatus", &RequestHandler::GetMediaInputStatus},

View File

@ -130,7 +130,6 @@ private:
RequestResult SetTBarPosition(const Request &); RequestResult SetTBarPosition(const Request &);
// Filters // Filters
RequestResult GetSourceFilterKindList(const Request &);
RequestResult GetSourceFilterList(const Request &); RequestResult GetSourceFilterList(const Request &);
RequestResult GetSourceFilterDefaultSettings(const Request &); RequestResult GetSourceFilterDefaultSettings(const Request &);
RequestResult CreateSourceFilter(const Request &); RequestResult CreateSourceFilter(const Request &);
@ -145,7 +144,6 @@ private:
RequestResult GetSceneItemList(const Request &); RequestResult GetSceneItemList(const Request &);
RequestResult GetGroupSceneItemList(const Request &); RequestResult GetGroupSceneItemList(const Request &);
RequestResult GetSceneItemId(const Request &); RequestResult GetSceneItemId(const Request &);
RequestResult GetSceneItemSource(const Request &);
RequestResult CreateSceneItem(const Request &); RequestResult CreateSceneItem(const Request &);
RequestResult RemoveSceneItem(const Request &); RequestResult RemoveSceneItem(const Request &);
RequestResult DuplicateSceneItem(const Request &); RequestResult DuplicateSceneItem(const Request &);
@ -196,8 +194,6 @@ private:
RequestResult ToggleRecordPause(const Request &); RequestResult ToggleRecordPause(const Request &);
RequestResult PauseRecord(const Request &); RequestResult PauseRecord(const Request &);
RequestResult ResumeRecord(const Request &); RequestResult ResumeRecord(const Request &);
RequestResult SplitRecordFile(const Request &);
RequestResult CreateRecordChapter(const Request &);
// Media Inputs // Media Inputs
RequestResult GetMediaInputStatus(const Request &); RequestResult GetMediaInputStatus(const Request &);

View File

@ -22,8 +22,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "RequestHandler.h" #include "RequestHandler.h"
#define GLOBAL_PERSISTENT_DATA_FILE_NAME "persistent_data.json"
/** /**
* Gets the value of a "slot" from the selected persistent data realm. * Gets the value of a "slot" from the selected persistent data realm.
* *
@ -49,11 +47,11 @@ RequestResult RequestHandler::GetPersistentData(const Request &request)
std::string realm = request.RequestData["realm"]; std::string realm = request.RequestData["realm"];
std::string slotName = request.RequestData["slotName"]; std::string slotName = request.RequestData["slotName"];
std::string persistentDataPath; std::string persistentDataPath = Utils::Obs::StringHelper::GetCurrentProfilePath();
if (realm == "OBS_WEBSOCKET_DATA_REALM_GLOBAL") if (realm == "OBS_WEBSOCKET_DATA_REALM_GLOBAL")
persistentDataPath = Utils::Obs::StringHelper::GetModuleConfigPath(GLOBAL_PERSISTENT_DATA_FILE_NAME); persistentDataPath += "/../../../obsWebSocketPersistentData.json";
else if (realm == "OBS_WEBSOCKET_DATA_REALM_PROFILE") else if (realm == "OBS_WEBSOCKET_DATA_REALM_PROFILE")
persistentDataPath = Utils::Obs::StringHelper::GetCurrentProfilePath() + "/obsWebSocketPersistentData.json"; persistentDataPath += "/obsWebSocketPersistentData.json";
else else
return RequestResult::Error(RequestStatus::ResourceNotFound, return RequestResult::Error(RequestStatus::ResourceNotFound,
"You have specified an invalid persistent data realm."); "You have specified an invalid persistent data realm.");
@ -94,16 +92,16 @@ RequestResult RequestHandler::SetPersistentData(const Request &request)
std::string slotName = request.RequestData["slotName"]; std::string slotName = request.RequestData["slotName"];
json slotValue = request.RequestData["slotValue"]; json slotValue = request.RequestData["slotValue"];
std::string persistentDataPath; std::string persistentDataPath = Utils::Obs::StringHelper::GetCurrentProfilePath();
if (realm == "OBS_WEBSOCKET_DATA_REALM_GLOBAL") if (realm == "OBS_WEBSOCKET_DATA_REALM_GLOBAL")
persistentDataPath = Utils::Obs::StringHelper::GetModuleConfigPath(GLOBAL_PERSISTENT_DATA_FILE_NAME); persistentDataPath += "/../../../obsWebSocketPersistentData.json";
else if (realm == "OBS_WEBSOCKET_DATA_REALM_PROFILE") else if (realm == "OBS_WEBSOCKET_DATA_REALM_PROFILE")
persistentDataPath = Utils::Obs::StringHelper::GetCurrentProfilePath() + "/obsWebSocketPersistentData.json"; persistentDataPath += "/obsWebSocketPersistentData.json";
else else
return RequestResult::Error(RequestStatus::ResourceNotFound, return RequestResult::Error(RequestStatus::ResourceNotFound,
"You have specified an invalid persistent data realm."); "You have specified an invalid persistent data realm.");
json persistentData; json persistentData = json::object();
Utils::Json::GetJsonFileContent(persistentDataPath, persistentData); Utils::Json::GetJsonFileContent(persistentDataPath, persistentData);
persistentData[slotName] = slotValue; persistentData[slotName] = slotValue;
if (!Utils::Json::SetJsonFileContent(persistentDataPath, persistentData)) if (!Utils::Json::SetJsonFileContent(persistentDataPath, persistentData))
@ -200,7 +198,10 @@ RequestResult RequestHandler::CreateSceneCollection(const Request &request)
if (std::find(sceneCollections.begin(), sceneCollections.end(), sceneCollectionName) != sceneCollections.end()) if (std::find(sceneCollections.begin(), sceneCollections.end(), sceneCollectionName) != sceneCollections.end())
return RequestResult::Error(RequestStatus::ResourceAlreadyExists); return RequestResult::Error(RequestStatus::ResourceAlreadyExists);
bool success = obs_frontend_add_scene_collection(sceneCollectionName.c_str()); 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)));
if (!success) if (!success)
return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Failed to create the scene collection."); return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Failed to create the scene collection.");
@ -598,8 +599,8 @@ RequestResult RequestHandler::SetStreamServiceSettings(const Request &request)
obs_service_update(currentStreamService, newStreamServiceSettings); obs_service_update(currentStreamService, newStreamServiceSettings);
} else { } else {
OBSServiceAutoRelease newStreamService = obs_service_create(requestedStreamServiceType.c_str(), // TODO: This leaks memory. I have no idea why.
"obs_websocket_custom_service", OBSService newStreamService = obs_service_create(requestedStreamServiceType.c_str(), "obs_websocket_custom_service",
requestedStreamServiceSettings, nullptr); requestedStreamServiceSettings, nullptr);
// TODO: Check service type here, instead of relying on service creation to fail. // TODO: Check service type here, instead of relying on service creation to fail.
if (!newStreamService) if (!newStreamService)

View File

@ -19,32 +19,10 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "RequestHandler.h" #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. * 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 * @responseField filters | Array<Object> | Array of filters
* *
@ -59,7 +37,7 @@ RequestResult RequestHandler::GetSourceFilterList(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment); OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
if (!source) if (!source)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -107,8 +85,7 @@ RequestResult RequestHandler::GetSourceFilterDefaultSettings(const Request &requ
/** /**
* Creates a new filter, adding it to the specified source. * 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 filterName | String | Name of the new filter to be created
* @requestField filterKind | String | The kind of 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 * @requestField ?filterSettings | Object | Settings object to initialize the filter with | Default settings used
@ -125,7 +102,7 @@ RequestResult RequestHandler::CreateSourceFilter(const Request &request)
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment); OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
if (!(source && request.ValidateString("filterName", statusCode, comment) && if (!(source && request.ValidateString("filterName", statusCode, comment) &&
request.ValidateString("filterKind", statusCode, comment))) request.ValidateString("filterKind", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -161,8 +138,7 @@ RequestResult RequestHandler::CreateSourceFilter(const Request &request)
/** /**
* Removes a filter from a source. * Removes a filter from 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 to remove * @requestField filterName | String | Name of the filter to remove
* *
* @requestType RemoveSourceFilter * @requestType RemoveSourceFilter
@ -176,7 +152,7 @@ RequestResult RequestHandler::RemoveSourceFilter(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
FilterPair pair = request.ValidateFilter(statusCode, comment); FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
if (!pair.filter) if (!pair.filter)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -188,8 +164,7 @@ RequestResult RequestHandler::RemoveSourceFilter(const Request &request)
/** /**
* Sets the name of a source filter (rename). * 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 filterName | String | Current name of the filter
* @requestField newFilterName | String | New name for the filter * @requestField newFilterName | String | New name for the filter
* *
@ -204,7 +179,7 @@ RequestResult RequestHandler::SetSourceFilterName(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
FilterPair pair = request.ValidateFilter(statusCode, comment); FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
if (!pair.filter || !request.ValidateString("newFilterName", statusCode, comment)) if (!pair.filter || !request.ValidateString("newFilterName", statusCode, comment))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -222,8 +197,7 @@ RequestResult RequestHandler::SetSourceFilterName(const Request &request)
/** /**
* Gets the info for a specific source filter. * Gets the info for a specific source filter.
* *
* @requestField ?sourceName | String | Name of the source * @requestField sourceName | String | Name of the source
* @requestField ?sourceUuid | String | UUID of the source
* @requestField filterName | String | Name of the filter * @requestField filterName | String | Name of the filter
* *
* @responseField filterEnabled | Boolean | Whether the filter is enabled * @responseField filterEnabled | Boolean | Whether the filter is enabled
@ -242,7 +216,7 @@ RequestResult RequestHandler::GetSourceFilter(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
FilterPair pair = request.ValidateFilter(statusCode, comment); FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
if (!pair.filter) if (!pair.filter)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -262,8 +236,7 @@ RequestResult RequestHandler::GetSourceFilter(const Request &request)
/** /**
* Sets the index position of a filter on a source. * 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 filterName | String | Name of the filter
* @requestField filterIndex | Number | New index position of the filter | >= 0 * @requestField filterIndex | Number | New index position of the filter | >= 0
* *
@ -278,7 +251,7 @@ RequestResult RequestHandler::SetSourceFilterIndex(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
FilterPair pair = request.ValidateFilter(statusCode, comment); FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
if (!(pair.filter && request.ValidateNumber("filterIndex", statusCode, comment, 0, 8192))) if (!(pair.filter && request.ValidateNumber("filterIndex", statusCode, comment, 0, 8192)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -292,8 +265,7 @@ RequestResult RequestHandler::SetSourceFilterIndex(const Request &request)
/** /**
* Sets the settings of a source filter. * 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 filterName | String | Name of the filter to set the settings of
* @requestField filterSettings | Object | Object of settings to apply * @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 * @requestField ?overlay | Boolean | True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. | true
@ -309,7 +281,7 @@ RequestResult RequestHandler::SetSourceFilterSettings(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
FilterPair pair = request.ValidateFilter(statusCode, comment); FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
if (!(pair.filter && request.ValidateObject("filterSettings", statusCode, comment, true))) if (!(pair.filter && request.ValidateObject("filterSettings", statusCode, comment, true)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -341,8 +313,7 @@ RequestResult RequestHandler::SetSourceFilterSettings(const Request &request)
/** /**
* Sets the enable state of a source filter. * 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 filterName | String | Name of the filter
* @requestField filterEnabled | Boolean | New enable state of the filter * @requestField filterEnabled | Boolean | New enable state of the filter
* *
@ -357,7 +328,7 @@ RequestResult RequestHandler::SetSourceFilterEnabled(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
FilterPair pair = request.ValidateFilter(statusCode, comment); FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
if (!(pair.filter && request.ValidateBoolean("filterEnabled", statusCode, comment))) if (!(pair.filter && request.ValidateBoolean("filterEnabled", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);

View File

@ -211,14 +211,12 @@ 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 * @responseField hotkeys | Array<String> | Array of hotkey names
* *
* @requestType GetHotkeyList * @requestType GetHotkeyList
* @complexity 4 * @complexity 3
* @rpcVersion -1 * @rpcVersion -1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @category general * @category general
@ -232,15 +230,12 @@ 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 hotkeyName | String | Name of the hotkey to trigger
* @requestField ?contextName | String | Name of context of the hotkey to trigger
* *
* @requestType TriggerHotkeyByName * @requestType TriggerHotkeyByName
* @complexity 4 * @complexity 3
* @rpcVersion -1 * @rpcVersion -1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @category general * @category general
@ -253,20 +248,11 @@ RequestResult RequestHandler::TriggerHotkeyByName(const Request &request)
if (!request.ValidateString("hotkeyName", statusCode, comment)) if (!request.ValidateString("hotkeyName", statusCode, comment))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
std::string contextName; obs_hotkey_t *hotkey = Utils::Obs::SearchHelper::GetHotkeyByName(request.RequestData["hotkeyName"]);
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) if (!hotkey)
return RequestResult::Error(RequestStatus::ResourceNotFound, "No hotkeys were found by that name."); 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), true);
obs_hotkey_trigger_routed_callback(obs_hotkey_get_id(hotkey), false);
return RequestResult::Success(); return RequestResult::Success();
} }
@ -274,8 +260,6 @@ RequestResult RequestHandler::TriggerHotkeyByName(const Request &request)
/** /**
* Triggers a hotkey using a sequence of keys. * 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 ?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 | Object | Object containing key modifiers to apply | Ignored
* @requestField ?keyModifiers.shift | Boolean | Press Shift | Not pressed * @requestField ?keyModifiers.shift | Boolean | Press Shift | Not pressed

View File

@ -123,14 +123,12 @@ RequestResult RequestHandler::GetSpecialInputs(const Request &)
/** /**
* Creates a new input, adding it as a scene item to the specified scene. * 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 inputName | String | Name of the new input to created
* @requestField inputKind | String | The kind of input to be 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 ?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 * @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 * @responseField sceneItemId | Number | ID of the newly created scene item
* *
* @requestType CreateInput * @requestType CreateInput
@ -144,7 +142,7 @@ RequestResult RequestHandler::CreateInput(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease sceneSource = request.ValidateScene(statusCode, comment); OBSSourceAutoRelease sceneSource = request.ValidateScene("sceneName", statusCode, comment);
if (!(sceneSource && request.ValidateString("inputName", statusCode, comment) && if (!(sceneSource && request.ValidateString("inputName", statusCode, comment) &&
request.ValidateString("inputKind", statusCode, comment))) request.ValidateString("inputKind", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -187,7 +185,6 @@ RequestResult RequestHandler::CreateInput(const Request &request)
return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Creation of the input or scene item failed."); return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Creation of the input or scene item failed.");
json responseData; json responseData;
responseData["inputUuid"] = obs_source_get_uuid(obs_sceneitem_get_source(sceneItem));
responseData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); responseData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
return RequestResult::Success(responseData); return RequestResult::Success(responseData);
} }
@ -197,8 +194,7 @@ RequestResult RequestHandler::CreateInput(const Request &request)
* *
* Note: Will immediately remove all associated scene items. * 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 * @requestType RemoveInput
* @complexity 2 * @complexity 2
@ -211,7 +207,7 @@ RequestResult RequestHandler::RemoveInput(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -226,8 +222,7 @@ RequestResult RequestHandler::RemoveInput(const Request &request)
/** /**
* Sets the name of an input (rename). * 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 * @requestField newInputName | String | New name for the input
* *
* @requestType SetInputName * @requestType SetInputName
@ -241,7 +236,7 @@ RequestResult RequestHandler::SetInputName(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!(input && request.ValidateString("newInputName", statusCode, comment))) if (!(input && request.ValidateString("newInputName", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -297,8 +292,7 @@ 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`. * 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 inputSettings | Object | Object of settings for the input
* @responseField inputKind | String | The kind of the input * @responseField inputKind | String | The kind of the input
@ -314,7 +308,7 @@ RequestResult RequestHandler::GetInputSettings(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -329,8 +323,7 @@ RequestResult RequestHandler::GetInputSettings(const Request &request)
/** /**
* Sets the settings of an input. * 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 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 * @requestField ?overlay | Boolean | True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. | true
* *
@ -345,7 +338,7 @@ RequestResult RequestHandler::SetInputSettings(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!(input && request.ValidateObject("inputSettings", statusCode, comment, true))) if (!(input && request.ValidateObject("inputSettings", statusCode, comment, true)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -380,8 +373,7 @@ RequestResult RequestHandler::SetInputSettings(const Request &request)
/** /**
* Gets the audio mute state of an input. * 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 * @responseField inputMuted | Boolean | Whether the input is muted
* *
@ -396,7 +388,7 @@ RequestResult RequestHandler::GetInputMute(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -411,8 +403,7 @@ RequestResult RequestHandler::GetInputMute(const Request &request)
/** /**
* Sets the audio mute state of an input. * 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 * @requestField inputMuted | Boolean | Whether to mute the input or not
* *
* @requestType SetInputMute * @requestType SetInputMute
@ -426,7 +417,7 @@ RequestResult RequestHandler::SetInputMute(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!(input && request.ValidateBoolean("inputMuted", statusCode, comment))) if (!(input && request.ValidateBoolean("inputMuted", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -441,8 +432,7 @@ RequestResult RequestHandler::SetInputMute(const Request &request)
/** /**
* Toggles the audio mute state of an input. * 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 * @responseField inputMuted | Boolean | Whether the input has been muted or unmuted
* *
@ -457,7 +447,7 @@ RequestResult RequestHandler::ToggleInputMute(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -475,8 +465,7 @@ RequestResult RequestHandler::ToggleInputMute(const Request &request)
/** /**
* Gets the current volume setting of an input. * 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 inputVolumeMul | Number | Volume setting in mul
* @responseField inputVolumeDb | Number | Volume setting in dB * @responseField inputVolumeDb | Number | Volume setting in dB
@ -492,7 +481,7 @@ RequestResult RequestHandler::GetInputVolume(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -513,8 +502,7 @@ RequestResult RequestHandler::GetInputVolume(const Request &request)
/** /**
* Sets the volume setting of an input. * 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 ?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 * @requestField ?inputVolumeDb | Number | Volume setting in dB | >= -100, <= 26 | `inputVolumeMul` should be specified
* *
@ -529,7 +517,7 @@ RequestResult RequestHandler::SetInputVolume(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -564,8 +552,7 @@ RequestResult RequestHandler::SetInputVolume(const Request &request)
/** /**
* Gets the audio balance of an input. * 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 * @responseField inputAudioBalance | Number | Audio balance value from 0.0-1.0
* *
@ -580,7 +567,7 @@ RequestResult RequestHandler::GetInputAudioBalance(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -596,8 +583,7 @@ RequestResult RequestHandler::GetInputAudioBalance(const Request &request)
/** /**
* Sets the audio balance of an input. * 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 * @requestField inputAudioBalance | Number | New audio balance value | >= 0.0, <= 1.0
* *
* @requestType SetInputAudioBalance * @requestType SetInputAudioBalance
@ -611,7 +597,7 @@ RequestResult RequestHandler::SetInputAudioBalance(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!(input && request.ValidateNumber("inputAudioBalance", statusCode, comment, 0.0, 1.0))) if (!(input && request.ValidateNumber("inputAudioBalance", statusCode, comment, 0.0, 1.0)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -629,8 +615,7 @@ RequestResult RequestHandler::SetInputAudioBalance(const Request &request)
* *
* Note: The audio sync offset can be negative too! * 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 * @responseField inputAudioSyncOffset | Number | Audio sync offset in milliseconds
* *
@ -645,7 +630,7 @@ RequestResult RequestHandler::GetInputAudioSyncOffset(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -662,8 +647,7 @@ RequestResult RequestHandler::GetInputAudioSyncOffset(const Request &request)
/** /**
* Sets the audio sync offset of an input. * 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 * @requestField inputAudioSyncOffset | Number | New audio sync offset in milliseconds | >= -950, <= 20000
* *
* @requestType SetInputAudioSyncOffset * @requestType SetInputAudioSyncOffset
@ -677,7 +661,7 @@ RequestResult RequestHandler::SetInputAudioSyncOffset(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!(input && request.ValidateNumber("inputAudioSyncOffset", statusCode, comment, -950, 20000))) if (!(input && request.ValidateNumber("inputAudioSyncOffset", statusCode, comment, -950, 20000)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -699,8 +683,7 @@ RequestResult RequestHandler::SetInputAudioSyncOffset(const Request &request)
* - `OBS_MONITORING_TYPE_MONITOR_ONLY` * - `OBS_MONITORING_TYPE_MONITOR_ONLY`
* - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` * - `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 * @responseField monitorType | String | Audio monitor type
* *
@ -715,7 +698,7 @@ RequestResult RequestHandler::GetInputAudioMonitorType(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -731,8 +714,7 @@ RequestResult RequestHandler::GetInputAudioMonitorType(const Request &request)
/** /**
* Sets the audio monitor type of an input. * 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 * @requestField monitorType | String | Audio monitor type
* *
* @requestType SetInputAudioMonitorType * @requestType SetInputAudioMonitorType
@ -746,7 +728,7 @@ RequestResult RequestHandler::SetInputAudioMonitorType(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!(input && request.ValidateString("monitorType", statusCode, comment))) if (!(input && request.ValidateString("monitorType", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -777,8 +759,7 @@ RequestResult RequestHandler::SetInputAudioMonitorType(const Request &request)
/** /**
* Gets the enable state of all audio tracks of an input. * 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 * @responseField inputAudioTracks | Object | Object of audio tracks and associated enable states
* *
@ -793,7 +774,7 @@ RequestResult RequestHandler::GetInputAudioTracks(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -816,8 +797,7 @@ RequestResult RequestHandler::GetInputAudioTracks(const Request &request)
/** /**
* Sets the enable state of audio tracks of an input. * 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 * @requestField inputAudioTracks | Object | Track settings to apply
* *
* @requestType SetInputAudioTracks * @requestType SetInputAudioTracks
@ -831,7 +811,7 @@ RequestResult RequestHandler::SetInputAudioTracks(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input || !request.ValidateObject("inputAudioTracks", statusCode, comment)) if (!input || !request.ValidateObject("inputAudioTracks", statusCode, comment))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -871,8 +851,7 @@ 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. * 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 * @requestField propertyName | String | Name of the list property to get the items of
* *
* @responseField propertyItems | Array<Object> | Array of items in the list property * @responseField propertyItems | Array<Object> | Array of items in the list property
@ -888,7 +867,7 @@ RequestResult RequestHandler::GetInputPropertiesListPropertyItems(const Request
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!(input && request.ValidateString("propertyName", statusCode, comment))) if (!(input && request.ValidateString("propertyName", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -916,8 +895,7 @@ 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. * 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 * @requestField propertyName | String | Name of the button property to press
* *
* @requestType PressInputPropertiesButton * @requestType PressInputPropertiesButton
@ -931,7 +909,7 @@ RequestResult RequestHandler::PressInputPropertiesButton(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!(input && request.ValidateString("propertyName", statusCode, comment))) if (!(input && request.ValidateString("propertyName", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);

View File

@ -39,8 +39,7 @@ bool IsMediaTimeValid(obs_source_t *input)
* - `OBS_MEDIA_STATE_ENDED` * - `OBS_MEDIA_STATE_ENDED`
* - `OBS_MEDIA_STATE_ERROR` * - `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 mediaState | String | State of the media input
* @responseField mediaDuration | Number | Total duration of the playing media in milliseconds. `null` if not playing * @responseField mediaDuration | Number | Total duration of the playing media in milliseconds. `null` if not playing
@ -57,7 +56,7 @@ RequestResult RequestHandler::GetMediaInputStatus(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -81,8 +80,7 @@ RequestResult RequestHandler::GetMediaInputStatus(const Request &request)
* *
* This request does not perform bounds checking of the cursor position. * 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 * @requestField mediaCursor | Number | New cursor position to set | >= 0
* *
* @requestType SetMediaInputCursor * @requestType SetMediaInputCursor
@ -96,7 +94,7 @@ RequestResult RequestHandler::SetMediaInputCursor(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!(input && request.ValidateNumber("mediaCursor", statusCode, comment, 0))) if (!(input && request.ValidateNumber("mediaCursor", statusCode, comment, 0)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -117,8 +115,7 @@ RequestResult RequestHandler::SetMediaInputCursor(const Request &request)
* *
* This request does not perform bounds checking of the cursor position. * 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 * @requestField mediaCursorOffset | Number | Value to offset the current cursor position by | None
* *
* @requestType OffsetMediaInputCursor * @requestType OffsetMediaInputCursor
@ -132,7 +129,7 @@ RequestResult RequestHandler::OffsetMediaInputCursor(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!(input && request.ValidateNumber("mediaCursorOffset", statusCode, comment))) if (!(input && request.ValidateNumber("mediaCursorOffset", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -154,8 +151,7 @@ RequestResult RequestHandler::OffsetMediaInputCursor(const Request &request)
/** /**
* Triggers an action on a media input. * 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 * @requestField mediaAction | String | Identifier of the `ObsMediaInputAction` enum
* *
* @requestType TriggerMediaInputAction * @requestType TriggerMediaInputAction
@ -169,7 +165,7 @@ RequestResult RequestHandler::TriggerMediaInputAction(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!(input && request.ValidateString("mediaAction", statusCode, comment))) if (!(input && request.ValidateString("mediaAction", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);

View File

@ -21,8 +21,11 @@ with this program. If not, see <https://www.gnu.org/licenses/>
static bool VirtualCamAvailable() static bool VirtualCamAvailable()
{ {
OBSOutputAutoRelease output = obs_frontend_get_virtualcam_output(); OBSDataAutoRelease privateData = obs_get_private_data();
return output != nullptr; if (!privateData)
return false;
return obs_data_get_bool(privateData, "vcamEnabled");
} }
static bool ReplayBufferAvailable() static bool ReplayBufferAvailable()

View File

@ -54,8 +54,6 @@ RequestResult RequestHandler::GetRecordStatus(const Request &)
/** /**
* Toggles the status of the record output. * Toggles the status of the record output.
* *
* @responseField outputActive | Boolean | The new active state of the output
*
* @requestType ToggleRecord * @requestType ToggleRecord
* @complexity 1 * @complexity 1
* @rpcVersion -1 * @rpcVersion -1
@ -189,60 +187,3 @@ RequestResult RequestHandler::ResumeRecord(const Request &)
return RequestResult::Success(); 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();
}

View File

@ -24,8 +24,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
* *
* Scenes only * 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 * @responseField sceneItems | Array<Object> | Array of scene items in the scene
* *
@ -40,7 +39,7 @@ RequestResult RequestHandler::GetSceneItemList(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment); OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
if (!scene) if (!scene)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -57,8 +56,7 @@ RequestResult RequestHandler::GetSceneItemList(const Request &request)
* *
* Groups only * 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 * @responseField sceneItems | Array<Object> | Array of scene items in the group
* *
@ -73,7 +71,7 @@ RequestResult RequestHandler::GetGroupSceneItemList(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_GROUP_ONLY); OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_GROUP_ONLY);
if (!scene) if (!scene)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -88,8 +86,7 @@ RequestResult RequestHandler::GetGroupSceneItemList(const Request &request)
* *
* Scenes and Groups * 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 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 * @requestField ?searchOffset | Number | Number of matches to skip during search. >= 0 means first forward. -1 means last (top) item | >= -1 | 0
* *
@ -106,8 +103,9 @@ RequestResult RequestHandler::GetSceneItemId(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneAutoRelease scene = request.ValidateScene2(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBSSceneAutoRelease scene =
if (!(scene && request.ValidateString("sourceName", statusCode, comment))) // TODO: Source UUID support request.ValidateScene2("sceneName", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!(scene && request.ValidateString("sourceName", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
std::string sourceName = request.RequestData["sourceName"]; std::string sourceName = request.RequestData["sourceName"];
@ -130,49 +128,13 @@ RequestResult RequestHandler::GetSceneItemId(const Request &request)
return RequestResult::Success(responseData); 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. * Creates a new scene item using a source.
* *
* Scenes only * Scenes only
* *
* @requestField ?sceneName | String | Name of the scene to create the new item in * @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 ?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 * @requestField ?sceneItemEnabled | Boolean | Enable state to apply to the scene item on creation | True
* *
* @responseField sceneItemId | Number | Numeric ID of the scene item * @responseField sceneItemId | Number | Numeric ID of the scene item
@ -188,17 +150,17 @@ RequestResult RequestHandler::CreateSceneItem(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease sceneSource = request.ValidateScene(statusCode, comment); OBSSourceAutoRelease sceneSource = request.ValidateScene("sceneName", statusCode, comment);
if (!sceneSource) if (!sceneSource)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
OBSScene scene = obs_scene_from_source(sceneSource); OBSScene scene = obs_scene_from_source(sceneSource);
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment); OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
if (!source) if (!source)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
if (sceneSource == source) if (request.RequestData["sceneName"] == request.RequestData["sourceName"])
return RequestResult::Error(RequestStatus::CannotAct, "You cannot create scene item of a scene within itself."); return RequestResult::Error(RequestStatus::CannotAct, "You cannot create scene item of a scene within itself.");
bool sceneItemEnabled = true; bool sceneItemEnabled = true;
@ -223,8 +185,7 @@ RequestResult RequestHandler::CreateSceneItem(const Request &request)
* *
* Scenes only * 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 sceneItemId | Number | Numeric ID of the scene item | >= 0
* *
* @requestType RemoveSceneItem * @requestType RemoveSceneItem
@ -238,7 +199,7 @@ RequestResult RequestHandler::RemoveSceneItem(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem(statusCode, comment); OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment);
if (!sceneItem) if (!sceneItem)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -253,11 +214,9 @@ RequestResult RequestHandler::RemoveSceneItem(const Request &request)
* *
* Scenes only * 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 sceneItemId | Number | Numeric ID of the scene item | >= 0
* @requestField ?destinationSceneName | String | Name of the scene to create the duplicated item in | From scene is assumed * @requestField ?destinationSceneName | String | Name of the scene to create the duplicated item in | `sceneName` 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 * @responseField sceneItemId | Number | Numeric ID of the duplicated scene item
* *
@ -272,26 +231,16 @@ RequestResult RequestHandler::DuplicateSceneItem(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem(statusCode, comment); OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment);
if (!sceneItem) if (!sceneItem)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
// Get destination scene // Get destination scene
obs_scene_t *destinationScene; obs_scene_t *destinationScene;
if (request.Contains("destinationSceneName")) { if (request.Contains("destinationSceneName")) {
OBSSourceAutoRelease destinationSceneSource = destinationScene = request.ValidateScene2("destinationSceneName", statusCode, comment);
request.ValidateSource("destinationSceneName", "destinationSceneUuid", statusCode, comment); if (!destinationScene)
if (!destinationSceneSource)
return RequestResult::Error(statusCode, comment); 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 { } else {
destinationScene = obs_scene_get_ref(obs_sceneitem_get_scene(sceneItem)); destinationScene = obs_scene_get_ref(obs_sceneitem_get_scene(sceneItem));
if (!destinationScene) if (!destinationScene)
@ -309,7 +258,7 @@ RequestResult RequestHandler::DuplicateSceneItem(const Request &request)
bool sceneItemEnabled = obs_sceneitem_visible(sceneItem); bool sceneItemEnabled = obs_sceneitem_visible(sceneItem);
obs_transform_info sceneItemTransform; obs_transform_info sceneItemTransform;
obs_sceneitem_crop sceneItemCrop; obs_sceneitem_crop sceneItemCrop;
obs_sceneitem_get_info2(sceneItem, &sceneItemTransform); obs_sceneitem_get_info(sceneItem, &sceneItemTransform);
obs_sceneitem_get_crop(sceneItem, &sceneItemCrop); obs_sceneitem_get_crop(sceneItem, &sceneItemCrop);
// Create the new item // Create the new item
@ -330,8 +279,7 @@ RequestResult RequestHandler::DuplicateSceneItem(const Request &request)
* *
* Scenes and Groups * 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 sceneItemId | Number | Numeric ID of the scene item | >= 0
* *
* @responseField sceneItemTransform | Object | Object containing scene item transform info * @responseField sceneItemTransform | Object | Object containing scene item transform info
@ -347,8 +295,8 @@ RequestResult RequestHandler::GetSceneItemTransform(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!sceneItem) if (!sceneItem)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -361,8 +309,7 @@ RequestResult RequestHandler::GetSceneItemTransform(const Request &request)
/** /**
* Sets the transform and crop info of a scene item. * 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 sceneItemId | Number | Numeric ID of the scene item | >= 0
* @requestField sceneItemTransform | Object | Object containing scene item transform info to update * @requestField sceneItemTransform | Object | Object containing scene item transform info to update
* *
@ -377,8 +324,8 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!(sceneItem && request.ValidateObject("sceneItemTransform", statusCode, comment))) if (!(sceneItem && request.ValidateObject("sceneItemTransform", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -389,7 +336,7 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request &request)
bool cropChanged = false; bool cropChanged = false;
obs_transform_info sceneItemTransform; obs_transform_info sceneItemTransform;
obs_sceneitem_crop sceneItemCrop; obs_sceneitem_crop sceneItemCrop;
obs_sceneitem_get_info2(sceneItem, &sceneItemTransform); obs_sceneitem_get_info(sceneItem, &sceneItemTransform);
obs_sceneitem_get_crop(sceneItem, &sceneItemCrop); obs_sceneitem_get_crop(sceneItem, &sceneItemCrop);
OBSSource source = obs_sceneitem_get_source(sceneItem); OBSSource source = obs_sceneitem_get_source(sceneItem);
@ -502,18 +449,11 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request &request)
cropChanged = true; 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) if (!transformChanged && !cropChanged)
return RequestResult::Error(RequestStatus::CannotAct, "You have not provided any valid transform changes."); return RequestResult::Error(RequestStatus::CannotAct, "You have not provided any valid transform changes.");
if (transformChanged) if (transformChanged)
obs_sceneitem_set_info2(sceneItem, &sceneItemTransform); obs_sceneitem_set_info(sceneItem, &sceneItemTransform);
if (cropChanged) if (cropChanged)
obs_sceneitem_set_crop(sceneItem, &sceneItemCrop); obs_sceneitem_set_crop(sceneItem, &sceneItemCrop);
@ -526,8 +466,7 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request &request)
* *
* Scenes and Groups * 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 sceneItemId | Number | Numeric ID of the scene item | >= 0
* *
* @responseField sceneItemEnabled | Boolean | Whether the scene item is enabled. `true` for enabled, `false` for disabled * @responseField sceneItemEnabled | Boolean | Whether the scene item is enabled. `true` for enabled, `false` for disabled
@ -543,8 +482,8 @@ RequestResult RequestHandler::GetSceneItemEnabled(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!sceneItem) if (!sceneItem)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -559,8 +498,7 @@ RequestResult RequestHandler::GetSceneItemEnabled(const Request &request)
* *
* Scenes and Groups * 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 sceneItemId | Number | Numeric ID of the scene item | >= 0
* @requestField sceneItemEnabled | Boolean | New enable state of the scene item * @requestField sceneItemEnabled | Boolean | New enable state of the scene item
* *
@ -575,8 +513,8 @@ RequestResult RequestHandler::SetSceneItemEnabled(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!(sceneItem && request.ValidateBoolean("sceneItemEnabled", statusCode, comment))) if (!(sceneItem && request.ValidateBoolean("sceneItemEnabled", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -592,8 +530,7 @@ RequestResult RequestHandler::SetSceneItemEnabled(const Request &request)
* *
* Scenes and Groups * 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 sceneItemId | Number | Numeric ID of the scene item | >= 0
* *
* @responseField sceneItemLocked | Boolean | Whether the scene item is locked. `true` for locked, `false` for unlocked * @responseField sceneItemLocked | Boolean | Whether the scene item is locked. `true` for locked, `false` for unlocked
@ -609,8 +546,8 @@ RequestResult RequestHandler::GetSceneItemLocked(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!sceneItem) if (!sceneItem)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -625,8 +562,7 @@ RequestResult RequestHandler::GetSceneItemLocked(const Request &request)
* *
* Scenes and Group * Scenes and Group
* *
* @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 sceneItemId | Number | Numeric ID of the scene item | >= 0
* @requestField sceneItemLocked | Boolean | New lock state of the scene item * @requestField sceneItemLocked | Boolean | New lock state of the scene item
* *
@ -641,8 +577,8 @@ RequestResult RequestHandler::SetSceneItemLocked(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!(sceneItem && request.ValidateBoolean("sceneItemLocked", statusCode, comment))) if (!(sceneItem && request.ValidateBoolean("sceneItemLocked", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -660,8 +596,7 @@ RequestResult RequestHandler::SetSceneItemLocked(const Request &request)
* *
* Scenes and Groups * 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 sceneItemId | Number | Numeric ID of the scene item | >= 0
* *
* @responseField sceneItemIndex | Number | Index position of the scene item * @responseField sceneItemIndex | Number | Index position of the scene item
@ -677,8 +612,8 @@ RequestResult RequestHandler::GetSceneItemIndex(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!sceneItem) if (!sceneItem)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -693,8 +628,7 @@ RequestResult RequestHandler::GetSceneItemIndex(const Request &request)
* *
* Scenes and Groups * 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 sceneItemId | Number | Numeric ID of the scene item | >= 0
* @requestField sceneItemIndex | Number | New index position of the scene item | >= 0 * @requestField sceneItemIndex | Number | New index position of the scene item | >= 0
* *
@ -709,8 +643,8 @@ RequestResult RequestHandler::SetSceneItemIndex(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!(sceneItem && request.ValidateNumber("sceneItemIndex", statusCode, comment, 0, 8192))) if (!(sceneItem && request.ValidateNumber("sceneItemIndex", statusCode, comment, 0, 8192)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -736,8 +670,7 @@ RequestResult RequestHandler::SetSceneItemIndex(const Request &request)
* *
* Scenes and Groups * 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 sceneItemId | Number | Numeric ID of the scene item | >= 0
* *
* @responseField sceneItemBlendMode | String | Current blend mode * @responseField sceneItemBlendMode | String | Current blend mode
@ -753,8 +686,8 @@ RequestResult RequestHandler::GetSceneItemBlendMode(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!sceneItem) if (!sceneItem)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -771,8 +704,7 @@ RequestResult RequestHandler::GetSceneItemBlendMode(const Request &request)
* *
* Scenes and Groups * 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 sceneItemId | Number | Numeric ID of the scene item | >= 0
* @requestField sceneItemBlendMode | String | New blend mode * @requestField sceneItemBlendMode | String | New blend mode
* *
@ -787,8 +719,8 @@ RequestResult RequestHandler::SetSceneItemBlendMode(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!(sceneItem && request.ValidateString("sceneItemBlendMode", statusCode, comment))) if (!(sceneItem && request.ValidateString("sceneItemBlendMode", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -807,8 +739,8 @@ RequestResult RequestHandler::GetSceneItemPrivateSettings(const Request &request
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!sceneItem) if (!sceneItem)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -825,8 +757,8 @@ RequestResult RequestHandler::SetSceneItemPrivateSettings(const Request &request
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSceneItemAutoRelease sceneItem = OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment,
request.ValidateSceneItem(statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
if (!sceneItem || !request.ValidateObject("sceneItemSettings", statusCode, comment, true)) if (!sceneItem || !request.ValidateObject("sceneItemSettings", statusCode, comment, true))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);

View File

@ -22,10 +22,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
/** /**
* Gets an array of all scenes in OBS. * Gets an array of all scenes in OBS.
* *
* @responseField currentProgramSceneName | String | Current program scene name. Can be `null` if internal state desync * @responseField currentProgramSceneName | String | Current program scene
* @responseField currentProgramSceneUuid | String | Current program scene UUID. Can be `null` if internal state desync * @responseField currentPreviewSceneName | String | Current preview scene. `null` if not in studio mode
* @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 * @responseField scenes | Array<Object> | Array of scenes
* *
* @requestType GetSceneList * @requestType GetSceneList
@ -40,22 +38,16 @@ RequestResult RequestHandler::GetSceneList(const Request &)
json responseData; json responseData;
OBSSourceAutoRelease currentProgramScene = obs_frontend_get_current_scene(); OBSSourceAutoRelease currentProgramScene = obs_frontend_get_current_scene();
if (currentProgramScene) { if (currentProgramScene)
responseData["currentProgramSceneName"] = obs_source_get_name(currentProgramScene); responseData["currentProgramSceneName"] = obs_source_get_name(currentProgramScene);
responseData["currentProgramSceneUuid"] = obs_source_get_uuid(currentProgramScene); else
} else {
responseData["currentProgramSceneName"] = nullptr; responseData["currentProgramSceneName"] = nullptr;
responseData["currentProgramSceneUuid"] = nullptr;
}
OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene(); OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene();
if (currentPreviewScene) { if (currentPreviewScene)
responseData["currentPreviewSceneName"] = obs_source_get_name(currentPreviewScene); responseData["currentPreviewSceneName"] = obs_source_get_name(currentPreviewScene);
responseData["currentPreviewSceneUuid"] = obs_source_get_uuid(currentPreviewScene); else
} else {
responseData["currentPreviewSceneName"] = nullptr; responseData["currentPreviewSceneName"] = nullptr;
responseData["currentPreviewSceneUuid"] = nullptr;
}
responseData["scenes"] = Utils::Obs::ArrayHelper::GetSceneList(); responseData["scenes"] = Utils::Obs::ArrayHelper::GetSceneList();
@ -88,12 +80,7 @@ RequestResult RequestHandler::GetGroupList(const Request &)
/** /**
* Gets the current program scene. * Gets the current program scene.
* *
* Note: This request is slated to have the `currentProgram`-prefixed fields removed from in an upcoming RPC version. * @responseField currentProgramSceneName | String | Current program scene
*
* @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 * @requestType GetCurrentProgramScene
* @complexity 1 * @complexity 1
@ -106,8 +93,7 @@ RequestResult RequestHandler::GetCurrentProgramScene(const Request &)
{ {
json responseData; json responseData;
OBSSourceAutoRelease currentProgramScene = obs_frontend_get_current_scene(); OBSSourceAutoRelease currentProgramScene = obs_frontend_get_current_scene();
responseData["sceneName"] = responseData["currentProgramSceneName"] = obs_source_get_name(currentProgramScene); responseData["currentProgramSceneName"] = obs_source_get_name(currentProgramScene);
responseData["sceneUuid"] = responseData["currentProgramSceneUuid"] = obs_source_get_uuid(currentProgramScene);
return RequestResult::Success(responseData); return RequestResult::Success(responseData);
} }
@ -115,8 +101,7 @@ RequestResult RequestHandler::GetCurrentProgramScene(const Request &)
/** /**
* Sets the current program scene. * Sets the current program scene.
* *
* @requestField ?sceneName | String | Scene name to set as the current program scene * @requestField sceneName | String | Scene to set as the current program scene
* @requestField ?sceneUuid | String | Scene UUID to set as the current program scene
* *
* @requestType SetCurrentProgramScene * @requestType SetCurrentProgramScene
* @complexity 1 * @complexity 1
@ -129,7 +114,7 @@ RequestResult RequestHandler::SetCurrentProgramScene(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment); OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
if (!scene) if (!scene)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -143,12 +128,7 @@ RequestResult RequestHandler::SetCurrentProgramScene(const Request &request)
* *
* Only available when studio mode is enabled. * Only available when studio mode is enabled.
* *
* Note: This request is slated to have the `currentPreview`-prefixed fields removed from in an upcoming RPC version. * @responseField currentPreviewSceneName | String | Current preview scene
*
* @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 * @requestType GetCurrentPreviewScene
* @complexity 1 * @complexity 1
@ -165,8 +145,7 @@ RequestResult RequestHandler::GetCurrentPreviewScene(const Request &)
OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene(); OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene();
json responseData; json responseData;
responseData["sceneName"] = responseData["currentPreviewSceneName"] = obs_source_get_name(currentPreviewScene); responseData["currentPreviewSceneName"] = obs_source_get_name(currentPreviewScene);
responseData["sceneUuid"] = responseData["currentPreviewSceneUuid"] = obs_source_get_uuid(currentPreviewScene);
return RequestResult::Success(responseData); return RequestResult::Success(responseData);
} }
@ -176,8 +155,7 @@ RequestResult RequestHandler::GetCurrentPreviewScene(const Request &)
* *
* Only available when studio mode is enabled. * Only available when studio mode is enabled.
* *
* @requestField ?sceneName | String | Scene name to set as the current preview scene * @requestField sceneName | String | Scene to set as the current preview scene
* @requestField ?sceneUuid | String | Scene UUID to set as the current preview scene
* *
* @requestType SetCurrentPreviewScene * @requestType SetCurrentPreviewScene
* @complexity 1 * @complexity 1
@ -193,7 +171,7 @@ RequestResult RequestHandler::SetCurrentPreviewScene(const Request &request)
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment); OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
if (!scene) if (!scene)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -207,8 +185,6 @@ RequestResult RequestHandler::SetCurrentPreviewScene(const Request &request)
* *
* @requestField sceneName | String | Name for the new scene * @requestField sceneName | String | Name for the new scene
* *
* @responseField sceneUuid | String | UUID of the created scene
*
* @requestType CreateScene * @requestType CreateScene
* @complexity 2 * @complexity 2
* @rpcVersion -1 * @rpcVersion -1
@ -229,21 +205,19 @@ RequestResult RequestHandler::CreateScene(const Request &request)
if (scene) if (scene)
return RequestResult::Error(RequestStatus::ResourceAlreadyExists, "A source already exists by that scene name."); return RequestResult::Error(RequestStatus::ResourceAlreadyExists, "A source already exists by that scene name.");
OBSSceneAutoRelease createdScene = obs_scene_create(sceneName.c_str()); obs_scene_t *createdScene = obs_scene_create(sceneName.c_str());
if (!createdScene) if (!createdScene)
return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Failed to create the scene."); return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Failed to create the scene.");
json responseData; obs_scene_release(createdScene);
responseData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(createdScene));
return RequestResult::Success(responseData); return RequestResult::Success();
} }
/** /**
* Removes a scene from OBS. * 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 * @requestType RemoveScene
* @complexity 2 * @complexity 2
@ -256,7 +230,7 @@ RequestResult RequestHandler::RemoveScene(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment); OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
if (!scene) if (!scene)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -272,8 +246,7 @@ RequestResult RequestHandler::RemoveScene(const Request &request)
/** /**
* Sets the name of a scene (rename). * 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 * @requestField newSceneName | String | New name for the scene
* *
* @requestType SetSceneName * @requestType SetSceneName
@ -287,7 +260,7 @@ RequestResult RequestHandler::SetSceneName(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment); OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
if (!(scene && request.ValidateString("newSceneName", statusCode, comment))) if (!(scene && request.ValidateString("newSceneName", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -306,10 +279,7 @@ RequestResult RequestHandler::SetSceneName(const Request &request)
/** /**
* Gets the scene transition overridden for a scene. * Gets the scene transition overridden for a 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 ?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 transitionName | String | Name of the overridden scene transition, else `null`
* @responseField transitionDuration | Number | Duration of the overridden scene transition, else `null` * @responseField transitionDuration | Number | Duration of the overridden scene transition, else `null`
@ -325,7 +295,7 @@ RequestResult RequestHandler::GetSceneSceneTransitionOverride(const Request &req
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment); OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
if (!scene) if (!scene)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -349,8 +319,7 @@ RequestResult RequestHandler::GetSceneSceneTransitionOverride(const Request &req
/** /**
* Sets the scene transition overridden for a scene. * 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 ?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 * @requestField ?transitionDuration | Number | Duration to use for any overridden transition. Specify `null` to remove | >= 50, <= 20000 | Unchanged
* *
@ -365,7 +334,7 @@ RequestResult RequestHandler::SetSceneSceneTransitionOverride(const Request &req
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment); OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment);
if (!scene) if (!scene)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);

View File

@ -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) QImage TakeSourceScreenshot(obs_source_t *source, bool &success, uint32_t requestedWidth = 0, uint32_t requestedHeight = 0)
{ {
// Get info about the requested source // Get info about the requested source
const uint32_t sourceWidth = obs_source_get_width(source); const uint32_t sourceWidth = obs_source_get_base_width(source);
const uint32_t sourceHeight = obs_source_get_height(source); const uint32_t sourceHeight = obs_source_get_base_height(source);
const double sourceAspectRatio = ((double)sourceWidth / (double)sourceHeight); const double sourceAspectRatio = ((double)sourceWidth / (double)sourceHeight);
uint32_t imgWidth = sourceWidth; uint32_t imgWidth = sourceWidth;
@ -114,8 +114,7 @@ bool IsImageFormatValid(std::string format)
* *
* **Compatible with inputs and scenes.** * **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 videoActive | Boolean | Whether the source is showing in Program
* @responseField videoShowing | Boolean | Whether the source is showing in the UI (Preview, Projector, Properties) * @responseField videoShowing | Boolean | Whether the source is showing in the UI (Preview, Projector, Properties)
@ -131,7 +130,7 @@ RequestResult RequestHandler::GetSourceActive(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment); OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
if (!source) if (!source)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -152,8 +151,7 @@ RequestResult RequestHandler::GetSourceActive(const Request &request)
* *
* **Compatible with inputs and scenes.** * **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 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 ?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 ?imageHeight | Number | Height to scale the screenshot to | >= 8, <= 4096 | Source value is used
@ -172,7 +170,7 @@ RequestResult RequestHandler::GetSourceScreenshot(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment); OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
if (!(source && request.ValidateString("imageFormat", statusCode, comment))) if (!(source && request.ValidateString("imageFormat", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -240,14 +238,15 @@ RequestResult RequestHandler::GetSourceScreenshot(const Request &request)
* *
* **Compatible with inputs and scenes.** * **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 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 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 ?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 ?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 * @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 * @requestType SaveSourceScreenshot
* @complexity 3 * @complexity 3
* @rpcVersion -1 * @rpcVersion -1
@ -259,7 +258,7 @@ RequestResult RequestHandler::SaveSourceScreenshot(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment); OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
if (!(source && request.ValidateString("imageFormat", statusCode, comment) && if (!(source && request.ValidateString("imageFormat", statusCode, comment) &&
request.ValidateString("imageFilePath", statusCode, comment))) request.ValidateString("imageFilePath", statusCode, comment)))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -322,7 +321,7 @@ RequestResult RequestHandler::GetSourcePrivateSettings(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment); OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
if (!source) if (!source)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -339,7 +338,7 @@ RequestResult RequestHandler::SetSourcePrivateSettings(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment); OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
if (!source || !request.ValidateObject("sourceSettings", statusCode, comment, true)) if (!source || !request.ValidateObject("sourceSettings", statusCode, comment, true))
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);

View File

@ -44,16 +44,12 @@ RequestResult RequestHandler::GetStreamStatus(const Request &)
uint64_t outputDuration = Utils::Obs::NumberHelper::GetOutputDuration(streamOutput); 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; json responseData;
responseData["outputActive"] = obs_output_active(streamOutput); responseData["outputActive"] = obs_output_active(streamOutput);
responseData["outputReconnecting"] = obs_output_reconnecting(streamOutput); responseData["outputReconnecting"] = obs_output_reconnecting(streamOutput);
responseData["outputTimecode"] = Utils::Obs::StringHelper::DurationToTimecode(outputDuration); responseData["outputTimecode"] = Utils::Obs::StringHelper::DurationToTimecode(outputDuration);
responseData["outputDuration"] = outputDuration; responseData["outputDuration"] = outputDuration;
responseData["outputCongestion"] = outputCongestion; responseData["outputCongestion"] = obs_output_get_congestion(streamOutput);
responseData["outputBytes"] = (uint64_t)obs_output_get_total_bytes(streamOutput); responseData["outputBytes"] = (uint64_t)obs_output_get_total_bytes(streamOutput);
responseData["outputSkippedFrames"] = obs_output_get_frames_dropped(streamOutput); responseData["outputSkippedFrames"] = obs_output_get_frames_dropped(streamOutput);
responseData["outputTotalFrames"] = obs_output_get_total_frames(streamOutput); responseData["outputTotalFrames"] = obs_output_get_total_frames(streamOutput);

View File

@ -46,7 +46,6 @@ RequestResult RequestHandler::GetTransitionKindList(const Request &)
* Gets an array of all scene transitions in OBS. * Gets an array of all scene transitions in OBS.
* *
* @responseField currentSceneTransitionName | String | Name of the current scene transition. Can be null * @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 currentSceneTransitionKind | String | Kind of the current scene transition. Can be null
* @responseField transitions | Array<Object> | Array of transitions * @responseField transitions | Array<Object> | Array of transitions
* *
@ -64,11 +63,9 @@ RequestResult RequestHandler::GetSceneTransitionList(const Request &)
OBSSourceAutoRelease transition = obs_frontend_get_current_transition(); OBSSourceAutoRelease transition = obs_frontend_get_current_transition();
if (transition) { if (transition) {
responseData["currentSceneTransitionName"] = obs_source_get_name(transition); responseData["currentSceneTransitionName"] = obs_source_get_name(transition);
responseData["currentSceneTransitionUuid"] = obs_source_get_uuid(transition);
responseData["currentSceneTransitionKind"] = obs_source_get_id(transition); responseData["currentSceneTransitionKind"] = obs_source_get_id(transition);
} else { } else {
responseData["currentSceneTransitionName"] = nullptr; responseData["currentSceneTransitionName"] = nullptr;
responseData["currentSceneTransitionUuid"] = nullptr;
responseData["currentSceneTransitionKind"] = nullptr; responseData["currentSceneTransitionKind"] = nullptr;
} }
@ -81,7 +78,6 @@ RequestResult RequestHandler::GetSceneTransitionList(const Request &)
* Gets information about the current scene transition. * Gets information about the current scene transition.
* *
* @responseField transitionName | String | Name of the transition * @responseField transitionName | String | Name of the transition
* @responseField transitionUuid | String | UUID of the transition
* @responseField transitionKind | String | Kind of the transition * @responseField transitionKind | String | Kind of the transition
* @responseField transitionFixed | Boolean | Whether the transition uses a fixed (unconfigurable) duration * @responseField transitionFixed | Boolean | Whether the transition uses a fixed (unconfigurable) duration
* @responseField transitionDuration | Number | Configured transition duration in milliseconds. `null` if transition is fixed * @responseField transitionDuration | Number | Configured transition duration in milliseconds. `null` if transition is fixed
@ -104,7 +100,6 @@ RequestResult RequestHandler::GetCurrentSceneTransition(const Request &)
json responseData; json responseData;
responseData["transitionName"] = obs_source_get_name(transition); responseData["transitionName"] = obs_source_get_name(transition);
responseData["transitionUuid"] = obs_source_get_uuid(transition);
responseData["transitionKind"] = obs_source_get_id(transition); responseData["transitionKind"] = obs_source_get_id(transition);
if (obs_transition_fixed(transition)) { if (obs_transition_fixed(transition)) {

View File

@ -82,8 +82,7 @@ RequestResult RequestHandler::SetStudioModeEnabled(const Request &request)
/** /**
* Opens the properties dialog of an input. * 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 * @requestType OpenInputPropertiesDialog
* @complexity 1 * @complexity 1
@ -96,7 +95,7 @@ RequestResult RequestHandler::OpenInputPropertiesDialog(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -108,8 +107,7 @@ RequestResult RequestHandler::OpenInputPropertiesDialog(const Request &request)
/** /**
* Opens the filters dialog of an input. * 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 * @requestType OpenInputFiltersDialog
* @complexity 1 * @complexity 1
@ -122,7 +120,7 @@ RequestResult RequestHandler::OpenInputFiltersDialog(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -134,8 +132,7 @@ RequestResult RequestHandler::OpenInputFiltersDialog(const Request &request)
/** /**
* Opens the interact dialog of an input. * 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 * @requestType OpenInputInteractDialog
* @complexity 1 * @complexity 1
@ -148,7 +145,7 @@ RequestResult RequestHandler::OpenInputInteractDialog(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease input = request.ValidateInput(statusCode, comment); OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment);
if (!input) if (!input)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);
@ -265,8 +262,7 @@ 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. * 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 ?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 * @requestField ?projectorGeometry | String | Size/Position data for a windowed projector, in Qt Base64 encoded format. Mutually exclusive with `monitorIndex` | N/A
* *
@ -281,7 +277,7 @@ RequestResult RequestHandler::OpenSourceProjector(const Request &request)
{ {
RequestStatus::RequestStatus statusCode; RequestStatus::RequestStatus statusCode;
std::string comment; std::string comment;
OBSSourceAutoRelease source = request.ValidateSource("sourceName", "sourceUuid", statusCode, comment); OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
if (!source) if (!source)
return RequestResult::Error(statusCode, comment); return RequestResult::Error(statusCode, comment);

View File

@ -211,41 +211,28 @@ bool Request::ValidateArray(const std::string &keyName, RequestStatus::RequestSt
return true; return true;
} }
obs_source_t *Request::ValidateSource(const std::string &nameKeyName, const std::string &uuidKeyName, obs_source_t *Request::ValidateSource(const std::string &keyName, RequestStatus::RequestStatus &statusCode,
RequestStatus::RequestStatus &statusCode, std::string &comment) const std::string &comment) const
{ {
if (ValidateString(nameKeyName, statusCode, comment)) { if (!ValidateString(keyName, statusCode, comment))
std::string sourceName = RequestData[nameKeyName]; return nullptr;
std::string sourceName = RequestData[keyName];
obs_source_t *ret = obs_get_source_by_name(sourceName.c_str()); obs_source_t *ret = obs_get_source_by_name(sourceName.c_str());
if (!ret) { if (!ret) {
statusCode = RequestStatus::ResourceNotFound; statusCode = RequestStatus::ResourceNotFound;
comment = std::string("No source was found by the name of `") + sourceName + "`."; comment = std::string("No source was found by the name of `") + sourceName + "`.";
return nullptr; return nullptr;
} }
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; 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(RequestStatus::RequestStatus &statusCode, std::string &comment, obs_source_t *Request::ValidateScene(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment,
const ObsWebSocketSceneFilter filter) const const ObsWebSocketSceneFilter filter) const
{ {
obs_source_t *ret = ValidateSource("sceneName", "sceneUuid", statusCode, comment); obs_source_t *ret = ValidateSource(keyName, statusCode, comment);
if (!ret) if (!ret)
return nullptr; return nullptr;
@ -272,10 +259,10 @@ obs_source_t *Request::ValidateScene(RequestStatus::RequestStatus &statusCode, s
return ret; return ret;
} }
obs_scene_t *Request::ValidateScene2(RequestStatus::RequestStatus &statusCode, std::string &comment, obs_scene_t *Request::ValidateScene2(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment,
const ObsWebSocketSceneFilter filter) const const ObsWebSocketSceneFilter filter) const
{ {
OBSSourceAutoRelease sceneSource = ValidateSource("sceneName", "sceneUuid", statusCode, comment); OBSSourceAutoRelease sceneSource = ValidateSource(keyName, statusCode, comment);
if (!sceneSource) if (!sceneSource)
return nullptr; return nullptr;
@ -303,9 +290,10 @@ obs_scene_t *Request::ValidateScene2(RequestStatus::RequestStatus &statusCode, s
} }
} }
obs_source_t *Request::ValidateInput(RequestStatus::RequestStatus &statusCode, std::string &comment) const obs_source_t *Request::ValidateInput(const std::string &keyName, RequestStatus::RequestStatus &statusCode,
std::string &comment) const
{ {
obs_source_t *ret = ValidateSource("inputName", "inputUuid", statusCode, comment); obs_source_t *ret = ValidateSource(keyName, statusCode, comment);
if (!ret) if (!ret)
return nullptr; return nullptr;
@ -319,46 +307,47 @@ obs_source_t *Request::ValidateInput(RequestStatus::RequestStatus &statusCode, s
return ret; return ret;
} }
FilterPair Request::ValidateFilter(RequestStatus::RequestStatus &statusCode, std::string &comment) const FilterPair Request::ValidateFilter(const std::string &sourceKeyName, const std::string &filterKeyName,
RequestStatus::RequestStatus &statusCode, std::string &comment) const
{ {
obs_source_t *source = ValidateSource("sourceName", "sourceUuid", statusCode, comment); obs_source_t *source = ValidateSource(sourceKeyName, statusCode, comment);
if (!source) if (!source)
return FilterPair{source, nullptr}; return FilterPair{source, nullptr};
if (!ValidateString("filterName", statusCode, comment)) if (!ValidateString(filterKeyName, statusCode, comment))
return FilterPair{source, nullptr}; return FilterPair{source, nullptr};
std::string filterName = RequestData["filterName"]; std::string filterName = RequestData[filterKeyName];
obs_source_t *filter = obs_source_get_filter_by_name(source, filterName.c_str()); obs_source_t *filter = obs_source_get_filter_by_name(source, filterName.c_str());
if (!filter) { if (!filter) {
std::string sourceName = obs_source_get_name(source);
statusCode = RequestStatus::ResourceNotFound; statusCode = RequestStatus::ResourceNotFound;
comment = std::string("No filter was found in the source `") + sourceName + "` with the name `" + filterName + "`."; comment = std::string("No filter was found in the source `") + RequestData[sourceKeyName].get<std::string>() +
"` with the name `" + filterName + "`.";
return FilterPair{source, nullptr}; return FilterPair{source, nullptr};
} }
return FilterPair{source, filter}; return FilterPair{source, filter};
} }
obs_sceneitem_t *Request::ValidateSceneItem(RequestStatus::RequestStatus &statusCode, std::string &comment, obs_sceneitem_t *Request::ValidateSceneItem(const std::string &sceneKeyName, const std::string &sceneItemIdKeyName,
RequestStatus::RequestStatus &statusCode, std::string &comment,
const ObsWebSocketSceneFilter filter) const const ObsWebSocketSceneFilter filter) const
{ {
OBSSceneAutoRelease scene = ValidateScene2(statusCode, comment, filter); OBSSceneAutoRelease scene = ValidateScene2(sceneKeyName, statusCode, comment, filter);
if (!scene) if (!scene)
return nullptr; return nullptr;
if (!ValidateNumber("sceneItemId", statusCode, comment, 0)) if (!ValidateNumber(sceneItemIdKeyName, statusCode, comment, 0))
return nullptr; return nullptr;
int64_t sceneItemId = RequestData["sceneItemId"]; int64_t sceneItemId = RequestData[sceneItemIdKeyName];
OBSSceneItem sceneItem = obs_scene_find_sceneitem_by_id(scene, sceneItemId); OBSSceneItem sceneItem = obs_scene_find_sceneitem_by_id(scene, sceneItemId);
if (!sceneItem) { if (!sceneItem) {
std::string sceneName = obs_source_get_name(obs_scene_get_source(scene));
statusCode = RequestStatus::ResourceNotFound; statusCode = RequestStatus::ResourceNotFound;
comment = std::string("No scene items were found in scene `") + sceneName + "` with the ID `" + comment = std::string("No scene items were found in scene `") + RequestData[sceneKeyName].get<std::string>() +
std::to_string(sceneItemId) + "`."; "` with the ID `" + std::to_string(sceneItemId) + "`.";
return nullptr; return nullptr;
} }

View File

@ -64,15 +64,18 @@ struct Request {
const bool allowEmpty = false) const; const bool allowEmpty = false) const;
// All return values have incremented refcounts // All return values have incremented refcounts
obs_source_t *ValidateSource(const std::string &nameKeyName, const std::string &uuidKeyName, 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,
const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const;
obs_scene_t *ValidateScene2(const std::string &keyName, 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; RequestStatus::RequestStatus &statusCode, std::string &comment) const;
obs_source_t *ValidateScene(RequestStatus::RequestStatus &statusCode, std::string &comment, obs_sceneitem_t *ValidateSceneItem(const std::string &sceneKeyName, const std::string &sceneItemIdKeyName,
const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const; 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(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; const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const;
obs_output_t *ValidateOutput(const std::string &keyName, RequestStatus::RequestStatus &statusCode, obs_output_t *ValidateOutput(const std::string &keyName, RequestStatus::RequestStatus &statusCode,
std::string &comment) const; std::string &comment) const;

View File

@ -21,8 +21,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
RequestBatchRequest::RequestBatchRequest(const std::string &requestType, const json &requestData, RequestBatchRequest::RequestBatchRequest(const std::string &requestType, const json &requestData,
RequestBatchExecutionType::RequestBatchExecutionType executionType, RequestBatchExecutionType::RequestBatchExecutionType executionType,
const json &inputVariables, const json &outputVariables) const json &inputVariables, const json &outputVariables)
: Request(requestType, requestData, executionType), : Request(requestType, requestData, executionType), InputVariables(inputVariables), OutputVariables(outputVariables)
InputVariables(inputVariables),
OutputVariables(outputVariables)
{ {
} }

View File

@ -20,10 +20,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "RequestResult.h" #include "RequestResult.h"
RequestResult::RequestResult(RequestStatus::RequestStatus statusCode, json responseData, std::string comment) RequestResult::RequestResult(RequestStatus::RequestStatus statusCode, json responseData, std::string comment)
: StatusCode(statusCode), : StatusCode(statusCode), ResponseData(responseData), Comment(comment), SleepFrames(0)
ResponseData(responseData),
Comment(comment),
SleepFrames(0)
{ {
} }

View File

@ -77,8 +77,5 @@ namespace RequestBatchExecutionType {
Parallel = 2, Parallel = 2,
}; };
inline bool IsValid(int8_t executionType) inline bool IsValid(int8_t executionType) { return executionType >= None && executionType <= Parallel; }
{
return executionType >= None && executionType <= Parallel;
}
} }

View File

@ -17,9 +17,8 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see <https://www.gnu.org/licenses/> with this program. If not, see <https://www.gnu.org/licenses/>
*/ */
#include <fstream>
#include "Json.h" #include "Json.h"
#include "Platform.h"
#include "plugin-macros.generated.h" #include "plugin-macros.generated.h"
bool Utils::Json::JsonArrayIsValidObsArray(const json &j) bool Utils::Json::JsonArrayIsValidObsArray(const json &j)
@ -178,43 +177,21 @@ json Utils::Json::ObsDataToJson(obs_data_t *d, bool includeDefault)
bool Utils::Json::GetJsonFileContent(std::string fileName, json &content) bool Utils::Json::GetJsonFileContent(std::string fileName, json &content)
{ {
std::ifstream f(fileName); std::string textContent;
if (!f.is_open()) if (!Utils::Platform::GetTextFileContent(fileName, textContent))
return false; return false;
try { try {
content = json::parse(f); content = json::parse(textContent);
} catch (json::parse_error &e) { } catch (json::parse_error &e) {
blog(LOG_WARNING, "[Utils::Json::GetJsonFileContent] Failed to decode content of JSON file `%s`. Error: %s", blog(LOG_WARNING, "Failed to decode content of JSON file `%s`. Error: %s", fileName.c_str(), e.what());
fileName.c_str(), e.what());
return false; return false;
} }
return true; return true;
} }
bool Utils::Json::SetJsonFileContent(std::string fileName, const json &content, bool makeDirs) bool Utils::Json::SetJsonFileContent(std::string fileName, const json &content, bool createNew)
{ {
if (makeDirs) { std::string textContent = content.dump(2);
std::error_code ec; return Utils::Platform::SetTextFileContent(fileName, textContent, createNew);
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;
} }

View File

@ -76,10 +76,7 @@ namespace Utils {
obs_data_t *JsonToObsData(json j); obs_data_t *JsonToObsData(json j);
json ObsDataToJson(obs_data_t *d, bool includeDefault = false); json ObsDataToJson(obs_data_t *d, bool includeDefault = false);
bool GetJsonFileContent(std::string fileName, json &content); bool GetJsonFileContent(std::string fileName, json &content);
bool SetJsonFileContent(std::string fileName, const json &content, bool makeDirs = true); bool SetJsonFileContent(std::string fileName, const json &content, bool createNew = true);
static inline bool Contains(const json &j, std::string key) static inline bool Contains(const json &j, std::string key) { return j.contains(key) && !j[key].is_null(); }
{
return j.contains(key) && !j[key].is_null();
}
} }
} }

View File

@ -29,6 +29,36 @@ with this program. If not, see <https://www.gnu.org/licenses/>
inline void ___properties_dummy_addref(obs_properties_t *) {} inline void ___properties_dummy_addref(obs_properties_t *) {}
using OBSPropertiesAutoDestroy = OBSRef<obs_properties_t *, ___properties_dummy_addref, obs_properties_destroy>; 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) template<typename T> T *GetCalldataPointer(const calldata_t *data, const char *name)
{ {
void *ptr = nullptr; void *ptr = nullptr;
@ -42,7 +72,7 @@ enum ObsOutputState {
* *
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_UNKNOWN * @enumIdentifier OBS_WEBSOCKET_OUTPUT_UNKNOWN
* @enumType ObsOutputState * @enumType ObsOutputState
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -52,7 +82,7 @@ enum ObsOutputState {
* *
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_STARTING * @enumIdentifier OBS_WEBSOCKET_OUTPUT_STARTING
* @enumType ObsOutputState * @enumType ObsOutputState
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -62,7 +92,7 @@ enum ObsOutputState {
* *
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_STARTED * @enumIdentifier OBS_WEBSOCKET_OUTPUT_STARTED
* @enumType ObsOutputState * @enumType ObsOutputState
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -72,7 +102,7 @@ enum ObsOutputState {
* *
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_STOPPING * @enumIdentifier OBS_WEBSOCKET_OUTPUT_STOPPING
* @enumType ObsOutputState * @enumType ObsOutputState
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -82,7 +112,7 @@ enum ObsOutputState {
* *
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_STOPPED * @enumIdentifier OBS_WEBSOCKET_OUTPUT_STOPPED
* @enumType ObsOutputState * @enumType ObsOutputState
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -92,7 +122,7 @@ enum ObsOutputState {
* *
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_RECONNECTING * @enumIdentifier OBS_WEBSOCKET_OUTPUT_RECONNECTING
* @enumType ObsOutputState * @enumType ObsOutputState
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -102,7 +132,7 @@ enum ObsOutputState {
* *
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_RECONNECTED * @enumIdentifier OBS_WEBSOCKET_OUTPUT_RECONNECTED
* @enumType ObsOutputState * @enumType ObsOutputState
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.1.0 * @initialVersion 5.1.0
* @api enums * @api enums
*/ */
@ -112,7 +142,7 @@ enum ObsOutputState {
* *
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_PAUSED * @enumIdentifier OBS_WEBSOCKET_OUTPUT_PAUSED
* @enumType ObsOutputState * @enumType ObsOutputState
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.1.0 * @initialVersion 5.1.0
* @api enums * @api enums
*/ */
@ -122,7 +152,7 @@ enum ObsOutputState {
* *
* @enumIdentifier OBS_WEBSOCKET_OUTPUT_RESUMED * @enumIdentifier OBS_WEBSOCKET_OUTPUT_RESUMED
* @enumType ObsOutputState * @enumType ObsOutputState
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -146,7 +176,7 @@ enum ObsMediaInputAction {
* *
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE
* @enumType ObsMediaInputAction * @enumType ObsMediaInputAction
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -156,7 +186,7 @@ enum ObsMediaInputAction {
* *
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY
* @enumType ObsMediaInputAction * @enumType ObsMediaInputAction
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -166,7 +196,7 @@ enum ObsMediaInputAction {
* *
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE
* @enumType ObsMediaInputAction * @enumType ObsMediaInputAction
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -176,7 +206,7 @@ enum ObsMediaInputAction {
* *
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP
* @enumType ObsMediaInputAction * @enumType ObsMediaInputAction
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -186,7 +216,7 @@ enum ObsMediaInputAction {
* *
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART
* @enumType ObsMediaInputAction * @enumType ObsMediaInputAction
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -196,7 +226,7 @@ enum ObsMediaInputAction {
* *
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT
* @enumType ObsMediaInputAction * @enumType ObsMediaInputAction
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -206,7 +236,7 @@ enum ObsMediaInputAction {
* *
* @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS
* @enumType ObsMediaInputAction * @enumType ObsMediaInputAction
* @rpcVersion -1 * @rpcVersion 1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
@ -227,7 +257,6 @@ namespace Utils {
namespace Obs { namespace Obs {
namespace StringHelper { namespace StringHelper {
std::string GetObsVersion(); std::string GetObsVersion();
std::string GetModuleConfigPath(std::string fileName);
std::string GetCurrentSceneCollection(); std::string GetCurrentSceneCollection();
std::string GetCurrentProfile(); std::string GetCurrentProfile();
std::string GetCurrentProfilePath(); std::string GetCurrentProfilePath();
@ -268,7 +297,7 @@ namespace Utils {
} }
namespace SearchHelper { namespace SearchHelper {
obs_hotkey_t *GetHotkeyByName(std::string name, std::string context); obs_hotkey_t *GetHotkeyByName(std::string name);
obs_source_t *GetSceneTransitionByName(std::string name); // Increments source ref. Use OBSSourceAutoRelease obs_source_t *GetSceneTransitionByName(std::string name); // Increments source ref. Use OBSSourceAutoRelease
obs_sceneitem_t *GetSceneItemByName(obs_scene_t *scene, std::string name, obs_sceneitem_t *GetSceneItemByName(obs_scene_t *scene, std::string name,
int offset = 0); // Increments ref. Use OBSSceneItemAutoRelease int offset = 0); // Increments ref. Use OBSSceneItemAutoRelease

View File

@ -33,7 +33,7 @@ static void CreateSceneItemHelper(void *_data, obs_scene_t *scene)
data->sceneItem = obs_scene_add(scene, data->source); data->sceneItem = obs_scene_add(scene, data->source);
if (data->sceneItemTransform) if (data->sceneItemTransform)
obs_sceneitem_set_info2(data->sceneItem, data->sceneItemTransform); obs_sceneitem_set_info(data->sceneItem, data->sceneItemTransform);
if (data->sceneItemCrop) if (data->sceneItemCrop)
obs_sceneitem_set_crop(data->sceneItem, data->sceneItemCrop); obs_sceneitem_set_crop(data->sceneItem, data->sceneItemCrop);

View File

@ -96,7 +96,6 @@ std::vector<json> Utils::Obs::ArrayHelper::GetSceneList()
json sceneJson; json sceneJson;
sceneJson["sceneName"] = obs_source_get_name(scene); sceneJson["sceneName"] = obs_source_get_name(scene);
sceneJson["sceneUuid"] = obs_source_get_uuid(scene);
sceneJson["sceneIndex"] = sceneList.sources.num - i - 1; sceneJson["sceneIndex"] = sceneList.sources.num - i - 1;
ret.push_back(sceneJson); ret.push_back(sceneJson);
@ -151,7 +150,6 @@ std::vector<json> Utils::Obs::ArrayHelper::GetSceneItemList(obs_scene_t *scene,
item["sceneItemBlendMode"] = obs_sceneitem_get_blending_mode(sceneItem); item["sceneItemBlendMode"] = obs_sceneitem_get_blending_mode(sceneItem);
OBSSource itemSource = obs_sceneitem_get_source(sceneItem); OBSSource itemSource = obs_sceneitem_get_source(sceneItem);
item["sourceName"] = obs_source_get_name(itemSource); item["sourceName"] = obs_source_get_name(itemSource);
item["sourceUuid"] = obs_source_get_uuid(itemSource);
item["sourceType"] = obs_source_get_type(itemSource); item["sourceType"] = obs_source_get_type(itemSource);
if (obs_source_get_type(itemSource) == OBS_SOURCE_TYPE_INPUT) if (obs_source_get_type(itemSource) == OBS_SOURCE_TYPE_INPUT)
item["inputKind"] = obs_source_get_id(itemSource); item["inputKind"] = obs_source_get_id(itemSource);
@ -197,7 +195,6 @@ std::vector<json> Utils::Obs::ArrayHelper::GetInputList(std::string inputKind)
json inputJson; json inputJson;
inputJson["inputName"] = obs_source_get_name(input); inputJson["inputName"] = obs_source_get_name(input);
inputJson["inputUuid"] = obs_source_get_uuid(input);
inputJson["inputKind"] = inputKind; inputJson["inputKind"] = inputKind;
inputJson["unversionedInputKind"] = obs_source_get_unversioned_id(input); inputJson["unversionedInputKind"] = obs_source_get_unversioned_id(input);
@ -284,7 +281,6 @@ std::vector<json> Utils::Obs::ArrayHelper::GetSceneTransitionList()
obs_source_t *transition = transitionList.sources.array[i]; obs_source_t *transition = transitionList.sources.array[i];
json transitionJson; json transitionJson;
transitionJson["transitionName"] = obs_source_get_name(transition); transitionJson["transitionName"] = obs_source_get_name(transition);
transitionJson["transitionUuid"] = obs_source_get_uuid(transition);
transitionJson["transitionKind"] = obs_source_get_id(transition); transitionJson["transitionKind"] = obs_source_get_id(transition);
transitionJson["transitionFixed"] = obs_transition_fixed(transition); transitionJson["transitionFixed"] = obs_transition_fixed(transition);
transitionJson["transitionConfigurable"] = obs_source_configurable(transition); transitionJson["transitionConfigurable"] = obs_source_configurable(transition);

View File

@ -50,7 +50,7 @@ json Utils::Obs::ObjectHelper::GetSceneItemTransform(obs_sceneitem_t *item)
obs_transform_info osi; obs_transform_info osi;
obs_sceneitem_crop crop; obs_sceneitem_crop crop;
obs_sceneitem_get_info2(item, &osi); obs_sceneitem_get_info(item, &osi);
obs_sceneitem_get_crop(item, &crop); obs_sceneitem_get_crop(item, &crop);
OBSSource source = obs_sceneitem_get_source(item); OBSSource source = obs_sceneitem_get_source(item);
@ -83,7 +83,5 @@ json Utils::Obs::ObjectHelper::GetSceneItemTransform(obs_sceneitem_t *item)
ret["cropTop"] = (int)crop.top; ret["cropTop"] = (int)crop.top;
ret["cropBottom"] = (int)crop.bottom; ret["cropBottom"] = (int)crop.bottom;
ret["cropToBounds"] = osi.crop_to_bounds;
return ret; return ret;
} }

View File

@ -19,7 +19,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "Obs.h" #include "Obs.h"
#include "plugin-macros.generated.h" #include "plugin-macros.generated.h"
obs_hotkey_t *Utils::Obs::SearchHelper::GetHotkeyByName(std::string name, std::string context) obs_hotkey_t *Utils::Obs::SearchHelper::GetHotkeyByName(std::string name)
{ {
if (name.empty()) if (name.empty())
return nullptr; return nullptr;
@ -27,49 +27,7 @@ obs_hotkey_t *Utils::Obs::SearchHelper::GetHotkeyByName(std::string name, std::s
auto hotkeys = ArrayHelper::GetHotkeyList(); auto hotkeys = ArrayHelper::GetHotkeyList();
for (auto hotkey : hotkeys) { 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 hotkey;
} }

View File

@ -20,13 +20,13 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <inttypes.h> #include <inttypes.h>
#include <QString> #include <QString>
#include <obs-module.h>
#include <util/util.hpp>
#include "Obs.h" #include "Obs.h"
#include "plugin-macros.generated.h" #include "plugin-macros.generated.h"
#define CASE(x) \
case x: \
return #x;
std::string Utils::Obs::StringHelper::GetObsVersion() std::string Utils::Obs::StringHelper::GetObsVersion()
{ {
uint32_t version = obs_get_version(); uint32_t version = obs_get_version();
@ -40,34 +40,36 @@ std::string Utils::Obs::StringHelper::GetObsVersion()
return combined.toStdString(); 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() std::string Utils::Obs::StringHelper::GetCurrentSceneCollection()
{ {
BPtr<char> sceneCollectionName = obs_frontend_get_current_scene_collection(); char *sceneCollectionName = obs_frontend_get_current_scene_collection();
return std::string(sceneCollectionName.Get()); std::string ret = sceneCollectionName;
bfree(sceneCollectionName);
return ret;
} }
std::string Utils::Obs::StringHelper::GetCurrentProfile() std::string Utils::Obs::StringHelper::GetCurrentProfile()
{ {
BPtr<char> profileName = obs_frontend_get_current_profile(); char *profileName = obs_frontend_get_current_profile();
return std::string(profileName.Get()); std::string ret = profileName;
bfree(profileName);
return ret;
} }
std::string Utils::Obs::StringHelper::GetCurrentProfilePath() std::string Utils::Obs::StringHelper::GetCurrentProfilePath()
{ {
BPtr<char> profilePath = obs_frontend_get_current_profile_path(); char *profilePath = obs_frontend_get_current_profile_path();
return std::string(profilePath.Get()); std::string ret = profilePath;
bfree(profilePath);
return ret;
} }
std::string Utils::Obs::StringHelper::GetCurrentRecordOutputPath() std::string Utils::Obs::StringHelper::GetCurrentRecordOutputPath()
{ {
BPtr<char> recordOutputPath = obs_frontend_get_current_record_output_path(); char *recordOutputPath = obs_frontend_get_current_record_output_path();
return std::string(recordOutputPath.Get()); std::string ret = recordOutputPath;
bfree(recordOutputPath);
return ret;
} }
std::string Utils::Obs::StringHelper::GetLastRecordFileName() std::string Utils::Obs::StringHelper::GetLastRecordFileName()
@ -92,14 +94,18 @@ std::string Utils::Obs::StringHelper::GetLastRecordFileName()
std::string Utils::Obs::StringHelper::GetLastReplayBufferFileName() std::string Utils::Obs::StringHelper::GetLastReplayBufferFileName()
{ {
BPtr<char> replayBufferPath = obs_frontend_get_last_replay(); char *replayBufferPath = obs_frontend_get_last_replay();
return std::string(replayBufferPath.Get()); std::string ret = replayBufferPath;
bfree(replayBufferPath);
return ret;
} }
std::string Utils::Obs::StringHelper::GetLastScreenshotFileName() std::string Utils::Obs::StringHelper::GetLastScreenshotFileName()
{ {
BPtr<char> screenshotPath = obs_frontend_get_last_screenshot(); char *screenshotPath = obs_frontend_get_last_screenshot();
return std::string(screenshotPath.Get()); std::string ret = screenshotPath;
bfree(screenshotPath);
return ret;
} }
std::string Utils::Obs::StringHelper::DurationToTimecode(uint64_t ms) std::string Utils::Obs::StringHelper::DurationToTimecode(uint64_t ms)

View File

@ -93,7 +93,6 @@ json Utils::Obs::VolumeMeter::Meter::GetMeterData()
l.unlock(); l.unlock();
ret["inputName"] = obs_source_get_name(input); ret["inputName"] = obs_source_get_name(input);
ret["inputUuid"] = obs_source_get_uuid(input);
ret["inputLevelsMul"] = levels; ret["inputLevelsMul"] = levels;
return ret; return ret;
@ -238,9 +237,7 @@ void Utils::Obs::VolumeMeter::Meter::InputVolumeCallback(void *priv_data, callda
} }
Utils::Obs::VolumeMeter::Handler::Handler(UpdateCallback cb, uint64_t updatePeriod) Utils::Obs::VolumeMeter::Handler::Handler(UpdateCallback cb, uint64_t updatePeriod)
: _updateCallback(cb), : _updateCallback(cb), _updatePeriod(updatePeriod), _running(false)
_updatePeriod(updatePeriod),
_running(false)
{ {
signal_handler_t *sh = obs_get_signal_handler(); signal_handler_t *sh = obs_get_signal_handler();
if (!sh) if (!sh)

View File

@ -21,6 +21,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QNetworkInterface> #include <QNetworkInterface>
#include <QHostAddress> #include <QHostAddress>
#include <QFile>
#include <obs-frontend-api.h> #include <obs-frontend-api.h>
#include "Platform.h" #include "Platform.h"
@ -115,13 +116,36 @@ void Utils::Platform::SendTrayNotification(QSystemTrayIcon::MessageIcon icon, QS
obs_queue_task( obs_queue_task(
OBS_TASK_UI, OBS_TASK_UI,
[](void *param) { [](void *param) {
auto notification = static_cast<SystemTrayNotification *>(param);
void *systemTrayPtr = obs_frontend_get_system_tray(); void *systemTrayPtr = obs_frontend_get_system_tray();
if (systemTrayPtr) {
auto systemTray = static_cast<QSystemTrayIcon *>(systemTrayPtr); auto systemTray = static_cast<QSystemTrayIcon *>(systemTrayPtr);
auto notification = static_cast<SystemTrayNotification *>(param);
systemTray->showMessage(notification->title, notification->body, notification->icon); systemTray->showMessage(notification->title, notification->body, notification->icon);
}
delete notification; delete notification;
}, },
(void *)notification, false); (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;
}

View File

@ -29,5 +29,7 @@ namespace Utils {
QString GetCommandLineArgument(QString arg); QString GetCommandLineArgument(QString arg);
bool GetCommandLineFlagSet(QString arg); bool GetCommandLineFlagSet(QString arg);
void SendTrayNotification(QSystemTrayIcon::MessageIcon icon, QString title, QString body); 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);
} }
} }

View File

@ -24,6 +24,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <obs-frontend-api.h> #include <obs-frontend-api.h>
#include "WebSocketServer.h" #include "WebSocketServer.h"
#include "../eventhandler/EventHandler.h"
#include "../obs-websocket.h" #include "../obs-websocket.h"
#include "../Config.h" #include "../Config.h"
#include "../utils/Crypto.h" #include "../utils/Crypto.h"
@ -46,6 +47,12 @@ WebSocketServer::WebSocketServer() : QObject(nullptr)
_server.set_close_handler(websocketpp::lib::bind(&WebSocketServer::onClose, this, websocketpp::lib::placeholders::_1)); _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, _server.set_message_handler(websocketpp::lib::bind(&WebSocketServer::onMessage, this, websocketpp::lib::placeholders::_1,
websocketpp::lib::placeholders::_2)); websocketpp::lib::placeholders::_2));
auto eventHandler = GetEventHandler();
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() WebSocketServer::~WebSocketServer()
@ -83,7 +90,7 @@ void WebSocketServer::Start()
} }
_authenticationSalt = Utils::Crypto::GenerateSalt(); _authenticationSalt = Utils::Crypto::GenerateSalt();
_authenticationSecret = Utils::Crypto::GenerateSecret(conf->ServerPassword, _authenticationSalt); _authenticationSecret = Utils::Crypto::GenerateSecret(conf->ServerPassword.toStdString(), _authenticationSalt);
// Set log levels if debug is enabled // Set log levels if debug is enabled
if (IsDebugEnabled()) { if (IsDebugEnabled()) {
@ -201,6 +208,11 @@ std::vector<WebSocketServer::WebSocketSessionState> WebSocketServer::GetWebSocke
return webSocketSessions; return webSocketSessions;
} }
void WebSocketServer::onObsReady(bool ready)
{
_obsReady = ready;
}
bool WebSocketServer::onValidate(websocketpp::connection_hdl hdl) bool WebSocketServer::onValidate(websocketpp::connection_hdl hdl)
{ {
auto conn = _server.get_con_from_hdl(hdl); auto conn = _server.get_con_from_hdl(hdl);
@ -308,9 +320,11 @@ void WebSocketServer::onClose(websocketpp::connection_hdl hdl)
_sessions.erase(hdl); _sessions.erase(hdl);
lock.unlock(); lock.unlock();
// If client was identified, announce unsubscription // If client was identified, decrement appropriate refs in eventhandler.
if (isIdentified && _clientSubscriptionCallback) if (isIdentified) {
_clientSubscriptionCallback(false, eventSubscriptions); auto eventHandler = GetEventHandler();
eventHandler->ProcessUnsubscription(eventSubscriptions);
}
// Build SessionState object for signal // Build SessionState object for signal
WebSocketSessionState state; WebSocketSessionState state;

View File

@ -30,8 +30,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "rpc/WebSocketSession.h" #include "rpc/WebSocketSession.h"
#include "types/WebSocketCloseCode.h" #include "types/WebSocketCloseCode.h"
#include "types/WebSocketOpCode.h" #include "types/WebSocketOpCode.h"
#include "../requesthandler/rpc/Request.h"
#include "../utils/Json.h" #include "../utils/Json.h"
#include "../requesthandler/rpc/Request.h"
#include "plugin-macros.generated.h" #include "plugin-macros.generated.h"
class WebSocketServer : QObject { class WebSocketServer : QObject {
@ -57,14 +57,12 @@ public:
void InvalidateSession(websocketpp::connection_hdl hdl); void InvalidateSession(websocketpp::connection_hdl hdl);
void BroadcastEvent(uint64_t requiredIntent, const std::string &eventType, const json &eventData = nullptr, void BroadcastEvent(uint64_t requiredIntent, const std::string &eventType, const json &eventData = nullptr,
uint8_t rpcVersion = 0); uint8_t rpcVersion = 0);
inline void SetObsReady(bool ready) { _obsReady = ready; }
inline bool IsListening() { return _server.is_listening(); }
std::vector<WebSocketSessionState> GetWebSocketSessions();
inline QThreadPool *GetThreadPool() { return &_threadPool; }
// Callback for when a client subscribes or unsubscribes. `true` for sub, `false` for unsub bool IsListening() { return _server.is_listening(); }
typedef std::function<void(bool, uint64_t)> ClientSubscriptionCallback; // bool type, uint64_t eventSubscriptions
inline void SetClientSubscriptionCallback(ClientSubscriptionCallback cb) { _clientSubscriptionCallback = cb; } std::vector<WebSocketSessionState> GetWebSocketSessions();
QThreadPool *GetThreadPool() { return &_threadPool; }
signals: signals:
void ClientConnected(WebSocketSessionState state); void ClientConnected(WebSocketSessionState state);
@ -79,6 +77,7 @@ private:
void ServerRunner(); void ServerRunner();
void onObsReady(bool loaded);
bool onValidate(websocketpp::connection_hdl hdl); bool onValidate(websocketpp::connection_hdl hdl);
void onOpen(websocketpp::connection_hdl hdl); void onOpen(websocketpp::connection_hdl hdl);
void onClose(websocketpp::connection_hdl hdl); void onClose(websocketpp::connection_hdl hdl);
@ -99,6 +98,4 @@ private:
std::map<websocketpp::connection_hdl, SessionPtr, std::owner_less<websocketpp::connection_hdl>> _sessions; std::map<websocketpp::connection_hdl, SessionPtr, std::owner_less<websocketpp::connection_hdl>> _sessions;
std::atomic<bool> _obsReady = false; std::atomic<bool> _obsReady = false;
ClientSubscriptionCallback _clientSubscriptionCallback;
}; };

View File

@ -23,6 +23,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "WebSocketServer.h" #include "WebSocketServer.h"
#include "../requesthandler/RequestHandler.h" #include "../requesthandler/RequestHandler.h"
#include "../requesthandler/RequestBatchHandler.h" #include "../requesthandler/RequestBatchHandler.h"
#include "../eventhandler/EventHandler.h"
#include "../obs-websocket.h" #include "../obs-websocket.h"
#include "../Config.h" #include "../Config.h"
#include "../utils/Crypto.h" #include "../utils/Crypto.h"
@ -31,7 +32,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
static bool IsSupportedRpcVersion(uint8_t requestedVersion) static bool IsSupportedRpcVersion(uint8_t requestedVersion)
{ {
return (requestedVersion == CURRENT_RPC_VERSION); return (requestedVersion == 1);
} }
static json ConstructRequestResult(RequestResult requestResult, const json &requestJson) static json ConstructRequestResult(RequestResult requestResult, const json &requestJson)
@ -148,9 +149,9 @@ void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::Proces
if (ret.closeCode != WebSocketCloseCode::DontClose) if (ret.closeCode != WebSocketCloseCode::DontClose)
return; return;
// Announce subscribe // Increment refs for event subscriptions
if (_clientSubscriptionCallback) auto eventHandler = GetEventHandler();
_clientSubscriptionCallback(true, session->EventSubscriptions()); eventHandler->ProcessSubscription(session->EventSubscriptions());
// Mark session as identified // Mark session as identified
session->SetIsIdentified(true); session->SetIsIdentified(true);
@ -171,17 +172,16 @@ void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::Proces
case WebSocketOpCode::Reidentify: { // Reidentify case WebSocketOpCode::Reidentify: { // Reidentify
std::unique_lock<std::mutex> sessionLock(session->OperationMutex); std::unique_lock<std::mutex> sessionLock(session->OperationMutex);
// Announce unsubscribe // Decrement refs for current subscriptions
if (_clientSubscriptionCallback) auto eventHandler = GetEventHandler();
_clientSubscriptionCallback(false, session->EventSubscriptions()); eventHandler->ProcessUnsubscription(session->EventSubscriptions());
SetSessionParameters(session, ret, payloadData); SetSessionParameters(session, ret, payloadData);
if (ret.closeCode != WebSocketCloseCode::DontClose) if (ret.closeCode != WebSocketCloseCode::DontClose)
return; return;
// Announce subscribe // Increment refs for new subscriptions
if (_clientSubscriptionCallback) eventHandler->ProcessSubscription(session->EventSubscriptions());
_clientSubscriptionCallback(true, session->EventSubscriptions());
ret.result["op"] = WebSocketOpCode::Identified; ret.result["op"] = WebSocketOpCode::Identified;
ret.result["d"]["negotiatedRpcVersion"] = session->RpcVersion(); ret.result["d"]["negotiatedRpcVersion"] = session->RpcVersion();

View File

@ -122,8 +122,5 @@ namespace WebSocketOpCode {
RequestBatchResponse = 9, RequestBatchResponse = 9,
}; };
inline bool IsValid(uint8_t opCode) inline bool IsValid(uint8_t opCode) { return opCode >= Hello && opCode <= RequestBatchResponse; }
{
return opCode >= Hello && opCode <= RequestBatchResponse;
}
} }