mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
Compare commits
66 Commits
Author | SHA1 | Date | |
---|---|---|---|
974d6b48b2 | |||
db2b1e2dc7 | |||
98656b5d2f | |||
3c7570d814 | |||
fc3e30a826 | |||
2f0476b43c | |||
e310c7d744 | |||
8a649b89c8 | |||
95f52987ef | |||
82b8c66d51 | |||
83fb1843ee | |||
58b10069ab | |||
9cda739672 | |||
276bba050b | |||
147e49b362 | |||
bc338c1f4a | |||
e8fbb18a71 | |||
682c349831 | |||
14b311f6ab | |||
8a40f355c8 | |||
ae2f90c5c2 | |||
7aff773e2c | |||
0cdfa6e7f6 | |||
fc637eef6d | |||
b4c3141170 | |||
41257f7af5 | |||
b204f3ec90 | |||
b4926b3535 | |||
77d63e9848 | |||
94dcd58c2e | |||
689ce16f1b | |||
edc64b8336 | |||
03db5bfd8d | |||
9ad340ab02 | |||
962e26040d | |||
b07884c1da | |||
bad0fb62ed | |||
28e522ce97 | |||
c206cdfa4c | |||
c31ec077f5 | |||
afc6a60746 | |||
0a495b67e6 | |||
37ea7073d5 | |||
feaeef5a70 | |||
5586670d38 | |||
65a9139ffe | |||
3d76f078cd | |||
a1de1b11bc | |||
b5a3e3a4f0 | |||
d7b0ad4916 | |||
2a80a6b217 | |||
9df72f54d5 | |||
ef75ca36c9 | |||
84c0b698f5 | |||
3d9a4ef1e6 | |||
cf51fdceef | |||
85a52ab01f | |||
f2792c0b40 | |||
97109087a4 | |||
953f07f21f | |||
03f1035690 | |||
a561c60f7e | |||
7963b328f9 | |||
3b7e216409 | |||
9ae43a6f75 | |||
6b86de1fb9 |
9
.editorconfig
Normal file
9
.editorconfig
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[*]
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{c,cpp,h,hpp}]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[*.{yml,yaml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "deps/mbedtls"]
|
|
||||||
path = deps/mbedtls
|
|
||||||
url = https://github.com/ARMmbed/mbedtls
|
|
@ -34,7 +34,7 @@ matrix:
|
|||||||
|
|
||||||
- os: osx
|
- os: osx
|
||||||
env: _macos_build
|
env: _macos_build
|
||||||
osx_image: xcode8.3
|
osx_image: xcode9.4
|
||||||
before_install:
|
before_install:
|
||||||
- "./CI/install-dependencies-macos.sh"
|
- "./CI/install-dependencies-macos.sh"
|
||||||
- "./CI/install-build-obs-macos.sh"
|
- "./CI/install-build-obs-macos.sh"
|
||||||
|
@ -1,8 +1,22 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -ex
|
|
||||||
|
OSTYPE=$(uname)
|
||||||
|
|
||||||
|
if [ "${OSTYPE}" != "Darwin" ]; then
|
||||||
|
echo "[obs-websocket - Error] macOS build script can be run on Darwin-type OS only."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
HAS_CMAKE=$(type cmake 2>/dev/null)
|
||||||
|
|
||||||
|
if [ "${HAS_CMAKE}" = "" ]; then
|
||||||
|
echo "[obs-websocket - Error] CMake not installed - please run 'install-dependencies-macos.sh' first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
#export QT_PREFIX="$(find /usr/local/Cellar/qt5 -d 1 | tail -n 1)"
|
#export QT_PREFIX="$(find /usr/local/Cellar/qt5 -d 1 | tail -n 1)"
|
||||||
|
|
||||||
|
echo "[obs-websocket] Building 'obs-websocket' for macOS."
|
||||||
mkdir -p build && cd build
|
mkdir -p build && cd build
|
||||||
cmake .. \
|
cmake .. \
|
||||||
-DQTDIR=/usr/local/opt/qt \
|
-DQTDIR=/usr/local/opt/qt \
|
||||||
|
@ -15,7 +15,7 @@ if git diff --quiet; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "4.3-maintenance" ]; then
|
if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "4.x-current" ]; then
|
||||||
echo "-- Skipping documentation deployment because this is either a pull request or a non-master branch."
|
echo "-- Skipping documentation deployment because this is either a pull request or a non-master branch."
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
@ -1,13 +1,34 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -ex
|
|
||||||
|
OSTYPE=$(uname)
|
||||||
|
|
||||||
|
if [ "${OSTYPE}" != "Darwin" ]; then
|
||||||
|
echo "[obs-websocket - Error] macOS obs-studio build script can be run on Darwin-type OS only."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
HAS_CMAKE=$(type cmake 2>/dev/null)
|
||||||
|
HAS_GIT=$(type git 2>/dev/null)
|
||||||
|
|
||||||
|
if [ "${HAS_CMAKE}" = "" ]; then
|
||||||
|
echo "[obs-websocket - Error] CMake not installed - please run 'install-dependencies-macos.sh' first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${HAS_GIT}" = "" ]; then
|
||||||
|
echo "[obs-websocket - Error] Git not installed - please install Xcode developer tools or via Homebrew."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Build obs-studio
|
# Build obs-studio
|
||||||
cd ..
|
cd ..
|
||||||
|
echo "[obs-websocket] Cloning obs-studio from GitHub.."
|
||||||
git clone https://github.com/obsproject/obs-studio
|
git clone https://github.com/obsproject/obs-studio
|
||||||
cd obs-studio
|
cd obs-studio
|
||||||
OBSLatestTag=$(git describe --tags --abbrev=0)
|
OBSLatestTag=$(git describe --tags --abbrev=0)
|
||||||
git checkout $OBSLatestTag
|
git checkout $OBSLatestTag
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
|
echo "[obs-websocket] Building obs-studio.."
|
||||||
cmake .. \
|
cmake .. \
|
||||||
-DDISABLE_PLUGINS=true \
|
-DDISABLE_PLUGINS=true \
|
||||||
-DCMAKE_PREFIX_PATH=/usr/local/opt/qt/lib/cmake \
|
-DCMAKE_PREFIX_PATH=/usr/local/opt/qt/lib/cmake \
|
||||||
|
@ -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 15 2017" -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 15 2017 Win64" -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%^)...
|
||||||
|
@ -1,15 +1,59 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -ex
|
|
||||||
|
OSTYPE=$(uname)
|
||||||
|
|
||||||
|
if [ "${OSTYPE}" != "Darwin" ]; then
|
||||||
|
echo "[obs-websocket - Error] macOS install dependencies script can be run on Darwin-type OS only."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
HAS_BREW=$(type brew 2>/dev/null)
|
||||||
|
|
||||||
|
if [ "${HAS_BREW}" = "" ]; then
|
||||||
|
echo "[obs-websocket - Error] Please install Homebrew (https://www.brew.sh/) to build obs-websocket on macOS."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# OBS Studio deps
|
# OBS Studio deps
|
||||||
brew update
|
echo "[obs-websocket] Updating Homebrew.."
|
||||||
brew install ffmpeg
|
brew update >/dev/null
|
||||||
brew install libav
|
echo "[obs-websocket] Checking installed Homebrew formulas.."
|
||||||
|
BREW_PACKAGES=$(brew list)
|
||||||
|
BREW_DEPENDENCIES="ffmpeg libav cmake"
|
||||||
|
|
||||||
|
for DEPENDENCY in ${BREW_DEPENDENCIES}; do
|
||||||
|
if echo "${BREW_PACKAGES}" | grep -q "^${DEPENDENCY}\$"; then
|
||||||
|
echo "[obs-websocket] Upgrading OBS-Studio dependency '${DEPENDENCY}'.."
|
||||||
|
brew upgrade ${DEPENDENCY} 2>/dev/null
|
||||||
|
else
|
||||||
|
echo "[obs-websocket] Installing OBS-Studio dependency '${DEPENDENCY}'.."
|
||||||
|
brew install ${DEPENDENCY} 2>/dev/null
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# qtwebsockets deps
|
# qtwebsockets deps
|
||||||
# qt latest
|
echo "[obs-websocket] Installing obs-websocket dependency 'QT 5.10.1'.."
|
||||||
brew install qt5
|
# =!= NOTICE =!=
|
||||||
|
# When building QT5 from sources on macOS 10.13+, use local qt5 formula:
|
||||||
|
# brew install ./CI/macos/qt.rb
|
||||||
|
# Pouring from the bottle is much quicker though, so use bottle for now.
|
||||||
|
# =!= NOTICE =!=
|
||||||
|
|
||||||
# Packages app
|
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/9a70413d137839de0054571e5f85fd07ee400955/Formula/qt.rb
|
||||||
wget --quiet --retry-connrefused --waitretry=1 https://s3-us-west-2.amazonaws.com/obs-nightly/Packages.pkg
|
|
||||||
|
# Pin this version of QT5 to avoid `brew upgrade`
|
||||||
|
# upgrading it to incompatible version
|
||||||
|
brew pin qt
|
||||||
|
|
||||||
|
# Fetch and install Packages app
|
||||||
|
# =!= NOTICE =!=
|
||||||
|
# Installs a LaunchDaemon under /Library/LaunchDaemons/fr.whitebox.packages.build.dispatcher.plist
|
||||||
|
# =!= NOTICE =!=
|
||||||
|
|
||||||
|
HAS_PACKAGES=$(type packagesbuild 2>/dev/null)
|
||||||
|
|
||||||
|
if [ "${HAS_PACKAGES}" = "" ]; then
|
||||||
|
echo "[obs-websocket] Installing Packaging app (might require password due to 'sudo').."
|
||||||
|
curl -o './Packages.pkg' --retry-connrefused -s --retry-delay 1 'https://s3-us-west-2.amazonaws.com/obs-nightly/Packages.pkg'
|
||||||
sudo installer -pkg ./Packages.pkg -target /
|
sudo installer -pkg ./Packages.pkg -target /
|
||||||
|
fi
|
@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
REM Set default values to use AppVeyor's built-in Qt.
|
REM Set default values to use AppVeyor's built-in Qt.
|
||||||
set QTDIR32=C:\Qt\5.10.1\msvc2015
|
set QTDIR32=C:\Qt\5.10.1\msvc2015
|
||||||
set QTDIR64=C:\Qt\5.10.1\msvc2017_64
|
set QTDIR64=C:\Qt\5.10.1\msvc2015_64
|
||||||
set QTCompileVersion=5.10.1
|
set QTCompileVersion=5.10.1
|
||||||
|
@ -635,7 +635,7 @@
|
|||||||
<key>OVERWRITE_PERMISSIONS</key>
|
<key>OVERWRITE_PERMISSIONS</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>VERSION</key>
|
<key>VERSION</key>
|
||||||
<string>4.4.0</string>
|
<string>4.5.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>PROJECT_COMMENTS</key>
|
<key>PROJECT_COMMENTS</key>
|
||||||
<dict>
|
<dict>
|
||||||
|
163
CI/macos/qt.rb
Normal file
163
CI/macos/qt.rb
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
# Patches for Qt must be at the very least submitted to Qt's Gerrit codereview
|
||||||
|
# rather than their bug-report Jira. The latter is rarely reviewed by Qt.
|
||||||
|
class Qt < Formula
|
||||||
|
desc "Cross-platform application and UI framework"
|
||||||
|
homepage "https://www.qt.io/"
|
||||||
|
url "https://download.qt.io/archive/qt/5.10/5.10.1/single/qt-everywhere-src-5.10.1.tar.xz"
|
||||||
|
mirror "https://mirrorservice.org/sites/download.qt-project.org/official_releases/qt/5.10/5.10.1/single/qt-everywhere-src-5.10.1.tar.xz"
|
||||||
|
sha256 "05ffba7b811b854ed558abf2be2ddbd3bb6ddd0b60ea4b5da75d277ac15e740a"
|
||||||
|
head "https://code.qt.io/qt/qt5.git", :branch => "5.10.1", :shallow => false
|
||||||
|
|
||||||
|
bottle do
|
||||||
|
sha256 "8b4bad005596a5f8790150fe455db998ac2406f4e0f04140d6656205d844d266" => :high_sierra
|
||||||
|
sha256 "9c488554935fb573554a4e36d36d3c81e47245b7fefc4b61edef894e67ba1740" => :sierra
|
||||||
|
sha256 "c0407afba5951df6cc4c6f6c1c315972bd41c99cecb4e029919c4c15ab6f7bdc" => :el_capitan
|
||||||
|
end
|
||||||
|
|
||||||
|
keg_only "Qt 5 has CMake issues when linked"
|
||||||
|
|
||||||
|
option "with-docs", "Build documentation"
|
||||||
|
option "with-examples", "Build examples"
|
||||||
|
|
||||||
|
deprecated_option "with-mysql" => "with-mysql-client"
|
||||||
|
|
||||||
|
# OS X 10.7 Lion is still supported in Qt 5.5, but is no longer a reference
|
||||||
|
# configuration and thus untested in practice. Builds on OS X 10.7 have been
|
||||||
|
# reported to fail: <https://github.com/Homebrew/homebrew/issues/45284>.
|
||||||
|
depends_on :macos => :mountain_lion
|
||||||
|
|
||||||
|
depends_on "pkg-config" => :build
|
||||||
|
depends_on :xcode => :build
|
||||||
|
depends_on "mysql-client" => :optional
|
||||||
|
depends_on "postgresql" => :optional
|
||||||
|
|
||||||
|
# Restore `.pc` files for framework-based build of Qt 5 on OS X. This
|
||||||
|
# partially reverts <https://codereview.qt-project.org/#/c/140954/> merged
|
||||||
|
# between the 5.5.1 and 5.6.0 releases. (Remove this as soon as feasible!)
|
||||||
|
#
|
||||||
|
# Core formulae known to fail without this patch (as of 2016-10-15):
|
||||||
|
# * gnuplot (with `--with-qt` option)
|
||||||
|
# * mkvtoolnix (with `--with-qt` option, silent build failure)
|
||||||
|
# * poppler (with `--with-qt` option)
|
||||||
|
patch do
|
||||||
|
url "https://raw.githubusercontent.com/Homebrew/formula-patches/e8fe6567/qt5/restore-pc-files.patch"
|
||||||
|
sha256 "48ff18be2f4050de7288bddbae7f47e949512ac4bcd126c2f504be2ac701158b"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fix compile error on macOS 10.13 around QFixed:
|
||||||
|
# https://github.com/Homebrew/homebrew-core/issues/27095
|
||||||
|
# https://bugreports.qt.io/browse/QTBUG-67545
|
||||||
|
patch do
|
||||||
|
url "https://raw.githubusercontent.com/z00m1n/formula-patches/0de0e229/qt/QTBUG-67545.patch"
|
||||||
|
sha256 "4a115097c7582c7dce4207f5500d13feb8c990eb8a05a43f41953985976ebe6c"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fix compile error on macOS 10.13 caused by qtlocation dependency
|
||||||
|
# mapbox-gl-native using Boost 1.62.0 does not build with C++ 17:
|
||||||
|
# https://github.com/Homebrew/homebrew-core/issues/27095
|
||||||
|
# https://bugreports.qt.io/browse/QTBUG-67810
|
||||||
|
patch do
|
||||||
|
url "https://raw.githubusercontent.com/z00m1n/formula-patches/a1a1f0dd/qt/QTBUG-67810.patch"
|
||||||
|
sha256 "8ee0bf71df1043f08ebae3aa35036be29c4d9ebff8a27e3b0411a6bd635e9382"
|
||||||
|
end
|
||||||
|
|
||||||
|
def install
|
||||||
|
args = %W[
|
||||||
|
-verbose
|
||||||
|
-prefix #{prefix}
|
||||||
|
-release
|
||||||
|
-opensource -confirm-license
|
||||||
|
-system-zlib
|
||||||
|
-qt-libpng
|
||||||
|
-qt-libjpeg
|
||||||
|
-qt-freetype
|
||||||
|
-qt-pcre
|
||||||
|
-nomake tests
|
||||||
|
-no-rpath
|
||||||
|
-pkg-config
|
||||||
|
-dbus-runtime
|
||||||
|
-no-assimp
|
||||||
|
]
|
||||||
|
|
||||||
|
args << "-nomake" << "examples" if build.without? "examples"
|
||||||
|
|
||||||
|
if build.with? "mysql-client"
|
||||||
|
args << "-plugin-sql-mysql"
|
||||||
|
(buildpath/"brew_shim/mysql_config").write <<~EOS
|
||||||
|
#!/bin/sh
|
||||||
|
if [ x"$1" = x"--libs" ]; then
|
||||||
|
mysql_config --libs | sed "s/-lssl -lcrypto//"
|
||||||
|
else
|
||||||
|
exec mysql_config "$@"
|
||||||
|
fi
|
||||||
|
EOS
|
||||||
|
chmod 0755, "brew_shim/mysql_config"
|
||||||
|
args << "-mysql_config" << buildpath/"brew_shim/mysql_config"
|
||||||
|
end
|
||||||
|
|
||||||
|
args << "-plugin-sql-psql" if build.with? "postgresql"
|
||||||
|
|
||||||
|
system "./configure", *args
|
||||||
|
system "make"
|
||||||
|
ENV.deparallelize
|
||||||
|
system "make", "install"
|
||||||
|
|
||||||
|
if build.with? "docs"
|
||||||
|
system "make", "docs"
|
||||||
|
system "make", "install_docs"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Some config scripts will only find Qt in a "Frameworks" folder
|
||||||
|
frameworks.install_symlink Dir["#{lib}/*.framework"]
|
||||||
|
|
||||||
|
# The pkg-config files installed suggest that headers can be found in the
|
||||||
|
# `include` directory. Make this so by creating symlinks from `include` to
|
||||||
|
# the Frameworks' Headers folders.
|
||||||
|
Pathname.glob("#{lib}/*.framework/Headers") do |path|
|
||||||
|
include.install_symlink path => path.parent.basename(".framework")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Move `*.app` bundles into `libexec` to expose them to `brew linkapps` and
|
||||||
|
# because we don't like having them in `bin`.
|
||||||
|
# (Note: This move breaks invocation of Assistant via the Help menu
|
||||||
|
# of both Designer and Linguist as that relies on Assistant being in `bin`.)
|
||||||
|
libexec.mkpath
|
||||||
|
Pathname.glob("#{bin}/*.app") { |app| mv app, libexec }
|
||||||
|
end
|
||||||
|
|
||||||
|
def caveats; <<~EOS
|
||||||
|
We agreed to the Qt opensource license for you.
|
||||||
|
If this is unacceptable you should uninstall.
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
test do
|
||||||
|
(testpath/"hello.pro").write <<~EOS
|
||||||
|
QT += core
|
||||||
|
QT -= gui
|
||||||
|
TARGET = hello
|
||||||
|
CONFIG += console
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
TEMPLATE = app
|
||||||
|
SOURCES += main.cpp
|
||||||
|
EOS
|
||||||
|
|
||||||
|
(testpath/"main.cpp").write <<~EOS
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication a(argc, argv);
|
||||||
|
qDebug() << "Hello World!";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EOS
|
||||||
|
|
||||||
|
system bin/"qmake", testpath/"hello.pro"
|
||||||
|
system "make"
|
||||||
|
assert_predicate testpath/"hello", :exist?
|
||||||
|
assert_predicate testpath/"main.o", :exist?
|
||||||
|
system "./hello"
|
||||||
|
end
|
||||||
|
end
|
@ -2,8 +2,15 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "-- Preparing package build"
|
OSTYPE=$(uname)
|
||||||
export QT_CELLAR_PREFIX="$(find /usr/local/Cellar/qt -d 1 | sort -t '.' -k 1,1n -k 2,2n -k 3,3n | tail -n 1)"
|
|
||||||
|
if [ "${OSTYPE}" != "Darwin" ]; then
|
||||||
|
echo "[obs-websocket - Error] macOS package script can be run on Darwin-type OS only."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
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 WS_LIB="/usr/local/opt/qt/lib/QtWebSockets.framework/QtWebSockets"
|
export WS_LIB="/usr/local/opt/qt/lib/QtWebSockets.framework/QtWebSockets"
|
||||||
export NET_LIB="/usr/local/opt/qt/lib/QtNetwork.framework/QtNetwork"
|
export NET_LIB="/usr/local/opt/qt/lib/QtNetwork.framework/QtNetwork"
|
||||||
@ -20,20 +27,20 @@ fi
|
|||||||
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 "-- Copying Qt dependencies"
|
echo "[obs-websocket] Copying Qt dependencies"
|
||||||
if [ ! -f ./build/$(basename $WS_LIB) ]; then cp $WS_LIB ./build; fi
|
if [ ! -f ./build/$(basename $WS_LIB) ]; then cp $WS_LIB ./build; fi
|
||||||
if [ ! -f ./build/$(basename $NET_LIB) ]; then cp $NET_LIB ./build; fi
|
if [ ! -f ./build/$(basename $NET_LIB) ]; then cp $NET_LIB ./build; fi
|
||||||
|
|
||||||
chmod +rw ./build/QtWebSockets ./build/QtNetwork
|
chmod +rw ./build/QtWebSockets ./build/QtNetwork
|
||||||
|
|
||||||
echo "-- Modifying QtNetwork"
|
echo "[obs-websocket] Modifying QtNetwork"
|
||||||
install_name_tool \
|
install_name_tool \
|
||||||
-id @rpath/QtNetwork \
|
-id @rpath/QtNetwork \
|
||||||
-change /usr/local/opt/qt/lib/QtNetwork.framework/Versions/5/QtNetwork @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 \
|
-change $QT_CELLAR_PREFIX/lib/QtCore.framework/Versions/5/QtCore @rpath/QtCore \
|
||||||
./build/QtNetwork
|
./build/QtNetwork
|
||||||
|
|
||||||
echo "-- Modifying QtWebSockets"
|
echo "[obs-websocket] Modifying QtWebSockets"
|
||||||
install_name_tool \
|
install_name_tool \
|
||||||
-id @rpath/QtWebSockets \
|
-id @rpath/QtWebSockets \
|
||||||
-change /usr/local/opt/qt/lib/QtWebSockets.framework/Versions/5/QtWebSockets @rpath/QtWebSockets \
|
-change /usr/local/opt/qt/lib/QtWebSockets.framework/Versions/5/QtWebSockets @rpath/QtWebSockets \
|
||||||
@ -41,7 +48,7 @@ install_name_tool \
|
|||||||
-change $QT_CELLAR_PREFIX/lib/QtCore.framework/Versions/5/QtCore @rpath/QtCore \
|
-change $QT_CELLAR_PREFIX/lib/QtCore.framework/Versions/5/QtCore @rpath/QtCore \
|
||||||
./build/QtWebSockets
|
./build/QtWebSockets
|
||||||
|
|
||||||
echo "-- 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/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 \
|
||||||
@ -51,18 +58,18 @@ install_name_tool \
|
|||||||
./build/obs-websocket.so
|
./build/obs-websocket.so
|
||||||
|
|
||||||
# Check if replacement worked
|
# Check if replacement worked
|
||||||
echo "-- Dependencies for QtNetwork"
|
echo "[obs-websocket] Dependencies for QtNetwork"
|
||||||
otool -L ./build/QtNetwork
|
otool -L ./build/QtNetwork
|
||||||
echo "-- Dependencies for QtWebSockets"
|
echo "[obs-websocket] Dependencies for QtWebSockets"
|
||||||
otool -L ./build/QtWebSockets
|
otool -L ./build/QtWebSockets
|
||||||
echo "-- 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
|
chmod -w ./build/QtWebSockets ./build/QtNetwork
|
||||||
|
|
||||||
echo "-- Actual package build"
|
echo "[obs-websocket] Actual package build"
|
||||||
packagesbuild ./CI/macos/obs-websocket.pkgproj
|
packagesbuild ./CI/macos/obs-websocket.pkgproj
|
||||||
|
|
||||||
echo "-- Renaming obs-websocket.pkg to $FILENAME"
|
echo "[obs-websocket] Renaming obs-websocket.pkg to $FILENAME"
|
||||||
mv ./release/obs-websocket.pkg ./release/$FILENAME
|
mv ./release/obs-websocket.pkg ./release/$FILENAME
|
||||||
cp ./release/$FILENAME ./release/$LATEST_FILENAME
|
cp ./release/$FILENAME ./release/$LATEST_FILENAME
|
||||||
|
@ -15,9 +15,6 @@ find_package(Qt5Core REQUIRED)
|
|||||||
find_package(Qt5WebSockets REQUIRED)
|
find_package(Qt5WebSockets REQUIRED)
|
||||||
find_package(Qt5Widgets REQUIRED)
|
find_package(Qt5Widgets REQUIRED)
|
||||||
|
|
||||||
add_subdirectory(deps/mbedtls EXCLUDE_FROM_ALL)
|
|
||||||
set(ENABLE_PROGRAMS false)
|
|
||||||
|
|
||||||
set(obs-websocket_SOURCES
|
set(obs-websocket_SOURCES
|
||||||
src/obs-websocket.cpp
|
src/obs-websocket.cpp
|
||||||
src/WSServer.cpp
|
src/WSServer.cpp
|
||||||
@ -52,22 +49,17 @@ add_library(obs-websocket MODULE
|
|||||||
${obs-websocket_SOURCES}
|
${obs-websocket_SOURCES}
|
||||||
${obs-websocket_HEADERS})
|
${obs-websocket_HEADERS})
|
||||||
|
|
||||||
add_dependencies(obs-websocket mbedcrypto)
|
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
"${LIBOBS_INCLUDE_DIR}/../UI/obs-frontend-api"
|
"${LIBOBS_INCLUDE_DIR}/../UI/obs-frontend-api"
|
||||||
${Qt5Core_INCLUDES}
|
${Qt5Core_INCLUDES}
|
||||||
${Qt5WebSockets_INCLUDES}
|
${Qt5WebSockets_INCLUDES}
|
||||||
${Qt5Widgets_INCLUDES}
|
${Qt5Widgets_INCLUDES})
|
||||||
${mbedcrypto_INCLUDES}
|
|
||||||
"${CMAKE_SOURCE_DIR}/deps/mbedtls/include")
|
|
||||||
|
|
||||||
target_link_libraries(obs-websocket
|
target_link_libraries(obs-websocket
|
||||||
libobs
|
libobs
|
||||||
Qt5::Core
|
Qt5::Core
|
||||||
Qt5::WebSockets
|
Qt5::WebSockets
|
||||||
Qt5::Widgets
|
Qt5::Widgets)
|
||||||
mbedcrypto)
|
|
||||||
|
|
||||||
# --- End of section ---
|
# --- End of section ---
|
||||||
|
|
||||||
@ -165,7 +157,6 @@ endif()
|
|||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||||
|
|
||||||
target_compile_options(mbedcrypto PRIVATE -fPIC)
|
|
||||||
set_target_properties(obs-websocket PROPERTIES PREFIX "")
|
set_target_properties(obs-websocket PROPERTIES PREFIX "")
|
||||||
target_link_libraries(obs-websocket
|
target_link_libraries(obs-websocket
|
||||||
obs-frontend-api)
|
obs-frontend-api)
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
image: Visual Studio 2017
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
CURL_VERSION: 7.39.0
|
CURL_VERSION: 7.39.0
|
||||||
|
|
||||||
@ -17,9 +15,9 @@ install:
|
|||||||
- mkdir build32
|
- mkdir build32
|
||||||
- mkdir build64
|
- mkdir build64
|
||||||
- cd ./build32
|
- cd ./build32
|
||||||
- cmake -G "Visual Studio 15 2017" -DQTDIR="%QTDIR32%" -DLibObs_DIR="C:\projects\obs-studio\build32\libobs" -DLIBOBS_INCLUDE_DIR="C:\projects\obs-studio\libobs" -DLIBOBS_LIB="C:\projects\obs-studio\build32\libobs\%build_config%\obs.lib" -DOBS_FRONTEND_LIB="C:\projects\obs-studio\build32\UI\obs-frontend-api\%build_config%\obs-frontend-api.lib" ..
|
- cmake -G "Visual Studio 14 2015" -DQTDIR="%QTDIR32%" -DLibObs_DIR="C:\projects\obs-studio\build32\libobs" -DLIBOBS_INCLUDE_DIR="C:\projects\obs-studio\libobs" -DLIBOBS_LIB="C:\projects\obs-studio\build32\libobs\%build_config%\obs.lib" -DOBS_FRONTEND_LIB="C:\projects\obs-studio\build32\UI\obs-frontend-api\%build_config%\obs-frontend-api.lib" ..
|
||||||
- cd ../build64
|
- cd ../build64
|
||||||
- cmake -G "Visual Studio 15 2017 Win64" -DQTDIR="%QTDIR64%" -DLibObs_DIR="C:\projects\obs-studio\build64\libobs" -DLIBOBS_INCLUDE_DIR="C:\projects\obs-studio\libobs" -DLIBOBS_LIB="C:\projects\obs-studio\build64\libobs\%build_config%\obs.lib" -DOBS_FRONTEND_LIB="C:\projects\obs-studio\build64\UI\obs-frontend-api\%build_config%\obs-frontend-api.lib" ..
|
- cmake -G "Visual Studio 14 2015 Win64" -DQTDIR="%QTDIR64%" -DLibObs_DIR="C:\projects\obs-studio\build64\libobs" -DLIBOBS_INCLUDE_DIR="C:\projects\obs-studio\libobs" -DLIBOBS_LIB="C:\projects\obs-studio\build64\libobs\%build_config%\obs.lib" -DOBS_FRONTEND_LIB="C:\projects\obs-studio\build64\UI\obs-frontend-api\%build_config%\obs-frontend-api.lib" ..
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- call msbuild /m /p:Configuration=%build_config% C:\projects\obs-websocket\build32\obs-websocket.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
- call msbuild /m /p:Configuration=%build_config% C:\projects\obs-websocket\build32\obs-websocket.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||||
|
1
deps/mbedtls
vendored
1
deps/mbedtls
vendored
Submodule deps/mbedtls deleted from 1a6a15c795
@ -30,6 +30,14 @@ const processComments = comments => {
|
|||||||
let errors = [];
|
let errors = [];
|
||||||
|
|
||||||
comments.forEach(comment => {
|
comments.forEach(comment => {
|
||||||
|
if (comment.typedef) {
|
||||||
|
comment.comment = undefined;
|
||||||
|
comment.context = undefined;
|
||||||
|
sorted['typedefs'] = sorted['typedefs'] || [];
|
||||||
|
sorted['typedefs'].push(comment);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof comment.api === 'undefined') return;
|
if (typeof comment.api === 'undefined') return;
|
||||||
let validationFailures = validateComment(comment);
|
let validationFailures = validateComment(comment);
|
||||||
|
|
||||||
@ -84,9 +92,7 @@ const validateComment = comment => {
|
|||||||
fullContext: Object.assign({}, comment)
|
fullContext: Object.assign({}, comment)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
};
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const files = glob.sync(config.srcGlob);
|
const files = glob.sync(config.srcGlob);
|
||||||
const comments = processComments(parseFiles(files));
|
const comments = processComments(parseFiles(files));
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,14 +1,13 @@
|
|||||||
<!-- 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.3.2 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.
|
||||||
This protocol is based on the original OBS Remote protocol created by Bill Hamilton, with new commands specific to OBS Studio.
|
This protocol is based on the original OBS Remote protocol created by Bill Hamilton, with new commands specific to OBS Studio.
|
||||||
|
|
||||||
|
|
||||||
# Authentication
|
# Authentication
|
||||||
OBSWebSocket uses SHA256 to transmit credentials.
|
`obs-websocket` uses SHA256 to transmit credentials.
|
||||||
|
|
||||||
A request for [`GetAuthRequired`](#getauthrequired) returns two elements:
|
A request for [`GetAuthRequired`](#getauthrequired) returns two elements:
|
||||||
- A `challenge`: a random string that will be used to generate the auth response.
|
- A `challenge`: a random string that will be used to generate the auth response.
|
||||||
@ -43,6 +42,9 @@ auth_response = base64_encode(auth_response_hash)
|
|||||||
|
|
||||||
<!-- toc -->
|
<!-- toc -->
|
||||||
|
|
||||||
|
- [Typedefs](#typedefs)
|
||||||
|
* [Scene](#scene)
|
||||||
|
* [Source](#source)
|
||||||
- [Events](#events)
|
- [Events](#events)
|
||||||
* [Scenes](#scenes)
|
* [Scenes](#scenes)
|
||||||
+ [SwitchScenes](#switchscenes)
|
+ [SwitchScenes](#switchscenes)
|
||||||
@ -120,10 +122,13 @@ auth_response = base64_encode(auth_response_hash)
|
|||||||
+ [SetSceneItemPosition](#setsceneitemposition)
|
+ [SetSceneItemPosition](#setsceneitemposition)
|
||||||
+ [SetSceneItemTransform](#setsceneitemtransform)
|
+ [SetSceneItemTransform](#setsceneitemtransform)
|
||||||
+ [SetSceneItemCrop](#setsceneitemcrop)
|
+ [SetSceneItemCrop](#setsceneitemcrop)
|
||||||
|
+ [DeleteSceneItem](#deletesceneitem)
|
||||||
|
+ [DuplicateSceneItem](#duplicatesceneitem)
|
||||||
* [Scenes](#scenes-1)
|
* [Scenes](#scenes-1)
|
||||||
+ [SetCurrentScene](#setcurrentscene)
|
+ [SetCurrentScene](#setcurrentscene)
|
||||||
+ [GetCurrentScene](#getcurrentscene)
|
+ [GetCurrentScene](#getcurrentscene)
|
||||||
+ [GetSceneList](#getscenelist)
|
+ [GetSceneList](#getscenelist)
|
||||||
|
+ [ReorderSceneItems](#reordersceneitems)
|
||||||
* [Sources](#sources-1)
|
* [Sources](#sources-1)
|
||||||
+ [GetSourcesList](#getsourceslist)
|
+ [GetSourcesList](#getsourceslist)
|
||||||
+ [GetSourcesTypesList](#getsourcestypeslist)
|
+ [GetSourcesTypesList](#getsourcestypeslist)
|
||||||
@ -138,9 +143,17 @@ auth_response = base64_encode(auth_response_hash)
|
|||||||
+ [SetSourceSettings](#setsourcesettings)
|
+ [SetSourceSettings](#setsourcesettings)
|
||||||
+ [GetTextGDIPlusProperties](#gettextgdiplusproperties)
|
+ [GetTextGDIPlusProperties](#gettextgdiplusproperties)
|
||||||
+ [SetTextGDIPlusProperties](#settextgdiplusproperties)
|
+ [SetTextGDIPlusProperties](#settextgdiplusproperties)
|
||||||
|
+ [GetTextFreetype2Properties](#gettextfreetype2properties)
|
||||||
|
+ [SetTextFreetype2Properties](#settextfreetype2properties)
|
||||||
+ [GetBrowserSourceProperties](#getbrowsersourceproperties)
|
+ [GetBrowserSourceProperties](#getbrowsersourceproperties)
|
||||||
+ [SetBrowserSourceProperties](#setbrowsersourceproperties)
|
+ [SetBrowserSourceProperties](#setbrowsersourceproperties)
|
||||||
+ [GetSpecialSources](#getspecialsources)
|
+ [GetSpecialSources](#getspecialsources)
|
||||||
|
+ [GetSourceFilters](#getsourcefilters)
|
||||||
|
+ [AddFilterToSource](#addfiltertosource)
|
||||||
|
+ [RemoveFilterFromSource](#removefilterfromsource)
|
||||||
|
+ [ReorderSourceFilter](#reordersourcefilter)
|
||||||
|
+ [MoveSourceFilter](#movesourcefilter)
|
||||||
|
+ [SetSourceFilterSettings](#setsourcefiltersettings)
|
||||||
* [Streaming](#streaming-1)
|
* [Streaming](#streaming-1)
|
||||||
+ [GetStreamingStatus](#getstreamingstatus)
|
+ [GetStreamingStatus](#getstreamingstatus)
|
||||||
+ [StartStopStreaming](#startstopstreaming)
|
+ [StartStopStreaming](#startstopstreaming)
|
||||||
@ -166,6 +179,31 @@ auth_response = base64_encode(auth_response_hash)
|
|||||||
|
|
||||||
<!-- tocstop -->
|
<!-- tocstop -->
|
||||||
|
|
||||||
|
# Typedefs
|
||||||
|
These are complex types, such as `Source` and `Scene`, which are used as arguments or return values in multiple requests and/or events.
|
||||||
|
|
||||||
|
|
||||||
|
## 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 |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `cy` | _Number_ | |
|
||||||
|
| `cx` | _Number_ | |
|
||||||
|
| `name` | _String_ | The name of this Scene Item. |
|
||||||
|
| `render` | _Boolean_ | Whether or not this Scene Item is set to "visible". |
|
||||||
|
| `source_cx` | _Number_ | |
|
||||||
|
| `source_cy` | _Number_ | |
|
||||||
|
| `type` | _String_ | Source type. Value is one of the following: "input", "filter", "transition", "scene" or "unknown" |
|
||||||
|
| `volume` | _Number_ | |
|
||||||
|
| `x` | _Number_ | |
|
||||||
|
| `y` | _Number_ | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Events
|
# Events
|
||||||
Events are broadcast by the server to each connected client when a recognized action occurs within OBS.
|
Events are broadcast by the server to each connected client when a recognized action occurs within OBS.
|
||||||
|
|
||||||
@ -193,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_ | List of sources in the new scene. |
|
| `sources` | _Array<Source>_ | List of sources in the new scene. Same specification as [`GetCurrentScene`](#getcurrentscene). |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -554,7 +592,7 @@ Emitted every 2 seconds after enabling it by calling SetHeartbeat.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `pulse` | _boolean_ | Toggles between every JSON meassage as an "I am alive" indicator. |
|
| `pulse` | _boolean_ | Toggles between every JSON message as an "I am alive" indicator. |
|
||||||
| `current-profile` | _string (optional)_ | Current active profile. |
|
| `current-profile` | _string (optional)_ | Current active profile. |
|
||||||
| `current-scene` | _string (optional)_ | Current active scene. |
|
| `current-scene` | _string (optional)_ | Current active scene. |
|
||||||
| `streaming` | _boolean (optional)_ | Current streaming state. |
|
| `streaming` | _boolean (optional)_ | Current streaming state. |
|
||||||
@ -653,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` | _Source\|Array_ | 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). |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -875,7 +913,7 @@ _No specified parameters._
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `profiles` | _Object\|Array_ | List of available profiles. |
|
| `profiles` | _Array<Object>_ | List of available profiles. |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1109,8 +1147,7 @@ _No specified parameters._
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-collections` | _Object\|Array_ | Scene collections list |
|
| `scene-collections` | _Array<String>_ | Scene collections list |
|
||||||
| `scene-collections.*.` | _String_ | |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1203,7 +1240,7 @@ Reset a scene item.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-name` | _String (optional)_ | Name of the scene the source belogns to. Defaults to the current scene. |
|
| `scene-name` | _String (optional)_ | Name of the scene the source belongs to. Defaults to the current scene. |
|
||||||
| `item` | _String_ | Name of the source item. |
|
| `item` | _String_ | Name of the source item. |
|
||||||
|
|
||||||
|
|
||||||
@ -1309,6 +1346,59 @@ Sets the crop coordinates of the specified source item.
|
|||||||
|
|
||||||
_No additional response items._
|
_No additional response items._
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### DeleteSceneItem
|
||||||
|
|
||||||
|
|
||||||
|
- Added in v4.5.0
|
||||||
|
|
||||||
|
Deletes a scene item.
|
||||||
|
|
||||||
|
**Request Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `scene` | _String (optional)_ | Name of the scene the source belongs to. Defaults to the current scene. |
|
||||||
|
| `item` | _Object_ | item to delete (required) |
|
||||||
|
| `item.name` | _String_ | name of the scene item (prefer `id`, including both is acceptable). |
|
||||||
|
| `item.id` | _int_ | id of the scene item. |
|
||||||
|
|
||||||
|
|
||||||
|
**Response Items:**
|
||||||
|
|
||||||
|
_No additional response items._
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### DuplicateSceneItem
|
||||||
|
|
||||||
|
|
||||||
|
- Added in v4.5.0
|
||||||
|
|
||||||
|
Duplicates a scene item.
|
||||||
|
|
||||||
|
**Request Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `fromScene` | _String (optional)_ | Name of the scene to copy the item from. Defaults to the current scene. |
|
||||||
|
| `toScene` | _String (optional)_ | Name of the scene to create the item in. Defaults to the current scene. |
|
||||||
|
| `item` | _Object_ | item to duplicate (required) |
|
||||||
|
| `item.name` | _String_ | name of the scene item (prefer `id`, including both is acceptable). |
|
||||||
|
| `item.id` | _int_ | id of the scene item. |
|
||||||
|
|
||||||
|
|
||||||
|
**Response Items:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `scene` | _String_ | Name of the scene where the new item was created |
|
||||||
|
| `item` | _Object_ | New item info |
|
||||||
|
| `̀item.id` | _int_ | New item ID |
|
||||||
|
| `item.name` | _String_ | New item name |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Scenes
|
## Scenes
|
||||||
@ -1349,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` | _Source\|Array_ | Ordered list of the current scene's source items. |
|
| `sources` | _Array<Source>_ | Ordered list of the current scene's source items. |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1370,9 +1460,32 @@ _No specified parameters._
|
|||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `current-scene` | _String_ | Name of the currently active scene. |
|
| `current-scene` | _String_ | Name of the currently active scene. |
|
||||||
| `scenes` | _Scene\|Array_ | Ordered list of the current profile's scenes (See `[GetCurrentScene](#getcurrentscene)` for more information). |
|
| `scenes` | _Array<Scene>_ | Ordered list of the current profile's scenes (See `[GetCurrentScene](#getcurrentscene)` for more information). |
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ReorderSceneItems
|
||||||
|
|
||||||
|
|
||||||
|
- Added in v4.5.0
|
||||||
|
|
||||||
|
Changes the order of scene items in the requested scene.
|
||||||
|
|
||||||
|
**Request Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `scene` | _String (optional)_ | Name of the scene to reorder (defaults to current). |
|
||||||
|
| `items` | _Scene\|Array_ | Ordered list of objects with name and/or id specified. Id preferred due to uniqueness per scene |
|
||||||
|
| `items[].id` | _int (optional)_ | Id of a specific scene item. Unique on a scene by scene basis. |
|
||||||
|
| `items[].name` | _String (optional)_ | Name of a scene item. Sufficiently unique if no scene items share sources within the scene. |
|
||||||
|
|
||||||
|
|
||||||
|
**Response Items:**
|
||||||
|
|
||||||
|
_No additional response items._
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Sources
|
## Sources
|
||||||
@ -1392,7 +1505,7 @@ _No specified parameters._
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `sources` | _Array of Objects_ | Array of sources as objects |
|
| `sources` | _Array<Object>_ | Array of sources |
|
||||||
| `sources.*.name` | _String_ | Unique source name |
|
| `sources.*.name` | _String_ | Unique source name |
|
||||||
| `sources.*.typeId` | _String_ | Non-unique source internal type (a.k.a type id) |
|
| `sources.*.typeId` | _String_ | Non-unique source internal type (a.k.a type id) |
|
||||||
| `sources.*.type` | _String_ | Source type. Value is one of the following: "input", "filter", "transition", "scene" or "unknown" |
|
| `sources.*.type` | _String_ | Source type. Value is one of the following: "input", "filter", "transition", "scene" or "unknown" |
|
||||||
@ -1415,7 +1528,7 @@ _No specified parameters._
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `ids` | _Array of Objects_ | Array of sources as objects |
|
| `ids` | _Array<Object>_ | Array of source types |
|
||||||
| `ids.*.typeId` | _String_ | Non-unique internal source type ID |
|
| `ids.*.typeId` | _String_ | Non-unique internal source type ID |
|
||||||
| `ids.*.displayName` | _String_ | Display name of the source type |
|
| `ids.*.displayName` | _String_ | Display name of the source type |
|
||||||
| `ids.*.type` | _String_ | Type. Value is one of the following: "input", "filter", "transition" or "other" |
|
| `ids.*.type` | _String_ | Type. Value is one of the following: "input", "filter", "transition" or "other" |
|
||||||
@ -1443,16 +1556,16 @@ Get the volume of the specified source.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `source` | _String_ | Name of the source. |
|
| `source` | _String_ | Source name. |
|
||||||
|
|
||||||
|
|
||||||
**Response Items:**
|
**Response Items:**
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `name` | _String_ | Name of the source. |
|
| `name` | _String_ | Source name. |
|
||||||
| `volume` | _double_ | Volume of the source. Between `0.0` and `1.0`. |
|
| `volume` | _double_ | Volume of the source. Between `0.0` and `1.0`. |
|
||||||
| `mute` | _boolean_ | Indicates whether the source is muted. |
|
| `muted` | _boolean_ | Indicates whether the source is muted. |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1468,7 +1581,7 @@ Set the volume of the specified source.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `source` | _String_ | Name of the source. |
|
| `source` | _String_ | Source name. |
|
||||||
| `volume` | _double_ | Desired volume. Must be between `0.0` and `1.0`. |
|
| `volume` | _double_ | Desired volume. Must be between `0.0` and `1.0`. |
|
||||||
|
|
||||||
|
|
||||||
@ -1489,14 +1602,14 @@ Get the mute status of a specified source.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `source` | _String_ | The name of the source. |
|
| `source` | _String_ | Source name. |
|
||||||
|
|
||||||
|
|
||||||
**Response Items:**
|
**Response Items:**
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `name` | _String_ | The name of the source. |
|
| `name` | _String_ | Source name. |
|
||||||
| `muted` | _boolean_ | Mute status of the source. |
|
| `muted` | _boolean_ | Mute status of the source. |
|
||||||
|
|
||||||
|
|
||||||
@ -1513,7 +1626,7 @@ Sets the mute status of a specified source.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `source` | _String_ | The name of the source. |
|
| `source` | _String_ | Source name. |
|
||||||
| `mute` | _boolean_ | Desired mute status. |
|
| `mute` | _boolean_ | Desired mute status. |
|
||||||
|
|
||||||
|
|
||||||
@ -1534,7 +1647,7 @@ Inverts the mute status of a specified source.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `source` | _String_ | The name of the source. |
|
| `source` | _String_ | Source name. |
|
||||||
|
|
||||||
|
|
||||||
**Response Items:**
|
**Response Items:**
|
||||||
@ -1554,7 +1667,7 @@ Set the audio sync offset of a specified source.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `source` | _String_ | The name of the source. |
|
| `source` | _String_ | Source name. |
|
||||||
| `offset` | _int_ | The desired audio sync offset (in nanoseconds). |
|
| `offset` | _int_ | The desired audio sync offset (in nanoseconds). |
|
||||||
|
|
||||||
|
|
||||||
@ -1575,14 +1688,14 @@ Get the audio sync offset of a specified source.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `source` | _String_ | The name of the source. |
|
| `source` | _String_ | Source name. |
|
||||||
|
|
||||||
|
|
||||||
**Response Items:**
|
**Response Items:**
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `name` | _String_ | The name of the source. |
|
| `name` | _String_ | Source name. |
|
||||||
| `offset` | _int_ | The audio sync offset (in nanoseconds). |
|
| `offset` | _int_ | The audio sync offset (in nanoseconds). |
|
||||||
|
|
||||||
|
|
||||||
@ -1599,7 +1712,7 @@ Get settings of the specified source
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `sourceName` | _String_ | Name of the source item. |
|
| `sourceName` | _String_ | Source name. |
|
||||||
| `sourceType` | _String (optional)_ | Type of the specified source. Useful for type-checking if you expect a specific settings schema. |
|
| `sourceType` | _String (optional)_ | Type of the specified source. Useful for type-checking if you expect a specific settings schema. |
|
||||||
|
|
||||||
|
|
||||||
@ -1609,7 +1722,7 @@ Get settings of the specified source
|
|||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `sourceName` | _String_ | Source name |
|
| `sourceName` | _String_ | Source name |
|
||||||
| `sourceType` | _String_ | Type of the specified source |
|
| `sourceType` | _String_ | Type of the specified source |
|
||||||
| `sourceSettings` | _Object_ | Source settings. Varying between source types. |
|
| `sourceSettings` | _Object_ | Source settings (varies between source types, may require some probing around). |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1625,9 +1738,9 @@ Set settings of the specified source.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `sourceName` | _String_ | Name of the source item. |
|
| `sourceName` | _String_ | Source name. |
|
||||||
| `sourceType` | _String (optional)_ | Type of the specified source. Useful for type-checking to avoid settings a set of settings incompatible with the actual source's type. |
|
| `sourceType` | _String (optional)_ | Type of the specified source. Useful for type-checking to avoid settings a set of settings incompatible with the actual source's type. |
|
||||||
| `sourceSettings` | _Object_ | Source settings. Varying between source types. |
|
| `sourceSettings` | _Object_ | Source settings (varies between source types, may require some probing around). |
|
||||||
|
|
||||||
|
|
||||||
**Response Items:**
|
**Response Items:**
|
||||||
@ -1636,7 +1749,7 @@ Set settings of the specified source.
|
|||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `sourceName` | _String_ | Source name |
|
| `sourceName` | _String_ | Source name |
|
||||||
| `sourceType` | _String_ | Type of the specified source |
|
| `sourceType` | _String_ | Type of the specified source |
|
||||||
| `sourceSettings` | _Object_ | Source settings. Varying between source types. |
|
| `sourceSettings` | _Object_ | Updated source settings |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1652,14 +1765,14 @@ Get the current properties of a Text GDI Plus source.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-name` | _String (optional)_ | Name of the scene to retrieve. Defaults to the current scene. |
|
| `source` | _String_ | Source name. |
|
||||||
| `source` | _String_ | Name of the source. |
|
|
||||||
|
|
||||||
|
|
||||||
**Response Items:**
|
**Response Items:**
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
|
| `source` | _String_ | Source name. |
|
||||||
| `align` | _String_ | Text Alignment ("left", "center", "right"). |
|
| `align` | _String_ | Text Alignment ("left", "center", "right"). |
|
||||||
| `bk-color` | _int_ | Background color. |
|
| `bk-color` | _int_ | Background color. |
|
||||||
| `bk-opacity` | _int_ | Background opacity (0-100). |
|
| `bk-opacity` | _int_ | Background opacity (0-100). |
|
||||||
@ -1687,7 +1800,6 @@ Get the current properties of a Text GDI Plus source.
|
|||||||
| `text` | _String_ | Text content to be displayed. |
|
| `text` | _String_ | Text content to be displayed. |
|
||||||
| `valign` | _String_ | Text vertical alignment ("top", "center", "bottom"). |
|
| `valign` | _String_ | Text vertical alignment ("top", "center", "bottom"). |
|
||||||
| `vertical` | _boolean_ | Vertical text enabled. |
|
| `vertical` | _boolean_ | Vertical text enabled. |
|
||||||
| `render` | _boolean_ | Visibility of the scene item. |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1697,13 +1809,12 @@ Get the current properties of a Text GDI Plus source.
|
|||||||
|
|
||||||
- Added in v4.1.0
|
- Added in v4.1.0
|
||||||
|
|
||||||
Get the current properties of a Text GDI Plus source.
|
Set the current properties of a Text GDI Plus source.
|
||||||
|
|
||||||
**Request Fields:**
|
**Request Fields:**
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-name` | _String (optional)_ | Name of the scene to retrieve. Defaults to the current scene. |
|
|
||||||
| `source` | _String_ | Name of the source. |
|
| `source` | _String_ | Name of the source. |
|
||||||
| `align` | _String (optional)_ | Text Alignment ("left", "center", "right"). |
|
| `align` | _String (optional)_ | Text Alignment ("left", "center", "right"). |
|
||||||
| `bk-color` | _int (optional)_ | Background color. |
|
| `bk-color` | _int (optional)_ | Background color. |
|
||||||
@ -1735,6 +1846,79 @@ Get the current properties of a Text GDI Plus source.
|
|||||||
| `render` | _boolean (optional)_ | Visibility of the scene item. |
|
| `render` | _boolean (optional)_ | Visibility of the scene item. |
|
||||||
|
|
||||||
|
|
||||||
|
**Response Items:**
|
||||||
|
|
||||||
|
_No additional response items._
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### GetTextFreetype2Properties
|
||||||
|
|
||||||
|
|
||||||
|
- Added in v4.5.0
|
||||||
|
|
||||||
|
Get the current properties of a Text Freetype 2 source.
|
||||||
|
|
||||||
|
**Request Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `source` | _String_ | Source name. |
|
||||||
|
|
||||||
|
|
||||||
|
**Response Items:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `source` | _String_ | Source name |
|
||||||
|
| `color1` | _int_ | Gradient top color. |
|
||||||
|
| `color2` | _int_ | Gradient bottom color. |
|
||||||
|
| `custom_width` | _int_ | Custom width (0 to disable). |
|
||||||
|
| `drop_shadow` | _boolean_ | Drop shadow. |
|
||||||
|
| `font` | _Object_ | Holds data for the font. Ex: `"font": { "face": "Arial", "flags": 0, "size": 150, "style": "" }` |
|
||||||
|
| `font.face` | _String_ | Font face. |
|
||||||
|
| `font.flags` | _int_ | Font text styling flag. `Bold=1, Italic=2, Bold Italic=3, Underline=5, Strikeout=8` |
|
||||||
|
| `font.size` | _int_ | Font text size. |
|
||||||
|
| `font.style` | _String_ | Font Style (unknown function). |
|
||||||
|
| `from_file` | _boolean_ | Read text from the specified file. |
|
||||||
|
| `log_mode` | _boolean_ | Chat log. |
|
||||||
|
| `outline` | _boolean_ | Outline. |
|
||||||
|
| `text` | _String_ | Text content to be displayed. |
|
||||||
|
| `text_file` | _String_ | File path. |
|
||||||
|
| `word_wrap` | _boolean_ | Word wrap. |
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### SetTextFreetype2Properties
|
||||||
|
|
||||||
|
|
||||||
|
- Added in v4.5.0
|
||||||
|
|
||||||
|
Set the current properties of a Text Freetype 2 source.
|
||||||
|
|
||||||
|
**Request Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `source` | _String_ | Source name. |
|
||||||
|
| `color1` | _int (optional)_ | Gradient top color. |
|
||||||
|
| `color2` | _int (optional)_ | Gradient bottom color. |
|
||||||
|
| `custom_width` | _int (optional)_ | Custom width (0 to disable). |
|
||||||
|
| `drop_shadow` | _boolean (optional)_ | Drop shadow. |
|
||||||
|
| `font` | _Object (optional)_ | Holds data for the font. Ex: `"font": { "face": "Arial", "flags": 0, "size": 150, "style": "" }` |
|
||||||
|
| `font.face` | _String (optional)_ | Font face. |
|
||||||
|
| `font.flags` | _int (optional)_ | Font text styling flag. `Bold=1, Italic=2, Bold Italic=3, Underline=5, Strikeout=8` |
|
||||||
|
| `font.size` | _int (optional)_ | Font text size. |
|
||||||
|
| `font.style` | _String (optional)_ | Font Style (unknown function). |
|
||||||
|
| `from_file` | _boolean (optional)_ | Read text from the specified file. |
|
||||||
|
| `log_mode` | _boolean (optional)_ | Chat log. |
|
||||||
|
| `outline` | _boolean (optional)_ | Outline. |
|
||||||
|
| `text` | _String (optional)_ | Text content to be displayed. |
|
||||||
|
| `text_file` | _String (optional)_ | File path. |
|
||||||
|
| `word_wrap` | _boolean (optional)_ | Word wrap. |
|
||||||
|
|
||||||
|
|
||||||
**Response Items:**
|
**Response Items:**
|
||||||
|
|
||||||
_No additional response items._
|
_No additional response items._
|
||||||
@ -1752,14 +1936,14 @@ Get current properties for a Browser Source.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-name` | _String (optional)_ | Name of the scene that the source belongs to. Defaults to the current scene. |
|
| `source` | _String_ | Source name. |
|
||||||
| `source` | _String_ | Name of the source. |
|
|
||||||
|
|
||||||
|
|
||||||
**Response Items:**
|
**Response Items:**
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
|
| `source` | _String_ | Source name. |
|
||||||
| `is_local_file` | _boolean_ | Indicates that a local file is in use. |
|
| `is_local_file` | _boolean_ | Indicates that a local file is in use. |
|
||||||
| `local_file` | _String_ | file path. |
|
| `local_file` | _String_ | file path. |
|
||||||
| `url` | _String_ | Url. |
|
| `url` | _String_ | Url. |
|
||||||
@ -1768,7 +1952,6 @@ Get current properties for a Browser Source.
|
|||||||
| `height` | _int_ | Height. |
|
| `height` | _int_ | Height. |
|
||||||
| `fps` | _int_ | Framerate. |
|
| `fps` | _int_ | Framerate. |
|
||||||
| `shutdown` | _boolean_ | Indicates whether the source should be shutdown when not visible. |
|
| `shutdown` | _boolean_ | Indicates whether the source should be shutdown when not visible. |
|
||||||
| `render` | _boolean (optional)_ | Visibility of the scene item. |
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1784,7 +1967,6 @@ Set current properties for a Browser Source.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `scene-name` | _String (optional)_ | Name of the scene that the source belongs to. Defaults to the current scene. |
|
|
||||||
| `source` | _String_ | Name of the source. |
|
| `source` | _String_ | Name of the source. |
|
||||||
| `is_local_file` | _boolean (optional)_ | Indicates that a local file is in use. |
|
| `is_local_file` | _boolean (optional)_ | Indicates that a local file is in use. |
|
||||||
| `local_file` | _String (optional)_ | file path. |
|
| `local_file` | _String (optional)_ | file path. |
|
||||||
@ -1825,6 +2007,142 @@ _No specified parameters._
|
|||||||
| `mic-3` | _String (optional)_ | NAme of the third Mic/Aux input source. |
|
| `mic-3` | _String (optional)_ | NAme of the third Mic/Aux input source. |
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### GetSourceFilters
|
||||||
|
|
||||||
|
|
||||||
|
- Added in v4.5.0
|
||||||
|
|
||||||
|
List filters applied to a source
|
||||||
|
|
||||||
|
**Request Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `sourceName` | _String_ | Source name |
|
||||||
|
|
||||||
|
|
||||||
|
**Response Items:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `filters` | _Array<Object>_ | List of filters for the specified source |
|
||||||
|
| `filters.*.type` | _String_ | Filter type |
|
||||||
|
| `filters.*.name` | _String_ | Filter name |
|
||||||
|
| `filters.*.settings` | _Object_ | Filter settings |
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### AddFilterToSource
|
||||||
|
|
||||||
|
|
||||||
|
- Added in v4.5.0
|
||||||
|
|
||||||
|
Add a new filter to a source. Available source types along with their settings properties are available from `GetSourceTypesList`.
|
||||||
|
|
||||||
|
**Request Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `sourceName` | _String_ | Name of the source on which the filter is added |
|
||||||
|
| `filterName` | _String_ | Name of the new filter |
|
||||||
|
| `filterType` | _String_ | Filter type |
|
||||||
|
| `filterSettings` | _Object_ | Filter settings |
|
||||||
|
|
||||||
|
|
||||||
|
**Response Items:**
|
||||||
|
|
||||||
|
_No additional response items._
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### RemoveFilterFromSource
|
||||||
|
|
||||||
|
|
||||||
|
- Added in v4.5.0
|
||||||
|
|
||||||
|
Remove a filter from a source
|
||||||
|
|
||||||
|
**Request Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `sourceName` | _String_ | Name of the source from which the specified filter is removed |
|
||||||
|
| `filterName` | _String_ | Name of the filter to remove |
|
||||||
|
|
||||||
|
|
||||||
|
**Response Items:**
|
||||||
|
|
||||||
|
_No additional response items._
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ReorderSourceFilter
|
||||||
|
|
||||||
|
|
||||||
|
- Added in v4.5.0
|
||||||
|
|
||||||
|
Move a filter in the chain (absolute index positioning)
|
||||||
|
|
||||||
|
**Request Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `sourceName` | _String_ | Name of the source to which the filter belongs |
|
||||||
|
| `filterName` | _String_ | Name of the filter to reorder |
|
||||||
|
| `newIndex` | _Integer_ | Desired position of the filter in the chain |
|
||||||
|
|
||||||
|
|
||||||
|
**Response Items:**
|
||||||
|
|
||||||
|
_No additional response items._
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### MoveSourceFilter
|
||||||
|
|
||||||
|
|
||||||
|
- Added in v4.5.0
|
||||||
|
|
||||||
|
Move a filter in the chain (relative positioning)
|
||||||
|
|
||||||
|
**Request Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `sourceName` | _String_ | Name of the source to which the filter belongs |
|
||||||
|
| `filterName` | _String_ | Name of the filter to reorder |
|
||||||
|
| `movementType` | _String_ | How to move the filter around in the source's filter chain. Either "up", "down", "top" or "bottom". |
|
||||||
|
|
||||||
|
|
||||||
|
**Response Items:**
|
||||||
|
|
||||||
|
_No additional response items._
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### SetSourceFilterSettings
|
||||||
|
|
||||||
|
|
||||||
|
- Added in v4.5.0
|
||||||
|
|
||||||
|
Update settings of a filter
|
||||||
|
|
||||||
|
**Request Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
| `sourceName` | _String_ | Name of the source to which the filter belongs |
|
||||||
|
| `filterName` | _String_ | Name of the filter to reconfigure |
|
||||||
|
| `filterSettings` | _Object_ | New settings. These will be merged to the current filter settings. |
|
||||||
|
|
||||||
|
|
||||||
|
**Response Items:**
|
||||||
|
|
||||||
|
_No additional response items._
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Streaming
|
## Streaming
|
||||||
@ -1963,7 +2281,7 @@ _No specified parameters._
|
|||||||
| `settings` | _Object_ | Stream settings object. |
|
| `settings` | _Object_ | Stream settings object. |
|
||||||
| `settings.server` | _String_ | The publish URL. |
|
| `settings.server` | _String_ | The publish URL. |
|
||||||
| `settings.key` | _String_ | The publish key of the stream. |
|
| `settings.key` | _String_ | The publish key of the stream. |
|
||||||
| `settings.use-auth` | _boolean_ | Indicates whether audentication should be used when connecting to the streaming server. |
|
| `settings.use-auth` | _boolean_ | Indicates whether authentication should be used when connecting to the streaming server. |
|
||||||
| `settings.username` | _String_ | The username to use when accessing the streaming server. Only present if `use-auth` is `true`. |
|
| `settings.username` | _String_ | The username to use when accessing the streaming server. Only present if `use-auth` is `true`. |
|
||||||
| `settings.password` | _String_ | The password to use when accessing the streaming server. Only present if `use-auth` is `true`. |
|
| `settings.password` | _String_ | The password to use when accessing the streaming server. Only present if `use-auth` is `true`. |
|
||||||
|
|
||||||
@ -2026,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` | _Source\|Array_ | |
|
| `sources` | _Array<Source>_ | |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -2144,8 +2462,8 @@ _No specified parameters._
|
|||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ------------|
|
| ---- | :---: | ------------|
|
||||||
| `current-transition` | _String_ | Name of the currently active transition. |
|
| `current-transition` | _String_ | Name of the currently active transition. |
|
||||||
| `transitions` | _Object\|Array_ | List of transitions. |
|
| `transitions` | _Array<Object>_ | List of transitions. |
|
||||||
| `transitions[].name` | _String_ | Name of the transition. |
|
| `transitions.*.name` | _String_ | Name of the transition. |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
# obs-websocket 4.3.2 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.
|
||||||
This protocol is based on the original OBS Remote protocol created by Bill Hamilton, with new commands specific to OBS Studio.
|
This protocol is based on the original OBS Remote protocol created by Bill Hamilton, with new commands specific to OBS Studio.
|
||||||
|
|
||||||
|
|
||||||
# Authentication
|
# Authentication
|
||||||
OBSWebSocket uses SHA256 to transmit credentials.
|
`obs-websocket` uses SHA256 to transmit credentials.
|
||||||
|
|
||||||
A request for [`GetAuthRequired`](#getauthrequired) returns two elements:
|
A request for [`GetAuthRequired`](#getauthrequired) returns two elements:
|
||||||
- A `challenge`: a random string that will be used to generate the auth response.
|
- A `challenge`: a random string that will be used to generate the auth response.
|
||||||
|
2
docs/partials/typedefsHeader.md
Normal file
2
docs/partials/typedefsHeader.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Typedefs
|
||||||
|
These are complex types, such as `Source` and `Scene`, which are used as arguments or return values in multiple requests and/or events.
|
@ -7,6 +7,19 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{{#read "partials/typedefsHeader.md"}}{{/read}}
|
||||||
|
|
||||||
|
{{#each typedefs}}
|
||||||
|
## {{typedefs.0.name}}
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ------------|
|
||||||
|
{{#each properties}}
|
||||||
|
| `{{name}}` | _{{depipe type}}_ | {{{depipe description}}} |
|
||||||
|
{{/each}}
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{{#read "partials/eventsHeader.md"}}{{/read}}
|
{{#read "partials/eventsHeader.md"}}{{/read}}
|
||||||
|
|
||||||
{{#each events}}
|
{{#each events}}
|
||||||
|
@ -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.4.0"
|
#define MyAppVersion "4.5.0"
|
||||||
#define MyAppPublisher "Stephane Lepin"
|
#define MyAppPublisher "Stephane Lepin"
|
||||||
#define MyAppURL "http://github.com/Palakis/obs-websocket"
|
#define MyAppURL "http://github.com/Palakis/obs-websocket"
|
||||||
|
|
||||||
|
@ -16,11 +16,11 @@ 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 <mbedtls/base64.h>
|
|
||||||
#include <mbedtls/sha256.h>
|
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
#include <util/config-file.h>
|
#include <util/config-file.h>
|
||||||
#include <string>
|
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
#include <QTime>
|
||||||
|
|
||||||
#define SECTION_NAME "WebsocketAPI"
|
#define SECTION_NAME "WebsocketAPI"
|
||||||
#define PARAM_ENABLE "ServerEnabled"
|
#define PARAM_ENABLE "ServerEnabled"
|
||||||
@ -48,6 +48,8 @@ Config::Config() :
|
|||||||
Salt(""),
|
Salt(""),
|
||||||
SettingsLoaded(false)
|
SettingsLoaded(false)
|
||||||
{
|
{
|
||||||
|
qsrand(QTime::currentTime().msec());
|
||||||
|
|
||||||
// OBS Config defaults
|
// OBS Config defaults
|
||||||
config_t* obsConfig = obs_frontend_get_global_config();
|
config_t* obsConfig = obs_frontend_get_global_config();
|
||||||
if (obsConfig) {
|
if (obsConfig) {
|
||||||
@ -69,19 +71,15 @@ Config::Config() :
|
|||||||
SECTION_NAME, PARAM_SALT, QT_TO_UTF8(Salt));
|
SECTION_NAME, PARAM_SALT, QT_TO_UTF8(Salt));
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_entropy_init(&entropy);
|
|
||||||
mbedtls_ctr_drbg_init(&rng);
|
|
||||||
mbedtls_ctr_drbg_seed(&rng, mbedtls_entropy_func, &entropy, nullptr, 0);
|
|
||||||
|
|
||||||
SessionChallenge = GenerateSalt();
|
SessionChallenge = GenerateSalt();
|
||||||
}
|
}
|
||||||
|
|
||||||
Config::~Config() {
|
Config::~Config()
|
||||||
mbedtls_ctr_drbg_free(&rng);
|
{
|
||||||
mbedtls_entropy_free(&entropy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::Load() {
|
void Config::Load()
|
||||||
|
{
|
||||||
config_t* obsConfig = obs_frontend_get_global_config();
|
config_t* obsConfig = obs_frontend_get_global_config();
|
||||||
|
|
||||||
ServerEnabled = config_get_bool(obsConfig, SECTION_NAME, PARAM_ENABLE);
|
ServerEnabled = config_get_bool(obsConfig, SECTION_NAME, PARAM_ENABLE);
|
||||||
@ -95,7 +93,8 @@ void Config::Load() {
|
|||||||
Salt = config_get_string(obsConfig, SECTION_NAME, PARAM_SALT);
|
Salt = config_get_string(obsConfig, SECTION_NAME, PARAM_SALT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::Save() {
|
void Config::Save()
|
||||||
|
{
|
||||||
config_t* obsConfig = obs_frontend_get_global_config();
|
config_t* obsConfig = obs_frontend_get_global_config();
|
||||||
|
|
||||||
config_set_bool(obsConfig, SECTION_NAME, PARAM_ENABLE, ServerEnabled);
|
config_set_bool(obsConfig, SECTION_NAME, PARAM_ENABLE, ServerEnabled);
|
||||||
@ -113,46 +112,42 @@ void Config::Save() {
|
|||||||
config_save(obsConfig);
|
config_save(obsConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Config::GenerateSalt() {
|
QString Config::GenerateSalt()
|
||||||
|
{
|
||||||
// Generate 32 random chars
|
// Generate 32 random chars
|
||||||
unsigned char* randomChars = (unsigned char*)bzalloc(32);
|
const size_t randomCount = 32;
|
||||||
mbedtls_ctr_drbg_random(&rng, randomChars, 32);
|
QByteArray randomChars;
|
||||||
|
for (size_t i = 0; i < randomCount; i++) {
|
||||||
|
randomChars.append((char)qrand());
|
||||||
|
}
|
||||||
|
|
||||||
// Convert the 32 random chars to a base64 string
|
// Convert the 32 random chars to a base64 string
|
||||||
char* salt = (char*)bzalloc(64);
|
QString salt = randomChars.toBase64();
|
||||||
size_t saltBytes;
|
|
||||||
mbedtls_base64_encode(
|
|
||||||
(unsigned char*)salt, 64, &saltBytes,
|
|
||||||
randomChars, 32);
|
|
||||||
|
|
||||||
bfree(randomChars);
|
|
||||||
return salt;
|
return salt;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Config::GenerateSecret(QString password, QString salt) {
|
QString Config::GenerateSecret(QString password, QString salt)
|
||||||
|
{
|
||||||
// Concatenate the password and the salt
|
// Concatenate the password and the salt
|
||||||
QString passAndSalt = "";
|
QString passAndSalt = "";
|
||||||
passAndSalt += password;
|
passAndSalt += password;
|
||||||
passAndSalt += salt;
|
passAndSalt += salt;
|
||||||
|
|
||||||
// Generate a SHA256 hash of the password
|
// Generate a SHA256 hash of the password and salt
|
||||||
unsigned char* challengeHash = (unsigned char*)bzalloc(32);
|
auto challengeHash = QCryptographicHash::hash(
|
||||||
mbedtls_sha256(
|
passAndSalt.toUtf8(),
|
||||||
(unsigned char*)passAndSalt.toUtf8().constData(), passAndSalt.length(),
|
QCryptographicHash::Algorithm::Sha256
|
||||||
challengeHash, 0);
|
);
|
||||||
|
|
||||||
// Encode SHA256 hash to Base64
|
// Encode SHA256 hash to Base64
|
||||||
char* challenge = (char*)bzalloc(64);
|
QString challenge = challengeHash.toBase64();
|
||||||
size_t challengeBytes = 0;
|
|
||||||
mbedtls_base64_encode(
|
|
||||||
(unsigned char*)challenge, 64, &challengeBytes,
|
|
||||||
challengeHash, 32);
|
|
||||||
|
|
||||||
bfree(challengeHash);
|
|
||||||
return challenge;
|
return challenge;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::SetPassword(QString password) {
|
void Config::SetPassword(QString password)
|
||||||
|
{
|
||||||
QString newSalt = GenerateSalt();
|
QString newSalt = GenerateSalt();
|
||||||
QString newChallenge = GenerateSecret(password, newSalt);
|
QString newChallenge = GenerateSecret(password, newSalt);
|
||||||
|
|
||||||
@ -160,37 +155,32 @@ void Config::SetPassword(QString password) {
|
|||||||
this->Secret = newChallenge;
|
this->Secret = newChallenge;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Config::CheckAuth(QString response) {
|
bool Config::CheckAuth(QString response)
|
||||||
|
{
|
||||||
// Concatenate auth secret with the challenge sent to the user
|
// Concatenate auth secret with the challenge sent to the user
|
||||||
QString challengeAndResponse = "";
|
QString challengeAndResponse = "";
|
||||||
challengeAndResponse += Secret;
|
challengeAndResponse += Secret;
|
||||||
challengeAndResponse += SessionChallenge;
|
challengeAndResponse += SessionChallenge;
|
||||||
|
|
||||||
// Generate a SHA256 hash of challengeAndResponse
|
// Generate a SHA256 hash of challengeAndResponse
|
||||||
unsigned char* hash = (unsigned char*)bzalloc(32);
|
auto hash = QCryptographicHash::hash(
|
||||||
mbedtls_sha256(
|
challengeAndResponse.toUtf8(),
|
||||||
(unsigned char*)challengeAndResponse.toUtf8().constData(),
|
QCryptographicHash::Algorithm::Sha256
|
||||||
challengeAndResponse.length(),
|
);
|
||||||
hash, 0);
|
|
||||||
|
|
||||||
// Encode the SHA256 hash to Base64
|
// Encode the SHA256 hash to Base64
|
||||||
char* expectedResponse = (char*)bzalloc(64);
|
QString expectedResponse = hash.toBase64();
|
||||||
size_t base64_size = 0;
|
|
||||||
mbedtls_base64_encode(
|
|
||||||
(unsigned char*)expectedResponse, 64, &base64_size,
|
|
||||||
hash, 32);
|
|
||||||
|
|
||||||
bool authSuccess = false;
|
bool authSuccess = false;
|
||||||
if (response == QString(expectedResponse)) {
|
if (response == expectedResponse) {
|
||||||
SessionChallenge = GenerateSalt();
|
SessionChallenge = GenerateSalt();
|
||||||
authSuccess = true;
|
authSuccess = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bfree(hash);
|
|
||||||
bfree(expectedResponse);
|
|
||||||
return authSuccess;
|
return authSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Config* Config::Current() {
|
Config* Config::Current()
|
||||||
|
{
|
||||||
return _instance;
|
return _instance;
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include <mbedtls/entropy.h>
|
|
||||||
#include <mbedtls/ctr_drbg.h>
|
|
||||||
|
|
||||||
class Config {
|
class Config {
|
||||||
public:
|
public:
|
||||||
Config();
|
Config();
|
||||||
@ -53,8 +50,6 @@ class Config {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static Config* _instance;
|
static Config* _instance;
|
||||||
mbedtls_entropy_context entropy;
|
|
||||||
mbedtls_ctr_drbg_context rng;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONFIG_H
|
#endif // CONFIG_H
|
@ -103,6 +103,22 @@ obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obs_sceneitem_t* Utils::GetSceneItemFromItem(obs_source_t* source, obs_data_t* item) {
|
||||||
|
OBSSceneItem sceneItem;
|
||||||
|
if (obs_data_has_user_value(item, "id")) {
|
||||||
|
sceneItem = GetSceneItemFromId(source, obs_data_get_int(item, "id"));
|
||||||
|
if (obs_data_has_user_value(item, "name") &&
|
||||||
|
(QString)obs_source_get_name(obs_sceneitem_get_source(sceneItem)) !=
|
||||||
|
(QString)obs_data_get_string(item, "name")) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (obs_data_has_user_value(item, "name")) {
|
||||||
|
sceneItem = GetSceneItemFromName(source, obs_data_get_string(item, "name"));
|
||||||
|
}
|
||||||
|
return sceneItem;
|
||||||
|
}
|
||||||
|
|
||||||
obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, QString name) {
|
obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, QString name) {
|
||||||
struct current_search {
|
struct current_search {
|
||||||
QString query;
|
QString query;
|
||||||
@ -139,6 +155,39 @@ obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, QString name)
|
|||||||
return search.result;
|
return search.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obs_sceneitem_t* Utils::GetSceneItemFromId(obs_source_t* source, size_t id) {
|
||||||
|
struct current_search {
|
||||||
|
size_t query;
|
||||||
|
obs_sceneitem_t* result;
|
||||||
|
};
|
||||||
|
|
||||||
|
current_search search;
|
||||||
|
search.query = id;
|
||||||
|
search.result = nullptr;
|
||||||
|
|
||||||
|
OBSScene scene = obs_scene_from_source(source);
|
||||||
|
if (!scene)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
obs_scene_enum_items(scene, [](
|
||||||
|
obs_scene_t* scene,
|
||||||
|
obs_sceneitem_t* currentItem,
|
||||||
|
void* param)
|
||||||
|
{
|
||||||
|
current_search* search = static_cast<current_search*>(param);
|
||||||
|
|
||||||
|
if (obs_sceneitem_get_id(currentItem) == search->query) {
|
||||||
|
search->result = currentItem;
|
||||||
|
obs_sceneitem_addref(search->result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}, &search);
|
||||||
|
|
||||||
|
return search.result;
|
||||||
|
}
|
||||||
|
|
||||||
bool Utils::IsValidAlignment(const uint32_t alignment) {
|
bool Utils::IsValidAlignment(const uint32_t alignment) {
|
||||||
switch (alignment) {
|
switch (alignment) {
|
||||||
case OBS_ALIGN_CENTER:
|
case OBS_ALIGN_CENTER:
|
||||||
|
@ -39,6 +39,8 @@ class Utils {
|
|||||||
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(
|
||||||
obs_source_t* source, QString name);
|
obs_source_t* source, QString name);
|
||||||
|
static obs_sceneitem_t* GetSceneItemFromId(obs_source_t* source, size_t id);
|
||||||
|
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);
|
||||||
|
|
||||||
|
@ -98,7 +98,6 @@ WSEvents::~WSEvents() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WSEvents::deferredInitOperations() {
|
void WSEvents::deferredInitOperations() {
|
||||||
OBSSourceAutoRelease transition = obs_frontend_get_current_transition();
|
|
||||||
hookTransitionBeginEvent();
|
hookTransitionBeginEvent();
|
||||||
|
|
||||||
OBSSourceAutoRelease scene = obs_frontend_get_current_scene();
|
OBSSourceAutoRelease scene = obs_frontend_get_current_scene();
|
||||||
@ -118,6 +117,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private
|
|||||||
owner->OnSceneListChange();
|
owner->OnSceneListChange();
|
||||||
}
|
}
|
||||||
else if (event == OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED) {
|
else if (event == OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED) {
|
||||||
|
owner->hookTransitionBeginEvent();
|
||||||
owner->OnSceneCollectionChange();
|
owner->OnSceneCollectionChange();
|
||||||
}
|
}
|
||||||
else if (event == OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED) {
|
else if (event == OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED) {
|
||||||
@ -292,7 +292,7 @@ const char* WSEvents::GetRecordingTimecode() {
|
|||||||
* Indicates a scene change.
|
* Indicates a scene change.
|
||||||
*
|
*
|
||||||
* @return {String} `scene-name` The new scene.
|
* @return {String} `scene-name` The new scene.
|
||||||
* @return {Array} `sources` List of sources in the new scene.
|
* @return {Array<Source>} `sources` List of sources in the new scene. Same specification as [`GetCurrentScene`](#getcurrentscene).
|
||||||
*
|
*
|
||||||
* @api events
|
* @api events
|
||||||
* @name SwitchScenes
|
* @name SwitchScenes
|
||||||
@ -657,7 +657,7 @@ void WSEvents::StreamStatus() {
|
|||||||
/**
|
/**
|
||||||
* Emitted every 2 seconds after enabling it by calling SetHeartbeat.
|
* Emitted every 2 seconds after enabling it by calling SetHeartbeat.
|
||||||
*
|
*
|
||||||
* @return {boolean} `pulse` Toggles between every JSON meassage as an "I am alive" indicator.
|
* @return {boolean} `pulse` Toggles between every JSON message as an "I am alive" indicator.
|
||||||
* @return {string (optional)} `current-profile` Current active profile.
|
* @return {string (optional)} `current-profile` Current active profile.
|
||||||
* @return {string (optional)} `current-scene` Current active scene.
|
* @return {string (optional)} `current-scene` Current active scene.
|
||||||
* @return {boolean (optional)} `streaming` Current streaming state.
|
* @return {boolean (optional)} `streaming` Current streaming state.
|
||||||
@ -907,7 +907,7 @@ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) {
|
|||||||
* The selected preview scene has changed (only available in Studio Mode).
|
* The selected preview scene has changed (only available in Studio Mode).
|
||||||
*
|
*
|
||||||
* @return {String} `scene-name` Name of the scene being previewed.
|
* @return {String} `scene-name` Name of the scene being previewed.
|
||||||
* @return {Source|Array} `sources` List of sources composing the scene. Same specification as [`GetCurrentScene`](#getcurrentscene).
|
* @return {Array<Source>} `sources` List of sources composing the scene. Same specification as [`GetCurrentScene`](#getcurrentscene).
|
||||||
*
|
*
|
||||||
* @api events
|
* @api events
|
||||||
* @name PreviewSceneChanged
|
* @name PreviewSceneChanged
|
||||||
|
@ -46,6 +46,9 @@ QHash<QString, void(*)(WSRequestHandler*)> WSRequestHandler::messageMap {
|
|||||||
{ "GetSceneItemProperties", WSRequestHandler::HandleGetSceneItemProperties },
|
{ "GetSceneItemProperties", WSRequestHandler::HandleGetSceneItemProperties },
|
||||||
{ "SetSceneItemProperties", WSRequestHandler::HandleSetSceneItemProperties },
|
{ "SetSceneItemProperties", WSRequestHandler::HandleSetSceneItemProperties },
|
||||||
{ "ResetSceneItem", WSRequestHandler::HandleResetSceneItem },
|
{ "ResetSceneItem", WSRequestHandler::HandleResetSceneItem },
|
||||||
|
{ "DeleteSceneItem", WSRequestHandler::HandleDeleteSceneItem },
|
||||||
|
{ "DuplicateSceneItem", WSRequestHandler::HandleDuplicateSceneItem },
|
||||||
|
{ "ReorderSceneItems", WSRequestHandler::HandleReorderSceneItems },
|
||||||
|
|
||||||
{ "GetStreamingStatus", WSRequestHandler::HandleGetStreamingStatus },
|
{ "GetStreamingStatus", WSRequestHandler::HandleGetStreamingStatus },
|
||||||
{ "StartStopStreaming", WSRequestHandler::HandleStartStopStreaming },
|
{ "StartStopStreaming", WSRequestHandler::HandleStartStopStreaming },
|
||||||
@ -82,6 +85,13 @@ QHash<QString, void(*)(WSRequestHandler*)> WSRequestHandler::messageMap {
|
|||||||
{ "GetSourceSettings", WSRequestHandler::HandleGetSourceSettings },
|
{ "GetSourceSettings", WSRequestHandler::HandleGetSourceSettings },
|
||||||
{ "SetSourceSettings", WSRequestHandler::HandleSetSourceSettings },
|
{ "SetSourceSettings", WSRequestHandler::HandleSetSourceSettings },
|
||||||
|
|
||||||
|
{ "GetSourceFilters", WSRequestHandler::HandleGetSourceFilters },
|
||||||
|
{ "AddFilterToSource", WSRequestHandler::HandleAddFilterToSource },
|
||||||
|
{ "RemoveFilterFromSource", WSRequestHandler::HandleRemoveFilterFromSource },
|
||||||
|
{ "ReorderSourceFilter", WSRequestHandler::HandleReorderSourceFilter },
|
||||||
|
{ "MoveSourceFilter", WSRequestHandler::HandleMoveSourceFilter },
|
||||||
|
{ "SetSourceFilterSettings", WSRequestHandler::HandleSetSourceFilterSettings },
|
||||||
|
|
||||||
{ "SetCurrentSceneCollection", WSRequestHandler::HandleSetCurrentSceneCollection },
|
{ "SetCurrentSceneCollection", WSRequestHandler::HandleSetCurrentSceneCollection },
|
||||||
{ "GetCurrentSceneCollection", WSRequestHandler::HandleGetCurrentSceneCollection },
|
{ "GetCurrentSceneCollection", WSRequestHandler::HandleGetCurrentSceneCollection },
|
||||||
{ "ListSceneCollections", WSRequestHandler::HandleListSceneCollections },
|
{ "ListSceneCollections", WSRequestHandler::HandleListSceneCollections },
|
||||||
@ -105,6 +115,9 @@ QHash<QString, void(*)(WSRequestHandler*)> WSRequestHandler::messageMap {
|
|||||||
{ "SetTextGDIPlusProperties", WSRequestHandler::HandleSetTextGDIPlusProperties },
|
{ "SetTextGDIPlusProperties", WSRequestHandler::HandleSetTextGDIPlusProperties },
|
||||||
{ "GetTextGDIPlusProperties", WSRequestHandler::HandleGetTextGDIPlusProperties },
|
{ "GetTextGDIPlusProperties", WSRequestHandler::HandleGetTextGDIPlusProperties },
|
||||||
|
|
||||||
|
{ "SetTextFreetype2Properties", WSRequestHandler::HandleSetTextFreetype2Properties },
|
||||||
|
{ "GetTextFreetype2Properties", WSRequestHandler::HandleGetTextFreetype2Properties },
|
||||||
|
|
||||||
{ "GetBrowserSourceProperties", WSRequestHandler::HandleGetBrowserSourceProperties },
|
{ "GetBrowserSourceProperties", WSRequestHandler::HandleGetBrowserSourceProperties },
|
||||||
{ "SetBrowserSourceProperties", WSRequestHandler::HandleSetBrowserSourceProperties }
|
{ "SetBrowserSourceProperties", WSRequestHandler::HandleSetBrowserSourceProperties }
|
||||||
};
|
};
|
||||||
|
@ -73,6 +73,9 @@ class WSRequestHandler : public QObject {
|
|||||||
static void HandleGetSceneItemProperties(WSRequestHandler* req);
|
static void HandleGetSceneItemProperties(WSRequestHandler* req);
|
||||||
static void HandleSetSceneItemProperties(WSRequestHandler* req);
|
static void HandleSetSceneItemProperties(WSRequestHandler* req);
|
||||||
static void HandleResetSceneItem(WSRequestHandler* req);
|
static void HandleResetSceneItem(WSRequestHandler* req);
|
||||||
|
static void HandleDuplicateSceneItem(WSRequestHandler* req);
|
||||||
|
static void HandleDeleteSceneItem(WSRequestHandler* req);
|
||||||
|
static void HandleReorderSceneItems(WSRequestHandler* req);
|
||||||
|
|
||||||
static void HandleGetStreamingStatus(WSRequestHandler* req);
|
static void HandleGetStreamingStatus(WSRequestHandler* req);
|
||||||
static void HandleStartStopStreaming(WSRequestHandler* req);
|
static void HandleStartStopStreaming(WSRequestHandler* req);
|
||||||
@ -107,6 +110,13 @@ class WSRequestHandler : public QObject {
|
|||||||
static void HandleGetSourceSettings(WSRequestHandler* req);
|
static void HandleGetSourceSettings(WSRequestHandler* req);
|
||||||
static void HandleSetSourceSettings(WSRequestHandler* req);
|
static void HandleSetSourceSettings(WSRequestHandler* req);
|
||||||
|
|
||||||
|
static void HandleGetSourceFilters(WSRequestHandler* req);
|
||||||
|
static void HandleAddFilterToSource(WSRequestHandler* req);
|
||||||
|
static void HandleRemoveFilterFromSource(WSRequestHandler* req);
|
||||||
|
static void HandleReorderSourceFilter(WSRequestHandler* req);
|
||||||
|
static void HandleMoveSourceFilter(WSRequestHandler* req);
|
||||||
|
static void HandleSetSourceFilterSettings(WSRequestHandler* req);
|
||||||
|
|
||||||
static void HandleSetCurrentSceneCollection(WSRequestHandler* req);
|
static void HandleSetCurrentSceneCollection(WSRequestHandler* req);
|
||||||
static void HandleGetCurrentSceneCollection(WSRequestHandler* req);
|
static void HandleGetCurrentSceneCollection(WSRequestHandler* req);
|
||||||
static void HandleListSceneCollections(WSRequestHandler* req);
|
static void HandleListSceneCollections(WSRequestHandler* req);
|
||||||
@ -132,6 +142,10 @@ class WSRequestHandler : public QObject {
|
|||||||
|
|
||||||
static void HandleSetTextGDIPlusProperties(WSRequestHandler* req);
|
static void HandleSetTextGDIPlusProperties(WSRequestHandler* req);
|
||||||
static void HandleGetTextGDIPlusProperties(WSRequestHandler* req);
|
static void HandleGetTextGDIPlusProperties(WSRequestHandler* req);
|
||||||
|
|
||||||
|
static void HandleSetTextFreetype2Properties(WSRequestHandler* req);
|
||||||
|
static void HandleGetTextFreetype2Properties(WSRequestHandler* req);
|
||||||
|
|
||||||
static void HandleSetBrowserSourceProperties(WSRequestHandler* req);
|
static void HandleSetBrowserSourceProperties(WSRequestHandler* req);
|
||||||
static void HandleGetBrowserSourceProperties(WSRequestHandler* req);
|
static void HandleGetBrowserSourceProperties(WSRequestHandler* req);
|
||||||
};
|
};
|
||||||
|
@ -50,7 +50,7 @@ void WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler* req) {
|
|||||||
/**
|
/**
|
||||||
* Get a list of available profiles.
|
* Get a list of available profiles.
|
||||||
*
|
*
|
||||||
* @return {Object|Array} `profiles` List of available profiles.
|
* @return {Array<Object>} `profiles` List of available profiles.
|
||||||
*
|
*
|
||||||
* @api requests
|
* @api requests
|
||||||
* @name ListProfiles
|
* @name ListProfiles
|
||||||
|
@ -50,8 +50,7 @@ void WSRequestHandler::HandleGetCurrentSceneCollection(WSRequestHandler* req) {
|
|||||||
/**
|
/**
|
||||||
* List available scene collections
|
* List available scene collections
|
||||||
*
|
*
|
||||||
* @return {Object|Array} `scene-collections` Scene collections list
|
* @return {Array<String>} `scene-collections` Scene collections list
|
||||||
* @return {String} `scene-collections.*.`
|
|
||||||
*
|
*
|
||||||
* @api requests
|
* @api requests
|
||||||
* @name ListSceneCollections
|
* @name ListSceneCollections
|
||||||
|
@ -322,7 +322,7 @@ void WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler* req) {
|
|||||||
/**
|
/**
|
||||||
* Reset a scene item.
|
* Reset a scene item.
|
||||||
*
|
*
|
||||||
* @param {String (optional)} `scene-name` Name of the scene the source belogns to. Defaults to the current scene.
|
* @param {String (optional)} `scene-name` Name of the scene the source belongs to. Defaults to the current scene.
|
||||||
* @param {String} `item` Name of the source item.
|
* @param {String} `item` Name of the source item.
|
||||||
*
|
*
|
||||||
* @api requests
|
* @api requests
|
||||||
@ -566,3 +566,124 @@ void WSRequestHandler::HandleSetSceneItemCrop(WSRequestHandler* req) {
|
|||||||
req->SendErrorResponse("specified scene item doesn't exist");
|
req->SendErrorResponse("specified scene item doesn't exist");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a scene item.
|
||||||
|
*
|
||||||
|
* @param {String (optional)} `scene` Name of the scene the source belongs to. Defaults to the current scene.
|
||||||
|
* @param {Object} `item` item to delete (required)
|
||||||
|
* @param {String} `item.name` name of the scene item (prefer `id`, including both is acceptable).
|
||||||
|
* @param {int} `item.id` id of the scene item.
|
||||||
|
*
|
||||||
|
* @api requests
|
||||||
|
* @name DeleteSceneItem
|
||||||
|
* @category scene items
|
||||||
|
* @since 4.5.0
|
||||||
|
*/
|
||||||
|
void WSRequestHandler::HandleDeleteSceneItem(WSRequestHandler* req) {
|
||||||
|
if (!req->hasField("item")) {
|
||||||
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* sceneName = obs_data_get_string(req->data, "scene");
|
||||||
|
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
||||||
|
if (!scene) {
|
||||||
|
req->SendErrorResponse("requested scene doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSDataAutoRelease item = obs_data_get_obj(req->data, "item");
|
||||||
|
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromItem(scene, item);
|
||||||
|
if (!sceneItem) {
|
||||||
|
req->SendErrorResponse("item with id/name combination not found in specified scene");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_sceneitem_remove(sceneItem);
|
||||||
|
|
||||||
|
req->SendOKResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DuplicateSceneItemData {
|
||||||
|
obs_sceneitem_t *referenceItem;
|
||||||
|
obs_source_t *fromSource;
|
||||||
|
obs_sceneitem_t *newItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void DuplicateSceneItem(void *_data, obs_scene_t *scene) {
|
||||||
|
DuplicateSceneItemData *data = (DuplicateSceneItemData *)_data;
|
||||||
|
data->newItem = obs_scene_add(scene, data->fromSource);
|
||||||
|
obs_sceneitem_set_visible(data->newItem, obs_sceneitem_visible(data->referenceItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duplicates a scene item.
|
||||||
|
*
|
||||||
|
* @param {String (optional)} `fromScene` Name of the scene to copy the item from. Defaults to the current scene.
|
||||||
|
* @param {String (optional)} `toScene` Name of the scene to create the item in. Defaults to the current scene.
|
||||||
|
* @param {Object} `item` item to duplicate (required)
|
||||||
|
* @param {String} `item.name` name of the scene item (prefer `id`, including both is acceptable).
|
||||||
|
* @param {int} `item.id` id of the scene item.
|
||||||
|
*
|
||||||
|
* @return {String} `scene` Name of the scene where the new item was created
|
||||||
|
* @return {Object} `item` New item info
|
||||||
|
* @return {int} `̀item.id` New item ID
|
||||||
|
* @return {String} `item.name` New item name
|
||||||
|
*
|
||||||
|
* @api requests
|
||||||
|
* @name DuplicateSceneItem
|
||||||
|
* @category scene items
|
||||||
|
* @since 4.5.0
|
||||||
|
*/
|
||||||
|
void WSRequestHandler::HandleDuplicateSceneItem(WSRequestHandler* req) {
|
||||||
|
if (!req->hasField("item")) {
|
||||||
|
req->SendErrorResponse("missing request parameters");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* fromSceneName = obs_data_get_string(req->data, "fromScene");
|
||||||
|
OBSSourceAutoRelease fromScene = Utils::GetSceneFromNameOrCurrent(fromSceneName);
|
||||||
|
if (!fromScene) {
|
||||||
|
req->SendErrorResponse("requested fromScene doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* toSceneName = obs_data_get_string(req->data, "toScene");
|
||||||
|
OBSSourceAutoRelease toScene = Utils::GetSceneFromNameOrCurrent(toSceneName);
|
||||||
|
if (!toScene) {
|
||||||
|
req->SendErrorResponse("requested toScene doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSDataAutoRelease item = obs_data_get_obj(req->data, "item");
|
||||||
|
OBSSceneItemAutoRelease referenceItem = Utils::GetSceneItemFromItem(fromScene, item);
|
||||||
|
if (!referenceItem) {
|
||||||
|
req->SendErrorResponse("item with id/name combination not found in specified scene");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DuplicateSceneItemData data;
|
||||||
|
data.fromSource = obs_sceneitem_get_source(referenceItem);
|
||||||
|
data.referenceItem = referenceItem;
|
||||||
|
|
||||||
|
obs_enter_graphics();
|
||||||
|
obs_scene_atomic_update(obs_scene_from_source(toScene), DuplicateSceneItem, &data);
|
||||||
|
obs_leave_graphics();
|
||||||
|
|
||||||
|
obs_sceneitem_t *newItem = data.newItem;
|
||||||
|
if (!newItem) {
|
||||||
|
req->SendErrorResponse("Error duplicating scene item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSDataAutoRelease itemData = obs_data_create();
|
||||||
|
obs_data_set_int(itemData, "id", obs_sceneitem_get_id(newItem));
|
||||||
|
obs_data_set_string(itemData, "name", obs_source_get_name(obs_sceneitem_get_source(newItem)));
|
||||||
|
|
||||||
|
OBSDataAutoRelease responseData = obs_data_create();
|
||||||
|
obs_data_set_obj(responseData, "item", itemData);
|
||||||
|
obs_data_set_string(responseData, "scene", obs_source_get_name(toScene));
|
||||||
|
|
||||||
|
req->SendOKResponse(responseData);
|
||||||
|
}
|
||||||
|
@ -3,6 +3,12 @@
|
|||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} `Scene`
|
||||||
|
* @property {String} `name` Name of the currently active scene.
|
||||||
|
* @property {Array<Source>} `sources` Ordered list of the current scene's source items.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch to the specified scene.
|
* Switch to the specified scene.
|
||||||
*
|
*
|
||||||
@ -34,7 +40,7 @@
|
|||||||
* 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 {Source|Array} `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
|
||||||
@ -56,7 +62,7 @@ void WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) {
|
|||||||
* Get a list of scenes in the currently active profile.
|
* Get a list of scenes in the currently active profile.
|
||||||
*
|
*
|
||||||
* @return {String} `current-scene` Name of the currently active scene.
|
* @return {String} `current-scene` Name of the currently active scene.
|
||||||
* @return {Scene|Array} `scenes` Ordered list of the current profile's scenes (See `[GetCurrentScene](#getcurrentscene)` for more information).
|
* @return {Array<Scene>} `scenes` Ordered list of the current profile's scenes (See `[GetCurrentScene](#getcurrentscene)` for more information).
|
||||||
*
|
*
|
||||||
* @api requests
|
* @api requests
|
||||||
* @name GetSceneList
|
* @name GetSceneList
|
||||||
@ -74,3 +80,69 @@ void WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) {
|
|||||||
|
|
||||||
req->SendOKResponse(data);
|
req->SendOKResponse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the order of scene items in the requested scene.
|
||||||
|
*
|
||||||
|
* @param {String (optional)} `scene` Name of the scene to reorder (defaults to current).
|
||||||
|
* @param {Scene|Array} `items` Ordered list of objects with name and/or id specified. Id preferred due to uniqueness per scene
|
||||||
|
* @param {int (optional)} `items[].id` Id of a specific scene item. Unique on a scene by scene basis.
|
||||||
|
* @param {String (optional)} `items[].name` Name of a scene item. Sufficiently unique if no scene items share sources within the scene.
|
||||||
|
*
|
||||||
|
* @api requests
|
||||||
|
* @name ReorderSceneItems
|
||||||
|
* @category scenes
|
||||||
|
* @since 4.5.0
|
||||||
|
*/
|
||||||
|
void WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req) {
|
||||||
|
QString sceneName = obs_data_get_string(req->data, "scene");
|
||||||
|
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName);
|
||||||
|
if (!scene) {
|
||||||
|
req->SendErrorResponse("requested scene doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSDataArrayAutoRelease items = obs_data_get_array(req->data, "items");
|
||||||
|
if (!items) {
|
||||||
|
req->SendErrorResponse("sceneItem order not specified");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t count = obs_data_array_count(items);
|
||||||
|
|
||||||
|
std::vector<obs_sceneitem_t*> newOrder;
|
||||||
|
newOrder.reserve(count);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
OBSDataAutoRelease item = obs_data_array_item(items, i);
|
||||||
|
|
||||||
|
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromItem(scene, item);
|
||||||
|
obs_sceneitem_release(sceneItem); // ref dec
|
||||||
|
|
||||||
|
if (!sceneItem) {
|
||||||
|
req->SendErrorResponse("Invalid sceneItem id or name specified");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = 0; j <= i; ++j) {
|
||||||
|
if (sceneItem == newOrder[j]) {
|
||||||
|
req->SendErrorResponse("Duplicate sceneItem in specified order");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newOrder.push_back(sceneItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = obs_scene_reorder_items(obs_scene_from_source(scene), newOrder.data(), count);
|
||||||
|
if (!success) {
|
||||||
|
req->SendErrorResponse("Invalid sceneItem order");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const& item: newOrder) {
|
||||||
|
obs_sceneitem_release(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
req->SendOKResponse();
|
||||||
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -252,7 +252,7 @@ void WSRequestHandler::HandleStopStreaming(WSRequestHandler* req) {
|
|||||||
* @return {Object} `settings` Stream settings object.
|
* @return {Object} `settings` Stream settings object.
|
||||||
* @return {String} `settings.server` The publish URL.
|
* @return {String} `settings.server` The publish URL.
|
||||||
* @return {String} `settings.key` The publish key of the stream.
|
* @return {String} `settings.key` The publish key of the stream.
|
||||||
* @return {boolean} `settings.use-auth` Indicates whether audentication should be used when connecting to the streaming server.
|
* @return {boolean} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.
|
||||||
* @return {String} `settings.username` The username to use when accessing the streaming server. Only present if `use-auth` is `true`.
|
* @return {String} `settings.username` The username to use when accessing the streaming server. Only present if `use-auth` is `true`.
|
||||||
* @return {String} `settings.password` The password to use when accessing the streaming server. Only present if `use-auth` is `true`.
|
* @return {String} `settings.password` The password to use when accessing the streaming server. Only present if `use-auth` is `true`.
|
||||||
*
|
*
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
* 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 {Source|Array} `sources`
|
* @return {Array<Source>} `sources`
|
||||||
*
|
*
|
||||||
* @api requests
|
* @api requests
|
||||||
* @name GetPreviewScene
|
* @name GetPreviewScene
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
* List of all transitions available in the frontend's dropdown menu.
|
* List of all transitions available in the frontend's dropdown menu.
|
||||||
*
|
*
|
||||||
* @return {String} `current-transition` Name of the currently active transition.
|
* @return {String} `current-transition` Name of the currently active transition.
|
||||||
* @return {Object|Array} `transitions` List of transitions.
|
* @return {Array<Object>} `transitions` List of transitions.
|
||||||
* @return {String} `transitions[].name` Name of the transition.
|
* @return {String} `transitions.*.name` Name of the transition.
|
||||||
*
|
*
|
||||||
* @api requests
|
* @api requests
|
||||||
* @name GetTransitionList
|
* @name GetTransitionList
|
||||||
|
@ -39,7 +39,7 @@ using OBSOutputAutoRelease =
|
|||||||
OBSRef<obs_output_t*, ___output_dummy_addref, obs_output_release>;
|
OBSRef<obs_output_t*, ___output_dummy_addref, obs_output_release>;
|
||||||
|
|
||||||
#define PROP_AUTHENTICATED "wsclient_authenticated"
|
#define PROP_AUTHENTICATED "wsclient_authenticated"
|
||||||
#define OBS_WEBSOCKET_VERSION "4.4.0"
|
#define OBS_WEBSOCKET_VERSION "4.5.0"
|
||||||
|
|
||||||
#define blog(level, msg, ...) blog(level, "[obs-websocket] " msg, ##__VA_ARGS__)
|
#define blog(level, msg, ...) blog(level, "[obs-websocket] " msg, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user