mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
ef5480dd7b | |||
de13707f8b | |||
7b81b81a3e | |||
2854c4e1b5 | |||
1848442e91 | |||
7a19b168b7 | |||
9adea8bab4 | |||
1db18e12b3 | |||
3be4c8ae0e | |||
437f4df84c |
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,6 +0,0 @@
|
|||||||
[submodule "deps/websocketpp"]
|
|
||||||
path = deps/websocketpp
|
|
||||||
url = https://github.com/zaphoyd/websocketpp.git
|
|
||||||
[submodule "deps/asio"]
|
|
||||||
path = deps/asio
|
|
||||||
url = https://github.com/chriskohlhoff/asio.git
|
|
19
BUILDING.md
19
BUILDING.md
@ -1,26 +1,21 @@
|
|||||||
# Compiling obs-websocket
|
# Compiling obs-websocket
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
You'll need [Qt 5.10.x](https://download.qt.io/official_releases/qt/5.10/),
|
You'll need [Qt 5.10.x](https://download.qt.io/official_releases/qt/5.10/),
|
||||||
[CMake](https://cmake.org/download/), [Boost](https://www.boost.org/) and a working [OBS Studio development environment](https://obsproject.com/wiki/install-instructions) installed on your
|
[CMake](https://cmake.org/download/), and a working [development environment for
|
||||||
|
OBS Studio](https://obsproject.com/wiki/install-instructions) installed on your
|
||||||
computer.
|
computer.
|
||||||
|
|
||||||
## Windows
|
## Windows
|
||||||
|
|
||||||
In cmake-gui, you'll have to set the following variables :
|
In cmake-gui, you'll have to set the following variables :
|
||||||
|
|
||||||
- **QTDIR** (path) : location of the Qt environment suited for your compiler and architecture
|
- **QTDIR** (path) : location of the Qt environment suited for your compiler and architecture
|
||||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source code of OBS Studio
|
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source code of OBS Studio
|
||||||
- **LIBOBS_LIB** (filepath) : location of the obs.lib file
|
- **LIBOBS_LIB** (filepath) : location of the obs.lib file
|
||||||
- **OBS_FRONTEND_LIB** (filepath) : location of the obs-frontend-api.lib file
|
- **OBS_FRONTEND_LIB** (filepath) : location of the obs-frontend-api.lib file
|
||||||
|
|
||||||
## Linux
|
## Linux
|
||||||
|
|
||||||
On Debian/Ubuntu :
|
On Debian/Ubuntu :
|
||||||
|
```
|
||||||
```shell
|
sudo apt-get install libqt5websockets5-dev
|
||||||
sudo apt-get install libboost-all-dev
|
|
||||||
git clone --recursive https://github.com/Palakis/obs-websocket.git
|
git clone --recursive https://github.com/Palakis/obs-websocket.git
|
||||||
cd obs-websocket
|
cd obs-websocket
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
@ -30,8 +25,7 @@ sudo make install
|
|||||||
```
|
```
|
||||||
|
|
||||||
## OS X
|
## OS X
|
||||||
|
As a prerequisite, you will need Xcode for your current OSX version, the command line tools, and [Homebrew](https://brew.sh/).
|
||||||
As a prerequisite, you will need Xcode for your current OSX version, the Xcode command line tools, and [Homebrew](https://brew.sh/).
|
|
||||||
Homebrew's setup will guide you in getting your system set up, you should be good to go once Homebrew is successfully up and running.
|
Homebrew's setup will guide you in getting your system set up, you should be good to go once Homebrew is successfully up and running.
|
||||||
|
|
||||||
Use of the Travis macOS CI scripts is recommended. Please note that these
|
Use of the Travis macOS CI scripts is recommended. Please note that these
|
||||||
@ -44,7 +38,7 @@ skip that script.
|
|||||||
Of course, you're encouraged to dig through the contents of these scripts to
|
Of course, you're encouraged to dig through the contents of these scripts to
|
||||||
look for issues or specificities.
|
look for issues or specificities.
|
||||||
|
|
||||||
```shell
|
```
|
||||||
git clone --recursive https://github.com/Palakis/obs-websocket.git
|
git clone --recursive https://github.com/Palakis/obs-websocket.git
|
||||||
cd obs-websocket
|
cd obs-websocket
|
||||||
./CI/install-dependencies-macos.sh
|
./CI/install-dependencies-macos.sh
|
||||||
@ -52,7 +46,6 @@ cd obs-websocket
|
|||||||
./CI/build-macos.sh
|
./CI/build-macos.sh
|
||||||
./CI/package-macos.sh
|
./CI/package-macos.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
This will result in a ready-to-use `obs-websocket.pkg` installer in the `release` subfolder.
|
This will result in a ready-to-use `obs-websocket.pkg` installer in the `release` subfolder.
|
||||||
|
|
||||||
## Automated Builds
|
## Automated Builds
|
||||||
|
@ -34,10 +34,8 @@ git checkout $OBSLatestTag
|
|||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
echo "[obs-websocket] Building obs-studio.."
|
echo "[obs-websocket] Building obs-studio.."
|
||||||
cmake .. \
|
cmake .. \
|
||||||
-DBUILD_CAPTIONS=true \
|
|
||||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 \
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 \
|
||||||
-DDISABLE_PLUGINS=true \
|
-DDISABLE_PLUGINS=true \
|
||||||
-DENABLE_SCRIPTING=0 \
|
|
||||||
-DDepsPath=/tmp/obsdeps \
|
-DDepsPath=/tmp/obsdeps \
|
||||||
-DCMAKE_PREFIX_PATH=/usr/local/opt/qt/lib/cmake \
|
-DCMAKE_PREFIX_PATH=/usr/local/opt/qt/lib/cmake \
|
||||||
&& make -j4
|
&& make -j4
|
||||||
|
@ -108,12 +108,12 @@ if defined BuildOBS (
|
|||||||
mkdir build64
|
mkdir build64
|
||||||
echo Running cmake for obs-studio %OBSLatestTag% 32-bit...
|
echo Running cmake for obs-studio %OBSLatestTag% 32-bit...
|
||||||
cd ./build32
|
cd ./build32
|
||||||
cmake -G "Visual Studio 14 2015" -DBUILD_CAPTIONS=true -DDISABLE_PLUGINS=true -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true ..
|
cmake -G "Visual Studio 14 2015" -DDISABLE_PLUGINS=true -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true ..
|
||||||
echo:
|
echo:
|
||||||
echo:
|
echo:
|
||||||
echo Running cmake for obs-studio %OBSLatestTag% 64-bit...
|
echo Running cmake for obs-studio %OBSLatestTag% 64-bit...
|
||||||
cd ../build64
|
cd ../build64
|
||||||
cmake -G "Visual Studio 14 2015 Win64" -DBUILD_CAPTIONS=true -DDISABLE_PLUGINS=true -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true ..
|
cmake -G "Visual Studio 14 2015 Win64" -DDISABLE_PLUGINS=true -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true ..
|
||||||
echo:
|
echo:
|
||||||
echo:
|
echo:
|
||||||
echo Building obs-studio %OBSLatestTag% 32-bit ^(Build Config: %build_config%^)...
|
echo Building obs-studio %OBSLatestTag% 32-bit ^(Build Config: %build_config%^)...
|
||||||
|
@ -11,7 +11,7 @@ apt-get install -y \
|
|||||||
checkinstall \
|
checkinstall \
|
||||||
cmake \
|
cmake \
|
||||||
obs-studio \
|
obs-studio \
|
||||||
qtbase5-dev
|
libqt5websockets5-dev
|
||||||
|
|
||||||
# Dirty hack
|
# Dirty hack
|
||||||
wget -O /usr/include/obs/obs-frontend-api.h https://raw.githubusercontent.com/obsproject/obs-studio/master/UI/obs-frontend-api/obs-frontend-api.h
|
wget -O /usr/include/obs/obs-frontend-api.h https://raw.githubusercontent.com/obsproject/obs-studio/master/UI/obs-frontend-api/obs-frontend-api.h
|
||||||
|
@ -12,6 +12,123 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>CHILDREN</key>
|
<key>CHILDREN</key>
|
||||||
<array>
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../build/QtNetwork</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>292</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../build/QtWebSockets</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>292</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>bin</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>509</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>2</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>Resources</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>509</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>2</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>Contents</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>509</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>2</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>OBS.app</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>509</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>2</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>Applications</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>509</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>CHILDREN</key>
|
<key>CHILDREN</key>
|
||||||
<array>
|
<array>
|
||||||
@ -518,7 +635,7 @@
|
|||||||
<key>OVERWRITE_PERMISSIONS</key>
|
<key>OVERWRITE_PERMISSIONS</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>VERSION</key>
|
<key>VERSION</key>
|
||||||
<string>4.6.1</string>
|
<string>4.5.1</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>PROJECT_COMMENTS</key>
|
<key>PROJECT_COMMENTS</key>
|
||||||
<dict>
|
<dict>
|
||||||
|
@ -12,6 +12,9 @@ fi
|
|||||||
echo "[obs-websocket] Preparing package build"
|
echo "[obs-websocket] Preparing package build"
|
||||||
export QT_CELLAR_PREFIX="$(/usr/bin/find /usr/local/Cellar/qt -d 1 | sort -t '.' -k 1,1n -k 2,2n -k 3,3n | tail -n 1)"
|
export QT_CELLAR_PREFIX="$(/usr/bin/find /usr/local/Cellar/qt -d 1 | sort -t '.' -k 1,1n -k 2,2n -k 3,3n | tail -n 1)"
|
||||||
|
|
||||||
|
export WS_LIB="/usr/local/opt/qt/lib/QtWebSockets.framework/QtWebSockets"
|
||||||
|
export NET_LIB="/usr/local/opt/qt/lib/QtNetwork.framework/QtNetwork"
|
||||||
|
|
||||||
export GIT_HASH=$(git rev-parse --short HEAD)
|
export GIT_HASH=$(git rev-parse --short HEAD)
|
||||||
export GIT_BRANCH_OR_TAG=$(git name-rev --name-only HEAD | awk -F/ '{print $NF}')
|
export GIT_BRANCH_OR_TAG=$(git name-rev --name-only HEAD | awk -F/ '{print $NF}')
|
||||||
|
|
||||||
@ -21,17 +24,46 @@ export LATEST_VERSION="$GIT_BRANCH_OR_TAG"
|
|||||||
export FILENAME="obs-websocket-$VERSION.pkg"
|
export FILENAME="obs-websocket-$VERSION.pkg"
|
||||||
export LATEST_FILENAME="obs-websocket-latest-$LATEST_VERSION.pkg"
|
export LATEST_FILENAME="obs-websocket-latest-$LATEST_VERSION.pkg"
|
||||||
|
|
||||||
|
echo "[obs-websocket] Copying Qt dependencies"
|
||||||
|
if [ ! -f ./build/$(basename $WS_LIB) ]; then cp $WS_LIB ./build; fi
|
||||||
|
if [ ! -f ./build/$(basename $NET_LIB) ]; then cp $NET_LIB ./build; fi
|
||||||
|
|
||||||
|
chmod +rw ./build/QtWebSockets ./build/QtNetwork
|
||||||
|
|
||||||
|
echo "[obs-websocket] Modifying QtNetwork"
|
||||||
|
install_name_tool \
|
||||||
|
-id @rpath/QtNetwork \
|
||||||
|
-change /usr/local/opt/qt/lib/QtNetwork.framework/Versions/5/QtNetwork @rpath/QtNetwork \
|
||||||
|
-change $QT_CELLAR_PREFIX/lib/QtCore.framework/Versions/5/QtCore @rpath/QtCore \
|
||||||
|
./build/QtNetwork
|
||||||
|
|
||||||
|
echo "[obs-websocket] Modifying QtWebSockets"
|
||||||
|
install_name_tool \
|
||||||
|
-id @rpath/QtWebSockets \
|
||||||
|
-change /usr/local/opt/qt/lib/QtWebSockets.framework/Versions/5/QtWebSockets @rpath/QtWebSockets \
|
||||||
|
-change $QT_CELLAR_PREFIX/lib/QtNetwork.framework/Versions/5/QtNetwork @rpath/QtNetwork \
|
||||||
|
-change $QT_CELLAR_PREFIX/lib/QtCore.framework/Versions/5/QtCore @rpath/QtCore \
|
||||||
|
./build/QtWebSockets
|
||||||
|
|
||||||
echo "[obs-websocket] Modifying obs-websocket.so"
|
echo "[obs-websocket] Modifying obs-websocket.so"
|
||||||
install_name_tool \
|
install_name_tool \
|
||||||
|
-change /usr/local/opt/qt/lib/QtWebSockets.framework/Versions/5/QtWebSockets @rpath/QtWebSockets \
|
||||||
-change /usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets @rpath/QtWidgets \
|
-change /usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets @rpath/QtWidgets \
|
||||||
|
-change /usr/local/opt/qt/lib/QtNetwork.framework/Versions/5/QtNetwork @rpath/QtNetwork \
|
||||||
-change /usr/local/opt/qt/lib/QtGui.framework/Versions/5/QtGui @rpath/QtGui \
|
-change /usr/local/opt/qt/lib/QtGui.framework/Versions/5/QtGui @rpath/QtGui \
|
||||||
-change /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore @rpath/QtCore \
|
-change /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore @rpath/QtCore \
|
||||||
./build/obs-websocket.so
|
./build/obs-websocket.so
|
||||||
|
|
||||||
# Check if replacement worked
|
# Check if replacement worked
|
||||||
|
echo "[obs-websocket] Dependencies for QtNetwork"
|
||||||
|
otool -L ./build/QtNetwork
|
||||||
|
echo "[obs-websocket] Dependencies for QtWebSockets"
|
||||||
|
otool -L ./build/QtWebSockets
|
||||||
echo "[obs-websocket] Dependencies for obs-websocket"
|
echo "[obs-websocket] Dependencies for obs-websocket"
|
||||||
otool -L ./build/obs-websocket.so
|
otool -L ./build/obs-websocket.so
|
||||||
|
|
||||||
|
chmod -w ./build/QtWebSockets ./build/QtNetwork
|
||||||
|
|
||||||
echo "[obs-websocket] Actual package build"
|
echo "[obs-websocket] Actual package build"
|
||||||
packagesbuild ./CI/macos/obs-websocket.pkgproj
|
packagesbuild ./CI/macos/obs-websocket.pkgproj
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ PAGER=cat checkinstall -y --type=debian --fstrans=no --nodoc \
|
|||||||
--backup=no --deldoc=yes --install=no \
|
--backup=no --deldoc=yes --install=no \
|
||||||
--pkgname=obs-websocket --pkgversion="$PKG_VERSION" \
|
--pkgname=obs-websocket --pkgversion="$PKG_VERSION" \
|
||||||
--pkglicense="GPLv2.0" --maintainer="contact@slepin.fr" \
|
--pkglicense="GPLv2.0" --maintainer="contact@slepin.fr" \
|
||||||
--pkggroup="video" \
|
--requires="libqt5websockets5" --pkggroup="video" \
|
||||||
--pkgsource="https://github.com/Palakis/obs-websocket" \
|
--pkgsource="https://github.com/Palakis/obs-websocket" \
|
||||||
--pakdir="/package"
|
--pakdir="/package"
|
||||||
|
|
||||||
|
@ -6,30 +6,18 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
if (WIN32 OR APPLE)
|
|
||||||
include(external/FindLibObs.cmake)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_definitions(-DASIO_STANDALONE)
|
|
||||||
|
|
||||||
if (UNIX)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WIN32 OR APPLE)
|
if (WIN32 OR APPLE)
|
||||||
include(external/FindLibObs.cmake)
|
include(external/FindLibObs.cmake)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(LibObs REQUIRED)
|
find_package(LibObs REQUIRED)
|
||||||
find_package(Qt5Core REQUIRED)
|
find_package(Qt5Core REQUIRED)
|
||||||
|
find_package(Qt5WebSockets REQUIRED)
|
||||||
find_package(Qt5Widgets REQUIRED)
|
find_package(Qt5Widgets REQUIRED)
|
||||||
|
|
||||||
set(obs-websocket_SOURCES
|
set(obs-websocket_SOURCES
|
||||||
src/obs-websocket.cpp
|
src/obs-websocket.cpp
|
||||||
src/WSServer.cpp
|
src/WSServer.cpp
|
||||||
src/ConnectionProperties.cpp
|
|
||||||
src/WSRequestHandler.cpp
|
src/WSRequestHandler.cpp
|
||||||
src/WSRequestHandler_General.cpp
|
src/WSRequestHandler_General.cpp
|
||||||
src/WSRequestHandler_Profiles.cpp
|
src/WSRequestHandler_Profiles.cpp
|
||||||
@ -50,7 +38,6 @@ set(obs-websocket_SOURCES
|
|||||||
set(obs-websocket_HEADERS
|
set(obs-websocket_HEADERS
|
||||||
src/obs-websocket.h
|
src/obs-websocket.h
|
||||||
src/WSServer.h
|
src/WSServer.h
|
||||||
src/ConnectionProperties.h
|
|
||||||
src/WSRequestHandler.h
|
src/WSRequestHandler.h
|
||||||
src/WSEvents.h
|
src/WSEvents.h
|
||||||
src/Config.h
|
src/Config.h
|
||||||
@ -65,13 +52,13 @@ add_library(obs-websocket MODULE
|
|||||||
include_directories(
|
include_directories(
|
||||||
"${LIBOBS_INCLUDE_DIR}/../UI/obs-frontend-api"
|
"${LIBOBS_INCLUDE_DIR}/../UI/obs-frontend-api"
|
||||||
${Qt5Core_INCLUDES}
|
${Qt5Core_INCLUDES}
|
||||||
${Qt5Widgets_INCLUDES}
|
${Qt5WebSockets_INCLUDES}
|
||||||
"${CMAKE_SOURCE_DIR}/deps/asio/asio/include"
|
${Qt5Widgets_INCLUDES})
|
||||||
"${CMAKE_SOURCE_DIR}/deps/websocketpp")
|
|
||||||
|
|
||||||
target_link_libraries(obs-websocket
|
target_link_libraries(obs-websocket
|
||||||
libobs
|
libobs
|
||||||
Qt5::Core
|
Qt5::Core
|
||||||
|
Qt5::WebSockets
|
||||||
Qt5::Widgets)
|
Qt5::Widgets)
|
||||||
|
|
||||||
# --- End of section ---
|
# --- End of section ---
|
||||||
@ -83,8 +70,6 @@ if(WIN32)
|
|||||||
message(FATAL_ERROR "Could not find OBS Frontend API's library !")
|
message(FATAL_ERROR "Could not find OBS Frontend API's library !")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
|
||||||
|
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
set(ARCH_NAME "64bit")
|
set(ARCH_NAME "64bit")
|
||||||
set(OBS_BUILDDIR_ARCH "build64")
|
set(OBS_BUILDDIR_ARCH "build64")
|
||||||
@ -117,6 +102,8 @@ if(WIN32)
|
|||||||
|
|
||||||
COMMAND if $<CONFIG:Release>==1 ("${CMAKE_COMMAND}" -E copy
|
COMMAND if $<CONFIG:Release>==1 ("${CMAKE_COMMAND}" -E copy
|
||||||
"$<TARGET_FILE:obs-websocket>"
|
"$<TARGET_FILE:obs-websocket>"
|
||||||
|
"${QTDIR}/bin/Qt5WebSockets.dll"
|
||||||
|
"${QTDIR}/bin/Qt5Network.dll"
|
||||||
"${RELEASE_DIR}/obs-plugins/${ARCH_NAME}")
|
"${RELEASE_DIR}/obs-plugins/${ARCH_NAME}")
|
||||||
|
|
||||||
# If config is RelWithDebInfo, package release files
|
# If config is RelWithDebInfo, package release files
|
||||||
@ -131,6 +118,8 @@ if(WIN32)
|
|||||||
|
|
||||||
COMMAND if $<CONFIG:RelWithDebInfo>==1 ("${CMAKE_COMMAND}" -E copy
|
COMMAND if $<CONFIG:RelWithDebInfo>==1 ("${CMAKE_COMMAND}" -E copy
|
||||||
"$<TARGET_FILE:obs-websocket>"
|
"$<TARGET_FILE:obs-websocket>"
|
||||||
|
"${QTDIR}/bin/Qt5WebSockets.dll"
|
||||||
|
"${QTDIR}/bin/Qt5Network.dll"
|
||||||
"${RELEASE_DIR}/obs-plugins/${ARCH_NAME}")
|
"${RELEASE_DIR}/obs-plugins/${ARCH_NAME}")
|
||||||
|
|
||||||
COMMAND if $<CONFIG:RelWithDebInfo>==1 ("${CMAKE_COMMAND}" -E copy
|
COMMAND if $<CONFIG:RelWithDebInfo>==1 ("${CMAKE_COMMAND}" -E copy
|
||||||
@ -141,6 +130,8 @@ if(WIN32)
|
|||||||
COMMAND if $<CONFIG:Debug>==1 (
|
COMMAND if $<CONFIG:Debug>==1 (
|
||||||
"${CMAKE_COMMAND}" -E copy
|
"${CMAKE_COMMAND}" -E copy
|
||||||
"$<TARGET_FILE:obs-websocket>"
|
"$<TARGET_FILE:obs-websocket>"
|
||||||
|
"${QTDIR}/bin/Qt5WebSocketsd.dll"
|
||||||
|
"${QTDIR}/bin/Qt5Networkd.dll"
|
||||||
"${LIBOBS_INCLUDE_DIR}/../${OBS_BUILDDIR_ARCH}/rundir/$<CONFIG>/obs-plugins/${ARCH_NAME}")
|
"${LIBOBS_INCLUDE_DIR}/../${OBS_BUILDDIR_ARCH}/rundir/$<CONFIG>/obs-plugins/${ARCH_NAME}")
|
||||||
|
|
||||||
COMMAND if $<CONFIG:Debug>==1 (
|
COMMAND if $<CONFIG:Debug>==1 (
|
||||||
@ -164,8 +155,11 @@ endif()
|
|||||||
|
|
||||||
# --- Linux-specific build settings and tasks ---
|
# --- Linux-specific build settings and tasks ---
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||||
|
|
||||||
set_target_properties(obs-websocket PROPERTIES PREFIX "")
|
set_target_properties(obs-websocket PROPERTIES PREFIX "")
|
||||||
target_link_libraries(obs-websocket obs-frontend-api)
|
target_link_libraries(obs-websocket
|
||||||
|
obs-frontend-api)
|
||||||
|
|
||||||
file(GLOB locale_files data/locale/*.ini)
|
file(GLOB locale_files data/locale/*.ini)
|
||||||
execute_process(COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE UNAME_MACHINE)
|
execute_process(COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE UNAME_MACHINE)
|
||||||
|
76
README.md
76
README.md
@ -2,9 +2,9 @@ obs-websocket
|
|||||||
==============
|
==============
|
||||||
Remote control of OBS Studio made easy.
|
Remote control of OBS Studio made easy.
|
||||||
|
|
||||||
Follow the main author on Twitter for news & updates : [@LePalakis](https://twitter.com/LePalakis)
|
Follow the project on Twitter for news & updates : [@obswebsocket](https://twitter.com/obswebsocket)
|
||||||
|
|
||||||
[](https://ci.appveyor.com/project/Palakis/obs-websocket/history) [](https://travis-ci.org/Palakis/obs-websocket)
|
[](https://gitter.im/obs-websocket/obs-websocket) [](https://ci.appveyor.com/project/Palakis/obs-websocket/history) [](https://travis-ci.org/Palakis/obs-websocket)
|
||||||
|
|
||||||
## Downloads
|
## Downloads
|
||||||
Binaries for Windows and Linux are available in the [Releases](https://github.com/Palakis/obs-websocket/releases) section.
|
Binaries for Windows and Linux are available in the [Releases](https://github.com/Palakis/obs-websocket/releases) section.
|
||||||
@ -20,7 +20,6 @@ It is **highly recommended** to protect obs-websocket with a password against un
|
|||||||
- Automate scene switching with a third-party program (e.g. : auto-pilot, foot pedal, ...)
|
- Automate scene switching with a third-party program (e.g. : auto-pilot, foot pedal, ...)
|
||||||
|
|
||||||
### For developers
|
### For developers
|
||||||
|
|
||||||
The server is a typical Websockets server running by default on port 4444 (the port number can be changed in the Settings dialog).
|
The server is a typical Websockets server running by default on port 4444 (the port number can be changed in the Settings dialog).
|
||||||
The protocol understood by the server is documented in [PROTOCOL.md](docs/generated/protocol.md).
|
The protocol understood by the server is documented in [PROTOCOL.md](docs/generated/protocol.md).
|
||||||
|
|
||||||
@ -30,72 +29,23 @@ Here's a list of available language APIs for obs-websocket :
|
|||||||
- Python 2 and 3: [obs-websocket-py](https://github.com/Elektordi/obs-websocket-py) by Guillaume Genty a.k.a Elektordi
|
- Python 2 and 3: [obs-websocket-py](https://github.com/Elektordi/obs-websocket-py) by Guillaume Genty a.k.a Elektordi
|
||||||
- Python 3.5+ with asyncio: [obs-ws-rc](https://github.com/KirillMysnik/obs-ws-rc) by Kirill Mysnik
|
- Python 3.5+ with asyncio: [obs-ws-rc](https://github.com/KirillMysnik/obs-ws-rc) by Kirill Mysnik
|
||||||
|
|
||||||
I'd like to know what you're building with or for obs-websocket. If you do something in this fashion, feel free to drop me an email at `stephane /dot/ lepin /at/ gmail /dot/ com` !
|
I'd like to know what you're building with or for obs-websocket. If you do something in this fashion, feel free to drop me an email at `contact at slepin dot fr` !
|
||||||
|
|
||||||
## Compiling obs-websocket
|
## Compiling obs-websocket
|
||||||
|
|
||||||
See the [build instructions](BUILDING.md).
|
See the [build instructions](BUILDING.md).
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
### Branches
|
|
||||||
|
|
||||||
The two main development branches are:
|
|
||||||
|
|
||||||
- `4.x-current`: actively-maintained codebase for 4.x releases. Backwards-compatible (unless stated otherwise) with existing clients until 5.0.
|
|
||||||
- `5.x`: upcoming 5.0 version
|
|
||||||
|
|
||||||
**New features and fixes must be based off and contributed to `4.x-current`**, as obs-websocket 5.0 is not in active development yet.
|
|
||||||
|
|
||||||
### Pull Requests
|
|
||||||
|
|
||||||
Pull Requests must never be based off your fork's main branch (in our case, `4.x-current` or `5.x`). Start your work in a new branch
|
|
||||||
based on the main one (e.g.: `cool-new-feature`, `fix-palakis-mistakes`, ...) and open a Pull Request once you feel ready to show your work.
|
|
||||||
|
|
||||||
If your Pull Request is not ready to merge yet, tag it with the `work in progress` label. You can also use the `help needed` label if you have questions, need a hand or want to ask for input.
|
|
||||||
|
|
||||||
### Code style & formatting
|
|
||||||
|
|
||||||
Source code is indented with tabs, with spaces allowed for alignment.
|
|
||||||
|
|
||||||
Regarding protocol changes: new and updated request types / events must always come with accompanying documentation comments (see existing protocol elements for examples).
|
|
||||||
These are using to automatically generate the [protocol specification](docs/generated/protocol.md).
|
|
||||||
|
|
||||||
Among other recommendations: favor return-early code and avoid wrapping huge portions of code in conditionals. As an example, this:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
if (success) {
|
|
||||||
return req->SendOKResponse();
|
|
||||||
} else {
|
|
||||||
return req->SendErrorResponse("something went wrong");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
is better like this:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
if (!success) {
|
|
||||||
return req->SendErrorResponse("something went wrong");
|
|
||||||
}
|
|
||||||
return req->SendOKResponse();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Translations
|
## Translations
|
||||||
|
**We need your help on translations**. Please join the localization project on Crowdin: https://crowdin.com/project/obs-websocket
|
||||||
**Your help is welcome on translations**. Please join the localization project on Crowdin: https://crowdin.com/project/obs-websocket
|
|
||||||
|
|
||||||
## Special thanks
|
## Special thanks
|
||||||
|
In order of appearance:
|
||||||
In (almost) order of appearance:
|
|
||||||
|
|
||||||
- [Brendan H.](https://github.com/haganbmj) : Code contributions and gooder English in the Protocol specification
|
- [Brendan H.](https://github.com/haganbmj) : Code contributions and gooder English in the Protocol specification
|
||||||
- [Mikhail Swift](https://github.com/mikhailswift) : Code contributions
|
- [Mikhail Swift](https://github.com/mikhailswift) : Code contributions
|
||||||
- [Tobias Frahmer](https://github.com/Frahmer): Initial German localization
|
- [Tobias Frahmer](https://github.com/Frahmer) : German localization
|
||||||
- [Genture](https://github.com/Genteure): Initial Simplified Chinese and Traditional Chinese localizations
|
- [Genture](https://github.com/Genteure) : Simplified Chinese and Traditional Chinese localizations
|
||||||
- [Larissa Gabilan](https://github.com/laris151): Initial Portuguese localization
|
- [Larissa Gabilan](https://github.com/laris151) : Portuguese localization
|
||||||
- [Andy Asquelt](https://github.com/asquelt): Initial Polish localization
|
- [Andy Asquelt](https://github.com/asquelt) : Polish localization
|
||||||
- [Marcel Haazen](https://github.com/nekocentral): Initial Dutch localization
|
- [Marcel Haazen](https://github.com/inpothet) : Dutch localization
|
||||||
- [Peter Antonvich](https://github.com/pantonvich) : Code contributions
|
- [Peter Antonvich](https://github.com/pantonvich) : Code contributions
|
||||||
- [yinzara](https://github.com/yinzara) : Code contributions
|
- [yinzara](https://github.com/yinzara) : Code contributions
|
||||||
- [Chris Angelico](https://github.com/Rosuav) : Code contributions
|
- [Chris Angelico](https://github.com/Rosuav) : Code contributions
|
||||||
@ -106,16 +56,10 @@ In (almost) order of appearance:
|
|||||||
- [RytoEX](https://github.com/RytoEX) : CI script and code contributions
|
- [RytoEX](https://github.com/RytoEX) : CI script and code contributions
|
||||||
- [Theodore Stoddard](https://github.com/TStod) : Code contributions
|
- [Theodore Stoddard](https://github.com/TStod) : Code contributions
|
||||||
- [Philip Loche](https://github.com/PicoCentauri) : Code contributions
|
- [Philip Loche](https://github.com/PicoCentauri) : Code contributions
|
||||||
- [Patrick Heyer](https://github.com/PatTheMav): Code contributions and CI fixes
|
|
||||||
- [Alex Van Camp](https://github.com/Lange): Code contributions
|
|
||||||
- [Freddie Meyer](https://github.com/DungFu): Code contributions
|
|
||||||
- [Casey Muller](https://github.com/caseymrm): CI fixes
|
|
||||||
- [Chris Angelico](https://github.com/Rosuav): Documentation fixes
|
|
||||||
|
|
||||||
And also: special thanks to supporters of the project!
|
And also: special thanks to supporters of the project!
|
||||||
|
|
||||||
## Supporters
|
## Supporters
|
||||||
|
|
||||||
They have contributed financially to the project and made possible the addition of several features into obs-websocket. Many thanks to them!
|
They have contributed financially to the project and made possible the addition of several features into obs-websocket. Many thanks to them!
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -2,9 +2,6 @@ pool:
|
|||||||
vmImage: 'macOS-10.13'
|
vmImage: 'macOS-10.13'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- checkout: self
|
|
||||||
submodules: true
|
|
||||||
|
|
||||||
- script: ./CI/install-dependencies-macos.sh
|
- script: ./CI/install-dependencies-macos.sh
|
||||||
displayName: 'Install Dependencies'
|
displayName: 'Install Dependencies'
|
||||||
|
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
OBSWebsocket.Settings.DialogTitle="WebSockets-Servereinstellungen"
|
OBSWebsocket.Menu.SettingsItem="Websocket-Server Einstellungen"
|
||||||
OBSWebsocket.Settings.ServerEnable="WebSockets-Server aktivieren"
|
OBSWebsocket.Settings.DialogTitle="Websocket-Server Einstellungen"
|
||||||
OBSWebsocket.Settings.ServerPort="Server-Port"
|
OBSWebsocket.Settings.ServerEnable="Websocket-Server aktivieren"
|
||||||
OBSWebsocket.Settings.AuthRequired="Authentifizierung aktivieren"
|
OBSWebsocket.Settings.ServerPort="Server Port"
|
||||||
|
OBSWebsocket.Settings.AuthRequired="Authentifizierung erforderlich"
|
||||||
OBSWebsocket.Settings.Password="Passwort"
|
OBSWebsocket.Settings.Password="Passwort"
|
||||||
OBSWebsocket.Settings.DebugEnable="Debug-Protokollierung aktivieren"
|
OBSWebsocket.Settings.DebugEnable="Debug-Protokollierung aktivieren"
|
||||||
OBSWebsocket.Settings.AlertsEnable="Infobereichbenachrichtigungen aktivieren"
|
OBSWebsocket.Settings.AlertsEnable="Infobereich-Benachrichtigungen aktivieren"
|
||||||
OBSWebsocket.NotifyConnect.Title="Neue Websocket-Verbindung"
|
OBSWebsocket.NotifyConnect.Title="Neue WebSocket Verbindung"
|
||||||
OBSWebsocket.NotifyConnect.Message="Client %1 verbunden"
|
OBSWebsocket.NotifyConnect.Message="Client %1 verbunden"
|
||||||
OBSWebsocket.NotifyDisconnect.Title="Websocket-Client getrennt"
|
OBSWebsocket.NotifyDisconnect.Title="WebSocket-Client getrennt"
|
||||||
OBSWebsocket.NotifyDisconnect.Message="Client %1 getrennt"
|
OBSWebsocket.NotifyDisconnect.Message="Client %1 getrennt"
|
||||||
OBSWebsocket.Server.StartFailed.Title="Websocket-Serverfehler"
|
OBSWebsocket.Server.StartFailed.Title="WebSocket-Server Fehler"
|
||||||
OBSWebsocket.Server.StartFailed.Message="Der WebSockets-Server konnte nicht gestartet werden, mögliche Gründe:\n - Der TCP-Port %1 wird möglicherweise gerade von einem anderen Programm verwendet. Versuchen Sie einen anderen Port in den Websocket-Servereinstellungen zu setzen oder alle Programme zu beenden, die den Port möglicherweise verwenden.\n - Ein unbekannter Netzwerkfehler ist aufgetreten. Versuchen Sie es mit anderen Einstellungen, einem OBS-Neustart oder einem Systemneustart erneut."
|
OBSWebsocket.Server.StartFailed.Message="Der WebSocket-Server konnte nicht gestartet werden, mögliche Gründe:\n - TCP Port %1 wird möglicherweise gerade von einem anderen Programm verwendet. Versuchen Sie einen anderen Port in den WebSocket-Server Einstellungen zu setzten oder alle Programme zu beenden, die den Port möglicherweise verwenden.\n - Ein unbekannter Netzwerkfehler ist aufgetreten. Versuchen Sie es erneut mit anderen Einstellungen, einem OBS neustart oder einem System neustart."
|
||||||
OBSWebsocket.ProfileChanged.Started="WebSockets-Server in diesem Profil aktiviert. Server gestartet."
|
|
||||||
OBSWebsocket.ProfileChanged.Stopped="WebSockets-Server in diesem Profil deaktiviert. Server gestoppt."
|
|
||||||
OBSWebsocket.ProfileChanged.Restarted="WebSockets-Server in diesem Profil geändert. Server startet neu."
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
OBSWebsocket.Settings.DialogTitle="WebSockets Server Settings"
|
OBSWebsocket.Menu.SettingsItem="Websocket server settings"
|
||||||
OBSWebsocket.Settings.ServerEnable="Enable WebSockets server"
|
OBSWebsocket.Settings.DialogTitle="obs-websocket"
|
||||||
|
OBSWebsocket.Settings.ServerEnable="Enable Websocket server"
|
||||||
OBSWebsocket.Settings.ServerPort="Server Port"
|
OBSWebsocket.Settings.ServerPort="Server Port"
|
||||||
OBSWebsocket.Settings.AuthRequired="Enable authentication"
|
OBSWebsocket.Settings.AuthRequired="Enable authentication"
|
||||||
OBSWebsocket.Settings.Password="Password"
|
OBSWebsocket.Settings.Password="Password"
|
||||||
@ -9,8 +10,5 @@ OBSWebsocket.NotifyConnect.Title="New WebSocket connection"
|
|||||||
OBSWebsocket.NotifyConnect.Message="Client %1 connected"
|
OBSWebsocket.NotifyConnect.Message="Client %1 connected"
|
||||||
OBSWebsocket.NotifyDisconnect.Title="WebSocket client disconnected"
|
OBSWebsocket.NotifyDisconnect.Title="WebSocket client disconnected"
|
||||||
OBSWebsocket.NotifyDisconnect.Message="Client %1 disconnected"
|
OBSWebsocket.NotifyDisconnect.Message="Client %1 disconnected"
|
||||||
OBSWebsocket.Server.StartFailed.Title="WebSockets Server failure"
|
OBSWebsocket.Server.StartFailed.Title="WebSocket Server failure"
|
||||||
OBSWebsocket.Server.StartFailed.Message="The WebSockets server failed to start, maybe because:\n - TCP port %1 may currently be in use elsewhere on this system, possibly by another application. Try setting a different TCP port in the WebSocket server settings, or stop any application that could be using this port.\n - An unknown network error happened on your system. Try again by changing settings, restarting OBS or restarting your system."
|
OBSWebsocket.Server.StartFailed.Message="The obs-websocket server failed to start, maybe because:\n - TCP port %1 may currently be in use elsewhere on this system, possibly by another application. Try setting a different TCP port in the WebSocket server settings, or stop any application that could be using this port.\n - An unknown network error happened on your system. Try again by changing settings, restarting OBS or restarting your system."
|
||||||
OBSWebsocket.ProfileChanged.Started="WebSockets server enabled in this profile. Server started."
|
|
||||||
OBSWebsocket.ProfileChanged.Stopped="WebSockets server disabled in this profile. Server stopped."
|
|
||||||
OBSWebsocket.ProfileChanged.Restarted="WebSockets server port changed in this profile. Server restarted."
|
|
@ -1,12 +1,14 @@
|
|||||||
OBSWebsocket.Settings.ServerEnable="Habilitar el servidor WebSockets"
|
OBSWebsocket.Menu.SettingsItem="Configuración del servidor obs-websocket"
|
||||||
|
OBSWebsocket.Settings.DialogTitle="obs-websocket"
|
||||||
|
OBSWebsocket.Settings.ServerEnable="Habilitar el servidor Websocket"
|
||||||
OBSWebsocket.Settings.ServerPort="Puerto del Servidor"
|
OBSWebsocket.Settings.ServerPort="Puerto del Servidor"
|
||||||
OBSWebsocket.Settings.AuthRequired="Habilitar autenticación"
|
OBSWebsocket.Settings.AuthRequired="Habilitar autenticación"
|
||||||
OBSWebsocket.Settings.Password="Contraseña"
|
OBSWebsocket.Settings.Password="Contraseña"
|
||||||
OBSWebsocket.Settings.DebugEnable="Habilitar registro de depuración"
|
OBSWebsocket.Settings.DebugEnable="Habilitar registro de depuración"
|
||||||
OBSWebsocket.Settings.AlertsEnable="Habilitar alertas en la bandeja de sistema"
|
OBSWebsocket.Settings.AlertsEnable="Habilitar alertas de la bandeja de sistema"
|
||||||
OBSWebsocket.NotifyConnect.Title="Nueva conexión WebSocket"
|
OBSWebsocket.NotifyConnect.Title="Nueva conexión WebSocket"
|
||||||
OBSWebsocket.NotifyConnect.Message="Cliente %1 conectado"
|
OBSWebsocket.NotifyConnect.Message="Cliente %1 conectado"
|
||||||
OBSWebsocket.NotifyDisconnect.Title="Cliente WebSocket desconectado"
|
OBSWebsocket.NotifyDisconnect.Title="Cliente WebSocket desconectado"
|
||||||
OBSWebsocket.NotifyDisconnect.Message="Cliente %1 desconectado"
|
OBSWebsocket.NotifyDisconnect.Message="Cliente %1 desconectado"
|
||||||
OBSWebsocket.Server.StartFailed.Title="Falla en el servidor WebSockets"
|
OBSWebsocket.Server.StartFailed.Title="Fallo del servidor WebSocket"
|
||||||
OBSWebsocket.Server.StartFailed.Message="El servidor obs-websocket no se pudo iniciar, tal vez porque: \n - el puerto TCP %1 podría estar actualmente siendo usado este sistema, posiblemente por otra aplicación. Intente configurar un puerto TCP diferente en la configuración del servidor WebSocket, o detenga cualquier aplicación que pudiese estar utilizando este puerto \n - Un error de red desconocido ha afectado su sistema. Inténtelo de nuevo cambiando la configuración, reiniciando OBS o reiniciando su sistema."
|
OBSWebsocket.Server.StartFailed.Message="El servidor obs-websocket no se pudo iniciar, tal vez porque: \n - el puerto TCP %1 podría estar actualmente en uso en este sistema, posiblemente por otra aplicación. Intente configurar un puerto TCP diferente en la configuración del servidor WebSocket, o detenga cualquier aplicación que pudiese estar utilizando este puerto \n - Un error de red desconocido ha ocurrido en su sistema. Inténtalo de nuevo cambiando la configuración, reiniciando OBS o reiniciando su sistema."
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
OBSWebsocket.Settings.DialogTitle="Paramètres du serveur WebSockets"
|
OBSWebsocket.Menu.SettingsItem="Paramètres du serveur Websocket"
|
||||||
OBSWebsocket.Settings.ServerEnable="Activer le serveur WebSocket"
|
OBSWebsocket.Settings.ServerEnable="Activer le serveur WebSocket"
|
||||||
OBSWebsocket.Settings.ServerPort="Port du serveur"
|
OBSWebsocket.Settings.ServerPort="Port du serveur"
|
||||||
OBSWebsocket.Settings.AuthRequired="Activer l'authentification"
|
OBSWebsocket.Settings.AuthRequired="Activer l'authentification"
|
||||||
@ -9,8 +9,5 @@ OBSWebsocket.NotifyConnect.Title="Nouvelle connexion WebSocket"
|
|||||||
OBSWebsocket.NotifyConnect.Message="Le client %1 s'est connecté"
|
OBSWebsocket.NotifyConnect.Message="Le client %1 s'est connecté"
|
||||||
OBSWebsocket.NotifyDisconnect.Title="Déconnexion WebSocket"
|
OBSWebsocket.NotifyDisconnect.Title="Déconnexion WebSocket"
|
||||||
OBSWebsocket.NotifyDisconnect.Message="Le client %1 s'est déconnecté"
|
OBSWebsocket.NotifyDisconnect.Message="Le client %1 s'est déconnecté"
|
||||||
OBSWebsocket.Server.StartFailed.Title="Impossible de démarrer le serveur WebSockets"
|
OBSWebsocket.Server.StartFailed.Title="Impossible de démarrer le serveur WebSocket"
|
||||||
OBSWebsocket.Server.StartFailed.Message="Le serveur WebSockets n'a pas pu démarrer, peut-être parce que :\n - Le port TCP %1 est en cours d'utilisation sur ce système, certainement par un autre programme. Essayez un port différent dans les réglages du serveur WebSocket, ou arrêtez tout programme susceptible d'utiliser ce port.\n - Une erreur réseau inconnue est survenue. Essayez à nouveau en modifiant vos réglages, en redémarrant OBS ou en redémarrant votre ordinateur."
|
OBSWebsocket.Server.StartFailed.Message="Le serveur WebSocket n'a pas pu démarrer, peut-être parce que :\n - Le port TCP %1 est en cours d'utilisation sur ce système, certainement par un autre programme. Essayez un port différent dans les réglages du serveur WebSocket, ou arrêtez tout programme susceptible d'utiliser ce port.\n - Une erreur réseau inconnue est survenue. Essayez à nouveau en modifiant vos réglages, en redémarrant OBS ou en redémarrant votre ordinateur."
|
||||||
OBSWebsocket.ProfileChanged.Started="Serveur WebSockets actif dans ce profil."
|
|
||||||
OBSWebsocket.ProfileChanged.Stopped="Serveur WebSockets désactivé dans ce profil."
|
|
||||||
OBSWebsocket.ProfileChanged.Restarted="Le port actuel diffère du port configuré dans ce profil. Serveur WebSockets redémarré."
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
OBSWebsocket.Settings.ServerEnable="Abilitare il server WebSockets"
|
OBSWebsocket.Menu.SettingsItem="Impostazioni del server di WebSocket"
|
||||||
|
OBSWebsocket.Settings.DialogTitle="obs-websocket"
|
||||||
|
OBSWebsocket.Settings.ServerEnable="Abilitare il server Websocket"
|
||||||
OBSWebsocket.Settings.ServerPort="Porta del server"
|
OBSWebsocket.Settings.ServerPort="Porta del server"
|
||||||
OBSWebsocket.Settings.AuthRequired="Abilitare l'autenticazione"
|
OBSWebsocket.Settings.AuthRequired="Abilitare l'autenticazione"
|
||||||
OBSWebsocket.Settings.Password="Password"
|
OBSWebsocket.Settings.Password="Password"
|
||||||
@ -9,4 +11,4 @@ OBSWebsocket.NotifyConnect.Message="%1 cliente collegato"
|
|||||||
OBSWebsocket.NotifyDisconnect.Title="WebSocket cliente disconnesso"
|
OBSWebsocket.NotifyDisconnect.Title="WebSocket cliente disconnesso"
|
||||||
OBSWebsocket.NotifyDisconnect.Message="%1 cliente disconnesso"
|
OBSWebsocket.NotifyDisconnect.Message="%1 cliente disconnesso"
|
||||||
OBSWebsocket.Server.StartFailed.Title="Errore del WebSocket Server"
|
OBSWebsocket.Server.StartFailed.Title="Errore del WebSocket Server"
|
||||||
OBSWebsocket.Server.StartFailed.Message="Impossibile avviare, forse perché il server di WebSockets: \n - %1 porta TCP potrebbe essere attualmente in uso altrove su questo sistema, possibilmente da un'altra applicazione. Provare a impostare una porta TCP diversa nelle impostazioni del server di WebSockets, o arrestare tutte le applicazioni che potrebbero utilizzare questa porta. \n - è verificato un errore di rete sconosciuto sul sistema. Riprova modificando le impostazioni, riavviare OBS o riavvio del sistema."
|
OBSWebsocket.Server.StartFailed.Message="Impossibile avviare, forse perché il server di obs-websocket: \n - %1 porta TCP potrebbe essere attualmente in uso altrove su questo sistema, possibilmente da un'altra applicazione. Provare a impostare una porta TCP diversa nelle impostazioni del server di WebSocket, o arrestare tutte le applicazioni che potrebbero utilizzare questa porta. \n - è verificato un errore di rete sconosciuto sul sistema. Riprova modificando le impostazioni, riavviare OBS o riavvio del sistema."
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
OBSWebsocket.Settings.ServerEnable="WebSockets サーバーを有効にする"
|
OBSWebsocket.Menu.SettingsItem="Websocket サーバー設定"
|
||||||
|
OBSWebsocket.Settings.DialogTitle="obs-websocket"
|
||||||
|
OBSWebsocket.Settings.ServerEnable="Websocket サーバーを有効にする"
|
||||||
OBSWebsocket.Settings.ServerPort="サーバーポート"
|
OBSWebsocket.Settings.ServerPort="サーバーポート"
|
||||||
OBSWebsocket.Settings.AuthRequired="認証を有効にする"
|
OBSWebsocket.Settings.AuthRequired="認証を有効にする"
|
||||||
OBSWebsocket.Settings.Password="パスワード"
|
OBSWebsocket.Settings.Password="パスワード"
|
||||||
OBSWebsocket.Settings.DebugEnable="デバッグログを有効にする"
|
OBSWebsocket.Settings.DebugEnable="デバッグログを有効にする"
|
||||||
OBSWebsocket.Settings.AlertsEnable="システムトレイ通知を有効にする"
|
|
||||||
OBSWebsocket.NotifyConnect.Title="新しいWebSocket接続"
|
OBSWebsocket.NotifyConnect.Title="新しいWebSocket接続"
|
||||||
OBSWebsocket.NotifyConnect.Message="接続されているクライアント %1"
|
|
||||||
OBSWebsocket.NotifyDisconnect.Title="WebSocket クライアントが切断されました"
|
|
||||||
OBSWebsocket.NotifyDisconnect.Message="切断されたクライアント %1"
|
|
||||||
OBSWebsocket.Server.StartFailed.Title="WebSockets サーバー障害"
|
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
|
OBSWebsocket.Menu.SettingsItem="Websocket server instellingen"
|
||||||
|
OBSWebsocket.Settings.DialogTitle="obs-websocket"
|
||||||
|
OBSWebsocket.Settings.ServerEnable="Activeer Websocket server"
|
||||||
OBSWebsocket.Settings.ServerPort="Serverpoort"
|
OBSWebsocket.Settings.ServerPort="Serverpoort"
|
||||||
|
OBSWebsocket.Settings.AuthRequired="Activeer authenticatie"
|
||||||
|
OBSWebsocket.Settings.Password="Wachtwoord"
|
||||||
OBSWebsocket.Settings.DebugEnable="Activeer debug logs"
|
OBSWebsocket.Settings.DebugEnable="Activeer debug logs"
|
||||||
OBSWebsocket.Settings.AlertsEnable="Systemvak waarschuwingen inschakelen"
|
OBSWebsocket.Settings.AlertsEnable="Systemvak waarschuwingen inschakelen"
|
||||||
OBSWebsocket.NotifyConnect.Title="Nieuwe WebSocket verbinding"
|
OBSWebsocket.NotifyConnect.Title="Nieuwe WebSocket verbinding"
|
||||||
OBSWebsocket.NotifyConnect.Message="Client %1 verbonden"
|
OBSWebsocket.NotifyConnect.Message="Client %1 verbonden"
|
||||||
OBSWebsocket.NotifyDisconnect.Title="WebSocket client connectie verbroken"
|
OBSWebsocket.NotifyDisconnect.Title="WebSocket client connectie verbroken"
|
||||||
OBSWebsocket.NotifyDisconnect.Message="Client %1 losgekoppeld"
|
OBSWebsocket.NotifyDisconnect.Message="Client %1 losgekoppeld"
|
||||||
OBSWebsocket.Server.StartFailed.Title="Fout in WebSocket server"
|
OBSWebsocket.Server.StartFailed.Title="WebSocket Server mislukt"
|
||||||
OBSWebsocket.Server.StartFailed.Message="De obs-websocket server kan niet worden gestart, misschien omdat: \n - TCP-poort %1 momenteel elders wordt gebruikt op dit systeem, eventueel door een andere toepassing. Probeer een andere TCP-poort in te stellen in de WebSocket Server-instellingen of stop elke toepassing die deze poort zou kunnen gebruiken.\n Een onbekende Netwerkfout op uw systeem. Probeer het opnieuw door de instellingen te wijzigen, OBS te herstarten of uw systeem te herstarten."
|
OBSWebsocket.Server.StartFailed.Message="De obs-websocket server kan niet worden gestart, misschien omdat: \n - TCP-poort %1 momenteel wordt gebruikt elders op dit systeem, eventueel door een andere toepassing. Probeer een andere TCP-poort instellen in de WebSocket Server-instellingen of stoppen van elke toepassing die deze poort zouden kunnen gebruiken.\n Een onbekende netwerkfout gebeurde op uw systeem. Probeer het opnieuw door de instellingen wijzigen, OBS herstarten of opnieuw opstarten van uw systeem."
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
OBSWebsocket.Settings.ServerEnable="Włącz serwer WebSockets"
|
OBSWebsocket.Menu.SettingsItem="Ustawienia serwera zdalnego sterowania"
|
||||||
OBSWebsocket.Settings.AuthRequired="Wymagaj uwierzytelniania"
|
OBSWebsocket.Settings.DialogTitle="Serwer zdalnego sterowania"
|
||||||
|
OBSWebsocket.Settings.ServerEnable="Włącz serwer zdalnego sterowania (Websocket)"
|
||||||
|
OBSWebsocket.Settings.ServerPort="Port serwera"
|
||||||
|
OBSWebsocket.Settings.AuthRequired="Wymagaj hasła"
|
||||||
|
OBSWebsocket.Settings.Password="Hasło"
|
||||||
OBSWebsocket.Settings.DebugEnable="Włącz rejestrowanie debugowania"
|
OBSWebsocket.Settings.DebugEnable="Włącz rejestrowanie debugowania"
|
||||||
OBSWebsocket.Settings.AlertsEnable="Włącz powiadomienia w zasobniku systemowym"
|
OBSWebsocket.Settings.AlertsEnable="Włącz powiadomienia o zasobniku systemowym"
|
||||||
OBSWebsocket.NotifyConnect.Title="Nowe połączenie WebSocket"
|
OBSWebsocket.NotifyConnect.Title="Nowe połączenie WebSocket"
|
||||||
OBSWebsocket.NotifyConnect.Message="Klient %1 połączony"
|
OBSWebsocket.NotifyConnect.Message="Klient %1 połączony"
|
||||||
OBSWebsocket.NotifyDisconnect.Title="Klient WebSocket odłączony"
|
OBSWebsocket.NotifyDisconnect.Title="Klient WebSocket odłączony"
|
||||||
OBSWebsocket.NotifyDisconnect.Message="Klient %1 rozłączony"
|
OBSWebsocket.NotifyDisconnect.Message="Klient %1 połączony"
|
||||||
OBSWebsocket.Server.StartFailed.Title="Awaria serwera WebSockets"
|
OBSWebsocket.Server.StartFailed.Title="Awaria serwera WebSocket"
|
||||||
OBSWebsocket.Server.StartFailed.Message="Nie udało się uruchomić serwera WebSockets, może a powodu: \n - TCP port %1 może być obecnie używany gdzie indziej w tym systemie, możliwie przez inną aplikację. Spróbuj ustawić inny port TCP w ustawieniach serwera WebSockets, lub zatrzymać dowolną aplikację, która może używać tego portu \n -nieznany błąd sieci wydarzył się w systemie. Spróbuj ponownie, zmieniając ustawienia, ponownie uruchamiając OBS lub ponownie uruchamiając system."
|
OBSWebsocket.Server.StartFailed.Message="Nie udało się uruchomić serwera obs-websocket, może a powodu: \n - TCP port %1 może być obecnie używany gdzie indziej w tym systemie, możliwie przez inną aplikację. Spróbuj ustawić inny port TCP w ustawieniach serwera WebSocket, lub zatrzymać dowolną aplikację, która może używać tego portu \n -nieznany błąd sieci wydarzył się w systemie. Spróbuj ponownie, zmieniając ustawienia, ponownie uruchamiając OBS lub ponownie uruchamiając system."
|
||||||
|
5
data/locale/pt-BR.ini
Normal file
5
data/locale/pt-BR.ini
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
OBSWebsocket.Menu.SettingsItem="Configuraçes do Servidor Websocket"
|
||||||
|
OBSWebsocket.Settings.ServerEnable="Habilitar o Servidor Websocket"
|
||||||
|
OBSWebsocket.Settings.ServerPort="Porta do Servidor"
|
||||||
|
OBSWebsocket.Settings.AuthRequired="Autenticação Requerida"
|
||||||
|
OBSWebsocket.Settings.Password="Senha"
|
@ -1,3 +1,5 @@
|
|||||||
|
OBSWebsocket.Menu.SettingsItem="Configurações do servidor Websocket"
|
||||||
|
OBSWebsocket.Settings.DialogTitle="obs-websocket"
|
||||||
OBSWebsocket.Settings.ServerEnable="Habilitar servidor de WebSockets"
|
OBSWebsocket.Settings.ServerEnable="Habilitar servidor de WebSockets"
|
||||||
OBSWebsocket.Settings.ServerPort="Porta do Servidor"
|
OBSWebsocket.Settings.ServerPort="Porta do Servidor"
|
||||||
OBSWebsocket.Settings.AuthRequired="Activar autenticação"
|
OBSWebsocket.Settings.AuthRequired="Activar autenticação"
|
||||||
@ -9,4 +11,4 @@ OBSWebsocket.NotifyConnect.Message="Cliente %1 conectado"
|
|||||||
OBSWebsocket.NotifyDisconnect.Title="WebSocket cliente desconectado"
|
OBSWebsocket.NotifyDisconnect.Title="WebSocket cliente desconectado"
|
||||||
OBSWebsocket.NotifyDisconnect.Message="Cliente %1 desconectado"
|
OBSWebsocket.NotifyDisconnect.Message="Cliente %1 desconectado"
|
||||||
OBSWebsocket.Server.StartFailed.Title="Falha do servidor de WebSocket"
|
OBSWebsocket.Server.StartFailed.Title="Falha do servidor de WebSocket"
|
||||||
OBSWebsocket.Server.StartFailed.Message="O servidor de WebSockets falhou ao iniciar, talvez porque: \n - TCP port %1 pode estar atualmente em uso em outro lugar sobre este sistema, possivelmente por outro aplicativo. Tente definir uma porta TCP diferente nas configurações do servidor de WebSockets, ou parar qualquer aplicativo que poderia estar usando este porto \n - um erro de rede desconhecido aconteceu no seu sistema. Tente novamente alterar configurações, reiniciando OBS ou reiniciando o sistema."
|
OBSWebsocket.Server.StartFailed.Message="O servidor obs-websocket falhou ao iniciar, talvez porque: \n - TCP port %1 pode estar atualmente em uso em outro lugar sobre este sistema, possivelmente por outro aplicativo. Tente definir uma porta TCP diferente nas configurações do servidor de WebSocket, ou parar qualquer aplicativo que poderia estar usando este porto \n - um erro de rede desconhecido aconteceu no seu sistema. Tente novamente alterar configurações, reiniciando OBS ou reiniciando o sistema."
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
OBSWebsocket.Settings.DialogTitle="Настройки сервера WebSockets"
|
OBSWebsocket.Menu.SettingsItem="Параметры сервера Websocket"
|
||||||
OBSWebsocket.Settings.ServerEnable="Включить сервер WebSockets"
|
OBSWebsocket.Settings.DialogTitle="obs-websocket"
|
||||||
|
OBSWebsocket.Settings.ServerEnable="Включить сервер Websocket"
|
||||||
OBSWebsocket.Settings.ServerPort="Порт сервера"
|
OBSWebsocket.Settings.ServerPort="Порт сервера"
|
||||||
OBSWebsocket.Settings.AuthRequired="Включить авторизацию"
|
OBSWebsocket.Settings.AuthRequired="Включить аутентификацию"
|
||||||
OBSWebsocket.Settings.Password="Пароль"
|
OBSWebsocket.Settings.Password="Пароль"
|
||||||
OBSWebsocket.Settings.DebugEnable="Включить ведение журнала отладки"
|
OBSWebsocket.Settings.DebugEnable="Включить ведение журнала отладки"
|
||||||
OBSWebsocket.Settings.AlertsEnable="Включить оповещения в системном трее"
|
OBSWebsocket.Settings.AlertsEnable="Включить оповещения в системном трее"
|
||||||
@ -9,5 +10,5 @@ OBSWebsocket.NotifyConnect.Title="Новое соединение WebSocket"
|
|||||||
OBSWebsocket.NotifyConnect.Message="Клиент %1 подключен"
|
OBSWebsocket.NotifyConnect.Message="Клиент %1 подключен"
|
||||||
OBSWebsocket.NotifyDisconnect.Title="Клиент WebSocket отключён"
|
OBSWebsocket.NotifyDisconnect.Title="Клиент WebSocket отключён"
|
||||||
OBSWebsocket.NotifyDisconnect.Message="Клиент %1 отключен"
|
OBSWebsocket.NotifyDisconnect.Message="Клиент %1 отключен"
|
||||||
OBSWebsocket.Server.StartFailed.Title="Сбой сервера WebSockets"
|
OBSWebsocket.Server.StartFailed.Title="Сбой сервера WebSocket"
|
||||||
OBSWebsocket.Server.StartFailed.Message="Ошибка запуска сервера WebSockets. Вероятные причины:\n - Возможно, TCP-порт %1 занят другим приложением в системе. Попробуйте задать другой TCP-порт в настройках сервера WebSockets или закройте приложение, которое может использовать данный порт.\n - Произошла неизвестная сетевая ошибка в системе. Попробуйте снова после изменения настроек, перезапуска OBS или системы."
|
OBSWebsocket.Server.StartFailed.Message="Сбой запуска сервера obs-websocket. Вероятные причины:\n - Возможно, TCP-порт %1 занят другим приложением в системе. Попробуйте задать другой TCP-порт в настройках сервера WebSocket или закройте приложение, которое может использовать данный порт.\n - Произошла неизвестная сетевая ошибка в системе. Попробуйте снова после изменения настроек, перезапуска OBS или перезапуска системы."
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
OBSWebsocket.Settings.ServerEnable="启用 WebSockets 服务器"
|
OBSWebsocket.Menu.SettingsItem="Websocket 服务器设置"
|
||||||
|
OBSWebsocket.Settings.DialogTitle="obs-websocket 设置"
|
||||||
|
OBSWebsocket.Settings.ServerEnable="启用 Websocket 服务器"
|
||||||
OBSWebsocket.Settings.ServerPort="服务器端口"
|
OBSWebsocket.Settings.ServerPort="服务器端口"
|
||||||
OBSWebsocket.Settings.AuthRequired="启用身份验证"
|
OBSWebsocket.Settings.AuthRequired="启用密码认证"
|
||||||
OBSWebsocket.Settings.Password="密码"
|
OBSWebsocket.Settings.Password="密码"
|
||||||
OBSWebsocket.Settings.DebugEnable="启用调试日志"
|
|
||||||
OBSWebsocket.Settings.AlertsEnable="启用系统托盘通知"
|
|
||||||
OBSWebsocket.NotifyConnect.Title="新 WebSocket 连接"
|
|
||||||
OBSWebsocket.NotifyConnect.Message="客户端 %1 已连接"
|
|
||||||
OBSWebsocket.NotifyDisconnect.Title="WebSocket 客户端已断开"
|
|
||||||
OBSWebsocket.NotifyDisconnect.Message="客户端 %1 已断开连接"
|
|
||||||
OBSWebsocket.Server.StartFailed.Title="WebSockets 服务器错误"
|
|
||||||
OBSWebsocket.Server.StartFailed.Message="WebSockets 服务器启动失败,可能是因为:\n - TCP 端口 %1 可能被本机的另一个应用程序占用。尝试在 WebSockets 服务器设置中设置不同的 TCP 端口,或关闭任何可能使用此端口的应用程序。\n - 在您的系统上发生了未知的网络错误。请尝试更改设置、重新启动 OBS 或重新启动系统。"
|
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
OBSWebsocket.Settings.ServerPort="伺服器連接埠"
|
OBSWebsocket.Menu.SettingsItem="Websocket 伺服器設定"
|
||||||
OBSWebsocket.Settings.DebugEnable="啟用除錯日誌"
|
OBSWebsocket.Settings.DialogTitle="obs-websocket 設定"
|
||||||
OBSWebsocket.Settings.AlertsEnable="啟用系統列通知"
|
OBSWebsocket.Settings.ServerEnable="啟用 Websocket 伺服器"
|
||||||
OBSWebsocket.NotifyConnect.Title="新的 WebSocket 連線"
|
OBSWebsocket.Settings.ServerPort="伺服器端口"
|
||||||
OBSWebsocket.NotifyConnect.Message="客戶端 %1 已連線"
|
OBSWebsocket.Settings.AuthRequired="啟用密碼認證"
|
||||||
OBSWebsocket.NotifyDisconnect.Title="WebSocket 客戶端已離線"
|
OBSWebsocket.Settings.Password="密碼"
|
||||||
OBSWebsocket.NotifyDisconnect.Message="客戶端 %1 已離線"
|
|
||||||
OBSWebsocket.Server.StartFailed.Title="WebSocket 伺服器錯誤"
|
|
||||||
OBSWebsocket.Server.StartFailed.Message="WebSockets 伺服器啟動失敗,可能的原因有:\n - TCP 連接埠 %1 被系統的其他程式所使用,試著為 WebSockets 伺服器指定不同的 TCP 連接埠,或是關閉任何可能使用此連接埠的程式。\n - 發生的未知的網路錯誤,試著更改設定、重新啟動 OBS 或是重新啟動您的系統。"
|
|
||||||
|
1
deps/asio
vendored
1
deps/asio
vendored
Submodule deps/asio deleted from b73dc1d2c0
1
deps/websocketpp
vendored
1
deps/websocketpp
vendored
Submodule deps/websocketpp deleted from c6d7e295bf
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
<!-- This file was generated based on handlebars templates. Do not edit directly! -->
|
<!-- This file was generated based on handlebars templates. Do not edit directly! -->
|
||||||
|
|
||||||
# obs-websocket 4.6.0 protocol reference
|
# obs-websocket 4.5.0 protocol reference
|
||||||
|
|
||||||
# General Introduction
|
# General Introduction
|
||||||
Messages are exchanged between the client and the server as JSON objects.
|
Messages are exchanged between the client and the server as JSON objects.
|
||||||
@ -43,10 +43,8 @@ auth_response = base64_encode(auth_response_hash)
|
|||||||
<!-- toc -->
|
<!-- toc -->
|
||||||
|
|
||||||
- [Typedefs](#typedefs)
|
- [Typedefs](#typedefs)
|
||||||
* [SceneItem](#sceneitem)
|
|
||||||
* [SceneItemTransform](#sceneitemtransform)
|
|
||||||
* [OBSStats](#obsstats)
|
|
||||||
* [Scene](#scene)
|
* [Scene](#scene)
|
||||||
|
* [Source](#source)
|
||||||
- [Events](#events)
|
- [Events](#events)
|
||||||
* [Scenes](#scenes)
|
* [Scenes](#scenes)
|
||||||
+ [SwitchScenes](#switchscenes)
|
+ [SwitchScenes](#switchscenes)
|
||||||
@ -82,23 +80,10 @@ auth_response = base64_encode(auth_response_hash)
|
|||||||
* [General](#general)
|
* [General](#general)
|
||||||
+ [Heartbeat](#heartbeat)
|
+ [Heartbeat](#heartbeat)
|
||||||
* [Sources](#sources)
|
* [Sources](#sources)
|
||||||
+ [SourceCreated](#sourcecreated)
|
|
||||||
+ [SourceDestroyed](#sourcedestroyed)
|
|
||||||
+ [SourceVolumeChanged](#sourcevolumechanged)
|
|
||||||
+ [SourceMuteStateChanged](#sourcemutestatechanged)
|
|
||||||
+ [SourceAudioSyncOffsetChanged](#sourceaudiosyncoffsetchanged)
|
|
||||||
+ [SourceAudioMixersChanged](#sourceaudiomixerschanged)
|
|
||||||
+ [SourceRenamed](#sourcerenamed)
|
|
||||||
+ [SourceFilterAdded](#sourcefilteradded)
|
|
||||||
+ [SourceFilterRemoved](#sourcefilterremoved)
|
|
||||||
+ [SourceFiltersReordered](#sourcefiltersreordered)
|
|
||||||
+ [SourceOrderChanged](#sourceorderchanged)
|
+ [SourceOrderChanged](#sourceorderchanged)
|
||||||
+ [SceneItemAdded](#sceneitemadded)
|
+ [SceneItemAdded](#sceneitemadded)
|
||||||
+ [SceneItemRemoved](#sceneitemremoved)
|
+ [SceneItemRemoved](#sceneitemremoved)
|
||||||
+ [SceneItemVisibilityChanged](#sceneitemvisibilitychanged)
|
+ [SceneItemVisibilityChanged](#sceneitemvisibilitychanged)
|
||||||
+ [SceneItemTransformChanged](#sceneitemtransformchanged)
|
|
||||||
+ [SceneItemSelected](#sceneitemselected)
|
|
||||||
+ [SceneItemDeselected](#sceneitemdeselected)
|
|
||||||
* [Studio Mode](#studio-mode)
|
* [Studio Mode](#studio-mode)
|
||||||
+ [PreviewSceneChanged](#previewscenechanged)
|
+ [PreviewSceneChanged](#previewscenechanged)
|
||||||
+ [StudioModeSwitched](#studiomodeswitched)
|
+ [StudioModeSwitched](#studiomodeswitched)
|
||||||
@ -110,8 +95,6 @@ auth_response = base64_encode(auth_response_hash)
|
|||||||
+ [SetHeartbeat](#setheartbeat)
|
+ [SetHeartbeat](#setheartbeat)
|
||||||
+ [SetFilenameFormatting](#setfilenameformatting)
|
+ [SetFilenameFormatting](#setfilenameformatting)
|
||||||
+ [GetFilenameFormatting](#getfilenameformatting)
|
+ [GetFilenameFormatting](#getfilenameformatting)
|
||||||
+ [GetStats](#getstats)
|
|
||||||
+ [GetVideoInfo](#getvideoinfo)
|
|
||||||
* [Profiles](#profiles-1)
|
* [Profiles](#profiles-1)
|
||||||
+ [SetCurrentProfile](#setcurrentprofile)
|
+ [SetCurrentProfile](#setcurrentprofile)
|
||||||
+ [GetCurrentProfile](#getcurrentprofile)
|
+ [GetCurrentProfile](#getcurrentprofile)
|
||||||
@ -148,7 +131,7 @@ auth_response = base64_encode(auth_response_hash)
|
|||||||
+ [ReorderSceneItems](#reordersceneitems)
|
+ [ReorderSceneItems](#reordersceneitems)
|
||||||
* [Sources](#sources-1)
|
* [Sources](#sources-1)
|
||||||
+ [GetSourcesList](#getsourceslist)
|
+ [GetSourcesList](#getsourceslist)
|
||||||
+ [GetSourceTypesList](#getsourcetypeslist)
|
+ [GetSourcesTypesList](#getsourcestypeslist)
|
||||||
+ [GetVolume](#getvolume)
|
+ [GetVolume](#getvolume)
|
||||||
+ [SetVolume](#setvolume)
|
+ [SetVolume](#setvolume)
|
||||||
+ [GetMute](#getmute)
|
+ [GetMute](#getmute)
|
||||||
@ -171,7 +154,6 @@ auth_response = base64_encode(auth_response_hash)
|
|||||||
+ [ReorderSourceFilter](#reordersourcefilter)
|
+ [ReorderSourceFilter](#reordersourcefilter)
|
||||||
+ [MoveSourceFilter](#movesourcefilter)
|
+ [MoveSourceFilter](#movesourcefilter)
|
||||||
+ [SetSourceFilterSettings](#setsourcefiltersettings)
|
+ [SetSourceFilterSettings](#setsourcefiltersettings)
|
||||||
+ [TakeSourceScreenshot](#takesourcescreenshot)
|
|
||||||
* [Streaming](#streaming-1)
|
* [Streaming](#streaming-1)
|
||||||
+ [GetStreamingStatus](#getstreamingstatus)
|
+ [GetStreamingStatus](#getstreamingstatus)
|
||||||
+ [StartStopStreaming](#startstopstreaming)
|
+ [StartStopStreaming](#startstopstreaming)
|
||||||
@ -180,7 +162,6 @@ auth_response = base64_encode(auth_response_hash)
|
|||||||
+ [SetStreamSettings](#setstreamsettings)
|
+ [SetStreamSettings](#setstreamsettings)
|
||||||
+ [GetStreamSettings](#getstreamsettings)
|
+ [GetStreamSettings](#getstreamsettings)
|
||||||
+ [SaveStreamSettings](#savestreamsettings)
|
+ [SaveStreamSettings](#savestreamsettings)
|
||||||
+ [SendCaptions](#sendcaptions)
|
|
||||||
* [Studio Mode](#studio-mode-1)
|
* [Studio Mode](#studio-mode-1)
|
||||||
+ [GetStudioModeStatus](#getstudiomodestatus)
|
+ [GetStudioModeStatus](#getstudiomodestatus)
|
||||||
+ [GetPreviewScene](#getpreviewscene)
|
+ [GetPreviewScene](#getpreviewscene)
|
||||||
@ -202,65 +183,24 @@ auth_response = base64_encode(auth_response_hash)
|
|||||||
These are complex types, such as `Source` and `Scene`, which are used as arguments or return values in multiple requests and/or events.
|
These are complex types, such as `Source` and `Scene`, which are used as arguments or return values in multiple requests and/or events.
|
||||||
|
|
||||||
|
|
||||||
## SceneItem
|
## Scene
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `name` | _String_ | Name of the currently active scene. |
|
||||||
|
| `sources` | _Array<Source>_ | Ordered list of the current scene's source items. |
|
||||||
|
## Source
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `cy` | _Number_ | |
|
| `cy` | _Number_ | |
|
||||||
| `cx` | _Number_ | |
|
| `cx` | _Number_ | |
|
||||||
| `name` | _String_ | The name of this Scene Item. |
|
| `name` | _String_ | The name of this Scene Item. |
|
||||||
| `id` | _int_ | Scene item ID |
|
|
||||||
| `render` | _Boolean_ | Whether or not this Scene Item is set to "visible". |
|
| `render` | _Boolean_ | Whether or not this Scene Item is set to "visible". |
|
||||||
| `locked` | _Boolean_ | Whether or not this Scene Item is locked and can't be moved around |
|
|
||||||
| `source_cx` | _Number_ | |
|
| `source_cx` | _Number_ | |
|
||||||
| `source_cy` | _Number_ | |
|
| `source_cy` | _Number_ | |
|
||||||
| `type` | _String_ | Source type. Value is one of the following: "input", "filter", "transition", "scene" or "unknown" |
|
| `type` | _String_ | Source type. Value is one of the following: "input", "filter", "transition", "scene" or "unknown" |
|
||||||
| `volume` | _Number_ | |
|
| `volume` | _Number_ | |
|
||||||
| `x` | _Number_ | |
|
| `x` | _Number_ | |
|
||||||
| `y` | _Number_ | |
|
| `y` | _Number_ | |
|
||||||
| `parentGroupName` | _String (optional)_ | Name of the item's parent (if this item belongs to a group) |
|
|
||||||
| `groupChildren` | _Array<SceneItem> (optional)_ | List of children (if this item is a group) |
|
|
||||||
## SceneItemTransform
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `position.x` | _int_ | The x position of the scene item from the left. |
|
|
||||||
| `position.y` | _int_ | The y position of the scene item from the top. |
|
|
||||||
| `position.alignment` | _int_ | The point on the scene item that the item is manipulated from. |
|
|
||||||
| `rotation` | _double_ | The clockwise rotation of the scene item in degrees around the point of alignment. |
|
|
||||||
| `scale.x` | _double_ | The x-scale factor of the scene item. |
|
|
||||||
| `scale.y` | _double_ | The y-scale factor of the scene item. |
|
|
||||||
| `crop.top` | _int_ | The number of pixels cropped off the top of the scene item before scaling. |
|
|
||||||
| `crop.right` | _int_ | The number of pixels cropped off the right of the scene item before scaling. |
|
|
||||||
| `crop.bottom` | _int_ | The number of pixels cropped off the bottom of the scene item before scaling. |
|
|
||||||
| `crop.left` | _int_ | The number of pixels cropped off the left of the scene item before scaling. |
|
|
||||||
| `visible` | _bool_ | If the scene item is visible. |
|
|
||||||
| `locked` | _bool_ | If the scene item is locked in position. |
|
|
||||||
| `bounds.type` | _String_ | Type of bounding box. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE". |
|
|
||||||
| `bounds.alignment` | _int_ | Alignment of the bounding box. |
|
|
||||||
| `bounds.x` | _double_ | Width of the bounding box. |
|
|
||||||
| `bounds.y` | _double_ | Height of the bounding box. |
|
|
||||||
| `sourceWidth` | _int_ | Base width (without scaling) of the source |
|
|
||||||
| `sourceHeight` | _int_ | Base source (without scaling) of the source |
|
|
||||||
| `width` | _double_ | Scene item width (base source width multiplied by the horizontal scaling factor) |
|
|
||||||
| `height` | _double_ | Scene item height (base source height multiplied by the vertical scaling factor) |
|
|
||||||
| `parentGroupName` | _String (optional)_ | Name of the item's parent (if this item belongs to a group) |
|
|
||||||
| `groupChildren` | _Array<SceneItemTransform> (optional)_ | List of children (if this item is a group) |
|
|
||||||
## OBSStats
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `fps` | _double_ | Current framerate. |
|
|
||||||
| `render-total-frames` | _int_ | Number of frames rendered |
|
|
||||||
| `render-missed-frames` | _int_ | Number of frames missed due to rendering lag |
|
|
||||||
| `output-total-frames` | _int_ | Number of frames outputted |
|
|
||||||
| `output-skipped-frames` | _int_ | Number of frames skipped due to encoding lag |
|
|
||||||
| `average-frame-time` | _double_ | Average frame render time (in milliseconds) |
|
|
||||||
| `cpu-usage` | _double_ | Current CPU usage (percentage) |
|
|
||||||
| `memory-usage` | _double_ | Current RAM usage (in megabytes) |
|
|
||||||
| `free-disk-space` | _double_ | Free recording disk space (in megabytes) |
|
|
||||||
## Scene
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `name` | _String_ | Name of the currently active scene. |
|
|
||||||
| `sources` | _Array<SceneItem>_ | Ordered list of the current scene's source items. |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -291,7 +231,7 @@ Indicates a scene change.
|
|||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-name` | _String_ | The new scene. |
|
| `scene-name` | _String_ | The new scene. |
|
||||||
| `sources` | _Array<SceneItem>_ | List of scene items in the new scene. Same specification as [`GetCurrentScene`](#getcurrentscene). |
|
| `sources` | _Array<Source>_ | List of sources in the new scene. Same specification as [`GetCurrentScene`](#getcurrentscene). |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -504,7 +444,7 @@ Emit every 2 seconds.
|
|||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `streaming` | _boolean_ | Current streaming state. |
|
| `streaming` | _boolean_ | Current streaming state. |
|
||||||
| `recording` | _boolean_ | Current recording state. |
|
| `recording` | _boolean_ | Current recording state. |
|
||||||
| `replay-buffer-active` | _boolean_ | Replay Buffer status |
|
| `preview-only` | _boolean_ | Always false (retrocompatibility). |
|
||||||
| `bytes-per-sec` | _int_ | Amount of data per second (in bytes) transmitted by the stream encoder. |
|
| `bytes-per-sec` | _int_ | Amount of data per second (in bytes) transmitted by the stream encoder. |
|
||||||
| `kbits-per-sec` | _int_ | Amount of data per second (in kilobits) transmitted by the stream encoder. |
|
| `kbits-per-sec` | _int_ | Amount of data per second (in kilobits) transmitted by the stream encoder. |
|
||||||
| `strain` | _double_ | Percentage of dropped frames. |
|
| `strain` | _double_ | Percentage of dropped frames. |
|
||||||
@ -512,15 +452,6 @@ Emit every 2 seconds.
|
|||||||
| `num-total-frames` | _int_ | Total number of frames transmitted since the stream started. |
|
| `num-total-frames` | _int_ | Total number of frames transmitted since the stream started. |
|
||||||
| `num-dropped-frames` | _int_ | Number of frames dropped by the encoder since the stream started. |
|
| `num-dropped-frames` | _int_ | Number of frames dropped by the encoder since the stream started. |
|
||||||
| `fps` | _double_ | Current framerate. |
|
| `fps` | _double_ | Current framerate. |
|
||||||
| `render-total-frames` | _int_ | Number of frames rendered |
|
|
||||||
| `render-missed-frames` | _int_ | Number of frames missed due to rendering lag |
|
|
||||||
| `output-total-frames` | _int_ | Number of frames outputted |
|
|
||||||
| `output-skipped-frames` | _int_ | Number of frames skipped due to encoding lag |
|
|
||||||
| `average-frame-time` | _double_ | Average frame time (in milliseconds) |
|
|
||||||
| `cpu-usage` | _double_ | Current CPU usage (percentage) |
|
|
||||||
| `memory-usage` | _double_ | Current RAM usage (in megabytes) |
|
|
||||||
| `free-disk-space` | _double_ | Free recording disk space (in megabytes) |
|
|
||||||
| `preview-only` | _boolean_ | Always false (retrocompatibility). |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -672,194 +603,12 @@ Emitted every 2 seconds after enabling it by calling SetHeartbeat.
|
|||||||
| `total-record-time` | _int (optional)_ | Total time (in seconds) since recording started. |
|
| `total-record-time` | _int (optional)_ | Total time (in seconds) since recording started. |
|
||||||
| `total-record-bytes` | _int (optional)_ | Total bytes recorded since the recording started. |
|
| `total-record-bytes` | _int (optional)_ | Total bytes recorded since the recording started. |
|
||||||
| `total-record-frames` | _int (optional)_ | Total frames recorded since the recording started. |
|
| `total-record-frames` | _int (optional)_ | Total frames recorded since the recording started. |
|
||||||
| `stats` | _OBSStats_ | OBS Stats |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Sources
|
## Sources
|
||||||
|
|
||||||
### SourceCreated
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
A source has been created. A source can be an input, a scene or a transition.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `sourceName` | _String_ | Source name |
|
|
||||||
| `sourceType` | _String_ | Source type. Can be "input", "scene", "transition" or "filter". |
|
|
||||||
| `sourceKind` | _String_ | Source kind. |
|
|
||||||
| `sourceSettings` | _Object_ | Source settings |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SourceDestroyed
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
A source has been destroyed/removed. A source can be an input, a scene or a transition.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `sourceName` | _String_ | Source name |
|
|
||||||
| `sourceType` | _String_ | Source type. Can be "input", "scene", "transition" or "filter". |
|
|
||||||
| `sourceKind` | _String_ | Source kind. |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SourceVolumeChanged
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
The volume of a source has changed.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `sourceName` | _String_ | Source name |
|
|
||||||
| `volume` | _float_ | Source volume |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SourceMuteStateChanged
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
A source has been muted or unmuted.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `sourceName` | _String_ | Source name |
|
|
||||||
| `muted` | _boolean_ | Mute status of the source |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SourceAudioSyncOffsetChanged
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
The audio sync offset of a source has changed.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `sourceName` | _String_ | Source name |
|
|
||||||
| `syncOffset` | _int_ | Audio sync offset of the source (in nanoseconds) |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SourceAudioMixersChanged
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
Audio mixer routing changed on a source.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `sourceName` | _String_ | Source name |
|
|
||||||
| `routingStatus` | _Array<Object>_ | Routing status of the source for each audio mixer (array of 6 values) |
|
|
||||||
| `routingStatus.*.id` | _int_ | Mixer number |
|
|
||||||
| `routingStatus.*.enabled` | _boolean_ | Routing status |
|
|
||||||
| `hexMixersValue` | _String_ | Raw mixer flags (little-endian, one bit per mixer) as an hexadecimal value |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SourceRenamed
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
A source has been renamed.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `previousName` | _String_ | Previous source name |
|
|
||||||
| `newName` | _String_ | New source name |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SourceFilterAdded
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
A filter was added to a source.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `sourceName` | _String_ | Source name |
|
|
||||||
| `filterName` | _String_ | Filter name |
|
|
||||||
| `filterType` | _String_ | Filter type |
|
|
||||||
| `filterSettings` | _Object_ | Filter settings |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SourceFilterRemoved
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
A filter was removed from a source.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `sourceName` | _String_ | Source name |
|
|
||||||
| `filterName` | _String_ | Filter name |
|
|
||||||
| `filterType` | _String_ | Filter type |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SourceFiltersReordered
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
Filters in a source have been reordered.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `sourceName` | _String_ | Source name |
|
|
||||||
| `filters` | _Array<Object>_ | Ordered Filters list |
|
|
||||||
| `filters.*.name` | _String_ | Filter name |
|
|
||||||
| `filters.*.type` | _String_ | Filter type |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SourceOrderChanged
|
### SourceOrderChanged
|
||||||
|
|
||||||
|
|
||||||
@ -872,9 +621,6 @@ Scene items have been reordered.
|
|||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-name` | _String_ | Name of the scene where items have been reordered. |
|
| `scene-name` | _String_ | Name of the scene where items have been reordered. |
|
||||||
| `scene-items` | _Array<Object>_ | Ordered list of scene items |
|
|
||||||
| `scene-items.*.source-name` | _String_ | Item source name |
|
|
||||||
| `scene-items.*.item-id` | _int_ | Scene item unique ID |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -892,7 +638,6 @@ An item has been added to the current scene.
|
|||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-name` | _String_ | Name of the scene. |
|
| `scene-name` | _String_ | Name of the scene. |
|
||||||
| `item-name` | _String_ | Name of the item added to the scene. |
|
| `item-name` | _String_ | Name of the item added to the scene. |
|
||||||
| `item-id` | _int_ | Scene item ID |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -910,7 +655,6 @@ An item has been removed from the current scene.
|
|||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-name` | _String_ | Name of the scene. |
|
| `scene-name` | _String_ | Name of the scene. |
|
||||||
| `item-name` | _String_ | Name of the item removed from the scene. |
|
| `item-name` | _String_ | Name of the item removed from the scene. |
|
||||||
| `item-id` | _int_ | Scene item ID |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -928,65 +672,9 @@ An item's visibility has been toggled.
|
|||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-name` | _String_ | Name of the scene. |
|
| `scene-name` | _String_ | Name of the scene. |
|
||||||
| `item-name` | _String_ | Name of the item in the scene. |
|
| `item-name` | _String_ | Name of the item in the scene. |
|
||||||
| `item-id` | _int_ | Scene item ID |
|
|
||||||
| `item-visible` | _boolean_ | New visibility state of the item. |
|
| `item-visible` | _boolean_ | New visibility state of the item. |
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SceneItemTransformChanged
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
An item's transform has been changed.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `scene-name` | _String_ | Name of the scene. |
|
|
||||||
| `item-name` | _String_ | Name of the item in the scene. |
|
|
||||||
| `item-id` | _int_ | Scene item ID |
|
|
||||||
| `transform` | _SceneItemTransform_ | Scene item transform properties |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SceneItemSelected
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
A scene item is selected.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `scene-name` | _String_ | Name of the scene. |
|
|
||||||
| `item-name` | _String_ | Name of the item in the scene. |
|
|
||||||
| `item-id` | _int_ | Name of the item in the scene. |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SceneItemDeselected
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
A scene item is deselected.
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `scene-name` | _String_ | Name of the scene. |
|
|
||||||
| `item-name` | _String_ | Name of the item in the scene. |
|
|
||||||
| `item-id` | _int_ | Name of the item in the scene. |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Studio Mode
|
## Studio Mode
|
||||||
@ -1003,7 +691,7 @@ The selected preview scene has changed (only available in Studio Mode).
|
|||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-name` | _String_ | Name of the scene being previewed. |
|
| `scene-name` | _String_ | Name of the scene being previewed. |
|
||||||
| `sources` | _Array<SceneItem>_ | List of sources composing the scene. Same specification as [`GetCurrentScene`](#getcurrentscene). |
|
| `sources` | _Array<Source>_ | List of sources composing the scene. Same specification as [`GetCurrentScene`](#getcurrentscene). |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1166,54 +854,6 @@ _No specified parameters._
|
|||||||
| `filename-formatting` | _String_ | Current filename formatting string. |
|
| `filename-formatting` | _String_ | Current filename formatting string. |
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### GetStats
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
Get OBS stats (almost the same info as provided in OBS' stats window)
|
|
||||||
|
|
||||||
**Request Fields:**
|
|
||||||
|
|
||||||
_No specified parameters._
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `stats` | _OBSStats_ | OBS stats |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### GetVideoInfo
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
Get basic OBS video information
|
|
||||||
|
|
||||||
**Request Fields:**
|
|
||||||
|
|
||||||
_No specified parameters._
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `baseWidth` | _int_ | Base (canvas) width |
|
|
||||||
| `baseHeight` | _int_ | Base (canvas) height |
|
|
||||||
| `outputWidth` | _int_ | Output width |
|
|
||||||
| `outputHeight` | _int_ | Output height |
|
|
||||||
| `scaleType` | _String_ | Scaling method used if output size differs from base size |
|
|
||||||
| `fps` | _double_ | Frames rendered per second |
|
|
||||||
| `videoFormat` | _String_ | Video color format |
|
|
||||||
| `colorSpace` | _String_ | Color space for YUV |
|
|
||||||
| `colorRange` | _String_ | Color range (full or partial) |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Profiles
|
## Profiles
|
||||||
@ -1338,11 +978,7 @@ _No additional response items._
|
|||||||
|
|
||||||
- Added in v4.1.0
|
- Added in v4.1.0
|
||||||
|
|
||||||
|
Change the current recording folder.
|
||||||
|
|
||||||
Please note: if `SetRecordingFolder` is called while a recording is
|
|
||||||
in progress, the change won't be applied immediately and will be
|
|
||||||
effective on the next recording.
|
|
||||||
|
|
||||||
**Request Fields:**
|
**Request Fields:**
|
||||||
|
|
||||||
@ -1524,7 +1160,6 @@ _No specified parameters._
|
|||||||
- Added in v4.3.0
|
- Added in v4.3.0
|
||||||
|
|
||||||
Gets the scene specific properties of the specified source item.
|
Gets the scene specific properties of the specified source item.
|
||||||
Coordinates are relative to the item's parent (the scene or group it belongs to).
|
|
||||||
|
|
||||||
**Request Fields:**
|
**Request Fields:**
|
||||||
|
|
||||||
@ -1550,15 +1185,10 @@ Coordinates are relative to the item's parent (the scene or group it belongs to)
|
|||||||
| `crop.bottom` | _int_ | The number of pixels cropped off the bottom of the source before scaling. |
|
| `crop.bottom` | _int_ | The number of pixels cropped off the bottom of the source before scaling. |
|
||||||
| `crop.left` | _int_ | The number of pixels cropped off the left of the source before scaling. |
|
| `crop.left` | _int_ | The number of pixels cropped off the left of the source before scaling. |
|
||||||
| `visible` | _bool_ | If the source is visible. |
|
| `visible` | _bool_ | If the source is visible. |
|
||||||
| `locked` | _bool_ | If the source's transform is locked. |
|
| `bounds.type` | _String_ | Type of bounding box. |
|
||||||
| `bounds.type` | _String_ | Type of bounding box. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE". |
|
|
||||||
| `bounds.alignment` | _int_ | Alignment of the bounding box. |
|
| `bounds.alignment` | _int_ | Alignment of the bounding box. |
|
||||||
| `bounds.x` | _double_ | Width of the bounding box. |
|
| `bounds.x` | _double_ | Width of the bounding box. |
|
||||||
| `bounds.y` | _double_ | Height of the bounding box. |
|
| `bounds.y` | _double_ | Height of the bounding box. |
|
||||||
| `sourceWidth` | _int_ | Base width (without scaling) of the source |
|
|
||||||
| `sourceHeight` | _int_ | Base source (without scaling) of the source |
|
|
||||||
| `width` | _double_ | Scene item width (base source width multiplied by the horizontal scaling factor) |
|
|
||||||
| `height` | _double_ | Scene item height (base source height multiplied by the vertical scaling factor) |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1569,7 +1199,6 @@ Coordinates are relative to the item's parent (the scene or group it belongs to)
|
|||||||
- Added in v4.3.0
|
- Added in v4.3.0
|
||||||
|
|
||||||
Sets the scene specific properties of a source. Unspecified properties will remain unchanged.
|
Sets the scene specific properties of a source. Unspecified properties will remain unchanged.
|
||||||
Coordinates are relative to the item's parent (the scene or group it belongs to).
|
|
||||||
|
|
||||||
**Request Fields:**
|
**Request Fields:**
|
||||||
|
|
||||||
@ -1577,22 +1206,21 @@ Coordinates are relative to the item's parent (the scene or group it belongs to)
|
|||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-name` | _String (optional)_ | the name of the scene that the source item belongs to. Defaults to the current scene. |
|
| `scene-name` | _String (optional)_ | the name of the scene that the source item belongs to. Defaults to the current scene. |
|
||||||
| `item` | _String_ | The name of the source. |
|
| `item` | _String_ | The name of the source. |
|
||||||
| `position.x` | _int (optional)_ | The new x position of the source. |
|
| `position.x` | _int_ | The new x position of the source. |
|
||||||
| `position.y` | _int (optional)_ | The new y position of the source. |
|
| `position.y` | _int_ | The new y position of the source. |
|
||||||
| `position.alignment` | _int (optional)_ | The new alignment of the source. |
|
| `position.alignment` | _int_ | The new alignment of the source. |
|
||||||
| `rotation` | _double (optional)_ | The new clockwise rotation of the item in degrees. |
|
| `rotation` | _double_ | The new clockwise rotation of the item in degrees. |
|
||||||
| `scale.x` | _double (optional)_ | The new x scale of the item. |
|
| `scale.x` | _double_ | The new x scale of the item. |
|
||||||
| `scale.y` | _double (optional)_ | The new y scale of the item. |
|
| `scale.y` | _double_ | The new y scale of the item. |
|
||||||
| `crop.top` | _int (optional)_ | The new amount of pixels cropped off the top of the source before scaling. |
|
| `crop.top` | _int_ | The new amount of pixels cropped off the top of the source before scaling. |
|
||||||
| `crop.bottom` | _int (optional)_ | The new amount of pixels cropped off the bottom of the source before scaling. |
|
| `crop.bottom` | _int_ | The new amount of pixels cropped off the bottom of the source before scaling. |
|
||||||
| `crop.left` | _int (optional)_ | The new amount of pixels cropped off the left of the source before scaling. |
|
| `crop.left` | _int_ | The new amount of pixels cropped off the left of the source before scaling. |
|
||||||
| `crop.right` | _int (optional)_ | The new amount of pixels cropped off the right of the source before scaling. |
|
| `crop.right` | _int_ | The new amount of pixels cropped off the right of the source before scaling. |
|
||||||
| `visible` | _bool (optional)_ | The new visibility of the source. 'true' shows source, 'false' hides source. |
|
| `visible` | _bool_ | The new visibility of the source. 'true' shows source, 'false' hides source. |
|
||||||
| `locked` | _bool (optional)_ | The new locked status of the source. 'true' keeps it in its current position, 'false' allows movement. |
|
| `bounds.type` | _String_ | The new bounds type of the source. |
|
||||||
| `bounds.type` | _String (optional)_ | The new bounds type of the source. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE". |
|
| `bounds.alignment` | _int_ | The new alignment of the bounding box. (0-2, 4-6, 8-10) |
|
||||||
| `bounds.alignment` | _int (optional)_ | The new alignment of the bounding box. (0-2, 4-6, 8-10) |
|
| `bounds.x` | _double_ | The new width of the bounding box. |
|
||||||
| `bounds.x` | _double (optional)_ | The new width of the bounding box. |
|
| `bounds.y` | _double_ | The new height of the bounding box. |
|
||||||
| `bounds.y` | _double (optional)_ | The new height of the bounding box. |
|
|
||||||
|
|
||||||
|
|
||||||
**Response Items:**
|
**Response Items:**
|
||||||
@ -1767,7 +1395,7 @@ Duplicates a scene item.
|
|||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene` | _String_ | Name of the scene where the new item was created |
|
| `scene` | _String_ | Name of the scene where the new item was created |
|
||||||
| `item` | _Object_ | New item info |
|
| `item` | _Object_ | New item info |
|
||||||
| `item.id` | _int_ | New item ID |
|
| `̀item.id` | _int_ | New item ID |
|
||||||
| `item.name` | _String_ | New item name |
|
| `item.name` | _String_ | New item name |
|
||||||
|
|
||||||
|
|
||||||
@ -1811,7 +1439,7 @@ _No specified parameters._
|
|||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `name` | _String_ | Name of the currently active scene. |
|
| `name` | _String_ | Name of the currently active scene. |
|
||||||
| `sources` | _Array<SceneItem>_ | Ordered list of the current scene's source items. |
|
| `sources` | _Array<Source>_ | Ordered list of the current scene's source items. |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1885,7 +1513,7 @@ _No specified parameters._
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### GetSourceTypesList
|
### GetSourcesTypesList
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.3.0
|
- Added in v4.3.0
|
||||||
@ -2515,40 +2143,6 @@ Update settings of a filter
|
|||||||
|
|
||||||
_No additional response items._
|
_No additional response items._
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### TakeSourceScreenshot
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
At least `embedPictureFormat` or `saveToFilePath` must be specified.
|
|
||||||
|
|
||||||
Clients can specify `width` and `height` parameters to receive scaled pictures. Aspect ratio is
|
|
||||||
preserved if only one of these two parameters is specified.
|
|
||||||
|
|
||||||
**Request Fields:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `sourceName` | _String_ | Source name |
|
|
||||||
| `embedPictureFormat` | _String (optional)_ | Format of the Data URI encoded picture. Can be "png", "jpg", "jpeg" or "bmp" (or any other value supported by Qt's Image module) |
|
|
||||||
| `saveToFilePath` | _String (optional)_ | Full file path (file extension included) where the captured image is to be saved. Can be in a format different from `pictureFormat`. Can be a relative path. |
|
|
||||||
| `width` | _int (optional)_ | Screenshot width. Defaults to the source's base width. |
|
|
||||||
| `height` | _int (optional)_ | Screenshot height. Defaults to the source's base height. |
|
|
||||||
|
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `sourceName` | _String_ | Source name |
|
|
||||||
| `img` | _String_ | Image Data URI (if `embedPictureFormat` was specified in the request) |
|
|
||||||
| `imageFile` | _String_ | Absolute path to the saved image file (if `saveToFilePath` was specified in the request) |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Streaming
|
## Streaming
|
||||||
@ -2705,27 +2299,6 @@ Save the current streaming server settings to disk.
|
|||||||
|
|
||||||
_No specified parameters._
|
_No specified parameters._
|
||||||
|
|
||||||
**Response Items:**
|
|
||||||
|
|
||||||
_No additional response items._
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SendCaptions
|
|
||||||
|
|
||||||
|
|
||||||
- Added in v4.6.0
|
|
||||||
|
|
||||||
Send the provided text as embedded CEA-608 caption data.
|
|
||||||
As of OBS Studio 23.1, captions are not yet available on Linux.
|
|
||||||
|
|
||||||
**Request Fields:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ------------|
|
|
||||||
| `text` | _String_ | Captions text |
|
|
||||||
|
|
||||||
|
|
||||||
**Response Items:**
|
**Response Items:**
|
||||||
|
|
||||||
_No additional response items._
|
_No additional response items._
|
||||||
@ -2771,7 +2344,7 @@ _No specified parameters._
|
|||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `name` | _String_ | The name of the active preview scene. |
|
| `name` | _String_ | The name of the active preview scene. |
|
||||||
| `sources` | _Array<SceneItem>_ | |
|
| `sources` | _Array<Source>_ | |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# obs-websocket 4.6.0 protocol reference
|
# obs-websocket 4.5.0 protocol reference
|
||||||
|
|
||||||
# General Introduction
|
# General Introduction
|
||||||
Messages are exchanged between the client and the server as JSON objects.
|
Messages are exchanged between the client and the server as JSON objects.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||||
|
|
||||||
#define MyAppName "obs-websocket"
|
#define MyAppName "obs-websocket"
|
||||||
#define MyAppVersion "4.6.1"
|
#define MyAppVersion "4.5.1"
|
||||||
#define MyAppPublisher "Stephane Lepin"
|
#define MyAppPublisher "Stephane Lepin"
|
||||||
#define MyAppURL "http://github.com/Palakis/obs-websocket"
|
#define MyAppURL "http://github.com/Palakis/obs-websocket"
|
||||||
|
|
||||||
@ -23,13 +23,14 @@ DefaultGroupName={#MyAppName}
|
|||||||
OutputBaseFilename=obs-websocket-Windows-Installer
|
OutputBaseFilename=obs-websocket-Windows-Installer
|
||||||
Compression=lzma
|
Compression=lzma
|
||||||
SolidCompression=yes
|
SolidCompression=yes
|
||||||
|
LicenseFile=..\LICENSE
|
||||||
|
|
||||||
[Languages]
|
[Languages]
|
||||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||||
|
Name: "french"; MessagesFile: "compiler:Languages\French.isl"
|
||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
Source: "..\release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
Source: "..\release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
Source: "..\LICENSE"; Flags: dontcopy
|
|
||||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
@ -37,21 +38,6 @@ Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}"
|
|||||||
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
|
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
|
||||||
|
|
||||||
[Code]
|
[Code]
|
||||||
procedure InitializeWizard();
|
|
||||||
var
|
|
||||||
GPLText: AnsiString;
|
|
||||||
Page: TOutputMsgMemoWizardPage;
|
|
||||||
begin
|
|
||||||
ExtractTemporaryFile('LICENSE');
|
|
||||||
LoadStringFromFile(ExpandConstant('{tmp}\LICENSE'), GPLText);
|
|
||||||
|
|
||||||
Page := CreateOutputMsgMemoPage(wpWelcome,
|
|
||||||
'License Information', 'Please review the license terms before installing obs-websocket',
|
|
||||||
'Press Page Down to see the rest of the agreement. Once you are aware of your rights, click Next to continue.',
|
|
||||||
String(GPLText)
|
|
||||||
);
|
|
||||||
end;
|
|
||||||
|
|
||||||
// credit where it's due :
|
// credit where it's due :
|
||||||
// following function come from https://github.com/Xaymar/obs-studio_amf-encoder-plugin/blob/master/%23Resources/Installer.in.iss#L45
|
// following function come from https://github.com/Xaymar/obs-studio_amf-encoder-plugin/blob/master/%23Resources/Installer.in.iss#L45
|
||||||
function GetDirName(Value: string): string;
|
function GetDirName(Value: string): string;
|
||||||
|
192
src/Config.cpp
192
src/Config.cpp
@ -17,10 +17,10 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
|
#include <util/config-file.h>
|
||||||
|
|
||||||
#include <QtCore/QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include <QtCore/QTime>
|
#include <QTime>
|
||||||
#include <QtWidgets/QSystemTrayIcon>
|
|
||||||
|
|
||||||
#define SECTION_NAME "WebsocketAPI"
|
#define SECTION_NAME "WebsocketAPI"
|
||||||
#define PARAM_ENABLE "ServerEnabled"
|
#define PARAM_ENABLE "ServerEnabled"
|
||||||
@ -31,13 +31,13 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
#define PARAM_SECRET "AuthSecret"
|
#define PARAM_SECRET "AuthSecret"
|
||||||
#define PARAM_SALT "AuthSalt"
|
#define PARAM_SALT "AuthSalt"
|
||||||
|
|
||||||
#include "Utils.h"
|
|
||||||
#include "WSServer.h"
|
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
#define QT_TO_UTF8(str) str.toUtf8().constData()
|
#define QT_TO_UTF8(str) str.toUtf8().constData()
|
||||||
|
|
||||||
|
Config* Config::_instance = new Config();
|
||||||
|
|
||||||
Config::Config() :
|
Config::Config() :
|
||||||
ServerEnabled(true),
|
ServerEnabled(true),
|
||||||
ServerPort(4444),
|
ServerPort(4444),
|
||||||
@ -50,55 +50,8 @@ Config::Config() :
|
|||||||
{
|
{
|
||||||
qsrand(QTime::currentTime().msec());
|
qsrand(QTime::currentTime().msec());
|
||||||
|
|
||||||
SetDefaults();
|
|
||||||
SessionChallenge = GenerateSalt();
|
|
||||||
|
|
||||||
obs_frontend_add_event_callback(OnFrontendEvent, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Config::~Config()
|
|
||||||
{
|
|
||||||
obs_frontend_remove_event_callback(OnFrontendEvent, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::Load()
|
|
||||||
{
|
|
||||||
config_t* obsConfig = GetConfigStore();
|
|
||||||
|
|
||||||
ServerEnabled = config_get_bool(obsConfig, SECTION_NAME, PARAM_ENABLE);
|
|
||||||
ServerPort = config_get_uint(obsConfig, SECTION_NAME, PARAM_PORT);
|
|
||||||
|
|
||||||
DebugEnabled = config_get_bool(obsConfig, SECTION_NAME, PARAM_DEBUG);
|
|
||||||
AlertsEnabled = config_get_bool(obsConfig, SECTION_NAME, PARAM_ALERT);
|
|
||||||
|
|
||||||
AuthRequired = config_get_bool(obsConfig, SECTION_NAME, PARAM_AUTHREQUIRED);
|
|
||||||
Secret = config_get_string(obsConfig, SECTION_NAME, PARAM_SECRET);
|
|
||||||
Salt = config_get_string(obsConfig, SECTION_NAME, PARAM_SALT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::Save()
|
|
||||||
{
|
|
||||||
config_t* obsConfig = GetConfigStore();
|
|
||||||
|
|
||||||
config_set_bool(obsConfig, SECTION_NAME, PARAM_ENABLE, ServerEnabled);
|
|
||||||
config_set_uint(obsConfig, SECTION_NAME, PARAM_PORT, ServerPort);
|
|
||||||
|
|
||||||
config_set_bool(obsConfig, SECTION_NAME, PARAM_DEBUG, DebugEnabled);
|
|
||||||
config_set_bool(obsConfig, SECTION_NAME, PARAM_ALERT, AlertsEnabled);
|
|
||||||
|
|
||||||
config_set_bool(obsConfig, SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired);
|
|
||||||
config_set_string(obsConfig, SECTION_NAME, PARAM_SECRET,
|
|
||||||
QT_TO_UTF8(Secret));
|
|
||||||
config_set_string(obsConfig, SECTION_NAME, PARAM_SALT,
|
|
||||||
QT_TO_UTF8(Salt));
|
|
||||||
|
|
||||||
config_save(obsConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SetDefaults()
|
|
||||||
{
|
|
||||||
// OBS Config defaults
|
// OBS Config defaults
|
||||||
config_t* obsConfig = GetConfigStore();
|
config_t* obsConfig = obs_frontend_get_global_config();
|
||||||
if (obsConfig) {
|
if (obsConfig) {
|
||||||
config_set_default_bool(obsConfig,
|
config_set_default_bool(obsConfig,
|
||||||
SECTION_NAME, PARAM_ENABLE, ServerEnabled);
|
SECTION_NAME, PARAM_ENABLE, ServerEnabled);
|
||||||
@ -117,11 +70,46 @@ void Config::SetDefaults()
|
|||||||
config_set_default_string(obsConfig,
|
config_set_default_string(obsConfig,
|
||||||
SECTION_NAME, PARAM_SALT, QT_TO_UTF8(Salt));
|
SECTION_NAME, PARAM_SALT, QT_TO_UTF8(Salt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SessionChallenge = GenerateSalt();
|
||||||
}
|
}
|
||||||
|
|
||||||
config_t* Config::GetConfigStore()
|
Config::~Config()
|
||||||
{
|
{
|
||||||
return obs_frontend_get_profile_config();
|
}
|
||||||
|
|
||||||
|
void Config::Load()
|
||||||
|
{
|
||||||
|
config_t* obsConfig = obs_frontend_get_global_config();
|
||||||
|
|
||||||
|
ServerEnabled = config_get_bool(obsConfig, SECTION_NAME, PARAM_ENABLE);
|
||||||
|
ServerPort = config_get_uint(obsConfig, SECTION_NAME, PARAM_PORT);
|
||||||
|
|
||||||
|
DebugEnabled = config_get_bool(obsConfig, SECTION_NAME, PARAM_DEBUG);
|
||||||
|
AlertsEnabled = config_get_bool(obsConfig, SECTION_NAME, PARAM_ALERT);
|
||||||
|
|
||||||
|
AuthRequired = config_get_bool(obsConfig, SECTION_NAME, PARAM_AUTHREQUIRED);
|
||||||
|
Secret = config_get_string(obsConfig, SECTION_NAME, PARAM_SECRET);
|
||||||
|
Salt = config_get_string(obsConfig, SECTION_NAME, PARAM_SALT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::Save()
|
||||||
|
{
|
||||||
|
config_t* obsConfig = obs_frontend_get_global_config();
|
||||||
|
|
||||||
|
config_set_bool(obsConfig, SECTION_NAME, PARAM_ENABLE, ServerEnabled);
|
||||||
|
config_set_uint(obsConfig, SECTION_NAME, PARAM_PORT, ServerPort);
|
||||||
|
|
||||||
|
config_set_bool(obsConfig, SECTION_NAME, PARAM_DEBUG, DebugEnabled);
|
||||||
|
config_set_bool(obsConfig, SECTION_NAME, PARAM_ALERT, AlertsEnabled);
|
||||||
|
|
||||||
|
config_set_bool(obsConfig, SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired);
|
||||||
|
config_set_string(obsConfig, SECTION_NAME, PARAM_SECRET,
|
||||||
|
QT_TO_UTF8(Secret));
|
||||||
|
config_set_string(obsConfig, SECTION_NAME, PARAM_SALT,
|
||||||
|
QT_TO_UTF8(Salt));
|
||||||
|
|
||||||
|
config_save(obsConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Config::GenerateSalt()
|
QString Config::GenerateSalt()
|
||||||
@ -192,95 +180,7 @@ bool Config::CheckAuth(QString response)
|
|||||||
return authSuccess;
|
return authSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::OnFrontendEvent(enum obs_frontend_event event, void* param)
|
Config* Config::Current()
|
||||||
{
|
{
|
||||||
auto config = reinterpret_cast<Config*>(param);
|
return _instance;
|
||||||
|
|
||||||
if (event == OBS_FRONTEND_EVENT_PROFILE_CHANGED) {
|
|
||||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
|
||||||
QString startMessage = QObject::tr("OBSWebsocket.ProfileChanged.Started");
|
|
||||||
QString stopMessage = QObject::tr("OBSWebsocket.ProfileChanged.Stopped");
|
|
||||||
QString restartMessage = QObject::tr("OBSWebsocket.ProfileChanged.Restarted");
|
|
||||||
obs_frontend_pop_ui_translation();
|
|
||||||
|
|
||||||
bool previousEnabled = config->ServerEnabled;
|
|
||||||
uint64_t previousPort = config->ServerPort;
|
|
||||||
|
|
||||||
config->SetDefaults();
|
|
||||||
config->Load();
|
|
||||||
|
|
||||||
if (config->ServerEnabled != previousEnabled || config->ServerPort != previousPort) {
|
|
||||||
auto server = GetServer();
|
|
||||||
server->stop();
|
|
||||||
|
|
||||||
if (config->ServerEnabled) {
|
|
||||||
server->start(config->ServerPort);
|
|
||||||
|
|
||||||
if (previousEnabled != config->ServerEnabled) {
|
|
||||||
Utils::SysTrayNotify(startMessage, QSystemTrayIcon::MessageIcon::Information);
|
|
||||||
} else {
|
|
||||||
Utils::SysTrayNotify(restartMessage, QSystemTrayIcon::MessageIcon::Information);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Utils::SysTrayNotify(stopMessage, QSystemTrayIcon::MessageIcon::Information);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::MigrateFromGlobalSettings()
|
|
||||||
{
|
|
||||||
config_t* source = obs_frontend_get_global_config();
|
|
||||||
config_t* destination = obs_frontend_get_profile_config();
|
|
||||||
|
|
||||||
if(config_has_user_value(source, SECTION_NAME, PARAM_ENABLE)) {
|
|
||||||
bool value = config_get_bool(source, SECTION_NAME, PARAM_ENABLE);
|
|
||||||
config_set_bool(destination, SECTION_NAME, PARAM_ENABLE, value);
|
|
||||||
|
|
||||||
config_remove_value(source, SECTION_NAME, PARAM_ENABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(config_has_user_value(source, SECTION_NAME, PARAM_PORT)) {
|
|
||||||
uint64_t value = config_get_uint(source, SECTION_NAME, PARAM_PORT);
|
|
||||||
config_set_uint(destination, SECTION_NAME, PARAM_PORT, value);
|
|
||||||
|
|
||||||
config_remove_value(source, SECTION_NAME, PARAM_PORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(config_has_user_value(source, SECTION_NAME, PARAM_DEBUG)) {
|
|
||||||
bool value = config_get_bool(source, SECTION_NAME, PARAM_DEBUG);
|
|
||||||
config_set_bool(destination, SECTION_NAME, PARAM_DEBUG, value);
|
|
||||||
|
|
||||||
config_remove_value(source, SECTION_NAME, PARAM_DEBUG);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(config_has_user_value(source, SECTION_NAME, PARAM_ALERT)) {
|
|
||||||
bool value = config_get_bool(source, SECTION_NAME, PARAM_ALERT);
|
|
||||||
config_set_bool(destination, SECTION_NAME, PARAM_ALERT, value);
|
|
||||||
|
|
||||||
config_remove_value(source, SECTION_NAME, PARAM_ALERT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(config_has_user_value(source, SECTION_NAME, PARAM_AUTHREQUIRED)) {
|
|
||||||
bool value = config_get_bool(source, SECTION_NAME, PARAM_AUTHREQUIRED);
|
|
||||||
config_set_bool(destination, SECTION_NAME, PARAM_AUTHREQUIRED, value);
|
|
||||||
|
|
||||||
config_remove_value(source, SECTION_NAME, PARAM_AUTHREQUIRED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(config_has_user_value(source, SECTION_NAME, PARAM_SECRET)) {
|
|
||||||
const char* value = config_get_string(source, SECTION_NAME, PARAM_SECRET);
|
|
||||||
config_set_string(destination, SECTION_NAME, PARAM_SECRET, value);
|
|
||||||
|
|
||||||
config_remove_value(source, SECTION_NAME, PARAM_SECRET);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(config_has_user_value(source, SECTION_NAME, PARAM_SALT)) {
|
|
||||||
const char* value = config_get_string(source, SECTION_NAME, PARAM_SALT);
|
|
||||||
config_set_string(destination, SECTION_NAME, PARAM_SALT, value);
|
|
||||||
|
|
||||||
config_remove_value(source, SECTION_NAME, PARAM_SALT);
|
|
||||||
}
|
|
||||||
|
|
||||||
config_save(destination);
|
|
||||||
}
|
}
|
||||||
|
20
src/Config.h
20
src/Config.h
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
obs-websocket
|
obs-websocket
|
||||||
Copyright (C) 2016-2019 Stéphane Lepin <stephane.lepin@gmail.com>
|
Copyright (C) 2016-2017 Stéphane Lepin <stephane.lepin@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -16,12 +16,10 @@ 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/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
#include <obs-frontend-api.h>
|
#include <QString>
|
||||||
#include <util/config-file.h>
|
|
||||||
#include <QtCore/QString>
|
|
||||||
#include <QtCore/QSharedPointer>
|
|
||||||
|
|
||||||
class Config {
|
class Config {
|
||||||
public:
|
public:
|
||||||
@ -29,10 +27,6 @@ class Config {
|
|||||||
~Config();
|
~Config();
|
||||||
void Load();
|
void Load();
|
||||||
void Save();
|
void Save();
|
||||||
void SetDefaults();
|
|
||||||
config_t* GetConfigStore();
|
|
||||||
|
|
||||||
void MigrateFromGlobalSettings();
|
|
||||||
|
|
||||||
void SetPassword(QString password);
|
void SetPassword(QString password);
|
||||||
bool CheckAuth(QString userChallenge);
|
bool CheckAuth(QString userChallenge);
|
||||||
@ -52,6 +46,10 @@ class Config {
|
|||||||
QString SessionChallenge;
|
QString SessionChallenge;
|
||||||
bool SettingsLoaded;
|
bool SettingsLoaded;
|
||||||
|
|
||||||
|
static Config* Current();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void OnFrontendEvent(enum obs_frontend_event event, void* param);
|
static Config* _instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // CONFIG_H
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
obs-websocket
|
|
||||||
Copyright (C) 2016-2019 Stéphane Lepin <stephane.lepin@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program. If not, see <https://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ConnectionProperties.h"
|
|
||||||
|
|
||||||
ConnectionProperties::ConnectionProperties()
|
|
||||||
: _authenticated(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ConnectionProperties::isAuthenticated()
|
|
||||||
{
|
|
||||||
return _authenticated.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConnectionProperties::setAuthenticated(bool authenticated)
|
|
||||||
{
|
|
||||||
_authenticated.store(authenticated);
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
obs-websocket
|
|
||||||
Copyright (C) 2016-2019 Stéphane Lepin <stephane.lepin@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program. If not, see <https://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
class ConnectionProperties
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit ConnectionProperties();
|
|
||||||
bool isAuthenticated();
|
|
||||||
void setAuthenticated(bool authenticated);
|
|
||||||
private:
|
|
||||||
std::atomic<bool> _authenticated;
|
|
||||||
};
|
|
321
src/Utils.cpp
321
src/Utils.cpp
@ -16,10 +16,9 @@ You should have received a copy of the GNU General Public License along
|
|||||||
with this program. If not, see <https://www.gnu.org/licenses/>
|
with this program. If not, see <https://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QtWidgets/QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QtCore/QDir>
|
#include <QDir>
|
||||||
#include <QtCore/QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
#include <obs.hpp>
|
#include <obs.hpp>
|
||||||
#include "obs-websocket.h"
|
#include "obs-websocket.h"
|
||||||
@ -29,48 +28,23 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
Q_DECLARE_METATYPE(OBSScene);
|
Q_DECLARE_METATYPE(OBSScene);
|
||||||
|
|
||||||
const QHash<obs_bounds_type, QString> boundTypeNames = {
|
obs_data_array_t* Utils::StringListToArray(char** strings, char* key) {
|
||||||
{ OBS_BOUNDS_STRETCH, "OBS_BOUNDS_STRETCH" },
|
if (!strings)
|
||||||
{ OBS_BOUNDS_SCALE_INNER, "OBS_BOUNDS_SCALE_INNER" },
|
return obs_data_array_create();
|
||||||
{ OBS_BOUNDS_SCALE_OUTER, "OBS_BOUNDS_SCALE_OUTER" },
|
|
||||||
{ OBS_BOUNDS_SCALE_TO_WIDTH, "OBS_BOUNDS_SCALE_TO_WIDTH" },
|
|
||||||
{ OBS_BOUNDS_SCALE_TO_HEIGHT, "OBS_BOUNDS_SCALE_TO_HEIGHT" },
|
|
||||||
{ OBS_BOUNDS_MAX_ONLY, "OBS_BOUNDS_MAX_ONLY" },
|
|
||||||
{ OBS_BOUNDS_NONE, "OBS_BOUNDS_NONE" },
|
|
||||||
};
|
|
||||||
|
|
||||||
QString getBoundsNameFromType(obs_bounds_type type) {
|
|
||||||
QString fallback = boundTypeNames.value(OBS_BOUNDS_NONE);
|
|
||||||
return boundTypeNames.value(type, fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
obs_bounds_type getBoundsTypeFromName(QString name) {
|
|
||||||
return boundTypeNames.key(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
obs_data_array_t* Utils::StringListToArray(char** strings, const char* key) {
|
|
||||||
obs_data_array_t* list = obs_data_array_create();
|
obs_data_array_t* list = obs_data_array_create();
|
||||||
|
|
||||||
if (!strings || !key) {
|
char* value = "";
|
||||||
return list; // empty list
|
for (int i = 0; value != nullptr; i++) {
|
||||||
}
|
value = strings[i];
|
||||||
|
|
||||||
size_t index = 0;
|
|
||||||
char* value = nullptr;
|
|
||||||
|
|
||||||
do {
|
|
||||||
value = strings[index];
|
|
||||||
|
|
||||||
OBSDataAutoRelease item = obs_data_create();
|
OBSDataAutoRelease item = obs_data_create();
|
||||||
obs_data_set_string(item, key, value);
|
obs_data_set_string(item, key, value);
|
||||||
|
|
||||||
if (value) {
|
if (value)
|
||||||
obs_data_array_push_back(list, item);
|
obs_data_array_push_back(list, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
index++;
|
|
||||||
} while (value != nullptr);
|
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,16 +52,15 @@ obs_data_array_t* Utils::GetSceneItems(obs_source_t* source) {
|
|||||||
obs_data_array_t* items = obs_data_array_create();
|
obs_data_array_t* items = obs_data_array_create();
|
||||||
OBSScene scene = obs_scene_from_source(source);
|
OBSScene scene = obs_scene_from_source(source);
|
||||||
|
|
||||||
if (!scene) {
|
if (!scene)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
obs_scene_enum_items(scene, [](
|
obs_scene_enum_items(scene, [](
|
||||||
obs_scene_t* scene,
|
obs_scene_t* scene,
|
||||||
obs_sceneitem_t* currentItem,
|
obs_sceneitem_t* currentItem,
|
||||||
void* param)
|
void* param)
|
||||||
{
|
{
|
||||||
obs_data_array_t* data = reinterpret_cast<obs_data_array_t*>(param);
|
obs_data_array_t* data = static_cast<obs_data_array_t*>(param);
|
||||||
|
|
||||||
OBSDataAutoRelease itemData = GetSceneItemData(currentItem);
|
OBSDataAutoRelease itemData = GetSceneItemData(currentItem);
|
||||||
obs_data_array_insert(data, 0, itemData);
|
obs_data_array_insert(data, 0, itemData);
|
||||||
@ -97,27 +70,9 @@ obs_data_array_t* Utils::GetSceneItems(obs_source_t* source) {
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} `SceneItem` An OBS Scene Item.
|
|
||||||
* @property {Number} `cy`
|
|
||||||
* @property {Number} `cx`
|
|
||||||
* @property {String} `name` The name of this Scene Item.
|
|
||||||
* @property {int} `id` Scene item ID
|
|
||||||
* @property {Boolean} `render` Whether or not this Scene Item is set to "visible".
|
|
||||||
* @property {Boolean} `locked` Whether or not this Scene Item is locked and can't be moved around
|
|
||||||
* @property {Number} `source_cx`
|
|
||||||
* @property {Number} `source_cy`
|
|
||||||
* @property {String} `type` Source type. Value is one of the following: "input", "filter", "transition", "scene" or "unknown"
|
|
||||||
* @property {Number} `volume`
|
|
||||||
* @property {Number} `x`
|
|
||||||
* @property {Number} `y`
|
|
||||||
* @property {String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group)
|
|
||||||
* @property {Array<SceneItem> (optional)} `groupChildren` List of children (if this item is a group)
|
|
||||||
*/
|
|
||||||
obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) {
|
obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) {
|
||||||
if (!item) {
|
if (!item)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
vec2 pos;
|
vec2 pos;
|
||||||
obs_sceneitem_get_pos(item, &pos);
|
obs_sceneitem_get_pos(item, &pos);
|
||||||
@ -132,13 +87,11 @@ obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) {
|
|||||||
|
|
||||||
obs_data_t* data = obs_data_create();
|
obs_data_t* data = obs_data_create();
|
||||||
obs_data_set_string(data, "name",
|
obs_data_set_string(data, "name",
|
||||||
obs_source_get_name(itemSource));
|
obs_source_get_name(obs_sceneitem_get_source(item)));
|
||||||
obs_data_set_int(data, "id",
|
|
||||||
obs_sceneitem_get_id(item));
|
|
||||||
obs_data_set_string(data, "type",
|
obs_data_set_string(data, "type",
|
||||||
obs_source_get_id(itemSource));
|
obs_source_get_id(obs_sceneitem_get_source(item)));
|
||||||
obs_data_set_double(data, "volume",
|
obs_data_set_double(data, "volume",
|
||||||
obs_source_get_volume(itemSource));
|
obs_source_get_volume(obs_sceneitem_get_source(item)));
|
||||||
obs_data_set_double(data, "x", pos.x);
|
obs_data_set_double(data, "x", pos.x);
|
||||||
obs_data_set_double(data, "y", pos.y);
|
obs_data_set_double(data, "y", pos.y);
|
||||||
obs_data_set_int(data, "source_cx", (int)item_width);
|
obs_data_set_int(data, "source_cx", (int)item_width);
|
||||||
@ -146,29 +99,6 @@ obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) {
|
|||||||
obs_data_set_double(data, "cx", item_width* scale.x);
|
obs_data_set_double(data, "cx", item_width* scale.x);
|
||||||
obs_data_set_double(data, "cy", item_height* scale.y);
|
obs_data_set_double(data, "cy", item_height* scale.y);
|
||||||
obs_data_set_bool(data, "render", obs_sceneitem_visible(item));
|
obs_data_set_bool(data, "render", obs_sceneitem_visible(item));
|
||||||
obs_data_set_bool(data, "locked", obs_sceneitem_locked(item));
|
|
||||||
|
|
||||||
obs_scene_t* parent = obs_sceneitem_get_scene(item);
|
|
||||||
if (parent) {
|
|
||||||
OBSSource parentSource = obs_scene_get_source(parent);
|
|
||||||
QString parentKind = obs_source_get_id(parentSource);
|
|
||||||
if (parentKind == "group") {
|
|
||||||
obs_data_set_string(data, "parentGroupName", obs_source_get_name(parentSource));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obs_sceneitem_is_group(item)) {
|
|
||||||
OBSDataArrayAutoRelease children = obs_data_array_create();
|
|
||||||
obs_sceneitem_group_enum_items(item, [](obs_scene_t*, obs_sceneitem_t* currentItem, void* param) {
|
|
||||||
obs_data_array_t* items = reinterpret_cast<obs_data_array_t*>(param);
|
|
||||||
|
|
||||||
OBSDataAutoRelease itemData = GetSceneItemData(currentItem);
|
|
||||||
obs_data_array_push_back(items, itemData);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}, children);
|
|
||||||
obs_data_set_array(data, "groupChildren", children);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -193,31 +123,22 @@ obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, QString name)
|
|||||||
struct current_search {
|
struct current_search {
|
||||||
QString query;
|
QString query;
|
||||||
obs_sceneitem_t* result;
|
obs_sceneitem_t* result;
|
||||||
bool (*enumCallback)(obs_scene_t*, obs_sceneitem_t*, void*);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
current_search search;
|
current_search search;
|
||||||
search.query = name;
|
search.query = name;
|
||||||
search.result = nullptr;
|
search.result = nullptr;
|
||||||
search.enumCallback = nullptr;
|
|
||||||
|
|
||||||
OBSScene scene = obs_scene_from_source(source);
|
OBSScene scene = obs_scene_from_source(source);
|
||||||
if (!scene)
|
if (!scene)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
search.enumCallback = [](
|
obs_scene_enum_items(scene, [](
|
||||||
obs_scene_t* scene,
|
obs_scene_t* scene,
|
||||||
obs_sceneitem_t* currentItem,
|
obs_sceneitem_t* currentItem,
|
||||||
void* param)
|
void* param)
|
||||||
{
|
{
|
||||||
current_search* search = reinterpret_cast<current_search*>(param);
|
current_search* search = static_cast<current_search*>(param);
|
||||||
|
|
||||||
if (obs_sceneitem_is_group(currentItem)) {
|
|
||||||
obs_sceneitem_group_enum_items(currentItem, search->enumCallback, search);
|
|
||||||
if (search->result) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString currentItemName =
|
QString currentItemName =
|
||||||
obs_source_get_name(obs_sceneitem_get_source(currentItem));
|
obs_source_get_name(obs_sceneitem_get_source(currentItem));
|
||||||
@ -229,43 +150,31 @@ obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, QString name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}, &search);
|
||||||
|
|
||||||
obs_scene_enum_items(scene, search.enumCallback, &search);
|
|
||||||
|
|
||||||
return search.result;
|
return search.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO refactor this to unify it with GetSceneItemFromName
|
|
||||||
obs_sceneitem_t* Utils::GetSceneItemFromId(obs_source_t* source, size_t id) {
|
obs_sceneitem_t* Utils::GetSceneItemFromId(obs_source_t* source, size_t id) {
|
||||||
struct current_search {
|
struct current_search {
|
||||||
size_t query;
|
size_t query;
|
||||||
obs_sceneitem_t* result;
|
obs_sceneitem_t* result;
|
||||||
bool (*enumCallback)(obs_scene_t*, obs_sceneitem_t*, void*);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
current_search search;
|
current_search search;
|
||||||
search.query = id;
|
search.query = id;
|
||||||
search.result = nullptr;
|
search.result = nullptr;
|
||||||
search.enumCallback = nullptr;
|
|
||||||
|
|
||||||
OBSScene scene = obs_scene_from_source(source);
|
OBSScene scene = obs_scene_from_source(source);
|
||||||
if (!scene)
|
if (!scene)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
search.enumCallback = [](
|
obs_scene_enum_items(scene, [](
|
||||||
obs_scene_t* scene,
|
obs_scene_t* scene,
|
||||||
obs_sceneitem_t* currentItem,
|
obs_sceneitem_t* currentItem,
|
||||||
void* param)
|
void* param)
|
||||||
{
|
{
|
||||||
current_search* search = reinterpret_cast<current_search*>(param);
|
current_search* search = static_cast<current_search*>(param);
|
||||||
|
|
||||||
if (obs_sceneitem_is_group(currentItem)) {
|
|
||||||
obs_sceneitem_group_enum_items(currentItem, search->enumCallback, param);
|
|
||||||
if (search->result) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obs_sceneitem_get_id(currentItem) == search->query) {
|
if (obs_sceneitem_get_id(currentItem) == search->query) {
|
||||||
search->result = currentItem;
|
search->result = currentItem;
|
||||||
@ -274,9 +183,7 @@ obs_sceneitem_t* Utils::GetSceneItemFromId(obs_source_t* source, size_t id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}, &search);
|
||||||
|
|
||||||
obs_scene_enum_items(scene, search.enumCallback, &search);
|
|
||||||
|
|
||||||
return search.result;
|
return search.result;
|
||||||
}
|
}
|
||||||
@ -392,6 +299,19 @@ QPushButton* Utils::GetPreviewModeButtonControl() {
|
|||||||
return main->findChild<QPushButton*>("modeSwitch");
|
return main->findChild<QPushButton*>("modeSwitch");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QListWidget* Utils::GetSceneListControl() {
|
||||||
|
QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window();
|
||||||
|
return main->findChild<QListWidget*>("scenes");
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_scene_t* Utils::SceneListItemToScene(QListWidgetItem* item) {
|
||||||
|
if (!item)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
QVariant itemData = item->data(static_cast<int>(Qt::UserRole));
|
||||||
|
return itemData.value<OBSScene>();
|
||||||
|
}
|
||||||
|
|
||||||
QLayout* Utils::GetPreviewLayout() {
|
QLayout* Utils::GetPreviewLayout() {
|
||||||
QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window();
|
QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window();
|
||||||
return main->findChild<QLayout*>("previewLayout");
|
return main->findChild<QLayout*>("previewLayout");
|
||||||
@ -439,13 +359,12 @@ QSystemTrayIcon* Utils::GetTrayIcon() {
|
|||||||
QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window();
|
QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window();
|
||||||
if (!main) return nullptr;
|
if (!main) return nullptr;
|
||||||
|
|
||||||
QList<QSystemTrayIcon*> trays = main->findChildren<QSystemTrayIcon*>();
|
return main->findChildren<QSystemTrayIcon*>().first();
|
||||||
return trays.isEmpty() ? nullptr : trays.first();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::SysTrayNotify(QString text,
|
void Utils::SysTrayNotify(QString &text,
|
||||||
QSystemTrayIcon::MessageIcon icon, QString title) {
|
QSystemTrayIcon::MessageIcon icon, QString title) {
|
||||||
if (!GetConfig()->AlertsEnabled ||
|
if (!Config::Current()->AlertsEnabled ||
|
||||||
!QSystemTrayIcon::isSystemTrayAvailable() ||
|
!QSystemTrayIcon::isSystemTrayAvailable() ||
|
||||||
!QSystemTrayIcon::supportsMessages())
|
!QSystemTrayIcon::supportsMessages())
|
||||||
{
|
{
|
||||||
@ -457,6 +376,15 @@ void Utils::SysTrayNotify(QString text,
|
|||||||
trayIcon->showMessage(title, text, icon);
|
trayIcon->showMessage(title, text, icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Utils::FormatIPAddress(QHostAddress &addr) {
|
||||||
|
QRegExp v4regex("(::ffff:)(((\\d).){3})", Qt::CaseInsensitive);
|
||||||
|
QString addrString = addr.toString();
|
||||||
|
if (addrString.contains(v4regex)) {
|
||||||
|
addrString = QHostAddress(addr.toIPv4Address()).toString();
|
||||||
|
}
|
||||||
|
return addrString;
|
||||||
|
}
|
||||||
|
|
||||||
const char* Utils::GetRecordingFolder() {
|
const char* Utils::GetRecordingFolder() {
|
||||||
config_t* profile = obs_frontend_get_profile_config();
|
config_t* profile = obs_frontend_get_profile_config();
|
||||||
QString outputMode = config_get_string(profile, "Output", "Mode");
|
QString outputMode = config_get_string(profile, "Output", "Mode");
|
||||||
@ -472,13 +400,17 @@ const char* Utils::GetRecordingFolder() {
|
|||||||
|
|
||||||
bool Utils::SetRecordingFolder(const char* path) {
|
bool Utils::SetRecordingFolder(const char* path) {
|
||||||
QDir dir(path);
|
QDir dir(path);
|
||||||
if (!dir.exists()) {
|
if (!dir.exists())
|
||||||
dir.mkpath(".");
|
dir.mkpath(".");
|
||||||
}
|
|
||||||
|
|
||||||
config_t* profile = obs_frontend_get_profile_config();
|
config_t* profile = obs_frontend_get_profile_config();
|
||||||
|
QString outputMode = config_get_string(profile, "Output", "Mode");
|
||||||
|
|
||||||
|
if (outputMode == "Advanced") {
|
||||||
config_set_string(profile, "AdvOut", "RecFilePath", path);
|
config_set_string(profile, "AdvOut", "RecFilePath", path);
|
||||||
|
} else {
|
||||||
config_set_string(profile, "SimpleOutput", "FilePath", path);
|
config_set_string(profile, "SimpleOutput", "FilePath", path);
|
||||||
|
}
|
||||||
|
|
||||||
config_save(profile);
|
config_save(profile);
|
||||||
return true;
|
return true;
|
||||||
@ -552,7 +484,7 @@ obs_hotkey_t* Utils::FindHotkeyByName(QString name) {
|
|||||||
search.result = nullptr;
|
search.result = nullptr;
|
||||||
|
|
||||||
obs_enum_hotkeys([](void* data, obs_hotkey_id id, obs_hotkey_t* hotkey) {
|
obs_enum_hotkeys([](void* data, obs_hotkey_id id, obs_hotkey_t* hotkey) {
|
||||||
current_search* search = reinterpret_cast<current_search*>(data);
|
current_search* search = static_cast<current_search*>(data);
|
||||||
|
|
||||||
const char* hk_name = obs_hotkey_get_name(hotkey);
|
const char* hk_name = obs_hotkey_get_name(hotkey);
|
||||||
if (hk_name == search->query) {
|
if (hk_name == search->query) {
|
||||||
@ -630,148 +562,3 @@ bool Utils::SetFilenameFormatting(const char* filenameFormatting) {
|
|||||||
config_save(profile);
|
config_save(profile);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform properties copy-pasted from WSRequestHandler_SceneItems.cpp because typedefs can't be extended yet
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} `SceneItemTransform`
|
|
||||||
* @property {int} `position.x` The x position of the scene item from the left.
|
|
||||||
* @property {int} `position.y` The y position of the scene item from the top.
|
|
||||||
* @property {int} `position.alignment` The point on the scene item that the item is manipulated from.
|
|
||||||
* @property {double} `rotation` The clockwise rotation of the scene item in degrees around the point of alignment.
|
|
||||||
* @property {double} `scale.x` The x-scale factor of the scene item.
|
|
||||||
* @property {double} `scale.y` The y-scale factor of the scene item.
|
|
||||||
* @property {int} `crop.top` The number of pixels cropped off the top of the scene item before scaling.
|
|
||||||
* @property {int} `crop.right` The number of pixels cropped off the right of the scene item before scaling.
|
|
||||||
* @property {int} `crop.bottom` The number of pixels cropped off the bottom of the scene item before scaling.
|
|
||||||
* @property {int} `crop.left` The number of pixels cropped off the left of the scene item before scaling.
|
|
||||||
* @property {bool} `visible` If the scene item is visible.
|
|
||||||
* @property {bool} `locked` If the scene item is locked in position.
|
|
||||||
* @property {String} `bounds.type` Type of bounding box. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE".
|
|
||||||
* @property {int} `bounds.alignment` Alignment of the bounding box.
|
|
||||||
* @property {double} `bounds.x` Width of the bounding box.
|
|
||||||
* @property {double} `bounds.y` Height of the bounding box.
|
|
||||||
* @property {int} `sourceWidth` Base width (without scaling) of the source
|
|
||||||
* @property {int} `sourceHeight` Base source (without scaling) of the source
|
|
||||||
* @property {double} `width` Scene item width (base source width multiplied by the horizontal scaling factor)
|
|
||||||
* @property {double} `height` Scene item height (base source height multiplied by the vertical scaling factor)
|
|
||||||
* @property {String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group)
|
|
||||||
* @property {Array<SceneItemTransform> (optional)} `groupChildren` List of children (if this item is a group)
|
|
||||||
*/
|
|
||||||
obs_data_t* Utils::GetSceneItemPropertiesData(obs_sceneitem_t* sceneItem) {
|
|
||||||
if (!sceneItem) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
OBSSource source = obs_sceneitem_get_source(sceneItem);
|
|
||||||
uint32_t baseSourceWidth = obs_source_get_width(source);
|
|
||||||
uint32_t baseSourceHeight = obs_source_get_height(source);
|
|
||||||
|
|
||||||
vec2 pos, scale, bounds;
|
|
||||||
obs_sceneitem_crop crop;
|
|
||||||
|
|
||||||
obs_sceneitem_get_pos(sceneItem, &pos);
|
|
||||||
obs_sceneitem_get_scale(sceneItem, &scale);
|
|
||||||
obs_sceneitem_get_crop(sceneItem, &crop);
|
|
||||||
obs_sceneitem_get_bounds(sceneItem, &bounds);
|
|
||||||
|
|
||||||
uint32_t alignment = obs_sceneitem_get_alignment(sceneItem);
|
|
||||||
float rotation = obs_sceneitem_get_rot(sceneItem);
|
|
||||||
bool isVisible = obs_sceneitem_visible(sceneItem);
|
|
||||||
bool isLocked = obs_sceneitem_locked(sceneItem);
|
|
||||||
|
|
||||||
obs_bounds_type boundsType = obs_sceneitem_get_bounds_type(sceneItem);
|
|
||||||
uint32_t boundsAlignment = obs_sceneitem_get_bounds_alignment(sceneItem);
|
|
||||||
QString boundsTypeName = getBoundsNameFromType(boundsType);
|
|
||||||
|
|
||||||
OBSDataAutoRelease posData = obs_data_create();
|
|
||||||
obs_data_set_double(posData, "x", pos.x);
|
|
||||||
obs_data_set_double(posData, "y", pos.y);
|
|
||||||
obs_data_set_int(posData, "alignment", alignment);
|
|
||||||
|
|
||||||
OBSDataAutoRelease scaleData = obs_data_create();
|
|
||||||
obs_data_set_double(scaleData, "x", scale.x);
|
|
||||||
obs_data_set_double(scaleData, "y", scale.y);
|
|
||||||
|
|
||||||
OBSDataAutoRelease cropData = obs_data_create();
|
|
||||||
obs_data_set_int(cropData, "left", crop.left);
|
|
||||||
obs_data_set_int(cropData, "top", crop.top);
|
|
||||||
obs_data_set_int(cropData, "right", crop.right);
|
|
||||||
obs_data_set_int(cropData, "bottom", crop.bottom);
|
|
||||||
|
|
||||||
OBSDataAutoRelease boundsData = obs_data_create();
|
|
||||||
obs_data_set_string(boundsData, "type", boundsTypeName.toUtf8());
|
|
||||||
obs_data_set_int(boundsData, "alignment", boundsAlignment);
|
|
||||||
obs_data_set_double(boundsData, "x", bounds.x);
|
|
||||||
obs_data_set_double(boundsData, "y", bounds.y);
|
|
||||||
|
|
||||||
obs_data_t* data = obs_data_create();
|
|
||||||
obs_data_set_obj(data, "position", posData);
|
|
||||||
obs_data_set_double(data, "rotation", rotation);
|
|
||||||
obs_data_set_obj(data, "scale", scaleData);
|
|
||||||
obs_data_set_obj(data, "crop", cropData);
|
|
||||||
obs_data_set_bool(data, "visible", isVisible);
|
|
||||||
obs_data_set_bool(data, "locked", isLocked);
|
|
||||||
obs_data_set_obj(data, "bounds", boundsData);
|
|
||||||
|
|
||||||
obs_data_set_int(data, "sourceWidth", baseSourceWidth);
|
|
||||||
obs_data_set_int(data, "sourceHeight", baseSourceHeight);
|
|
||||||
obs_data_set_double(data, "width", baseSourceWidth * scale.x);
|
|
||||||
obs_data_set_double(data, "height", baseSourceHeight * scale.y);
|
|
||||||
|
|
||||||
obs_scene_t* parent = obs_sceneitem_get_scene(sceneItem);
|
|
||||||
if (parent) {
|
|
||||||
OBSSource parentSource = obs_scene_get_source(parent);
|
|
||||||
QString parentKind = obs_source_get_id(parentSource);
|
|
||||||
if (parentKind == "group") {
|
|
||||||
obs_data_set_string(data, "parentGroupName", obs_source_get_name(parentSource));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obs_sceneitem_is_group(sceneItem)) {
|
|
||||||
OBSDataArrayAutoRelease children = obs_data_array_create();
|
|
||||||
obs_sceneitem_group_enum_items(sceneItem, [](obs_scene_t*, obs_sceneitem_t* subItem, void* param) {
|
|
||||||
obs_data_array_t* items = reinterpret_cast<obs_data_array_t*>(param);
|
|
||||||
|
|
||||||
OBSDataAutoRelease itemData = GetSceneItemPropertiesData(subItem);
|
|
||||||
obs_data_array_push_back(items, itemData);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}, children);
|
|
||||||
obs_data_set_array(data, "groupChildren", children);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
obs_data_array_t* Utils::GetSourceFiltersList(obs_source_t* source, bool includeSettings)
|
|
||||||
{
|
|
||||||
struct enum_params {
|
|
||||||
obs_data_array_t* filters;
|
|
||||||
bool includeSettings;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!source) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct enum_params enumParams;
|
|
||||||
|
|
||||||
enumParams.filters = obs_data_array_create();
|
|
||||||
enumParams.includeSettings = includeSettings;
|
|
||||||
|
|
||||||
obs_source_enum_filters(source, [](obs_source_t* parent, obs_source_t* child, void* param)
|
|
||||||
{
|
|
||||||
auto enumParams = reinterpret_cast<struct enum_params*>(param);
|
|
||||||
|
|
||||||
OBSDataAutoRelease filter = obs_data_create();
|
|
||||||
obs_data_set_string(filter, "type", obs_source_get_id(child));
|
|
||||||
obs_data_set_string(filter, "name", obs_source_get_name(child));
|
|
||||||
if (enumParams->includeSettings) {
|
|
||||||
obs_data_set_obj(filter, "settings", obs_source_get_settings(child));
|
|
||||||
}
|
|
||||||
obs_data_array_push_back(enumParams->filters, filter);
|
|
||||||
}, &enumParams);
|
|
||||||
|
|
||||||
return enumParams.filters;
|
|
||||||
}
|
|
||||||
|
32
src/Utils.h
32
src/Utils.h
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
obs-websocket
|
obs-websocket
|
||||||
Copyright (C) 2016-2019 Stéphane Lepin <stephane.lepin@gmail.com>
|
Copyright (C) 2016-2017 Stéphane Lepin <stephane.lepin@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -16,16 +16,17 @@ 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/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef UTILS_H
|
||||||
|
#define UTILS_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <QtCore/QString>
|
#include <QSpinBox>
|
||||||
#include <QtWidgets/QSpinBox>
|
#include <QPushButton>
|
||||||
#include <QtWidgets/QPushButton>
|
#include <QLayout>
|
||||||
#include <QtWidgets/QLayout>
|
#include <QListWidget>
|
||||||
#include <QtWidgets/QListWidget>
|
#include <QSystemTrayIcon>
|
||||||
#include <QtWidgets/QSystemTrayIcon>
|
#include <QHostAddress>
|
||||||
|
|
||||||
#include <obs.hpp>
|
#include <obs.hpp>
|
||||||
#include <obs-module.h>
|
#include <obs-module.h>
|
||||||
@ -33,7 +34,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
class Utils {
|
class Utils {
|
||||||
public:
|
public:
|
||||||
static obs_data_array_t* StringListToArray(char** strings, const char* key);
|
static obs_data_array_t* StringListToArray(char** strings, char* key);
|
||||||
static obs_data_array_t* GetSceneItems(obs_source_t* source);
|
static obs_data_array_t* GetSceneItems(obs_source_t* source);
|
||||||
static obs_data_t* GetSceneItemData(obs_sceneitem_t* item);
|
static obs_data_t* GetSceneItemData(obs_sceneitem_t* item);
|
||||||
static obs_sceneitem_t* GetSceneItemFromName(
|
static obs_sceneitem_t* GetSceneItemFromName(
|
||||||
@ -42,16 +43,12 @@ class Utils {
|
|||||||
static obs_sceneitem_t* GetSceneItemFromItem(obs_source_t* source, obs_data_t* item);
|
static obs_sceneitem_t* GetSceneItemFromItem(obs_source_t* source, obs_data_t* item);
|
||||||
static obs_source_t* GetTransitionFromName(QString transitionName);
|
static obs_source_t* GetTransitionFromName(QString transitionName);
|
||||||
static obs_source_t* GetSceneFromNameOrCurrent(QString sceneName);
|
static obs_source_t* GetSceneFromNameOrCurrent(QString sceneName);
|
||||||
static obs_data_t* GetSceneItemPropertiesData(obs_sceneitem_t* item);
|
|
||||||
|
|
||||||
static obs_data_array_t* GetSourceFiltersList(obs_source_t* source, bool includeSettings);
|
|
||||||
|
|
||||||
static bool IsValidAlignment(const uint32_t alignment);
|
static bool IsValidAlignment(const uint32_t alignment);
|
||||||
|
|
||||||
static obs_data_array_t* GetScenes();
|
static obs_data_array_t* GetScenes();
|
||||||
static obs_data_t* GetSceneData(obs_source_t* source);
|
static obs_data_t* GetSceneData(obs_source_t* source);
|
||||||
|
|
||||||
// TODO contribute a proper frontend API method for this to OBS and remove this hack
|
|
||||||
static QSpinBox* GetTransitionDurationControl();
|
static QSpinBox* GetTransitionDurationControl();
|
||||||
static int GetTransitionDuration();
|
static int GetTransitionDuration();
|
||||||
static void SetTransitionDuration(int ms);
|
static void SetTransitionDuration(int ms);
|
||||||
@ -60,18 +57,21 @@ class Utils {
|
|||||||
|
|
||||||
static QPushButton* GetPreviewModeButtonControl();
|
static QPushButton* GetPreviewModeButtonControl();
|
||||||
static QLayout* GetPreviewLayout();
|
static QLayout* GetPreviewLayout();
|
||||||
|
static QListWidget* GetSceneListControl();
|
||||||
|
static obs_scene_t* SceneListItemToScene(QListWidgetItem* item);
|
||||||
|
|
||||||
// TODO contribute a proper frontend API method for this to OBS and remove this hack
|
|
||||||
static void TransitionToProgram();
|
static void TransitionToProgram();
|
||||||
|
|
||||||
static QString OBSVersionString();
|
static QString OBSVersionString();
|
||||||
|
|
||||||
static QSystemTrayIcon* GetTrayIcon();
|
static QSystemTrayIcon* GetTrayIcon();
|
||||||
static void SysTrayNotify(
|
static void SysTrayNotify(
|
||||||
QString text,
|
QString &text,
|
||||||
QSystemTrayIcon::MessageIcon n,
|
QSystemTrayIcon::MessageIcon n,
|
||||||
QString title = QString("obs-websocket"));
|
QString title = QString("obs-websocket"));
|
||||||
|
|
||||||
|
static QString FormatIPAddress(QHostAddress &addr);
|
||||||
|
|
||||||
static const char* GetRecordingFolder();
|
static const char* GetRecordingFolder();
|
||||||
static bool SetRecordingFolder(const char* path);
|
static bool SetRecordingFolder(const char* path);
|
||||||
|
|
||||||
@ -83,3 +83,5 @@ class Utils {
|
|||||||
static const char* GetFilenameFormatting();
|
static const char* GetFilenameFormatting();
|
||||||
static bool SetFilenameFormatting(const char* filenameFormatting);
|
static bool SetFilenameFormatting(const char* filenameFormatting);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // UTILS_H
|
||||||
|
779
src/WSEvents.cpp
779
src/WSEvents.cpp
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
obs-websocket
|
obs-websocket
|
||||||
Copyright (C) 2016-2019 Stéphane Lepin <stephane.lepin@gmail.com>
|
Copyright (C) 2016-2017 Stéphane Lepin <stephane.lepin@gmail.com>
|
||||||
Copyright (C) 2017 Brendan Hagan <https://github.com/haganbmj>
|
Copyright (C) 2017 Brendan Hagan <https://github.com/haganbmj>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
@ -17,53 +17,48 @@ 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/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef WSEVENTS_H
|
||||||
|
#define WSEVENTS_H
|
||||||
|
|
||||||
#include <obs.hpp>
|
#include <obs.hpp>
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
#include <util/platform.h>
|
#include <QListWidgetItem>
|
||||||
|
|
||||||
#include <QtWidgets/QListWidgetItem>
|
|
||||||
#include <QtCore/QSharedPointer>
|
|
||||||
#include <QtCore/QTimer>
|
|
||||||
|
|
||||||
#include "WSServer.h"
|
#include "WSServer.h"
|
||||||
|
|
||||||
class WSEvents : public QObject
|
class WSEvents : public QObject {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit WSEvents(WSServerPtr srv);
|
explicit WSEvents(WSServer* srv);
|
||||||
~WSEvents();
|
~WSEvents();
|
||||||
|
static void FrontendEventHandler(
|
||||||
void connectSourceSignals(obs_source_t* source);
|
enum obs_frontend_event event, void* privateData);
|
||||||
void disconnectSourceSignals(obs_source_t* source);
|
static WSEvents* Instance;
|
||||||
|
void connectSceneSignals(obs_source_t* scene);
|
||||||
|
|
||||||
void hookTransitionBeginEvent();
|
void hookTransitionBeginEvent();
|
||||||
void unhookTransitionBeginEvent();
|
|
||||||
|
|
||||||
uint64_t GetStreamingTime();
|
uint64_t GetStreamingTime();
|
||||||
const char* GetStreamingTimecode();
|
const char* GetStreamingTimecode();
|
||||||
uint64_t GetRecordingTime();
|
uint64_t GetRecordingTime();
|
||||||
const char* GetRecordingTimecode();
|
const char* GetRecordingTimecode();
|
||||||
obs_data_t* GetStats();
|
|
||||||
|
|
||||||
bool HeartbeatIsActive;
|
bool HeartbeatIsActive;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void deferredInitOperations();
|
||||||
void StreamStatus();
|
void StreamStatus();
|
||||||
void Heartbeat();
|
void Heartbeat();
|
||||||
void TransitionDurationChanged(int ms);
|
void TransitionDurationChanged(int ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WSServerPtr _srv;
|
WSServer* _srv;
|
||||||
QTimer streamStatusTimer;
|
OBSSource currentScene;
|
||||||
QTimer heartbeatTimer;
|
|
||||||
os_cpu_usage_info_t* cpuUsageInfo;
|
|
||||||
|
|
||||||
bool pulse;
|
bool pulse;
|
||||||
|
|
||||||
|
bool _streamingActive;
|
||||||
|
bool _recordingActive;
|
||||||
|
|
||||||
uint64_t _streamStarttime;
|
uint64_t _streamStarttime;
|
||||||
uint64_t _recStarttime;
|
uint64_t _recStarttime;
|
||||||
|
|
||||||
@ -104,30 +99,12 @@ private:
|
|||||||
|
|
||||||
void OnExit();
|
void OnExit();
|
||||||
|
|
||||||
static void FrontendEventHandler(
|
|
||||||
enum obs_frontend_event event, void* privateData);
|
|
||||||
|
|
||||||
static void OnTransitionBegin(void* param, calldata_t* data);
|
static void OnTransitionBegin(void* param, calldata_t* data);
|
||||||
|
|
||||||
static void OnSourceCreate(void* param, calldata_t* data);
|
|
||||||
static void OnSourceDestroy(void* param, calldata_t* data);
|
|
||||||
|
|
||||||
static void OnSourceVolumeChange(void* param, calldata_t* data);
|
|
||||||
static void OnSourceMuteStateChange(void* param, calldata_t* data);
|
|
||||||
static void OnSourceAudioSyncOffsetChanged(void* param, calldata_t* data);
|
|
||||||
static void OnSourceAudioMixersChanged(void* param, calldata_t* data);
|
|
||||||
|
|
||||||
static void OnSourceRename(void* param, calldata_t* data);
|
|
||||||
|
|
||||||
static void OnSourceFilterAdded(void* param, calldata_t* data);
|
|
||||||
static void OnSourceFilterRemoved(void* param, calldata_t* data);
|
|
||||||
static void OnSourceFilterOrderChanged(void* param, calldata_t* data);
|
|
||||||
|
|
||||||
static void OnSceneReordered(void* param, calldata_t* data);
|
static void OnSceneReordered(void* param, calldata_t* data);
|
||||||
static void OnSceneItemAdd(void* param, calldata_t* data);
|
static void OnSceneItemAdd(void* param, calldata_t* data);
|
||||||
static void OnSceneItemDelete(void* param, calldata_t* data);
|
static void OnSceneItemDelete(void* param, calldata_t* data);
|
||||||
static void OnSceneItemVisibilityChanged(void* param, calldata_t* data);
|
static void OnSceneItemVisibilityChanged(void* param, calldata_t* data);
|
||||||
static void OnSceneItemTransform(void* param, calldata_t* data);
|
|
||||||
static void OnSceneItemSelected(void* param, calldata_t* data);
|
|
||||||
static void OnSceneItemDeselected(void* param, calldata_t* data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // WSEVENTS_H
|
||||||
|
@ -24,14 +24,12 @@
|
|||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
|
|
||||||
QHash<QString, HandlerResponse(*)(WSRequestHandler*)> WSRequestHandler::messageMap {
|
QHash<QString, void(*)(WSRequestHandler*)> WSRequestHandler::messageMap {
|
||||||
{ "GetVersion", WSRequestHandler::HandleGetVersion },
|
{ "GetVersion", WSRequestHandler::HandleGetVersion },
|
||||||
{ "GetAuthRequired", WSRequestHandler::HandleGetAuthRequired },
|
{ "GetAuthRequired", WSRequestHandler::HandleGetAuthRequired },
|
||||||
{ "Authenticate", WSRequestHandler::HandleAuthenticate },
|
{ "Authenticate", WSRequestHandler::HandleAuthenticate },
|
||||||
|
|
||||||
{ "GetStats", WSRequestHandler::HandleGetStats },
|
|
||||||
{ "SetHeartbeat", WSRequestHandler::HandleSetHeartbeat },
|
{ "SetHeartbeat", WSRequestHandler::HandleSetHeartbeat },
|
||||||
{ "GetVideoInfo", WSRequestHandler::HandleGetVideoInfo },
|
|
||||||
|
|
||||||
{ "SetFilenameFormatting", WSRequestHandler::HandleSetFilenameFormatting },
|
{ "SetFilenameFormatting", WSRequestHandler::HandleSetFilenameFormatting },
|
||||||
{ "GetFilenameFormatting", WSRequestHandler::HandleGetFilenameFormatting },
|
{ "GetFilenameFormatting", WSRequestHandler::HandleGetFilenameFormatting },
|
||||||
@ -86,7 +84,6 @@ QHash<QString, HandlerResponse(*)(WSRequestHandler*)> WSRequestHandler::messageM
|
|||||||
{ "GetSourceTypesList", WSRequestHandler::HandleGetSourceTypesList },
|
{ "GetSourceTypesList", WSRequestHandler::HandleGetSourceTypesList },
|
||||||
{ "GetSourceSettings", WSRequestHandler::HandleGetSourceSettings },
|
{ "GetSourceSettings", WSRequestHandler::HandleGetSourceSettings },
|
||||||
{ "SetSourceSettings", WSRequestHandler::HandleSetSourceSettings },
|
{ "SetSourceSettings", WSRequestHandler::HandleSetSourceSettings },
|
||||||
{ "TakeSourceScreenshot", WSRequestHandler::HandleTakeSourceScreenshot },
|
|
||||||
|
|
||||||
{ "GetSourceFilters", WSRequestHandler::HandleGetSourceFilters },
|
{ "GetSourceFilters", WSRequestHandler::HandleGetSourceFilters },
|
||||||
{ "AddFilterToSource", WSRequestHandler::HandleAddFilterToSource },
|
{ "AddFilterToSource", WSRequestHandler::HandleAddFilterToSource },
|
||||||
@ -106,9 +103,6 @@ QHash<QString, HandlerResponse(*)(WSRequestHandler*)> WSRequestHandler::messageM
|
|||||||
{ "SetStreamSettings", WSRequestHandler::HandleSetStreamSettings },
|
{ "SetStreamSettings", WSRequestHandler::HandleSetStreamSettings },
|
||||||
{ "GetStreamSettings", WSRequestHandler::HandleGetStreamSettings },
|
{ "GetStreamSettings", WSRequestHandler::HandleGetStreamSettings },
|
||||||
{ "SaveStreamSettings", WSRequestHandler::HandleSaveStreamSettings },
|
{ "SaveStreamSettings", WSRequestHandler::HandleSaveStreamSettings },
|
||||||
#if BUILD_CAPTIONS
|
|
||||||
{ "SendCaptions", WSRequestHandler::HandleSendCaptions },
|
|
||||||
#endif
|
|
||||||
|
|
||||||
{ "GetStudioModeStatus", WSRequestHandler::HandleGetStudioModeStatus },
|
{ "GetStudioModeStatus", WSRequestHandler::HandleGetStudioModeStatus },
|
||||||
{ "GetPreviewScene", WSRequestHandler::HandleGetPreviewScene },
|
{ "GetPreviewScene", WSRequestHandler::HandleGetPreviewScene },
|
||||||
@ -134,89 +128,98 @@ QSet<QString> WSRequestHandler::authNotRequired {
|
|||||||
"Authenticate"
|
"Authenticate"
|
||||||
};
|
};
|
||||||
|
|
||||||
WSRequestHandler::WSRequestHandler(ConnectionProperties& connProperties) :
|
WSRequestHandler::WSRequestHandler(QWebSocket* client) :
|
||||||
_messageId(0),
|
_messageId(0),
|
||||||
_requestType(""),
|
_requestType(""),
|
||||||
data(nullptr),
|
data(nullptr),
|
||||||
_connProperties(connProperties)
|
_client(client)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string WSRequestHandler::processIncomingMessage(std::string& textMessage) {
|
void WSRequestHandler::processIncomingMessage(QString textMessage) {
|
||||||
if (GetConfig()->DebugEnabled) {
|
QByteArray msgData = textMessage.toUtf8();
|
||||||
blog(LOG_INFO, "Request >> '%s'", textMessage.c_str());
|
const char* msg = msgData.constData();
|
||||||
}
|
|
||||||
|
|
||||||
OBSDataAutoRelease responseData = processRequest(textMessage);
|
|
||||||
std::string response = obs_data_get_json(responseData);
|
|
||||||
|
|
||||||
if (GetConfig()->DebugEnabled) {
|
|
||||||
blog(LOG_INFO, "Response << '%s'", response.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
HandlerResponse WSRequestHandler::processRequest(std::string& textMessage){
|
|
||||||
std::string msgContainer(textMessage);
|
|
||||||
const char* msg = msgContainer.c_str();
|
|
||||||
|
|
||||||
data = obs_data_create_from_json(msg);
|
data = obs_data_create_from_json(msg);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
|
if (!msg)
|
||||||
|
msg = "<null pointer>";
|
||||||
|
|
||||||
blog(LOG_ERROR, "invalid JSON payload received for '%s'", msg);
|
blog(LOG_ERROR, "invalid JSON payload received for '%s'", msg);
|
||||||
return SendErrorResponse("invalid JSON payload");
|
SendErrorResponse("invalid JSON payload");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasField("request-type") || !hasField("message-id")) {
|
if (Config::Current()->DebugEnabled) {
|
||||||
return SendErrorResponse("missing request parameters");
|
blog(LOG_DEBUG, "Request >> '%s'", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasField("request-type")
|
||||||
|
|| !hasField("message-id"))
|
||||||
|
{
|
||||||
|
SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_requestType = obs_data_get_string(data, "request-type");
|
_requestType = obs_data_get_string(data, "request-type");
|
||||||
_messageId = obs_data_get_string(data, "message-id");
|
_messageId = obs_data_get_string(data, "message-id");
|
||||||
|
|
||||||
if (GetConfig()->AuthRequired
|
if (Config::Current()->AuthRequired
|
||||||
&& (!authNotRequired.contains(_requestType))
|
&& (_client->property(PROP_AUTHENTICATED).toBool() == false)
|
||||||
&& (!_connProperties.isAuthenticated()))
|
&& (authNotRequired.find(_requestType) == authNotRequired.end()))
|
||||||
{
|
{
|
||||||
return SendErrorResponse("Not Authenticated");
|
SendErrorResponse("Not Authenticated");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandlerResponse (*handlerFunc)(WSRequestHandler*) = (messageMap[_requestType]);
|
void (*handlerFunc)(WSRequestHandler*) = (messageMap[_requestType]);
|
||||||
if (!handlerFunc) {
|
|
||||||
return SendErrorResponse("invalid request type");
|
|
||||||
}
|
|
||||||
|
|
||||||
return handlerFunc(this);
|
if (handlerFunc != nullptr)
|
||||||
|
handlerFunc(this);
|
||||||
|
else
|
||||||
|
SendErrorResponse("invalid request type");
|
||||||
}
|
}
|
||||||
|
|
||||||
WSRequestHandler::~WSRequestHandler() {
|
WSRequestHandler::~WSRequestHandler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
HandlerResponse WSRequestHandler::SendOKResponse(obs_data_t* additionalFields) {
|
void WSRequestHandler::SendOKResponse(obs_data_t* additionalFields) {
|
||||||
return SendResponse("ok", additionalFields);
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
}
|
obs_data_set_string(response, "status", "ok");
|
||||||
|
|
||||||
HandlerResponse WSRequestHandler::SendErrorResponse(const char* errorMessage) {
|
|
||||||
OBSDataAutoRelease fields = obs_data_create();
|
|
||||||
obs_data_set_string(fields, "error", errorMessage);
|
|
||||||
|
|
||||||
return SendResponse("error", fields);
|
|
||||||
}
|
|
||||||
|
|
||||||
HandlerResponse WSRequestHandler::SendErrorResponse(obs_data_t* additionalFields) {
|
|
||||||
return SendResponse("error", additionalFields);
|
|
||||||
}
|
|
||||||
|
|
||||||
HandlerResponse WSRequestHandler::SendResponse(const char* status, obs_data_t* fields) {
|
|
||||||
obs_data_t* response = obs_data_create();
|
|
||||||
obs_data_set_string(response, "message-id", _messageId);
|
obs_data_set_string(response, "message-id", _messageId);
|
||||||
obs_data_set_string(response, "status", status);
|
|
||||||
|
|
||||||
if (fields) {
|
if (additionalFields)
|
||||||
obs_data_apply(response, fields);
|
obs_data_apply(response, additionalFields);
|
||||||
|
|
||||||
|
SendResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
void WSRequestHandler::SendErrorResponse(const char* errorMessage) {
|
||||||
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
|
obs_data_set_string(response, "status", "error");
|
||||||
|
obs_data_set_string(response, "error", errorMessage);
|
||||||
|
obs_data_set_string(response, "message-id", _messageId);
|
||||||
|
|
||||||
|
SendResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WSRequestHandler::SendErrorResponse(obs_data_t* additionalFields) {
|
||||||
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
|
obs_data_set_string(response, "status", "error");
|
||||||
|
obs_data_set_string(response, "message-id", _messageId);
|
||||||
|
|
||||||
|
if (additionalFields)
|
||||||
|
obs_data_set_obj(response, "error", additionalFields);
|
||||||
|
|
||||||
|
SendResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WSRequestHandler::SendResponse(obs_data_t* response) {
|
||||||
|
QString json = obs_data_get_json(response);
|
||||||
|
_client->sendTextMessage(json);
|
||||||
|
|
||||||
|
if (Config::Current()->DebugEnabled)
|
||||||
|
blog(LOG_DEBUG, "Response << '%s'", json.toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WSRequestHandler::hasField(QString name) {
|
bool WSRequestHandler::hasField(QString name) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
obs-websocket
|
obs-websocket
|
||||||
Copyright (C) 2016-2019 Stéphane Lepin <stephane.lepin@gmail.com>
|
Copyright (C) 2016-2017 Stéphane Lepin <stephane.lepin@gmail.com>
|
||||||
Copyright (C) 2017 Mikhail Swift <https://github.com/mikhailswift>
|
Copyright (C) 2017 Mikhail Swift <https://github.com/mikhailswift>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
@ -17,147 +17,137 @@ 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/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef WSREQUESTHANDLER_H
|
||||||
|
#define WSREQUESTHANDLER_H
|
||||||
|
|
||||||
#include <QtCore/QHash>
|
#include <QHash>
|
||||||
#include <QtCore/QSet>
|
#include <QSet>
|
||||||
#include <QtCore/QVariantHash>
|
#include <QWebSocket>
|
||||||
#include <QtCore/QString>
|
#include <QWebSocketServer>
|
||||||
#include <QtCore/QSharedPointer>
|
|
||||||
|
|
||||||
#include <obs.hpp>
|
#include <obs.hpp>
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
|
|
||||||
#include "ConnectionProperties.h"
|
|
||||||
|
|
||||||
#include "obs-websocket.h"
|
#include "obs-websocket.h"
|
||||||
|
|
||||||
typedef obs_data_t* HandlerResponse;
|
|
||||||
|
|
||||||
class WSRequestHandler : public QObject {
|
class WSRequestHandler : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit WSRequestHandler(ConnectionProperties& connProperties);
|
explicit WSRequestHandler(QWebSocket* client);
|
||||||
~WSRequestHandler();
|
~WSRequestHandler();
|
||||||
std::string processIncomingMessage(std::string& textMessage);
|
void processIncomingMessage(QString textMessage);
|
||||||
bool hasField(QString name);
|
bool hasField(QString name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QWebSocket* _client;
|
||||||
const char* _messageId;
|
const char* _messageId;
|
||||||
const char* _requestType;
|
const char* _requestType;
|
||||||
ConnectionProperties& _connProperties;
|
|
||||||
OBSDataAutoRelease data;
|
OBSDataAutoRelease data;
|
||||||
|
|
||||||
HandlerResponse processRequest(std::string& textMessage);
|
void SendOKResponse(obs_data_t* additionalFields = NULL);
|
||||||
|
void SendErrorResponse(const char* errorMessage);
|
||||||
|
void SendErrorResponse(obs_data_t* additionalFields = NULL);
|
||||||
|
void SendResponse(obs_data_t* response);
|
||||||
|
|
||||||
HandlerResponse SendOKResponse(obs_data_t* additionalFields = nullptr);
|
static QHash<QString, void(*)(WSRequestHandler*)> messageMap;
|
||||||
HandlerResponse SendErrorResponse(const char* errorMessage);
|
|
||||||
HandlerResponse SendErrorResponse(obs_data_t* additionalFields = nullptr);
|
|
||||||
HandlerResponse SendResponse(const char* status, obs_data_t* additionalFields = nullptr);
|
|
||||||
|
|
||||||
static QHash<QString, HandlerResponse(*)(WSRequestHandler*)> messageMap;
|
|
||||||
static QSet<QString> authNotRequired;
|
static QSet<QString> authNotRequired;
|
||||||
|
|
||||||
static HandlerResponse HandleGetVersion(WSRequestHandler* req);
|
static void HandleGetVersion(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetAuthRequired(WSRequestHandler* req);
|
static void HandleGetAuthRequired(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleAuthenticate(WSRequestHandler* req);
|
static void HandleAuthenticate(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleGetStats(WSRequestHandler* req);
|
static void HandleSetHeartbeat(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSetHeartbeat(WSRequestHandler* req);
|
|
||||||
static HandlerResponse HandleGetVideoInfo(WSRequestHandler* req);
|
|
||||||
|
|
||||||
static HandlerResponse HandleSetFilenameFormatting(WSRequestHandler* req);
|
static void HandleSetFilenameFormatting(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetFilenameFormatting(WSRequestHandler* req);
|
static void HandleGetFilenameFormatting(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleSetCurrentScene(WSRequestHandler* req);
|
static void HandleSetCurrentScene(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetCurrentScene(WSRequestHandler* req);
|
static void HandleGetCurrentScene(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetSceneList(WSRequestHandler* req);
|
static void HandleGetSceneList(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleSetSceneItemRender(WSRequestHandler* req);
|
static void HandleSetSceneItemRender(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSetSceneItemPosition(WSRequestHandler* req);
|
static void HandleSetSceneItemPosition(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSetSceneItemTransform(WSRequestHandler* req);
|
static void HandleSetSceneItemTransform(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSetSceneItemCrop(WSRequestHandler* req);
|
static void HandleSetSceneItemCrop(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetSceneItemProperties(WSRequestHandler* req);
|
static void HandleGetSceneItemProperties(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSetSceneItemProperties(WSRequestHandler* req);
|
static void HandleSetSceneItemProperties(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleResetSceneItem(WSRequestHandler* req);
|
static void HandleResetSceneItem(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleDuplicateSceneItem(WSRequestHandler* req);
|
static void HandleDuplicateSceneItem(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleDeleteSceneItem(WSRequestHandler* req);
|
static void HandleDeleteSceneItem(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleReorderSceneItems(WSRequestHandler* req);
|
static void HandleReorderSceneItems(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleGetStreamingStatus(WSRequestHandler* req);
|
static void HandleGetStreamingStatus(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleStartStopStreaming(WSRequestHandler* req);
|
static void HandleStartStopStreaming(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleStartStopRecording(WSRequestHandler* req);
|
static void HandleStartStopRecording(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleStartStreaming(WSRequestHandler* req);
|
static void HandleStartStreaming(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleStopStreaming(WSRequestHandler* req);
|
static void HandleStopStreaming(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleStartRecording(WSRequestHandler* req);
|
static void HandleStartRecording(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleStopRecording(WSRequestHandler* req);
|
static void HandleStopRecording(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleStartStopReplayBuffer(WSRequestHandler* req);
|
static void HandleStartStopReplayBuffer(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleStartReplayBuffer(WSRequestHandler* req);
|
static void HandleStartReplayBuffer(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleStopReplayBuffer(WSRequestHandler* req);
|
static void HandleStopReplayBuffer(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSaveReplayBuffer(WSRequestHandler* req);
|
static void HandleSaveReplayBuffer(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleSetRecordingFolder(WSRequestHandler* req);
|
static void HandleSetRecordingFolder(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetRecordingFolder(WSRequestHandler* req);
|
static void HandleGetRecordingFolder(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleGetTransitionList(WSRequestHandler* req);
|
static void HandleGetTransitionList(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetCurrentTransition(WSRequestHandler* req);
|
static void HandleGetCurrentTransition(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSetCurrentTransition(WSRequestHandler* req);
|
static void HandleSetCurrentTransition(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleSetVolume(WSRequestHandler* req);
|
static void HandleSetVolume(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetVolume(WSRequestHandler* req);
|
static void HandleGetVolume(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleToggleMute(WSRequestHandler* req);
|
static void HandleToggleMute(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSetMute(WSRequestHandler* req);
|
static void HandleSetMute(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetMute(WSRequestHandler* req);
|
static void HandleGetMute(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSetSyncOffset(WSRequestHandler* req);
|
static void HandleSetSyncOffset(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetSyncOffset(WSRequestHandler* req);
|
static void HandleGetSyncOffset(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetSpecialSources(WSRequestHandler* req);
|
static void HandleGetSpecialSources(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetSourcesList(WSRequestHandler* req);
|
static void HandleGetSourcesList(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetSourceTypesList(WSRequestHandler* req);
|
static void HandleGetSourceTypesList(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetSourceSettings(WSRequestHandler* req);
|
static void HandleGetSourceSettings(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSetSourceSettings(WSRequestHandler* req);
|
static void HandleSetSourceSettings(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleTakeSourceScreenshot(WSRequestHandler* req);
|
|
||||||
|
|
||||||
static HandlerResponse HandleGetSourceFilters(WSRequestHandler* req);
|
static void HandleGetSourceFilters(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleAddFilterToSource(WSRequestHandler* req);
|
static void HandleAddFilterToSource(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleRemoveFilterFromSource(WSRequestHandler* req);
|
static void HandleRemoveFilterFromSource(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleReorderSourceFilter(WSRequestHandler* req);
|
static void HandleReorderSourceFilter(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleMoveSourceFilter(WSRequestHandler* req);
|
static void HandleMoveSourceFilter(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSetSourceFilterSettings(WSRequestHandler* req);
|
static void HandleSetSourceFilterSettings(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleSetCurrentSceneCollection(WSRequestHandler* req);
|
static void HandleSetCurrentSceneCollection(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetCurrentSceneCollection(WSRequestHandler* req);
|
static void HandleGetCurrentSceneCollection(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleListSceneCollections(WSRequestHandler* req);
|
static void HandleListSceneCollections(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleSetCurrentProfile(WSRequestHandler* req);
|
static void HandleSetCurrentProfile(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetCurrentProfile(WSRequestHandler* req);
|
static void HandleGetCurrentProfile(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleListProfiles(WSRequestHandler* req);
|
static void HandleListProfiles(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleSetStreamSettings(WSRequestHandler* req);
|
static void HandleSetStreamSettings(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetStreamSettings(WSRequestHandler* req);
|
static void HandleGetStreamSettings(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSaveStreamSettings(WSRequestHandler* req);
|
static void HandleSaveStreamSettings(WSRequestHandler* req);
|
||||||
#if BUILD_CAPTIONS
|
|
||||||
static HandlerResponse HandleSendCaptions(WSRequestHandler * req);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static HandlerResponse HandleSetTransitionDuration(WSRequestHandler* req);
|
static void HandleSetTransitionDuration(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetTransitionDuration(WSRequestHandler* req);
|
static void HandleGetTransitionDuration(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleGetStudioModeStatus(WSRequestHandler* req);
|
static void HandleGetStudioModeStatus(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetPreviewScene(WSRequestHandler* req);
|
static void HandleGetPreviewScene(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleSetPreviewScene(WSRequestHandler* req);
|
static void HandleSetPreviewScene(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleTransitionToProgram(WSRequestHandler* req);
|
static void HandleTransitionToProgram(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleEnableStudioMode(WSRequestHandler* req);
|
static void HandleEnableStudioMode(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleDisableStudioMode(WSRequestHandler* req);
|
static void HandleDisableStudioMode(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleToggleStudioMode(WSRequestHandler* req);
|
static void HandleToggleStudioMode(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleSetTextGDIPlusProperties(WSRequestHandler* req);
|
static void HandleSetTextGDIPlusProperties(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetTextGDIPlusProperties(WSRequestHandler* req);
|
static void HandleGetTextGDIPlusProperties(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleSetTextFreetype2Properties(WSRequestHandler* req);
|
static void HandleSetTextFreetype2Properties(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetTextFreetype2Properties(WSRequestHandler* req);
|
static void HandleGetTextFreetype2Properties(WSRequestHandler* req);
|
||||||
|
|
||||||
static HandlerResponse HandleSetBrowserSourceProperties(WSRequestHandler* req);
|
static void HandleSetBrowserSourceProperties(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetBrowserSourceProperties(WSRequestHandler* req);
|
static void HandleGetBrowserSourceProperties(WSRequestHandler* req);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // WSPROTOCOL_H
|
||||||
|
@ -1,58 +1,11 @@
|
|||||||
#include "obs-websocket.h"
|
#include <QString>
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "WSEvents.h"
|
#include "WSEvents.h"
|
||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
|
|
||||||
#define CASE(x) case x: return #x;
|
|
||||||
const char *describe_output_format(int format) {
|
|
||||||
switch (format) {
|
|
||||||
default:
|
|
||||||
CASE(VIDEO_FORMAT_NONE)
|
|
||||||
CASE(VIDEO_FORMAT_I420)
|
|
||||||
CASE(VIDEO_FORMAT_NV12)
|
|
||||||
CASE(VIDEO_FORMAT_YVYU)
|
|
||||||
CASE(VIDEO_FORMAT_YUY2)
|
|
||||||
CASE(VIDEO_FORMAT_UYVY)
|
|
||||||
CASE(VIDEO_FORMAT_RGBA)
|
|
||||||
CASE(VIDEO_FORMAT_BGRA)
|
|
||||||
CASE(VIDEO_FORMAT_BGRX)
|
|
||||||
CASE(VIDEO_FORMAT_Y800)
|
|
||||||
CASE(VIDEO_FORMAT_I444)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *describe_color_space(int cs) {
|
|
||||||
switch (cs) {
|
|
||||||
default:
|
|
||||||
CASE(VIDEO_CS_DEFAULT)
|
|
||||||
CASE(VIDEO_CS_601)
|
|
||||||
CASE(VIDEO_CS_709)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *describe_color_range(int range) {
|
|
||||||
switch (range) {
|
|
||||||
default:
|
|
||||||
CASE(VIDEO_RANGE_DEFAULT)
|
|
||||||
CASE(VIDEO_RANGE_PARTIAL)
|
|
||||||
CASE(VIDEO_RANGE_FULL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *describe_scale_type(int scale) {
|
|
||||||
switch (scale) {
|
|
||||||
default:
|
|
||||||
CASE(VIDEO_SCALE_DEFAULT)
|
|
||||||
CASE(VIDEO_SCALE_POINT)
|
|
||||||
CASE(VIDEO_SCALE_FAST_BILINEAR)
|
|
||||||
CASE(VIDEO_SCALE_BILINEAR)
|
|
||||||
CASE(VIDEO_SCALE_BICUBIC)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#undef CASE
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the latest version of the plugin and the API.
|
* Returns the latest version of the plugin and the API.
|
||||||
*
|
*
|
||||||
@ -66,7 +19,7 @@ const char *describe_scale_type(int scale) {
|
|||||||
* @category general
|
* @category general
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetVersion(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetVersion(WSRequestHandler* req) {
|
||||||
QString obsVersion = Utils::OBSVersionString();
|
QString obsVersion = Utils::OBSVersionString();
|
||||||
|
|
||||||
QList<QString> names = req->messageMap.keys();
|
QList<QString> names = req->messageMap.keys();
|
||||||
@ -80,12 +33,11 @@ HandlerResponse WSRequestHandler::HandleGetVersion(WSRequestHandler* req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OBSDataAutoRelease data = obs_data_create();
|
OBSDataAutoRelease data = obs_data_create();
|
||||||
obs_data_set_double(data, "version", 1.1);
|
|
||||||
obs_data_set_string(data, "obs-websocket-version", OBS_WEBSOCKET_VERSION);
|
obs_data_set_string(data, "obs-websocket-version", OBS_WEBSOCKET_VERSION);
|
||||||
obs_data_set_string(data, "obs-studio-version", obsVersion.toUtf8());
|
obs_data_set_string(data, "obs-studio-version", obsVersion.toUtf8());
|
||||||
obs_data_set_string(data, "available-requests", requests.toUtf8());
|
obs_data_set_string(data, "available-requests", requests.toUtf8());
|
||||||
|
|
||||||
return req->SendOKResponse(data);
|
req->SendOKResponse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,21 +53,20 @@ HandlerResponse WSRequestHandler::HandleGetVersion(WSRequestHandler* req) {
|
|||||||
* @category general
|
* @category general
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetAuthRequired(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetAuthRequired(WSRequestHandler* req) {
|
||||||
bool authRequired = GetConfig()->AuthRequired;
|
bool authRequired = Config::Current()->AuthRequired;
|
||||||
|
|
||||||
OBSDataAutoRelease data = obs_data_create();
|
OBSDataAutoRelease data = obs_data_create();
|
||||||
obs_data_set_bool(data, "authRequired", authRequired);
|
obs_data_set_bool(data, "authRequired", authRequired);
|
||||||
|
|
||||||
if (authRequired) {
|
if (authRequired) {
|
||||||
auto config = GetConfig();
|
|
||||||
obs_data_set_string(data, "challenge",
|
obs_data_set_string(data, "challenge",
|
||||||
config->SessionChallenge.toUtf8());
|
Config::Current()->SessionChallenge.toUtf8());
|
||||||
obs_data_set_string(data, "salt",
|
obs_data_set_string(data, "salt",
|
||||||
config->Salt.toUtf8());
|
Config::Current()->Salt.toUtf8());
|
||||||
}
|
}
|
||||||
|
|
||||||
return req->SendOKResponse(data);
|
req->SendOKResponse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,26 +79,26 @@ HandlerResponse WSRequestHandler::HandleGetAuthRequired(WSRequestHandler* req) {
|
|||||||
* @category general
|
* @category general
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleAuthenticate(WSRequestHandler* req) {
|
void WSRequestHandler::HandleAuthenticate(WSRequestHandler* req) {
|
||||||
if (!req->hasField("auth")) {
|
if (!req->hasField("auth")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
}
|
return;
|
||||||
|
|
||||||
if (req->_connProperties.isAuthenticated()) {
|
|
||||||
return req->SendErrorResponse("already authenticated");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString auth = obs_data_get_string(req->data, "auth");
|
QString auth = obs_data_get_string(req->data, "auth");
|
||||||
if (auth.isEmpty()) {
|
if (auth.isEmpty()) {
|
||||||
return req->SendErrorResponse("auth not specified!");
|
req->SendErrorResponse("auth not specified!");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetConfig()->CheckAuth(auth) == false) {
|
if ((req->_client->property(PROP_AUTHENTICATED).toBool() == false)
|
||||||
return req->SendErrorResponse("Authentication Failed.");
|
&& Config::Current()->CheckAuth(auth))
|
||||||
|
{
|
||||||
|
req->_client->setProperty(PROP_AUTHENTICATED, true);
|
||||||
|
req->SendOKResponse();
|
||||||
|
} else {
|
||||||
|
req->SendErrorResponse("Authentication Failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
req->_connProperties.setAuthenticated(true);
|
|
||||||
return req->SendOKResponse();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,17 +111,19 @@ HandlerResponse WSRequestHandler::HandleAuthenticate(WSRequestHandler* req) {
|
|||||||
* @category general
|
* @category general
|
||||||
* @since 4.3.0
|
* @since 4.3.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetHeartbeat(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetHeartbeat(WSRequestHandler* req) {
|
||||||
if (!req->hasField("enable")) {
|
if (!req->hasField("enable")) {
|
||||||
return req->SendErrorResponse("Heartbeat <enable> parameter missing");
|
req->SendErrorResponse("Heartbeat <enable> parameter missing");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto events = GetEventsSystem();
|
WSEvents::Instance->HeartbeatIsActive =
|
||||||
events->HeartbeatIsActive = obs_data_get_bool(req->data, "enable");
|
obs_data_get_bool(req->data, "enable");
|
||||||
|
|
||||||
OBSDataAutoRelease response = obs_data_create();
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
obs_data_set_bool(response, "enable", events->HeartbeatIsActive);
|
obs_data_set_bool(response, "enable",
|
||||||
return req->SendOKResponse(response);
|
WSEvents::Instance->HeartbeatIsActive);
|
||||||
|
req->SendOKResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -183,18 +136,19 @@ HandlerResponse WSRequestHandler::HandleSetHeartbeat(WSRequestHandler* req) {
|
|||||||
* @category general
|
* @category general
|
||||||
* @since 4.3.0
|
* @since 4.3.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetFilenameFormatting(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetFilenameFormatting(WSRequestHandler* req) {
|
||||||
if (!req->hasField("filename-formatting")) {
|
if (!req->hasField("filename-formatting")) {
|
||||||
return req->SendErrorResponse("<filename-formatting> parameter missing");
|
req->SendErrorResponse("<filename-formatting> parameter missing");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString filenameFormatting = obs_data_get_string(req->data, "filename-formatting");
|
QString filenameFormatting = obs_data_get_string(req->data, "filename-formatting");
|
||||||
if (filenameFormatting.isEmpty()) {
|
if (!filenameFormatting.isEmpty()) {
|
||||||
return req->SendErrorResponse("invalid request parameters");
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::SetFilenameFormatting(filenameFormatting.toUtf8());
|
Utils::SetFilenameFormatting(filenameFormatting.toUtf8());
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
|
} else {
|
||||||
|
req->SendErrorResponse("invalid request parameters");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -207,60 +161,8 @@ HandlerResponse WSRequestHandler::HandleSetFilenameFormatting(WSRequestHandler*
|
|||||||
* @category general
|
* @category general
|
||||||
* @since 4.3.0
|
* @since 4.3.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetFilenameFormatting(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetFilenameFormatting(WSRequestHandler* req) {
|
||||||
OBSDataAutoRelease response = obs_data_create();
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
obs_data_set_string(response, "filename-formatting", Utils::GetFilenameFormatting());
|
obs_data_set_string(response, "filename-formatting", Utils::GetFilenameFormatting());
|
||||||
return req->SendOKResponse(response);
|
req->SendOKResponse(response);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get OBS stats (almost the same info as provided in OBS' stats window)
|
|
||||||
*
|
|
||||||
* @return {OBSStats} `stats` OBS stats
|
|
||||||
*
|
|
||||||
* @api requests
|
|
||||||
* @name GetStats
|
|
||||||
* @category general
|
|
||||||
* @since 4.6.0
|
|
||||||
*/
|
|
||||||
HandlerResponse WSRequestHandler::HandleGetStats(WSRequestHandler* req) {
|
|
||||||
OBSDataAutoRelease stats = GetEventsSystem()->GetStats();
|
|
||||||
|
|
||||||
OBSDataAutoRelease response = obs_data_create();
|
|
||||||
obs_data_set_obj(response, "stats", stats);
|
|
||||||
return req->SendOKResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get basic OBS video information
|
|
||||||
*
|
|
||||||
* @return {int} `baseWidth` Base (canvas) width
|
|
||||||
* @return {int} `baseHeight` Base (canvas) height
|
|
||||||
* @return {int} `outputWidth` Output width
|
|
||||||
* @return {int} `outputHeight` Output height
|
|
||||||
* @return {String} `scaleType` Scaling method used if output size differs from base size
|
|
||||||
* @return {double} `fps` Frames rendered per second
|
|
||||||
* @return {String} `videoFormat` Video color format
|
|
||||||
* @return {String} `colorSpace` Color space for YUV
|
|
||||||
* @return {String} `colorRange` Color range (full or partial)
|
|
||||||
*
|
|
||||||
* @api requests
|
|
||||||
* @name GetVideoInfo
|
|
||||||
* @category general
|
|
||||||
* @since 4.6.0
|
|
||||||
*/
|
|
||||||
HandlerResponse WSRequestHandler::HandleGetVideoInfo(WSRequestHandler* req) {
|
|
||||||
obs_video_info ovi;
|
|
||||||
obs_get_video_info(&ovi);
|
|
||||||
OBSDataAutoRelease response = obs_data_create();
|
|
||||||
obs_data_set_int(response, "baseWidth", ovi.base_width);
|
|
||||||
obs_data_set_int(response, "baseHeight", ovi.base_height);
|
|
||||||
obs_data_set_int(response, "outputWidth", ovi.output_width);
|
|
||||||
obs_data_set_int(response, "outputHeight", ovi.output_height);
|
|
||||||
obs_data_set_double(response, "fps", (double)ovi.fps_num / ovi.fps_den);
|
|
||||||
obs_data_set_string(response, "videoFormat", describe_output_format(ovi.output_format));
|
|
||||||
obs_data_set_string(response, "colorSpace", describe_color_space(ovi.colorspace));
|
|
||||||
obs_data_set_string(response, "colorRange", describe_color_range(ovi.range));
|
|
||||||
obs_data_set_string(response, "scaleType", describe_scale_type(ovi.scale_type));
|
|
||||||
return req->SendOKResponse(response);
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <QString>
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
@ -12,19 +13,20 @@
|
|||||||
* @category profiles
|
* @category profiles
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetCurrentProfile(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetCurrentProfile(WSRequestHandler* req) {
|
||||||
if (!req->hasField("profile-name")) {
|
if (!req->hasField("profile-name")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString profileName = obs_data_get_string(req->data, "profile-name");
|
QString profileName = obs_data_get_string(req->data, "profile-name");
|
||||||
if (profileName.isEmpty()) {
|
if (!profileName.isEmpty()) {
|
||||||
return req->SendErrorResponse("invalid request parameters");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO : check if profile exists
|
// TODO : check if profile exists
|
||||||
obs_frontend_set_current_profile(profileName.toUtf8());
|
obs_frontend_set_current_profile(profileName.toUtf8());
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
|
} else {
|
||||||
|
req->SendErrorResponse("invalid request parameters");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,10 +39,12 @@ HandlerResponse WSRequestHandler::HandleSetCurrentProfile(WSRequestHandler* req)
|
|||||||
* @category profiles
|
* @category profiles
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler* req) {
|
||||||
OBSDataAutoRelease response = obs_data_create();
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
obs_data_set_string(response, "profile-name", obs_frontend_get_current_profile());
|
obs_data_set_string(response, "profile-name",
|
||||||
return req->SendOKResponse(response);
|
obs_frontend_get_current_profile());
|
||||||
|
|
||||||
|
req->SendOKResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,13 +57,14 @@ HandlerResponse WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler* req)
|
|||||||
* @category profiles
|
* @category profiles
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleListProfiles(WSRequestHandler* req) {
|
void WSRequestHandler::HandleListProfiles(WSRequestHandler* req) {
|
||||||
char** profiles = obs_frontend_get_profiles();
|
char** profiles = obs_frontend_get_profiles();
|
||||||
OBSDataArrayAutoRelease list = Utils::StringListToArray(profiles, "profile-name");
|
OBSDataArrayAutoRelease list =
|
||||||
|
Utils::StringListToArray(profiles, "profile-name");
|
||||||
bfree(profiles);
|
bfree(profiles);
|
||||||
|
|
||||||
OBSDataAutoRelease response = obs_data_create();
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
obs_data_set_array(response, "profiles", list);
|
obs_data_set_array(response, "profiles", list);
|
||||||
|
|
||||||
return req->SendOKResponse(response);
|
req->SendOKResponse(response);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <QString>
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
@ -10,13 +11,13 @@
|
|||||||
* @category recording
|
* @category recording
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleStartStopRecording(WSRequestHandler* req) {
|
void WSRequestHandler::HandleStartStopRecording(WSRequestHandler* req) {
|
||||||
if (obs_frontend_recording_active())
|
if (obs_frontend_recording_active())
|
||||||
obs_frontend_recording_stop();
|
obs_frontend_recording_stop();
|
||||||
else
|
else
|
||||||
obs_frontend_recording_start();
|
obs_frontend_recording_start();
|
||||||
|
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,12 +29,12 @@ HandlerResponse WSRequestHandler::HandleStartStopRecording(WSRequestHandler* req
|
|||||||
* @category recording
|
* @category recording
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleStartRecording(WSRequestHandler* req) {
|
void WSRequestHandler::HandleStartRecording(WSRequestHandler* req) {
|
||||||
if (obs_frontend_recording_active() == false) {
|
if (obs_frontend_recording_active() == false) {
|
||||||
obs_frontend_recording_start();
|
obs_frontend_recording_start();
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
} else {
|
} else {
|
||||||
return req->SendErrorResponse("recording already active");
|
req->SendErrorResponse("recording already active");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,23 +47,17 @@ HandlerResponse WSRequestHandler::HandleStartRecording(WSRequestHandler* req) {
|
|||||||
* @category recording
|
* @category recording
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleStopRecording(WSRequestHandler* req) {
|
void WSRequestHandler::HandleStopRecording(WSRequestHandler* req) {
|
||||||
if (obs_frontend_recording_active() == true) {
|
if (obs_frontend_recording_active() == true) {
|
||||||
obs_frontend_recording_stop();
|
obs_frontend_recording_stop();
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
} else {
|
} else {
|
||||||
return req->SendErrorResponse("recording not active");
|
req->SendErrorResponse("recording not active");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In the current profile, sets the recording folder of the Simple and Advanced
|
* Change the current recording folder.
|
||||||
* output modes to the specified value.
|
|
||||||
*
|
|
||||||
* Please note: if `SetRecordingFolder` is called while a recording is
|
|
||||||
* in progress, the change won't be applied immediately and will be
|
|
||||||
* effective on the next recording.
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
* @param {String} `rec-folder` Path of the recording folder.
|
* @param {String} `rec-folder` Path of the recording folder.
|
||||||
*
|
*
|
||||||
@ -71,18 +66,18 @@ HandlerResponse WSRequestHandler::HandleStartRecording(WSRequestHandler* req) {
|
|||||||
* @category recording
|
* @category recording
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetRecordingFolder(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetRecordingFolder(WSRequestHandler* req) {
|
||||||
if (!req->hasField("rec-folder")) {
|
if (!req->hasField("rec-folder")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* newRecFolder = obs_data_get_string(req->data, "rec-folder");
|
const char* newRecFolder = obs_data_get_string(req->data, "rec-folder");
|
||||||
bool success = Utils::SetRecordingFolder(newRecFolder);
|
bool success = Utils::SetRecordingFolder(newRecFolder);
|
||||||
if (!success) {
|
if (success)
|
||||||
return req->SendErrorResponse("invalid request parameters");
|
req->SendOKResponse();
|
||||||
}
|
else
|
||||||
|
req->SendErrorResponse("invalid request parameters");
|
||||||
return req->SendOKResponse();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,11 +90,11 @@ HandlerResponse WSRequestHandler::HandleSetRecordingFolder(WSRequestHandler* req
|
|||||||
* @category recording
|
* @category recording
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetRecordingFolder(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetRecordingFolder(WSRequestHandler* req) {
|
||||||
const char* recFolder = Utils::GetRecordingFolder();
|
const char* recFolder = Utils::GetRecordingFolder();
|
||||||
|
|
||||||
OBSDataAutoRelease response = obs_data_create();
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
obs_data_set_string(response, "rec-folder", recFolder);
|
obs_data_set_string(response, "rec-folder", recFolder);
|
||||||
|
|
||||||
return req->SendOKResponse(response);
|
req->SendOKResponse(response);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <QString>
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
@ -10,13 +11,13 @@
|
|||||||
* @category replay buffer
|
* @category replay buffer
|
||||||
* @since 4.2.0
|
* @since 4.2.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleStartStopReplayBuffer(WSRequestHandler* req) {
|
void WSRequestHandler::HandleStartStopReplayBuffer(WSRequestHandler* req) {
|
||||||
if (obs_frontend_replay_buffer_active()) {
|
if (obs_frontend_replay_buffer_active()) {
|
||||||
obs_frontend_replay_buffer_stop();
|
obs_frontend_replay_buffer_stop();
|
||||||
} else {
|
} else {
|
||||||
Utils::StartReplayBuffer();
|
Utils::StartReplayBuffer();
|
||||||
}
|
}
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,17 +32,19 @@ HandlerResponse WSRequestHandler::HandleStartStopReplayBuffer(WSRequestHandler*
|
|||||||
* @category replay buffer
|
* @category replay buffer
|
||||||
* @since 4.2.0
|
* @since 4.2.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleStartReplayBuffer(WSRequestHandler* req) {
|
void WSRequestHandler::HandleStartReplayBuffer(WSRequestHandler* req) {
|
||||||
if (!Utils::ReplayBufferEnabled()) {
|
if (!Utils::ReplayBufferEnabled()) {
|
||||||
return req->SendErrorResponse("replay buffer disabled in settings");
|
req->SendErrorResponse("replay buffer disabled in settings");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obs_frontend_replay_buffer_active() == true) {
|
if (obs_frontend_replay_buffer_active() == true) {
|
||||||
return req->SendErrorResponse("replay buffer already active");
|
req->SendErrorResponse("replay buffer already active");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::StartReplayBuffer();
|
Utils::StartReplayBuffer();
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,12 +56,12 @@ HandlerResponse WSRequestHandler::HandleStartReplayBuffer(WSRequestHandler* req)
|
|||||||
* @category replay buffer
|
* @category replay buffer
|
||||||
* @since 4.2.0
|
* @since 4.2.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleStopReplayBuffer(WSRequestHandler* req) {
|
void WSRequestHandler::HandleStopReplayBuffer(WSRequestHandler* req) {
|
||||||
if (obs_frontend_replay_buffer_active() == true) {
|
if (obs_frontend_replay_buffer_active() == true) {
|
||||||
obs_frontend_replay_buffer_stop();
|
obs_frontend_replay_buffer_stop();
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
} else {
|
} else {
|
||||||
return req->SendErrorResponse("replay buffer not active");
|
req->SendErrorResponse("replay buffer not active");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,9 +75,10 @@ HandlerResponse WSRequestHandler::HandleStopReplayBuffer(WSRequestHandler* req)
|
|||||||
* @category replay buffer
|
* @category replay buffer
|
||||||
* @since 4.2.0
|
* @since 4.2.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSaveReplayBuffer(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSaveReplayBuffer(WSRequestHandler* req) {
|
||||||
if (!obs_frontend_replay_buffer_active()) {
|
if (!obs_frontend_replay_buffer_active()) {
|
||||||
return req->SendErrorResponse("replay buffer not active");
|
req->SendErrorResponse("replay buffer not active");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSOutputAutoRelease replayOutput = obs_frontend_get_replay_buffer_output();
|
OBSOutputAutoRelease replayOutput = obs_frontend_get_replay_buffer_output();
|
||||||
@ -84,5 +88,5 @@ HandlerResponse WSRequestHandler::HandleSaveReplayBuffer(WSRequestHandler* req)
|
|||||||
proc_handler_call(ph, "save", &cd);
|
proc_handler_call(ph, "save", &cd);
|
||||||
calldata_free(&cd);
|
calldata_free(&cd);
|
||||||
|
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <QString>
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
@ -12,19 +13,20 @@
|
|||||||
* @category scene collections
|
* @category scene collections
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetCurrentSceneCollection(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetCurrentSceneCollection(WSRequestHandler* req) {
|
||||||
if (!req->hasField("sc-name")) {
|
if (!req->hasField("sc-name")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString sceneCollection = obs_data_get_string(req->data, "sc-name");
|
QString sceneCollection = obs_data_get_string(req->data, "sc-name");
|
||||||
if (sceneCollection.isEmpty()) {
|
if (!sceneCollection.isEmpty()) {
|
||||||
return req->SendErrorResponse("invalid request parameters");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO : Check if specified profile exists and if changing is allowed
|
// TODO : Check if specified profile exists and if changing is allowed
|
||||||
obs_frontend_set_current_scene_collection(sceneCollection.toUtf8());
|
obs_frontend_set_current_scene_collection(sceneCollection.toUtf8());
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
|
} else {
|
||||||
|
req->SendErrorResponse("invalid request parameters");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,12 +39,12 @@ HandlerResponse WSRequestHandler::HandleSetCurrentSceneCollection(WSRequestHandl
|
|||||||
* @category scene collections
|
* @category scene collections
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetCurrentSceneCollection(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetCurrentSceneCollection(WSRequestHandler* req) {
|
||||||
OBSDataAutoRelease response = obs_data_create();
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
obs_data_set_string(response, "sc-name",
|
obs_data_set_string(response, "sc-name",
|
||||||
obs_frontend_get_current_scene_collection());
|
obs_frontend_get_current_scene_collection());
|
||||||
|
|
||||||
return req->SendOKResponse(response);
|
req->SendOKResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,7 +57,7 @@ HandlerResponse WSRequestHandler::HandleGetCurrentSceneCollection(WSRequestHandl
|
|||||||
* @category scene collections
|
* @category scene collections
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleListSceneCollections(WSRequestHandler* req) {
|
void WSRequestHandler::HandleListSceneCollections(WSRequestHandler* req) {
|
||||||
char** sceneCollections = obs_frontend_get_scene_collections();
|
char** sceneCollections = obs_frontend_get_scene_collections();
|
||||||
OBSDataArrayAutoRelease list =
|
OBSDataArrayAutoRelease list =
|
||||||
Utils::StringListToArray(sceneCollections, "sc-name");
|
Utils::StringListToArray(sceneCollections, "sc-name");
|
||||||
@ -64,5 +66,5 @@ HandlerResponse WSRequestHandler::HandleListSceneCollections(WSRequestHandler* r
|
|||||||
OBSDataAutoRelease response = obs_data_create();
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
obs_data_set_array(response, "scene-collections", list);
|
obs_data_set_array(response, "scene-collections", list);
|
||||||
|
|
||||||
return req->SendOKResponse(response);
|
req->SendOKResponse(response);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
|
#include <QString>
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the scene specific properties of the specified source item.
|
* Gets the scene specific properties of the specified source item.
|
||||||
* Coordinates are relative to the item's parent (the scene or group it belongs to).
|
|
||||||
*
|
*
|
||||||
* @param {String (optional)} `scene-name` the name of the scene that the source item belongs to. Defaults to the current scene.
|
* @param {String (optional)} `scene-name` the name of the scene that the source item belongs to. Defaults to the current scene.
|
||||||
* @param {String} `item` The name of the source.
|
* @param {String} `item` The name of the source.
|
||||||
@ -21,106 +21,171 @@
|
|||||||
* @return {int} `crop.bottom` The number of pixels cropped off the bottom of the source before scaling.
|
* @return {int} `crop.bottom` The number of pixels cropped off the bottom of the source before scaling.
|
||||||
* @return {int} `crop.left` The number of pixels cropped off the left of the source before scaling.
|
* @return {int} `crop.left` The number of pixels cropped off the left of the source before scaling.
|
||||||
* @return {bool} `visible` If the source is visible.
|
* @return {bool} `visible` If the source is visible.
|
||||||
* @return {bool} `locked` If the source's transform is locked.
|
* @return {String} `bounds.type` Type of bounding box.
|
||||||
* @return {String} `bounds.type` Type of bounding box. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE".
|
|
||||||
* @return {int} `bounds.alignment` Alignment of the bounding box.
|
* @return {int} `bounds.alignment` Alignment of the bounding box.
|
||||||
* @return {double} `bounds.x` Width of the bounding box.
|
* @return {double} `bounds.x` Width of the bounding box.
|
||||||
* @return {double} `bounds.y` Height of the bounding box.
|
* @return {double} `bounds.y` Height of the bounding box.
|
||||||
* @return {int} `sourceWidth` Base width (without scaling) of the source
|
|
||||||
* @return {int} `sourceHeight` Base source (without scaling) of the source
|
|
||||||
* @return {double} `width` Scene item width (base source width multiplied by the horizontal scaling factor)
|
|
||||||
* @return {double} `height` Scene item height (base source height multiplied by the vertical scaling factor)
|
|
||||||
* @property {String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group)
|
|
||||||
* @property {Array<SceneItemTransform> (optional)} `groupChildren` List of children (if this item is a group)
|
|
||||||
*
|
*
|
||||||
* @api requests
|
* @api requests
|
||||||
* @name GetSceneItemProperties
|
* @name GetSceneItemProperties
|
||||||
* @category scene items
|
* @category scene items
|
||||||
* @since 4.3.0
|
* @since 4.3.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetSceneItemProperties(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetSceneItemProperties(WSRequestHandler* req) {
|
||||||
if (!req->hasField("item")) {
|
if (!req->hasField("item")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString itemName = obs_data_get_string(req->data, "item");
|
QString itemName = obs_data_get_string(req->data, "item");
|
||||||
if (itemName.isEmpty()) {
|
if (itemName.isEmpty()) {
|
||||||
return req->SendErrorResponse("invalid request parameters");
|
req->SendErrorResponse("invalid request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString sceneName = obs_data_get_string(req->data, "scene-name");
|
QString sceneName = obs_data_get_string(req->data, "scene-name");
|
||||||
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return req->SendErrorResponse("requested scene doesn't exist");
|
req->SendErrorResponse("requested scene doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSSceneItemAutoRelease sceneItem =
|
OBSSceneItemAutoRelease sceneItem =
|
||||||
Utils::GetSceneItemFromName(scene, itemName);
|
Utils::GetSceneItemFromName(scene, itemName);
|
||||||
if (!sceneItem) {
|
if (!sceneItem) {
|
||||||
return req->SendErrorResponse("specified scene item doesn't exist");
|
req->SendErrorResponse("specified scene item doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSDataAutoRelease data = Utils::GetSceneItemPropertiesData(sceneItem);
|
OBSDataAutoRelease data = obs_data_create();
|
||||||
obs_data_set_string(data, "name", itemName.toUtf8());
|
obs_data_set_string(data, "name", itemName.toUtf8());
|
||||||
|
|
||||||
return req->SendOKResponse(data);
|
OBSDataAutoRelease posData = obs_data_create();
|
||||||
|
vec2 pos;
|
||||||
|
obs_sceneitem_get_pos(sceneItem, &pos);
|
||||||
|
obs_data_set_double(posData, "x", pos.x);
|
||||||
|
obs_data_set_double(posData, "y", pos.y);
|
||||||
|
obs_data_set_int(posData, "alignment", obs_sceneitem_get_alignment(sceneItem));
|
||||||
|
obs_data_set_obj(data, "position", posData);
|
||||||
|
|
||||||
|
obs_data_set_double(data, "rotation", obs_sceneitem_get_rot(sceneItem));
|
||||||
|
|
||||||
|
OBSDataAutoRelease scaleData = obs_data_create();
|
||||||
|
vec2 scale;
|
||||||
|
obs_sceneitem_get_scale(sceneItem, &scale);
|
||||||
|
obs_data_set_double(scaleData, "x", scale.x);
|
||||||
|
obs_data_set_double(scaleData, "y", scale.y);
|
||||||
|
obs_data_set_obj(data, "scale", scaleData);
|
||||||
|
|
||||||
|
OBSDataAutoRelease cropData = obs_data_create();
|
||||||
|
obs_sceneitem_crop crop;
|
||||||
|
obs_sceneitem_get_crop(sceneItem, &crop);
|
||||||
|
obs_data_set_int(cropData, "left", crop.left);
|
||||||
|
obs_data_set_int(cropData, "top", crop.top);
|
||||||
|
obs_data_set_int(cropData, "right", crop.right);
|
||||||
|
obs_data_set_int(cropData, "bottom", crop.bottom);
|
||||||
|
obs_data_set_obj(data, "crop", cropData);
|
||||||
|
|
||||||
|
obs_data_set_bool(data, "visible", obs_sceneitem_visible(sceneItem));
|
||||||
|
|
||||||
|
OBSDataAutoRelease boundsData = obs_data_create();
|
||||||
|
obs_bounds_type boundsType = obs_sceneitem_get_bounds_type(sceneItem);
|
||||||
|
if (boundsType == OBS_BOUNDS_NONE) {
|
||||||
|
obs_data_set_string(boundsData, "type", "OBS_BOUNDS_NONE");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (boundsType) {
|
||||||
|
case OBS_BOUNDS_STRETCH: {
|
||||||
|
obs_data_set_string(boundsData, "type", "OBS_BOUNDS_STRETCH");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OBS_BOUNDS_SCALE_INNER: {
|
||||||
|
obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_INNER");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OBS_BOUNDS_SCALE_OUTER: {
|
||||||
|
obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_OUTER");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OBS_BOUNDS_SCALE_TO_WIDTH: {
|
||||||
|
obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_WIDTH");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OBS_BOUNDS_SCALE_TO_HEIGHT: {
|
||||||
|
obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_HEIGHT");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OBS_BOUNDS_MAX_ONLY: {
|
||||||
|
obs_data_set_string(boundsData, "type", "OBS_BOUNDS_MAX_ONLY");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
obs_data_set_int(boundsData, "alignment", obs_sceneitem_get_bounds_alignment(sceneItem));
|
||||||
|
vec2 bounds;
|
||||||
|
obs_sceneitem_get_bounds(sceneItem, &bounds);
|
||||||
|
obs_data_set_double(boundsData, "x", bounds.x);
|
||||||
|
obs_data_set_double(boundsData, "y", bounds.y);
|
||||||
|
}
|
||||||
|
obs_data_set_obj(data, "bounds", boundsData);
|
||||||
|
|
||||||
|
req->SendOKResponse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the scene specific properties of a source. Unspecified properties will remain unchanged.
|
* Sets the scene specific properties of a source. Unspecified properties will remain unchanged.
|
||||||
* Coordinates are relative to the item's parent (the scene or group it belongs to).
|
|
||||||
*
|
*
|
||||||
* @param {String (optional)} `scene-name` the name of the scene that the source item belongs to. Defaults to the current scene.
|
* @param {String (optional)} `scene-name` the name of the scene that the source item belongs to. Defaults to the current scene.
|
||||||
* @param {String} `item` The name of the source.
|
* @param {String} `item` The name of the source.
|
||||||
* @param {int (optional)} `position.x` The new x position of the source.
|
* @param {int} `position.x` The new x position of the source.
|
||||||
* @param {int (optional)} `position.y` The new y position of the source.
|
* @param {int} `position.y` The new y position of the source.
|
||||||
* @param {int (optional)} `position.alignment` The new alignment of the source.
|
* @param {int} `position.alignment` The new alignment of the source.
|
||||||
* @param {double (optional)} `rotation` The new clockwise rotation of the item in degrees.
|
* @param {double} `rotation` The new clockwise rotation of the item in degrees.
|
||||||
* @param {double (optional)} `scale.x` The new x scale of the item.
|
* @param {double} `scale.x` The new x scale of the item.
|
||||||
* @param {double (optional)} `scale.y` The new y scale of the item.
|
* @param {double} `scale.y` The new y scale of the item.
|
||||||
* @param {int (optional)} `crop.top` The new amount of pixels cropped off the top of the source before scaling.
|
* @param {int} `crop.top` The new amount of pixels cropped off the top of the source before scaling.
|
||||||
* @param {int (optional)} `crop.bottom` The new amount of pixels cropped off the bottom of the source before scaling.
|
* @param {int} `crop.bottom` The new amount of pixels cropped off the bottom of the source before scaling.
|
||||||
* @param {int (optional)} `crop.left` The new amount of pixels cropped off the left of the source before scaling.
|
* @param {int} `crop.left` The new amount of pixels cropped off the left of the source before scaling.
|
||||||
* @param {int (optional)} `crop.right` The new amount of pixels cropped off the right of the source before scaling.
|
* @param {int} `crop.right` The new amount of pixels cropped off the right of the source before scaling.
|
||||||
* @param {bool (optional)} `visible` The new visibility of the source. 'true' shows source, 'false' hides source.
|
* @param {bool} `visible` The new visibility of the source. 'true' shows source, 'false' hides source.
|
||||||
* @param {bool (optional)} `locked` The new locked status of the source. 'true' keeps it in its current position, 'false' allows movement.
|
* @param {String} `bounds.type` The new bounds type of the source.
|
||||||
* @param {String (optional)} `bounds.type` The new bounds type of the source. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE".
|
* @param {int} `bounds.alignment` The new alignment of the bounding box. (0-2, 4-6, 8-10)
|
||||||
* @param {int (optional)} `bounds.alignment` The new alignment of the bounding box. (0-2, 4-6, 8-10)
|
* @param {double} `bounds.x` The new width of the bounding box.
|
||||||
* @param {double (optional)} `bounds.x` The new width of the bounding box.
|
* @param {double} `bounds.y` The new height of the bounding box.
|
||||||
* @param {double (optional)} `bounds.y` The new height of the bounding box.
|
|
||||||
*
|
*
|
||||||
* @api requests
|
* @api requests
|
||||||
* @name SetSceneItemProperties
|
* @name SetSceneItemProperties
|
||||||
* @category scene items
|
* @category scene items
|
||||||
* @since 4.3.0
|
* @since 4.3.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler* req) {
|
||||||
if (!req->hasField("item")) {
|
if (!req->hasField("item")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString itemName = obs_data_get_string(req->data, "item");
|
QString itemName = obs_data_get_string(req->data, "item");
|
||||||
if (itemName.isEmpty()) {
|
if (itemName.isEmpty()) {
|
||||||
return req->SendErrorResponse("invalid request parameters");
|
req->SendErrorResponse("invalid request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString sceneName = obs_data_get_string(req->data, "scene-name");
|
QString sceneName = obs_data_get_string(req->data, "scene-name");
|
||||||
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return req->SendErrorResponse("requested scene doesn't exist");
|
req->SendErrorResponse("requested scene doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSSceneItemAutoRelease sceneItem =
|
OBSSceneItemAutoRelease sceneItem =
|
||||||
Utils::GetSceneItemFromName(scene, itemName);
|
Utils::GetSceneItemFromName(scene, itemName);
|
||||||
if (!sceneItem) {
|
if (!sceneItem) {
|
||||||
return req->SendErrorResponse("specified scene item doesn't exist");
|
req->SendErrorResponse("specified scene item doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool badRequest = false;
|
bool badRequest = false;
|
||||||
OBSDataAutoRelease errorMessage = obs_data_create();
|
OBSDataAutoRelease errorMessage = obs_data_create();
|
||||||
|
|
||||||
obs_sceneitem_defer_update_begin(sceneItem);
|
|
||||||
|
|
||||||
if (req->hasField("position")) {
|
if (req->hasField("position")) {
|
||||||
vec2 oldPosition;
|
vec2 oldPosition;
|
||||||
OBSDataAutoRelease positionError = obs_data_create();
|
OBSDataAutoRelease positionError = obs_data_create();
|
||||||
@ -189,16 +254,12 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler*
|
|||||||
obs_sceneitem_set_visible(sceneItem, obs_data_get_bool(req->data, "visible"));
|
obs_sceneitem_set_visible(sceneItem, obs_data_get_bool(req->data, "visible"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->hasField("locked")) {
|
|
||||||
obs_sceneitem_set_locked(sceneItem, obs_data_get_bool(req->data, "locked"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req->hasField("bounds")) {
|
if (req->hasField("bounds")) {
|
||||||
bool badBounds = false;
|
bool badBounds = false;
|
||||||
OBSDataAutoRelease boundsError = obs_data_create();
|
OBSDataAutoRelease boundsError = obs_data_create();
|
||||||
OBSDataAutoRelease reqBounds = obs_data_get_obj(req->data, "bounds");
|
OBSDataAutoRelease reqBounds = obs_data_get_obj(req->data, "bounds");
|
||||||
if (obs_data_has_user_value(reqBounds, "type")) {
|
if (obs_data_has_user_value(reqBounds, "type")) {
|
||||||
QString newBoundsType = obs_data_get_string(reqBounds, "type");
|
const char* newBoundsType = obs_data_get_string(reqBounds, "type");
|
||||||
if (newBoundsType == "OBS_BOUNDS_NONE") {
|
if (newBoundsType == "OBS_BOUNDS_NONE") {
|
||||||
obs_sceneitem_set_bounds_type(sceneItem, OBS_BOUNDS_NONE);
|
obs_sceneitem_set_bounds_type(sceneItem, OBS_BOUNDS_NONE);
|
||||||
}
|
}
|
||||||
@ -250,13 +311,12 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_sceneitem_defer_update_end(sceneItem);
|
|
||||||
|
|
||||||
if (badRequest) {
|
if (badRequest) {
|
||||||
return req->SendErrorResponse(errorMessage);
|
req->SendErrorResponse(errorMessage);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
return req->SendOKResponse();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -270,35 +330,39 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler*
|
|||||||
* @category scene items
|
* @category scene items
|
||||||
* @since 4.2.0
|
* @since 4.2.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleResetSceneItem(WSRequestHandler* req) {
|
void WSRequestHandler::HandleResetSceneItem(WSRequestHandler* req) {
|
||||||
// TODO: remove this request, or refactor it to ResetSource
|
// TODO: remove this request, or refactor it to ResetSource
|
||||||
|
|
||||||
if (!req->hasField("item")) {
|
if (!req->hasField("item")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* itemName = obs_data_get_string(req->data, "item");
|
const char* itemName = obs_data_get_string(req->data, "item");
|
||||||
if (!itemName) {
|
if (!itemName) {
|
||||||
return req->SendErrorResponse("invalid request parameters");
|
req->SendErrorResponse("invalid request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* sceneName = obs_data_get_string(req->data, "scene-name");
|
const char* sceneName = obs_data_get_string(req->data, "scene-name");
|
||||||
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return req->SendErrorResponse("requested scene doesn't exist");
|
req->SendErrorResponse("requested scene doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName);
|
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName);
|
||||||
if (!sceneItem) {
|
if (sceneItem) {
|
||||||
return req->SendErrorResponse("specified scene item doesn't exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
OBSSource sceneItemSource = obs_sceneitem_get_source(sceneItem);
|
OBSSource sceneItemSource = obs_sceneitem_get_source(sceneItem);
|
||||||
|
|
||||||
OBSDataAutoRelease settings = obs_source_get_settings(sceneItemSource);
|
OBSDataAutoRelease settings = obs_source_get_settings(sceneItemSource);
|
||||||
obs_source_update(sceneItemSource, settings);
|
obs_source_update(sceneItemSource, settings);
|
||||||
|
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
req->SendErrorResponse("specified scene item doesn't exist");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -314,34 +378,38 @@ HandlerResponse WSRequestHandler::HandleResetSceneItem(WSRequestHandler* req) {
|
|||||||
* @since 0.3
|
* @since 0.3
|
||||||
* @deprecated Since 4.3.0. Prefer the use of SetSceneItemProperties.
|
* @deprecated Since 4.3.0. Prefer the use of SetSceneItemProperties.
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetSceneItemRender(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetSceneItemRender(WSRequestHandler* req) {
|
||||||
if (!req->hasField("source") ||
|
if (!req->hasField("source") ||
|
||||||
!req->hasField("render"))
|
!req->hasField("render"))
|
||||||
{
|
{
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* itemName = obs_data_get_string(req->data, "source");
|
const char* itemName = obs_data_get_string(req->data, "source");
|
||||||
bool isVisible = obs_data_get_bool(req->data, "render");
|
bool isVisible = obs_data_get_bool(req->data, "render");
|
||||||
|
|
||||||
if (!itemName) {
|
if (!itemName) {
|
||||||
return req->SendErrorResponse("invalid request parameters");
|
req->SendErrorResponse("invalid request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* sceneName = obs_data_get_string(req->data, "scene-name");
|
const char* sceneName = obs_data_get_string(req->data, "scene-name");
|
||||||
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return req->SendErrorResponse("requested scene doesn't exist");
|
req->SendErrorResponse("requested scene doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSSceneItemAutoRelease sceneItem =
|
OBSSceneItemAutoRelease sceneItem =
|
||||||
Utils::GetSceneItemFromName(scene, itemName);
|
Utils::GetSceneItemFromName(scene, itemName);
|
||||||
if (!sceneItem) {
|
if (sceneItem) {
|
||||||
return req->SendErrorResponse("specified scene item doesn't exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
obs_sceneitem_set_visible(sceneItem, isVisible);
|
obs_sceneitem_set_visible(sceneItem, isVisible);
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
req->SendErrorResponse("specified scene item doesn't exist");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -359,34 +427,38 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemRender(WSRequestHandler* req
|
|||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
* @deprecated Since 4.3.0. Prefer the use of SetSceneItemProperties.
|
* @deprecated Since 4.3.0. Prefer the use of SetSceneItemProperties.
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetSceneItemPosition(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetSceneItemPosition(WSRequestHandler* req) {
|
||||||
if (!req->hasField("item") ||
|
if (!req->hasField("item") ||
|
||||||
!req->hasField("x") || !req->hasField("y")) {
|
!req->hasField("x") || !req->hasField("y")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString itemName = obs_data_get_string(req->data, "item");
|
QString itemName = obs_data_get_string(req->data, "item");
|
||||||
if (itemName.isEmpty()) {
|
if (itemName.isEmpty()) {
|
||||||
return req->SendErrorResponse("invalid request parameters");
|
req->SendErrorResponse("invalid request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString sceneName = obs_data_get_string(req->data, "scene-name");
|
QString sceneName = obs_data_get_string(req->data, "scene-name");
|
||||||
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return req->SendErrorResponse("requested scene could not be found");
|
req->SendErrorResponse("requested scene could not be found");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSSceneItem sceneItem = Utils::GetSceneItemFromName(scene, itemName);
|
OBSSceneItem sceneItem = Utils::GetSceneItemFromName(scene, itemName);
|
||||||
if (!sceneItem) {
|
if (sceneItem) {
|
||||||
return req->SendErrorResponse("specified scene item doesn't exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 item_position = { 0 };
|
vec2 item_position = { 0 };
|
||||||
item_position.x = obs_data_get_double(req->data, "x");
|
item_position.x = obs_data_get_double(req->data, "x");
|
||||||
item_position.y = obs_data_get_double(req->data, "y");
|
item_position.y = obs_data_get_double(req->data, "y");
|
||||||
obs_sceneitem_set_pos(sceneItem, &item_position);
|
obs_sceneitem_set_pos(sceneItem, &item_position);
|
||||||
|
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
req->SendErrorResponse("specified scene item doesn't exist");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -404,24 +476,27 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemPosition(WSRequestHandler* r
|
|||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
* @deprecated Since 4.3.0. Prefer the use of SetSceneItemProperties.
|
* @deprecated Since 4.3.0. Prefer the use of SetSceneItemProperties.
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler* req) {
|
||||||
if (!req->hasField("item") ||
|
if (!req->hasField("item") ||
|
||||||
!req->hasField("x-scale") ||
|
!req->hasField("x-scale") ||
|
||||||
!req->hasField("y-scale") ||
|
!req->hasField("y-scale") ||
|
||||||
!req->hasField("rotation"))
|
!req->hasField("rotation"))
|
||||||
{
|
{
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString itemName = obs_data_get_string(req->data, "item");
|
QString itemName = obs_data_get_string(req->data, "item");
|
||||||
if (itemName.isEmpty()) {
|
if (itemName.isEmpty()) {
|
||||||
return req->SendErrorResponse("invalid request parameters");
|
req->SendErrorResponse("invalid request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString sceneName = obs_data_get_string(req->data, "scene-name");
|
QString sceneName = obs_data_get_string(req->data, "scene-name");
|
||||||
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return req->SendErrorResponse("requested scene doesn't exist");
|
req->SendErrorResponse("requested scene doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 scale;
|
vec2 scale;
|
||||||
@ -430,18 +505,14 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler*
|
|||||||
float rotation = obs_data_get_double(req->data, "rotation");
|
float rotation = obs_data_get_double(req->data, "rotation");
|
||||||
|
|
||||||
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName);
|
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName);
|
||||||
if (!sceneItem) {
|
if (sceneItem) {
|
||||||
return req->SendErrorResponse("specified scene item doesn't exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
obs_sceneitem_defer_update_begin(sceneItem);
|
|
||||||
|
|
||||||
obs_sceneitem_set_scale(sceneItem, &scale);
|
obs_sceneitem_set_scale(sceneItem, &scale);
|
||||||
obs_sceneitem_set_rot(sceneItem, rotation);
|
obs_sceneitem_set_rot(sceneItem, rotation);
|
||||||
|
req->SendOKResponse();
|
||||||
obs_sceneitem_defer_update_end(sceneItem);
|
}
|
||||||
|
else {
|
||||||
return req->SendOKResponse();
|
req->SendErrorResponse("specified scene item doesn't exist");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -460,27 +531,27 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler*
|
|||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
* @deprecated Since 4.3.0. Prefer the use of SetSceneItemProperties.
|
* @deprecated Since 4.3.0. Prefer the use of SetSceneItemProperties.
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetSceneItemCrop(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetSceneItemCrop(WSRequestHandler* req) {
|
||||||
if (!req->hasField("item")) {
|
if (!req->hasField("item")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString itemName = obs_data_get_string(req->data, "item");
|
QString itemName = obs_data_get_string(req->data, "item");
|
||||||
if (itemName.isEmpty()) {
|
if (itemName.isEmpty()) {
|
||||||
return req->SendErrorResponse("invalid request parameters");
|
req->SendErrorResponse("invalid request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString sceneName = obs_data_get_string(req->data, "scene-name");
|
QString sceneName = obs_data_get_string(req->data, "scene-name");
|
||||||
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return req->SendErrorResponse("requested scene doesn't exist");
|
req->SendErrorResponse("requested scene doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName);
|
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName);
|
||||||
if (!sceneItem) {
|
if (sceneItem) {
|
||||||
return req->SendErrorResponse("specified scene item doesn't exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct obs_sceneitem_crop crop = { 0 };
|
struct obs_sceneitem_crop crop = { 0 };
|
||||||
crop.top = obs_data_get_int(req->data, "top");
|
crop.top = obs_data_get_int(req->data, "top");
|
||||||
crop.bottom = obs_data_get_int(req->data, "bottom");
|
crop.bottom = obs_data_get_int(req->data, "bottom");
|
||||||
@ -489,7 +560,11 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemCrop(WSRequestHandler* req)
|
|||||||
|
|
||||||
obs_sceneitem_set_crop(sceneItem, &crop);
|
obs_sceneitem_set_crop(sceneItem, &crop);
|
||||||
|
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
req->SendErrorResponse("specified scene item doesn't exist");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -505,26 +580,29 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemCrop(WSRequestHandler* req)
|
|||||||
* @category scene items
|
* @category scene items
|
||||||
* @since 4.5.0
|
* @since 4.5.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleDeleteSceneItem(WSRequestHandler* req) {
|
void WSRequestHandler::HandleDeleteSceneItem(WSRequestHandler* req) {
|
||||||
if (!req->hasField("item")) {
|
if (!req->hasField("item")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* sceneName = obs_data_get_string(req->data, "scene");
|
const char* sceneName = obs_data_get_string(req->data, "scene");
|
||||||
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return req->SendErrorResponse("requested scene doesn't exist");
|
req->SendErrorResponse("requested scene doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSDataAutoRelease item = obs_data_get_obj(req->data, "item");
|
OBSDataAutoRelease item = obs_data_get_obj(req->data, "item");
|
||||||
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromItem(scene, item);
|
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromItem(scene, item);
|
||||||
if (!sceneItem) {
|
if (!sceneItem) {
|
||||||
return req->SendErrorResponse("item with id/name combination not found in specified scene");
|
req->SendErrorResponse("item with id/name combination not found in specified scene");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_sceneitem_remove(sceneItem);
|
obs_sceneitem_remove(sceneItem);
|
||||||
|
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DuplicateSceneItemData {
|
struct DuplicateSceneItemData {
|
||||||
@ -550,7 +628,7 @@ static void DuplicateSceneItem(void *_data, obs_scene_t *scene) {
|
|||||||
*
|
*
|
||||||
* @return {String} `scene` Name of the scene where the new item was created
|
* @return {String} `scene` Name of the scene where the new item was created
|
||||||
* @return {Object} `item` New item info
|
* @return {Object} `item` New item info
|
||||||
* @return {int} `item.id` New item ID
|
* @return {int} `̀item.id` New item ID
|
||||||
* @return {String} `item.name` New item name
|
* @return {String} `item.name` New item name
|
||||||
*
|
*
|
||||||
* @api requests
|
* @api requests
|
||||||
@ -558,27 +636,31 @@ static void DuplicateSceneItem(void *_data, obs_scene_t *scene) {
|
|||||||
* @category scene items
|
* @category scene items
|
||||||
* @since 4.5.0
|
* @since 4.5.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleDuplicateSceneItem(WSRequestHandler* req) {
|
void WSRequestHandler::HandleDuplicateSceneItem(WSRequestHandler* req) {
|
||||||
if (!req->hasField("item")) {
|
if (!req->hasField("item")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* fromSceneName = obs_data_get_string(req->data, "fromScene");
|
const char* fromSceneName = obs_data_get_string(req->data, "fromScene");
|
||||||
OBSSourceAutoRelease fromScene = Utils::GetSceneFromNameOrCurrent(fromSceneName);
|
OBSSourceAutoRelease fromScene = Utils::GetSceneFromNameOrCurrent(fromSceneName);
|
||||||
if (!fromScene) {
|
if (!fromScene) {
|
||||||
return req->SendErrorResponse("requested fromScene doesn't exist");
|
req->SendErrorResponse("requested fromScene doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* toSceneName = obs_data_get_string(req->data, "toScene");
|
const char* toSceneName = obs_data_get_string(req->data, "toScene");
|
||||||
OBSSourceAutoRelease toScene = Utils::GetSceneFromNameOrCurrent(toSceneName);
|
OBSSourceAutoRelease toScene = Utils::GetSceneFromNameOrCurrent(toSceneName);
|
||||||
if (!toScene) {
|
if (!toScene) {
|
||||||
return req->SendErrorResponse("requested toScene doesn't exist");
|
req->SendErrorResponse("requested toScene doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSDataAutoRelease item = obs_data_get_obj(req->data, "item");
|
OBSDataAutoRelease item = obs_data_get_obj(req->data, "item");
|
||||||
OBSSceneItemAutoRelease referenceItem = Utils::GetSceneItemFromItem(fromScene, item);
|
OBSSceneItemAutoRelease referenceItem = Utils::GetSceneItemFromItem(fromScene, item);
|
||||||
if (!referenceItem) {
|
if (!referenceItem) {
|
||||||
return req->SendErrorResponse("item with id/name combination not found in specified scene");
|
req->SendErrorResponse("item with id/name combination not found in specified scene");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DuplicateSceneItemData data;
|
DuplicateSceneItemData data;
|
||||||
@ -591,7 +673,8 @@ HandlerResponse WSRequestHandler::HandleDuplicateSceneItem(WSRequestHandler* req
|
|||||||
|
|
||||||
obs_sceneitem_t *newItem = data.newItem;
|
obs_sceneitem_t *newItem = data.newItem;
|
||||||
if (!newItem) {
|
if (!newItem) {
|
||||||
return req->SendErrorResponse("Error duplicating scene item");
|
req->SendErrorResponse("Error duplicating scene item");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSDataAutoRelease itemData = obs_data_create();
|
OBSDataAutoRelease itemData = obs_data_create();
|
||||||
@ -602,5 +685,5 @@ HandlerResponse WSRequestHandler::HandleDuplicateSceneItem(WSRequestHandler* req
|
|||||||
obs_data_set_obj(responseData, "item", itemData);
|
obs_data_set_obj(responseData, "item", itemData);
|
||||||
obs_data_set_string(responseData, "scene", obs_source_get_name(toScene));
|
obs_data_set_string(responseData, "scene", obs_source_get_name(toScene));
|
||||||
|
|
||||||
return req->SendOKResponse(responseData);
|
req->SendOKResponse(responseData);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <QString>
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
@ -5,7 +6,7 @@
|
|||||||
/**
|
/**
|
||||||
* @typedef {Object} `Scene`
|
* @typedef {Object} `Scene`
|
||||||
* @property {String} `name` Name of the currently active scene.
|
* @property {String} `name` Name of the currently active scene.
|
||||||
* @property {Array<SceneItem>} `sources` Ordered list of the current scene's source items.
|
* @property {Array<Source>} `sources` Ordered list of the current scene's source items.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,9 +19,10 @@
|
|||||||
* @category scenes
|
* @category scenes
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) {
|
||||||
if (!req->hasField("scene-name")) {
|
if (!req->hasField("scene-name")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* sceneName = obs_data_get_string(req->data, "scene-name");
|
const char* sceneName = obs_data_get_string(req->data, "scene-name");
|
||||||
@ -28,9 +30,9 @@ HandlerResponse WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) {
|
|||||||
|
|
||||||
if (source) {
|
if (source) {
|
||||||
obs_frontend_set_current_scene(source);
|
obs_frontend_set_current_scene(source);
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
} else {
|
} else {
|
||||||
return req->SendErrorResponse("requested scene does not exist");
|
req->SendErrorResponse("requested scene does not exist");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,14 +40,14 @@ HandlerResponse WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) {
|
|||||||
* Get the current scene's name and source items.
|
* Get the current scene's name and source items.
|
||||||
*
|
*
|
||||||
* @return {String} `name` Name of the currently active scene.
|
* @return {String} `name` Name of the currently active scene.
|
||||||
* @return {Array<SceneItem>} `sources` Ordered list of the current scene's source items.
|
* @return {Array<Source>} `sources` Ordered list of the current scene's source items.
|
||||||
*
|
*
|
||||||
* @api requests
|
* @api requests
|
||||||
* @name GetCurrentScene
|
* @name GetCurrentScene
|
||||||
* @category scenes
|
* @category scenes
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) {
|
||||||
OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene();
|
OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene();
|
||||||
OBSDataArrayAutoRelease sceneItems = Utils::GetSceneItems(currentScene);
|
OBSDataArrayAutoRelease sceneItems = Utils::GetSceneItems(currentScene);
|
||||||
|
|
||||||
@ -53,7 +55,7 @@ HandlerResponse WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) {
|
|||||||
obs_data_set_string(data, "name", obs_source_get_name(currentScene));
|
obs_data_set_string(data, "name", obs_source_get_name(currentScene));
|
||||||
obs_data_set_array(data, "sources", sceneItems);
|
obs_data_set_array(data, "sources", sceneItems);
|
||||||
|
|
||||||
return req->SendOKResponse(data);
|
req->SendOKResponse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,7 +69,7 @@ HandlerResponse WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) {
|
|||||||
* @category scenes
|
* @category scenes
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) {
|
||||||
OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene();
|
OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene();
|
||||||
OBSDataArrayAutoRelease scenes = Utils::GetScenes();
|
OBSDataArrayAutoRelease scenes = Utils::GetScenes();
|
||||||
|
|
||||||
@ -76,7 +78,7 @@ HandlerResponse WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) {
|
|||||||
obs_source_get_name(currentScene));
|
obs_source_get_name(currentScene));
|
||||||
obs_data_set_array(data, "scenes", scenes);
|
obs_data_set_array(data, "scenes", scenes);
|
||||||
|
|
||||||
return req->SendOKResponse(data);
|
req->SendOKResponse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,16 +94,18 @@ HandlerResponse WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) {
|
|||||||
* @category scenes
|
* @category scenes
|
||||||
* @since 4.5.0
|
* @since 4.5.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req) {
|
void WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req) {
|
||||||
QString sceneName = obs_data_get_string(req->data, "scene");
|
QString sceneName = obs_data_get_string(req->data, "scene");
|
||||||
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return req->SendErrorResponse("requested scene doesn't exist");
|
req->SendErrorResponse("requested scene doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSDataArrayAutoRelease items = obs_data_get_array(req->data, "items");
|
OBSDataArrayAutoRelease items = obs_data_get_array(req->data, "items");
|
||||||
if (!items) {
|
if (!items) {
|
||||||
return req->SendErrorResponse("sceneItem order not specified");
|
req->SendErrorResponse("sceneItem order not specified");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t count = obs_data_array_count(items);
|
size_t count = obs_data_array_count(items);
|
||||||
@ -116,12 +120,14 @@ HandlerResponse WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req)
|
|||||||
obs_sceneitem_release(sceneItem); // ref dec
|
obs_sceneitem_release(sceneItem); // ref dec
|
||||||
|
|
||||||
if (!sceneItem) {
|
if (!sceneItem) {
|
||||||
return req->SendErrorResponse("Invalid sceneItem id or name specified");
|
req->SendErrorResponse("Invalid sceneItem id or name specified");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t j = 0; j <= i; ++j) {
|
for (size_t j = 0; j <= i; ++j) {
|
||||||
if (sceneItem == newOrder[j]) {
|
if (sceneItem == newOrder[j]) {
|
||||||
return req->SendErrorResponse("Duplicate sceneItem in specified order");
|
req->SendErrorResponse("Duplicate sceneItem in specified order");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,12 +136,13 @@ HandlerResponse WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req)
|
|||||||
|
|
||||||
bool success = obs_scene_reorder_items(obs_scene_from_source(scene), newOrder.data(), count);
|
bool success = obs_scene_reorder_items(obs_scene_from_source(scene), newOrder.data(), count);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return req->SendErrorResponse("Invalid sceneItem order");
|
req->SendErrorResponse("Invalid sceneItem order");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& item: newOrder) {
|
for (auto const& item: newOrder) {
|
||||||
obs_sceneitem_release(item);
|
obs_sceneitem_release(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
#include "obs-websocket.h"
|
#include <QString>
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "WSEvents.h"
|
#include "WSEvents.h"
|
||||||
|
|
||||||
@ -20,9 +20,7 @@
|
|||||||
* @category streaming
|
* @category streaming
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req) {
|
||||||
auto events = GetEventsSystem();
|
|
||||||
|
|
||||||
OBSDataAutoRelease data = obs_data_create();
|
OBSDataAutoRelease data = obs_data_create();
|
||||||
obs_data_set_bool(data, "streaming", obs_frontend_streaming_active());
|
obs_data_set_bool(data, "streaming", obs_frontend_streaming_active());
|
||||||
obs_data_set_bool(data, "recording", obs_frontend_recording_active());
|
obs_data_set_bool(data, "recording", obs_frontend_recording_active());
|
||||||
@ -30,18 +28,18 @@ HandlerResponse WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req
|
|||||||
|
|
||||||
const char* tc = nullptr;
|
const char* tc = nullptr;
|
||||||
if (obs_frontend_streaming_active()) {
|
if (obs_frontend_streaming_active()) {
|
||||||
tc = events->GetStreamingTimecode();
|
tc = WSEvents::Instance->GetStreamingTimecode();
|
||||||
obs_data_set_string(data, "stream-timecode", tc);
|
obs_data_set_string(data, "stream-timecode", tc);
|
||||||
bfree((void*)tc);
|
bfree((void*)tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obs_frontend_recording_active()) {
|
if (obs_frontend_recording_active()) {
|
||||||
tc = events->GetRecordingTimecode();
|
tc = WSEvents::Instance->GetRecordingTimecode();
|
||||||
obs_data_set_string(data, "rec-timecode", tc);
|
obs_data_set_string(data, "rec-timecode", tc);
|
||||||
bfree((void*)tc);
|
bfree((void*)tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return req->SendOKResponse(data);
|
req->SendOKResponse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,11 +50,11 @@ HandlerResponse WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req
|
|||||||
* @category streaming
|
* @category streaming
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleStartStopStreaming(WSRequestHandler* req) {
|
void WSRequestHandler::HandleStartStopStreaming(WSRequestHandler* req) {
|
||||||
if (obs_frontend_streaming_active())
|
if (obs_frontend_streaming_active())
|
||||||
return HandleStopStreaming(req);
|
HandleStopStreaming(req);
|
||||||
else
|
else
|
||||||
return HandleStartStreaming(req);
|
HandleStartStreaming(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,7 +76,7 @@ HandlerResponse WSRequestHandler::HandleStartStopStreaming(WSRequestHandler* req
|
|||||||
* @category streaming
|
* @category streaming
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) {
|
void WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) {
|
||||||
if (obs_frontend_streaming_active() == false) {
|
if (obs_frontend_streaming_active() == false) {
|
||||||
OBSService configuredService = obs_frontend_get_streaming_service();
|
OBSService configuredService = obs_frontend_get_streaming_service();
|
||||||
OBSService newService = nullptr;
|
OBSService newService = nullptr;
|
||||||
@ -159,9 +157,9 @@ HandlerResponse WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) {
|
|||||||
obs_frontend_set_streaming_service(configuredService);
|
obs_frontend_set_streaming_service(configuredService);
|
||||||
}
|
}
|
||||||
|
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
} else {
|
} else {
|
||||||
return req->SendErrorResponse("streaming already active");
|
req->SendErrorResponse("streaming already active");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,12 +172,12 @@ HandlerResponse WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) {
|
|||||||
* @category streaming
|
* @category streaming
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleStopStreaming(WSRequestHandler* req) {
|
void WSRequestHandler::HandleStopStreaming(WSRequestHandler* req) {
|
||||||
if (obs_frontend_streaming_active() == true) {
|
if (obs_frontend_streaming_active() == true) {
|
||||||
obs_frontend_streaming_stop();
|
obs_frontend_streaming_stop();
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
} else {
|
} else {
|
||||||
return req->SendErrorResponse("streaming not active");
|
req->SendErrorResponse("streaming not active");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,12 +198,13 @@ HandlerResponse WSRequestHandler::HandleStopStreaming(WSRequestHandler* req) {
|
|||||||
* @category streaming
|
* @category streaming
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req) {
|
||||||
OBSService service = obs_frontend_get_streaming_service();
|
OBSService service = obs_frontend_get_streaming_service();
|
||||||
|
|
||||||
OBSDataAutoRelease requestSettings = obs_data_get_obj(req->data, "settings");
|
OBSDataAutoRelease requestSettings = obs_data_get_obj(req->data, "settings");
|
||||||
if (!requestSettings) {
|
if (!requestSettings) {
|
||||||
return req->SendErrorResponse("'settings' are required'");
|
req->SendErrorResponse("'settings' are required'");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString serviceType = obs_service_get_type(service);
|
QString serviceType = obs_service_get_type(service);
|
||||||
@ -243,7 +242,7 @@ HandlerResponse WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req)
|
|||||||
obs_data_set_string(response, "type", requestedType.toUtf8());
|
obs_data_set_string(response, "type", requestedType.toUtf8());
|
||||||
obs_data_set_obj(response, "settings", serviceSettings);
|
obs_data_set_obj(response, "settings", serviceSettings);
|
||||||
|
|
||||||
return req->SendOKResponse(response);
|
req->SendOKResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -262,7 +261,7 @@ HandlerResponse WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req)
|
|||||||
* @category streaming
|
* @category streaming
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetStreamSettings(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetStreamSettings(WSRequestHandler* req) {
|
||||||
OBSService service = obs_frontend_get_streaming_service();
|
OBSService service = obs_frontend_get_streaming_service();
|
||||||
|
|
||||||
const char* serviceType = obs_service_get_type(service);
|
const char* serviceType = obs_service_get_type(service);
|
||||||
@ -272,7 +271,7 @@ HandlerResponse WSRequestHandler::HandleGetStreamSettings(WSRequestHandler* req)
|
|||||||
obs_data_set_string(response, "type", serviceType);
|
obs_data_set_string(response, "type", serviceType);
|
||||||
obs_data_set_obj(response, "settings", settings);
|
obs_data_set_obj(response, "settings", settings);
|
||||||
|
|
||||||
return req->SendOKResponse(response);
|
req->SendOKResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -283,36 +282,7 @@ HandlerResponse WSRequestHandler::HandleGetStreamSettings(WSRequestHandler* req)
|
|||||||
* @category streaming
|
* @category streaming
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSaveStreamSettings(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSaveStreamSettings(WSRequestHandler* req) {
|
||||||
obs_frontend_save_streaming_service();
|
obs_frontend_save_streaming_service();
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the provided text as embedded CEA-608 caption data.
|
|
||||||
* As of OBS Studio 23.1, captions are not yet available on Linux.
|
|
||||||
*
|
|
||||||
* @param {String} `text` Captions text
|
|
||||||
*
|
|
||||||
* @api requests
|
|
||||||
* @name SendCaptions
|
|
||||||
* @category streaming
|
|
||||||
* @since 4.6.0
|
|
||||||
*/
|
|
||||||
#if BUILD_CAPTIONS
|
|
||||||
HandlerResponse WSRequestHandler::HandleSendCaptions(WSRequestHandler* req) {
|
|
||||||
if (!req->hasField("text")) {
|
|
||||||
return req->SendErrorResponse("missing request parameters");
|
|
||||||
}
|
|
||||||
|
|
||||||
OBSOutputAutoRelease output = obs_frontend_get_streaming_output();
|
|
||||||
if (output) {
|
|
||||||
const char* caption = obs_data_get_string(req->data, "text");
|
|
||||||
obs_output_output_caption_text1(output, caption);
|
|
||||||
}
|
|
||||||
|
|
||||||
return req->SendOKResponse();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <QString>
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
@ -12,13 +13,13 @@
|
|||||||
* @category studio mode
|
* @category studio mode
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetStudioModeStatus(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetStudioModeStatus(WSRequestHandler* req) {
|
||||||
bool previewActive = obs_frontend_preview_program_mode_active();
|
bool previewActive = obs_frontend_preview_program_mode_active();
|
||||||
|
|
||||||
OBSDataAutoRelease response = obs_data_create();
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
obs_data_set_bool(response, "studio-mode", previewActive);
|
obs_data_set_bool(response, "studio-mode", previewActive);
|
||||||
|
|
||||||
return req->SendOKResponse(response);
|
req->SendOKResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,16 +27,17 @@ HandlerResponse WSRequestHandler::HandleGetStudioModeStatus(WSRequestHandler* re
|
|||||||
* Will return an `error` if Studio Mode is not enabled.
|
* Will return an `error` if Studio Mode is not enabled.
|
||||||
*
|
*
|
||||||
* @return {String} `name` The name of the active preview scene.
|
* @return {String} `name` The name of the active preview scene.
|
||||||
* @return {Array<SceneItem>} `sources`
|
* @return {Array<Source>} `sources`
|
||||||
*
|
*
|
||||||
* @api requests
|
* @api requests
|
||||||
* @name GetPreviewScene
|
* @name GetPreviewScene
|
||||||
* @category studio mode
|
* @category studio mode
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetPreviewScene(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetPreviewScene(WSRequestHandler* req) {
|
||||||
if (!obs_frontend_preview_program_mode_active()) {
|
if (!obs_frontend_preview_program_mode_active()) {
|
||||||
return req->SendErrorResponse("studio mode not enabled");
|
req->SendErrorResponse("studio mode not enabled");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSSourceAutoRelease scene = obs_frontend_get_current_preview_scene();
|
OBSSourceAutoRelease scene = obs_frontend_get_current_preview_scene();
|
||||||
@ -45,7 +47,7 @@ HandlerResponse WSRequestHandler::HandleGetPreviewScene(WSRequestHandler* req) {
|
|||||||
obs_data_set_string(data, "name", obs_source_get_name(scene));
|
obs_data_set_string(data, "name", obs_source_get_name(scene));
|
||||||
obs_data_set_array(data, "sources", sceneItems);
|
obs_data_set_array(data, "sources", sceneItems);
|
||||||
|
|
||||||
return req->SendOKResponse(data);
|
req->SendOKResponse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,23 +61,26 @@ HandlerResponse WSRequestHandler::HandleGetPreviewScene(WSRequestHandler* req) {
|
|||||||
* @category studio mode
|
* @category studio mode
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetPreviewScene(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetPreviewScene(WSRequestHandler* req) {
|
||||||
if (!obs_frontend_preview_program_mode_active()) {
|
if (!obs_frontend_preview_program_mode_active()) {
|
||||||
return req->SendErrorResponse("studio mode not enabled");
|
req->SendErrorResponse("studio mode not enabled");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!req->hasField("scene-name")) {
|
if (!req->hasField("scene-name")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* scene_name = obs_data_get_string(req->data, "scene-name");
|
const char* scene_name = obs_data_get_string(req->data, "scene-name");
|
||||||
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(scene_name);
|
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(scene_name);
|
||||||
if (!scene) {
|
|
||||||
return req->SendErrorResponse("specified scene doesn't exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (scene) {
|
||||||
obs_frontend_set_current_preview_scene(scene);
|
obs_frontend_set_current_preview_scene(scene);
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
|
} else {
|
||||||
|
req->SendErrorResponse("specified scene doesn't exist");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,9 +96,10 @@ HandlerResponse WSRequestHandler::HandleSetPreviewScene(WSRequestHandler* req) {
|
|||||||
* @category studio mode
|
* @category studio mode
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* req) {
|
void WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* req) {
|
||||||
if (!obs_frontend_preview_program_mode_active()) {
|
if (!obs_frontend_preview_program_mode_active()) {
|
||||||
return req->SendErrorResponse("studio mode not enabled");
|
req->SendErrorResponse("studio mode not enabled");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->hasField("with-transition")) {
|
if (req->hasField("with-transition")) {
|
||||||
@ -104,12 +110,14 @@ HandlerResponse WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* re
|
|||||||
QString transitionName =
|
QString transitionName =
|
||||||
obs_data_get_string(transitionInfo, "name");
|
obs_data_get_string(transitionInfo, "name");
|
||||||
if (transitionName.isEmpty()) {
|
if (transitionName.isEmpty()) {
|
||||||
return req->SendErrorResponse("invalid request parameters");
|
req->SendErrorResponse("invalid request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = Utils::SetTransitionByName(transitionName);
|
bool success = Utils::SetTransitionByName(transitionName);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return req->SendErrorResponse("specified transition doesn't exist");
|
req->SendErrorResponse("specified transition doesn't exist");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +129,7 @@ HandlerResponse WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* re
|
|||||||
}
|
}
|
||||||
|
|
||||||
Utils::TransitionToProgram();
|
Utils::TransitionToProgram();
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,9 +140,9 @@ HandlerResponse WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* re
|
|||||||
* @category studio mode
|
* @category studio mode
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleEnableStudioMode(WSRequestHandler* req) {
|
void WSRequestHandler::HandleEnableStudioMode(WSRequestHandler* req) {
|
||||||
obs_frontend_set_preview_program_mode(true);
|
obs_frontend_set_preview_program_mode(true);
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,9 +153,9 @@ HandlerResponse WSRequestHandler::HandleEnableStudioMode(WSRequestHandler* req)
|
|||||||
* @category studio mode
|
* @category studio mode
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleDisableStudioMode(WSRequestHandler* req) {
|
void WSRequestHandler::HandleDisableStudioMode(WSRequestHandler* req) {
|
||||||
obs_frontend_set_preview_program_mode(false);
|
obs_frontend_set_preview_program_mode(false);
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,8 +166,8 @@ HandlerResponse WSRequestHandler::HandleDisableStudioMode(WSRequestHandler* req)
|
|||||||
* @category studio mode
|
* @category studio mode
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleToggleStudioMode(WSRequestHandler* req) {
|
void WSRequestHandler::HandleToggleStudioMode(WSRequestHandler* req) {
|
||||||
bool previewProgramMode = obs_frontend_preview_program_mode_active();
|
bool previewProgramMode = obs_frontend_preview_program_mode_active();
|
||||||
obs_frontend_set_preview_program_mode(!previewProgramMode);
|
obs_frontend_set_preview_program_mode(!previewProgramMode);
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <QString>
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
@ -14,7 +15,7 @@
|
|||||||
* @category transitions
|
* @category transitions
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req) {
|
||||||
OBSSourceAutoRelease currentTransition = obs_frontend_get_current_transition();
|
OBSSourceAutoRelease currentTransition = obs_frontend_get_current_transition();
|
||||||
obs_frontend_source_list transitionList = {};
|
obs_frontend_source_list transitionList = {};
|
||||||
obs_frontend_get_transitions(&transitionList);
|
obs_frontend_get_transitions(&transitionList);
|
||||||
@ -34,7 +35,7 @@ HandlerResponse WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req)
|
|||||||
obs_source_get_name(currentTransition));
|
obs_source_get_name(currentTransition));
|
||||||
obs_data_set_array(response, "transitions", transitions);
|
obs_data_set_array(response, "transitions", transitions);
|
||||||
|
|
||||||
return req->SendOKResponse(response);
|
req->SendOKResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,7 +49,7 @@ HandlerResponse WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req)
|
|||||||
* @category transitions
|
* @category transitions
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetCurrentTransition(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetCurrentTransition(WSRequestHandler* req) {
|
||||||
OBSSourceAutoRelease currentTransition = obs_frontend_get_current_transition();
|
OBSSourceAutoRelease currentTransition = obs_frontend_get_current_transition();
|
||||||
|
|
||||||
OBSDataAutoRelease response = obs_data_create();
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
@ -58,7 +59,7 @@ HandlerResponse WSRequestHandler::HandleGetCurrentTransition(WSRequestHandler* r
|
|||||||
if (!obs_transition_fixed(currentTransition))
|
if (!obs_transition_fixed(currentTransition))
|
||||||
obs_data_set_int(response, "duration", Utils::GetTransitionDuration());
|
obs_data_set_int(response, "duration", Utils::GetTransitionDuration());
|
||||||
|
|
||||||
return req->SendOKResponse(response);
|
req->SendOKResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,18 +72,18 @@ HandlerResponse WSRequestHandler::HandleGetCurrentTransition(WSRequestHandler* r
|
|||||||
* @category transitions
|
* @category transitions
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetCurrentTransition(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetCurrentTransition(WSRequestHandler* req) {
|
||||||
if (!req->hasField("transition-name")) {
|
if (!req->hasField("transition-name")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString name = obs_data_get_string(req->data, "transition-name");
|
QString name = obs_data_get_string(req->data, "transition-name");
|
||||||
bool success = Utils::SetTransitionByName(name);
|
bool success = Utils::SetTransitionByName(name);
|
||||||
if (!success) {
|
if (success)
|
||||||
return req->SendErrorResponse("requested transition does not exist");
|
req->SendOKResponse();
|
||||||
}
|
else
|
||||||
|
req->SendErrorResponse("requested transition does not exist");
|
||||||
return req->SendOKResponse();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,14 +96,15 @@ HandlerResponse WSRequestHandler::HandleSetCurrentTransition(WSRequestHandler* r
|
|||||||
* @category transitions
|
* @category transitions
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleSetTransitionDuration(WSRequestHandler* req) {
|
void WSRequestHandler::HandleSetTransitionDuration(WSRequestHandler* req) {
|
||||||
if (!req->hasField("duration")) {
|
if (!req->hasField("duration")) {
|
||||||
return req->SendErrorResponse("missing request parameters");
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ms = obs_data_get_int(req->data, "duration");
|
int ms = obs_data_get_int(req->data, "duration");
|
||||||
Utils::SetTransitionDuration(ms);
|
Utils::SetTransitionDuration(ms);
|
||||||
return req->SendOKResponse();
|
req->SendOKResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,8 +117,10 @@ HandlerResponse WSRequestHandler::HandleSetTransitionDuration(WSRequestHandler*
|
|||||||
* @category transitions
|
* @category transitions
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
HandlerResponse WSRequestHandler::HandleGetTransitionDuration(WSRequestHandler* req) {
|
void WSRequestHandler::HandleGetTransitionDuration(WSRequestHandler* req) {
|
||||||
OBSDataAutoRelease response = obs_data_create();
|
OBSDataAutoRelease response = obs_data_create();
|
||||||
obs_data_set_int(response, "transition-duration", Utils::GetTransitionDuration());
|
obs_data_set_int(response, "transition-duration",
|
||||||
return req->SendOKResponse(response);
|
Utils::GetTransitionDuration());
|
||||||
|
|
||||||
|
req->SendOKResponse(response);
|
||||||
}
|
}
|
||||||
|
228
src/WSServer.cpp
228
src/WSServer.cpp
@ -16,16 +16,12 @@ 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 <chrono>
|
#include <QtWebSockets/QWebSocket>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
#include <QtCore/QByteArray>
|
#include <QtCore/QByteArray>
|
||||||
#include <QtWidgets/QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QtWidgets/QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QtConcurrent/QtConcurrent>
|
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
#include <util/platform.h>
|
|
||||||
|
|
||||||
#include "WSServer.h"
|
#include "WSServer.h"
|
||||||
#include "obs-websocket.h"
|
#include "obs-websocket.h"
|
||||||
@ -34,181 +30,139 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
QT_USE_NAMESPACE
|
QT_USE_NAMESPACE
|
||||||
|
|
||||||
using websocketpp::lib::placeholders::_1;
|
WSServer* WSServer::Instance = nullptr;
|
||||||
using websocketpp::lib::placeholders::_2;
|
|
||||||
using websocketpp::lib::bind;
|
|
||||||
|
|
||||||
WSServer::WSServer()
|
WSServer::WSServer(QObject* parent)
|
||||||
: QObject(nullptr),
|
: QObject(parent),
|
||||||
_connections(),
|
_wsServer(Q_NULLPTR),
|
||||||
|
_clients(),
|
||||||
_clMutex(QMutex::Recursive)
|
_clMutex(QMutex::Recursive)
|
||||||
{
|
{
|
||||||
_server.init_asio();
|
_wsServer = new QWebSocketServer(
|
||||||
#ifndef _WIN32
|
QStringLiteral("obs-websocket"),
|
||||||
_server.set_reuse_addr(true);
|
QWebSocketServer::NonSecureMode);
|
||||||
#endif
|
|
||||||
|
|
||||||
_server.set_open_handler(bind(&WSServer::onOpen, this, ::_1));
|
|
||||||
_server.set_close_handler(bind(&WSServer::onClose, this, ::_1));
|
|
||||||
_server.set_message_handler(bind(&WSServer::onMessage, this, ::_1, ::_2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WSServer::~WSServer()
|
WSServer::~WSServer() {
|
||||||
{
|
Stop();
|
||||||
stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSServer::start(quint16 port)
|
void WSServer::Start(quint16 port) {
|
||||||
{
|
if (port == _wsServer->serverPort())
|
||||||
if (_server.is_listening() && port == _serverPort) {
|
|
||||||
blog(LOG_INFO, "WSServer::start: server already on this port. no restart needed");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(_wsServer->isListening())
|
||||||
|
Stop();
|
||||||
|
|
||||||
|
bool serverStarted = _wsServer->listen(QHostAddress::Any, port);
|
||||||
|
if (serverStarted) {
|
||||||
|
blog(LOG_INFO, "server started successfully on TCP port %d", port);
|
||||||
|
|
||||||
|
connect(_wsServer, SIGNAL(newConnection()),
|
||||||
|
this, SLOT(onNewConnection()));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
QString errorString = _wsServer->errorString();
|
||||||
|
blog(LOG_ERROR,
|
||||||
|
"error: failed to start server on TCP port %d: %s",
|
||||||
|
port, errorString.toUtf8().constData());
|
||||||
|
|
||||||
if (_server.is_listening()) {
|
QMainWindow* mainWindow = (QMainWindow*)obs_frontend_get_main_window();
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
_server.reset();
|
|
||||||
|
|
||||||
_serverPort = port;
|
|
||||||
|
|
||||||
websocketpp::lib::error_code errorCode;
|
|
||||||
_server.listen(_serverPort, errorCode);
|
|
||||||
|
|
||||||
if (errorCode) {
|
|
||||||
std::string errorCodeMessage = errorCode.message();
|
|
||||||
blog(LOG_INFO, "server: listen failed: %s", errorCodeMessage.c_str());
|
|
||||||
|
|
||||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||||
QString errorTitle = tr("OBSWebsocket.Server.StartFailed.Title");
|
QString title = tr("OBSWebsocket.Server.StartFailed.Title");
|
||||||
QString errorMessage = tr("OBSWebsocket.Server.StartFailed.Message").arg(_serverPort);
|
QString msg = tr("OBSWebsocket.Server.StartFailed.Message").arg(port);
|
||||||
obs_frontend_pop_ui_translation();
|
obs_frontend_pop_ui_translation();
|
||||||
|
|
||||||
QMainWindow* mainWindow = reinterpret_cast<QMainWindow*>(obs_frontend_get_main_window());
|
QMessageBox::warning(mainWindow, title, msg);
|
||||||
QMessageBox::warning(mainWindow, errorTitle, errorMessage);
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_server.start_accept();
|
void WSServer::Stop() {
|
||||||
|
QMutexLocker locker(&_clMutex);
|
||||||
QtConcurrent::run([=]() {
|
for(QWebSocket* pClient : _clients) {
|
||||||
blog(LOG_INFO, "io thread started");
|
pClient->close();
|
||||||
_server.run();
|
|
||||||
blog(LOG_INFO, "io thread exited");
|
|
||||||
});
|
|
||||||
|
|
||||||
blog(LOG_INFO, "server started successfully on port %d", _serverPort);
|
|
||||||
}
|
}
|
||||||
|
locker.unlock();
|
||||||
|
|
||||||
void WSServer::stop()
|
_wsServer->close();
|
||||||
{
|
|
||||||
if (!_server.is_listening()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_server.stop_listening();
|
|
||||||
for (connection_hdl hdl : _connections) {
|
|
||||||
_server.close(hdl, websocketpp::close::status::going_away, "Server stopping");
|
|
||||||
}
|
|
||||||
_connections.clear();
|
|
||||||
_connectionProperties.clear();
|
|
||||||
|
|
||||||
_threadPool.waitForDone();
|
|
||||||
|
|
||||||
while (!_server.stopped()) {
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
blog(LOG_INFO, "server stopped successfully");
|
blog(LOG_INFO, "server stopped successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSServer::broadcast(std::string message)
|
void WSServer::broadcast(QString message) {
|
||||||
{
|
|
||||||
QMutexLocker locker(&_clMutex);
|
QMutexLocker locker(&_clMutex);
|
||||||
for (connection_hdl hdl : _connections) {
|
for(QWebSocket* pClient : _clients) {
|
||||||
if (GetConfig()->AuthRequired) {
|
if (Config::Current()->AuthRequired
|
||||||
bool authenticated = _connectionProperties[hdl].isAuthenticated();
|
&& (pClient->property(PROP_AUTHENTICATED).toBool() == false)) {
|
||||||
if (!authenticated) {
|
// Skip this client if unauthenticated
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
pClient->sendTextMessage(message);
|
||||||
_server.send(hdl, message, websocketpp::frame::opcode::text);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSServer::onOpen(connection_hdl hdl)
|
void WSServer::onNewConnection() {
|
||||||
{
|
QWebSocket* pSocket = _wsServer->nextPendingConnection();
|
||||||
QMutexLocker locker(&_clMutex);
|
if (pSocket) {
|
||||||
_connections.insert(hdl);
|
connect(pSocket, SIGNAL(textMessageReceived(const QString&)),
|
||||||
locker.unlock();
|
this, SLOT(onTextMessageReceived(QString)));
|
||||||
|
connect(pSocket, SIGNAL(disconnected()),
|
||||||
|
this, SLOT(onSocketDisconnected()));
|
||||||
|
|
||||||
QString clientIp = getRemoteEndpoint(hdl);
|
pSocket->setProperty(PROP_AUTHENTICATED, false);
|
||||||
notifyConnection(clientIp);
|
|
||||||
blog(LOG_INFO, "new client connection from %s", clientIp.toUtf8().constData());
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSServer::onMessage(connection_hdl hdl, server::message_ptr message)
|
|
||||||
{
|
|
||||||
auto opcode = message->get_opcode();
|
|
||||||
if (opcode != websocketpp::frame::opcode::text) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QtConcurrent::run(&_threadPool, [=]() {
|
|
||||||
std::string payload = message->get_payload();
|
|
||||||
|
|
||||||
QMutexLocker locker(&_clMutex);
|
QMutexLocker locker(&_clMutex);
|
||||||
ConnectionProperties& connProperties = _connectionProperties[hdl];
|
_clients << pSocket;
|
||||||
locker.unlock();
|
locker.unlock();
|
||||||
|
|
||||||
WSRequestHandler handler(connProperties);
|
QHostAddress clientAddr = pSocket->peerAddress();
|
||||||
std::string response = handler.processIncomingMessage(payload);
|
QString clientIp = Utils::FormatIPAddress(clientAddr);
|
||||||
|
|
||||||
_server.send(hdl, response, websocketpp::frame::opcode::text);
|
blog(LOG_INFO, "new client connection from %s:%d",
|
||||||
});
|
clientIp.toUtf8().constData(), pSocket->peerPort());
|
||||||
}
|
|
||||||
|
|
||||||
void WSServer::onClose(connection_hdl hdl)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&_clMutex);
|
|
||||||
_connections.erase(hdl);
|
|
||||||
_connectionProperties.erase(hdl);
|
|
||||||
locker.unlock();
|
|
||||||
|
|
||||||
auto conn = _server.get_con_from_hdl(hdl);
|
|
||||||
auto localCloseCode = conn->get_local_close_code();
|
|
||||||
|
|
||||||
if (localCloseCode != websocketpp::close::status::going_away) {
|
|
||||||
QString clientIp = getRemoteEndpoint(hdl);
|
|
||||||
notifyDisconnection(clientIp);
|
|
||||||
blog(LOG_INFO, "client %s disconnected", clientIp.toUtf8().constData());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString WSServer::getRemoteEndpoint(connection_hdl hdl)
|
|
||||||
{
|
|
||||||
auto conn = _server.get_con_from_hdl(hdl);
|
|
||||||
return QString::fromStdString(conn->get_remote_endpoint());
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSServer::notifyConnection(QString clientIp)
|
|
||||||
{
|
|
||||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||||
QString title = tr("OBSWebsocket.NotifyConnect.Title");
|
QString title = tr("OBSWebsocket.NotifyConnect.Title");
|
||||||
QString msg = tr("OBSWebsocket.NotifyConnect.Message").arg(clientIp);
|
QString msg = tr("OBSWebsocket.NotifyConnect.Message")
|
||||||
|
.arg(Utils::FormatIPAddress(clientAddr));
|
||||||
obs_frontend_pop_ui_translation();
|
obs_frontend_pop_ui_translation();
|
||||||
|
|
||||||
Utils::SysTrayNotify(msg, QSystemTrayIcon::Information, title);
|
Utils::SysTrayNotify(msg, QSystemTrayIcon::Information, title);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WSServer::onTextMessageReceived(QString message) {
|
||||||
|
QWebSocket* pSocket = qobject_cast<QWebSocket*>(sender());
|
||||||
|
if (pSocket) {
|
||||||
|
WSRequestHandler handler(pSocket);
|
||||||
|
handler.processIncomingMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WSServer::onSocketDisconnected() {
|
||||||
|
QWebSocket* pSocket = qobject_cast<QWebSocket*>(sender());
|
||||||
|
if (pSocket) {
|
||||||
|
pSocket->setProperty(PROP_AUTHENTICATED, false);
|
||||||
|
|
||||||
|
QMutexLocker locker(&_clMutex);
|
||||||
|
_clients.removeAll(pSocket);
|
||||||
|
locker.unlock();
|
||||||
|
|
||||||
|
pSocket->deleteLater();
|
||||||
|
|
||||||
|
QHostAddress clientAddr = pSocket->peerAddress();
|
||||||
|
QString clientIp = Utils::FormatIPAddress(clientAddr);
|
||||||
|
|
||||||
|
blog(LOG_INFO, "client %s:%d disconnected",
|
||||||
|
clientIp.toUtf8().constData(), pSocket->peerPort());
|
||||||
|
|
||||||
void WSServer::notifyDisconnection(QString clientIp)
|
|
||||||
{
|
|
||||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||||
QString title = tr("OBSWebsocket.NotifyDisconnect.Title");
|
QString title = tr("OBSWebsocket.NotifyDisconnect.Title");
|
||||||
QString msg = tr("OBSWebsocket.NotifyDisconnect.Message").arg(clientIp);
|
QString msg = tr("OBSWebsocket.NotifyDisconnect.Message")
|
||||||
|
.arg(Utils::FormatIPAddress(clientAddr));
|
||||||
obs_frontend_pop_ui_translation();
|
obs_frontend_pop_ui_translation();
|
||||||
|
|
||||||
Utils::SysTrayNotify(msg, QSystemTrayIcon::Information, title);
|
Utils::SysTrayNotify(msg, QSystemTrayIcon::Information, title);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
obs-websocket
|
obs-websocket
|
||||||
Copyright (C) 2016-2019 Stéphane Lepin <stephane.lepin@gmail.com>
|
Copyright (C) 2016-2017 Stéphane Lepin <stephane.lepin@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -16,57 +16,37 @@ 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/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef WSSERVER_H
|
||||||
|
#define WSSERVER_H
|
||||||
|
|
||||||
#include <map>
|
#include <QObject>
|
||||||
#include <set>
|
#include <QList>
|
||||||
#include <QtCore/QObject>
|
#include <QMutex>
|
||||||
#include <QtCore/QMutex>
|
|
||||||
#include <QtCore/QSharedPointer>
|
|
||||||
#include <QtCore/QVariantHash>
|
|
||||||
#include <QtCore/QThreadPool>
|
|
||||||
|
|
||||||
#include <websocketpp/config/asio_no_tls.hpp>
|
|
||||||
#include <websocketpp/server.hpp>
|
|
||||||
|
|
||||||
#include "ConnectionProperties.h"
|
|
||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
|
QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
|
||||||
QT_FORWARD_DECLARE_CLASS(QWebSocket)
|
QT_FORWARD_DECLARE_CLASS(QWebSocket)
|
||||||
|
|
||||||
using websocketpp::connection_hdl;
|
class WSServer : public QObject {
|
||||||
|
|
||||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
|
||||||
|
|
||||||
class WSServer : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit WSServer();
|
explicit WSServer(QObject* parent = Q_NULLPTR);
|
||||||
virtual ~WSServer();
|
virtual ~WSServer();
|
||||||
void start(quint16 port);
|
void Start(quint16 port);
|
||||||
void stop();
|
void Stop();
|
||||||
void broadcast(std::string message);
|
void broadcast(QString message);
|
||||||
QThreadPool* threadPool() {
|
static WSServer* Instance;
|
||||||
return &_threadPool;
|
|
||||||
}
|
private slots:
|
||||||
|
void onNewConnection();
|
||||||
|
void onTextMessageReceived(QString message);
|
||||||
|
void onSocketDisconnected();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onOpen(connection_hdl hdl);
|
QWebSocketServer* _wsServer;
|
||||||
void onMessage(connection_hdl hdl, server::message_ptr message);
|
QList<QWebSocket*> _clients;
|
||||||
void onClose(connection_hdl hdl);
|
|
||||||
|
|
||||||
QString getRemoteEndpoint(connection_hdl hdl);
|
|
||||||
void notifyConnection(QString clientIp);
|
|
||||||
void notifyDisconnection(QString clientIp);
|
|
||||||
|
|
||||||
server _server;
|
|
||||||
quint16 _serverPort;
|
|
||||||
std::set<connection_hdl, std::owner_less<connection_hdl>> _connections;
|
|
||||||
std::map<connection_hdl, ConnectionProperties, std::owner_less<connection_hdl>> _connectionProperties;
|
|
||||||
QMutex _clMutex;
|
QMutex _clMutex;
|
||||||
QThreadPool _threadPool;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // WSSERVER_H
|
||||||
|
@ -41,7 +41,7 @@ SettingsDialog::SettingsDialog(QWidget* parent) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SettingsDialog::showEvent(QShowEvent* event) {
|
void SettingsDialog::showEvent(QShowEvent* event) {
|
||||||
auto conf = GetConfig();
|
Config* conf = Config::Current();
|
||||||
|
|
||||||
ui->serverEnabled->setChecked(conf->ServerEnabled);
|
ui->serverEnabled->setChecked(conf->ServerEnabled);
|
||||||
ui->serverPort->setValue(conf->ServerPort);
|
ui->serverPort->setValue(conf->ServerPort);
|
||||||
@ -68,7 +68,7 @@ void SettingsDialog::AuthCheckboxChanged() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SettingsDialog::FormAccepted() {
|
void SettingsDialog::FormAccepted() {
|
||||||
auto conf = GetConfig();
|
Config* conf = Config::Current();
|
||||||
|
|
||||||
conf->ServerEnabled = ui->serverEnabled->isChecked();
|
conf->ServerEnabled = ui->serverEnabled->isChecked();
|
||||||
conf->ServerPort = ui->serverPort->value();
|
conf->ServerPort = ui->serverPort->value();
|
||||||
@ -81,7 +81,7 @@ void SettingsDialog::FormAccepted() {
|
|||||||
conf->SetPassword(ui->password->text());
|
conf->SetPassword(ui->password->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetConfig()->Secret.isEmpty())
|
if (!Config::Current()->Secret.isEmpty())
|
||||||
conf->AuthRequired = true;
|
conf->AuthRequired = true;
|
||||||
else
|
else
|
||||||
conf->AuthRequired = false;
|
conf->AuthRequired = false;
|
||||||
@ -93,12 +93,10 @@ void SettingsDialog::FormAccepted() {
|
|||||||
|
|
||||||
conf->Save();
|
conf->Save();
|
||||||
|
|
||||||
auto server = GetServer();
|
if (conf->ServerEnabled)
|
||||||
if (conf->ServerEnabled) {
|
WSServer::Instance->Start(conf->ServerPort);
|
||||||
server->start(conf->ServerPort);
|
else
|
||||||
} else {
|
WSServer::Instance->Stop();
|
||||||
server->stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsDialog::~SettingsDialog() {
|
SettingsDialog::~SettingsDialog() {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
obs-websocket
|
obs-websocket
|
||||||
Copyright (C) 2016-2019 Stéphane Lepin <stephane.lepin@gmail.com>
|
Copyright (C) 2016-2017 Stéphane Lepin <stephane.lepin@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -16,9 +16,10 @@ 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/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef SETTINGSDIALOG_H
|
||||||
|
#define SETTINGSDIALOG_H
|
||||||
|
|
||||||
#include <QtWidgets/QDialog>
|
#include <QDialog>
|
||||||
|
|
||||||
#include "ui_settings-dialog.h"
|
#include "ui_settings-dialog.h"
|
||||||
|
|
||||||
@ -39,3 +40,5 @@ private Q_SLOTS:
|
|||||||
private:
|
private:
|
||||||
Ui::SettingsDialog* ui;
|
Ui::SettingsDialog* ui;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // SETTINGSDIALOG_H
|
||||||
|
@ -18,10 +18,9 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include <obs-module.h>
|
#include <obs-module.h>
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
|
#include <QAction>
|
||||||
#include <QtCore/QTimer>
|
#include <QMainWindow>
|
||||||
#include <QtWidgets/QAction>
|
#include <QTimer>
|
||||||
#include <QtWidgets/QMainWindow>
|
|
||||||
|
|
||||||
#include "obs-websocket.h"
|
#include "obs-websocket.h"
|
||||||
#include "WSServer.h"
|
#include "WSServer.h"
|
||||||
@ -38,9 +37,7 @@ void ___output_dummy_addref(obs_output_t*) {}
|
|||||||
OBS_DECLARE_MODULE()
|
OBS_DECLARE_MODULE()
|
||||||
OBS_MODULE_USE_DEFAULT_LOCALE("obs-websocket", "en-US")
|
OBS_MODULE_USE_DEFAULT_LOCALE("obs-websocket", "en-US")
|
||||||
|
|
||||||
ConfigPtr _config;
|
SettingsDialog* settings_dialog;
|
||||||
WSServerPtr _server;
|
|
||||||
WSEventsPtr _eventsSystem;
|
|
||||||
|
|
||||||
bool obs_module_load(void) {
|
bool obs_module_load(void) {
|
||||||
blog(LOG_INFO, "you can haz websockets (version %s)", OBS_WEBSOCKET_VERSION);
|
blog(LOG_INFO, "you can haz websockets (version %s)", OBS_WEBSOCKET_VERSION);
|
||||||
@ -48,32 +45,28 @@ bool obs_module_load(void) {
|
|||||||
QT_VERSION_STR, qVersion());
|
QT_VERSION_STR, qVersion());
|
||||||
|
|
||||||
// Core setup
|
// Core setup
|
||||||
_config = ConfigPtr(new Config());
|
Config* config = Config::Current();
|
||||||
_config->MigrateFromGlobalSettings(); // TODO remove this on the next minor jump
|
config->Load();
|
||||||
_config->Load();
|
|
||||||
|
|
||||||
_server = WSServerPtr(new WSServer());
|
WSServer::Instance = new WSServer();
|
||||||
_eventsSystem = WSEventsPtr(new WSEvents(_server));
|
WSEvents::Instance = new WSEvents(WSServer::Instance);
|
||||||
|
|
||||||
if (_config->ServerEnabled) {
|
if (config->ServerEnabled)
|
||||||
_server->start(_config->ServerPort);
|
WSServer::Instance->Start(config->ServerPort);
|
||||||
}
|
|
||||||
|
|
||||||
// UI setup
|
// UI setup
|
||||||
|
QAction* menu_action = (QAction*)obs_frontend_add_tools_menu_qaction(
|
||||||
|
obs_module_text("OBSWebsocket.Menu.SettingsItem"));
|
||||||
|
|
||||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||||
QMainWindow* mainWindow = (QMainWindow*)obs_frontend_get_main_window();
|
QMainWindow* main_window = (QMainWindow*)obs_frontend_get_main_window();
|
||||||
SettingsDialog* settingsDialog = new SettingsDialog(mainWindow);
|
settings_dialog = new SettingsDialog(main_window);
|
||||||
obs_frontend_pop_ui_translation();
|
obs_frontend_pop_ui_translation();
|
||||||
|
|
||||||
const char* menuActionText =
|
auto menu_cb = [] {
|
||||||
obs_module_text("OBSWebsocket.Settings.DialogTitle");
|
settings_dialog->ToggleShowHide();
|
||||||
QAction* menuAction =
|
};
|
||||||
(QAction*)obs_frontend_add_tools_menu_qaction(menuActionText);
|
menu_action->connect(menu_action, &QAction::triggered, menu_cb);
|
||||||
QObject::connect(menuAction, &QAction::triggered, [settingsDialog] {
|
|
||||||
// The settings dialog belongs to the main window. Should be ok
|
|
||||||
// to pass the pointer to this QAction belonging to the main window
|
|
||||||
settingsDialog->ToggleShowHide();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Loading finished
|
// Loading finished
|
||||||
blog(LOG_INFO, "module loaded!");
|
blog(LOG_INFO, "module loaded!");
|
||||||
@ -82,23 +75,6 @@ bool obs_module_load(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void obs_module_unload() {
|
void obs_module_unload() {
|
||||||
_server->stop();
|
|
||||||
|
|
||||||
_eventsSystem.reset();
|
|
||||||
_server.reset();
|
|
||||||
_config.reset();
|
|
||||||
|
|
||||||
blog(LOG_INFO, "goodbye!");
|
blog(LOG_INFO, "goodbye!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigPtr GetConfig() {
|
|
||||||
return _config;
|
|
||||||
}
|
|
||||||
|
|
||||||
WSServerPtr GetServer() {
|
|
||||||
return _server;
|
|
||||||
}
|
|
||||||
|
|
||||||
WSEventsPtr GetEventsSystem() {
|
|
||||||
return _eventsSystem;
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
obs-websocket
|
obs-websocket
|
||||||
Copyright (C) 2016-2019 Stéphane Lepin <stephane.lepin@gmail.com>
|
Copyright (C) 2016-2017 Stéphane Lepin <stephane.lepin@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -16,10 +16,10 @@ 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/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef OBSWEBSOCKET_H
|
||||||
|
#define OBSWEBSOCKET_H
|
||||||
|
|
||||||
#include <obs.hpp>
|
#include <obs.hpp>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
void ___source_dummy_addref(obs_source_t*);
|
void ___source_dummy_addref(obs_source_t*);
|
||||||
void ___sceneitem_dummy_addref(obs_sceneitem_t*);
|
void ___sceneitem_dummy_addref(obs_sceneitem_t*);
|
||||||
@ -38,19 +38,9 @@ using OBSDataArrayAutoRelease =
|
|||||||
using OBSOutputAutoRelease =
|
using OBSOutputAutoRelease =
|
||||||
OBSRef<obs_output_t*, ___output_dummy_addref, obs_output_release>;
|
OBSRef<obs_output_t*, ___output_dummy_addref, obs_output_release>;
|
||||||
|
|
||||||
class Config;
|
#define PROP_AUTHENTICATED "wsclient_authenticated"
|
||||||
typedef std::shared_ptr<Config> ConfigPtr;
|
#define OBS_WEBSOCKET_VERSION "4.5.1"
|
||||||
|
|
||||||
class WSServer;
|
|
||||||
typedef std::shared_ptr<WSServer> WSServerPtr;
|
|
||||||
|
|
||||||
class WSEvents;
|
|
||||||
typedef std::shared_ptr<WSEvents> WSEventsPtr;
|
|
||||||
|
|
||||||
ConfigPtr GetConfig();
|
|
||||||
WSServerPtr GetServer();
|
|
||||||
WSEventsPtr GetEventsSystem();
|
|
||||||
|
|
||||||
#define OBS_WEBSOCKET_VERSION "4.6.1"
|
|
||||||
|
|
||||||
#define blog(level, msg, ...) blog(level, "[obs-websocket] " msg, ##__VA_ARGS__)
|
#define blog(level, msg, ...) blog(level, "[obs-websocket] " msg, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#endif // OBSWEBSOCKET_H
|
||||||
|
Reference in New Issue
Block a user