mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
Merge branch '4.x-current' into bugfix/crash-get-streaming-time
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@
|
||||
/build32/
|
||||
/build64/
|
||||
/release/
|
||||
/package/
|
||||
/installer/Output/
|
||||
.idea
|
||||
.vscode
|
||||
|
49
.travis.yml
49
.travis.yml
@ -1,49 +0,0 @@
|
||||
language: cpp
|
||||
|
||||
env:
|
||||
global:
|
||||
# AWS key ID
|
||||
- secure: pAiNUGVbjP12BfnWPk0FFTkbnk4Tocvv88XiT3rzRqkQaD7/iyEogLBfHM4nOEgFiIMHbC41aE83w5JgRNPwn6mTgoQBOglzqq1tGuXfqPyV2VStk8beji1evubGoVjjPaoPTFyIdQc5GGxdHyogI/ed9Hb3ccyykYvjyolj9XoCiW42QHx60AHGwl+So+dEa8xydj9SLRPlZ/AitmI/cPVN3YotA7s37BLFiab54enxk7T4rwpR1nU0HVfoCpn5F4wZYxRq+LlSVFzC8vVE9cpDSLS5kjrZIZaT18tYG1/untCj+wqMIZbghaJXLtPSRW2YPHcJTz8q1YSXnJ19+0uiAIMAqaVv0kD5BAM97byYDBW+b9H6SYFkb/Pw/qcK9amMzMBjDPFpYFkl9Q2kzhsNs3HsZf/flSZjtrkQJiP3SOi/KvKzVK9X4Wym6hYZWHgmMTTYFrvr6BYnf2GkpfKNjm1d2kc0NNrq4d5H4NOEQB8MP+QH+o+BPeM6d9dthrUc1Pw+BXzOAr85CN4qtpPGoAl/Dbfgd6eu/88E2LpUufW2VFAOPWjykSOqzSN3orh7AaWuE34VFEnQ+2y3uIE8AKoyXzJv6zYkyNnNewKZeGe2kKYNwLn5UxQA9JEj7a+tvVevk4xBSkkjFAvjSG2z8/F1FXNbEfoLX1Hz/bU=
|
||||
# AWS key secret
|
||||
- secure: bGwljoP3E1OVBXLXox0O6p8kwQXLcNQ8YDKVa4H8u9Y+Ic7uqE4iV3rYS3ynNWSBMVRWY3ZbyClnhrCNwRhBAlcd8qWSJdpjVzs6HdQyzhuKa1P3V4FJPb7upGP/5R/DECGwex8Mun9dmXpYDak75LxfKIJUidPis5VDCYqul7k/xVVCou6Ctjpj7vQhWXDj2G/py+mdB8DERhymnQCtyK1Ziu8c4QlFKByZmnD72GFm/h3JPI1Pq1V2mz3x6x6GaYjb9Rdbd0UNwqjGQX4q2M/c3GEJa6B2JBCoTncawNZBNnPUF9qtv+zh0TNaNHMRWX13AJ/qYB+nVDub0C9b/6Mc48mt0Tv4ze15MproVrylZdV6qHYEG8yGPBqpTVbRP6gv6Y2TXIHWoTzqA+F/Gv2IDChyHXsld/MQQS2MSo5iaYktIrZKtX8Z0qAmTzPwIVBromaSI3vrE7UH0fRSQ6fAM8+Tn+MRthOBdqu23kS1dnG+X2CPbUhBfsJp0OSwVQD5jQtA51/sREVeGFiJvzQIkvwQDjb5MYilsRnwmoBXemkLmqaviXVY4rz1o5AIvz2pgZS2YggK1xHZCuI5tSjcNEkb77VwZTfsqrdDo9EJh6VgfdnGlHQhR2/A5hUJ4ANpJ/LgZlgfVp71Xg2GWQW6M4Znc5uj6A6xLBkO6FA=
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
env: _generate_docs
|
||||
script: "./CI/generate-docs.sh"
|
||||
|
||||
- os: linux
|
||||
env: _linux_build
|
||||
dist: trusty
|
||||
sudo: required
|
||||
services:
|
||||
- docker
|
||||
before_install:
|
||||
- docker run -d --name xenial -v $(dirname $(pwd)):/root -v /home/travis/package:/package
|
||||
-e TRAVIS_BRANCH="$TRAVIS_BRANCH" -e TRAVIS_TAG="$TRAVIS_TAG" -w /root nimmis/ubuntu:16.04
|
||||
- docker exec -it xenial /root/obs-websocket/CI/install-dependencies-xenial.sh
|
||||
script:
|
||||
- docker exec -it xenial /root/obs-websocket/CI/build-xenial.sh
|
||||
after_success:
|
||||
- docker exec -it xenial /root/obs-websocket/CI/package-xenial.sh
|
||||
|
||||
deploy:
|
||||
- provider: s3
|
||||
region: eu-central-1
|
||||
bucket: obs-websocket-linux-builds
|
||||
access_key_id: "$AWS_ID"
|
||||
secret_access_key: "$AWS_SECRET"
|
||||
local_dir: /home/travis/package
|
||||
skip_cleanup: true
|
||||
acl: public_read
|
||||
on:
|
||||
repo: Palakis/obs-websocket
|
||||
condition:
|
||||
- "$TRAVIS_OS_NAME = linux"
|
||||
- "-d /home/travis/package"
|
||||
all_branches: true
|
@ -1,8 +1,6 @@
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
|
||||
cd /root/obs-websocket
|
||||
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
|
||||
make -j4
|
@ -18,25 +18,25 @@ REM Set up the build flag as undefined.
|
||||
set "BuildOBS="
|
||||
|
||||
REM Check the last tag successfully built by CI.
|
||||
if exist C:\projects\obs-studio-last-tag-built.txt (
|
||||
set /p OBSLastTagBuilt=<C:\projects\obs-studio-last-tag-built.txt
|
||||
if exist "%OBSPath%\obs-studio-last-tag-built.txt" (
|
||||
set /p OBSLastTagBuilt=<"%OBSPath%\obs-studio-last-tag-built.txt"
|
||||
) else (
|
||||
set OBSLastTagBuilt=0
|
||||
)
|
||||
|
||||
REM If obs-studio directory exists, run git pull and get the latest tag number.
|
||||
if exist C:\projects\obs-studio\ (
|
||||
if exist %OBSPath% (
|
||||
echo obs-studio directory exists
|
||||
echo Updating tag info
|
||||
cd C:\projects\obs-studio\
|
||||
git describe --tags --abbrev=0 --exclude="*-rc*" > C:\projects\latest-obs-studio-tag-pre-pull.txt
|
||||
set /p OBSLatestTagPrePull=<C:\projects\latest-obs-studio-tag-pre-pull.txt
|
||||
cd /D %OBSPath%
|
||||
git describe --tags --abbrev=0 --exclude="*-rc*" > "%OBSPath%\latest-obs-studio-tag-pre-pull.txt"
|
||||
set /p OBSLatestTagPrePull=<"%OBSPath%\latest-obs-studio-tag-pre-pull.txt"
|
||||
git checkout master
|
||||
git pull
|
||||
git describe --tags --abbrev=0 --exclude="*-rc*" > C:\projects\latest-obs-studio-tag-post-pull.txt
|
||||
set /p OBSLatestTagPostPull=<C:\projects\latest-obs-studio-tag-post-pull.txt
|
||||
set /p OBSLatestTag=<C:\projects\latest-obs-studio-tag-post-pull.txt
|
||||
echo %OBSLatestTagPostPull%> C:\projects\latest-obs-studio-tag.txt
|
||||
git describe --tags --abbrev=0 --exclude="*-rc*" > "%OBSPath%\latest-obs-studio-tag-post-pull.txt"
|
||||
set /p OBSLatestTagPostPull=<"%OBSPath%\latest-obs-studio-tag-post-pull.txt"
|
||||
set /p OBSLatestTag=<"%OBSPath%\latest-obs-studio-tag-post-pull.txt"
|
||||
echo %OBSLatestTagPostPull%> "%OBSPath%\latest-obs-studio-tag.txt"
|
||||
)
|
||||
|
||||
REM Check the obs-studio tags for mismatches.
|
||||
@ -58,22 +58,22 @@ if not %OBSLatestTagPostPull%==%OBSLastTagBuilt% (
|
||||
|
||||
REM If obs-studio directory does not exist, clone the git repo, get the latest
|
||||
REM tag number, and set the build flag.
|
||||
if not exist C:\projects\obs-studio (
|
||||
if not exist %OBSPath% (
|
||||
echo obs-studio directory does not exist
|
||||
git clone https://github.com/obsproject/obs-studio
|
||||
cd C:\projects\obs-studio\
|
||||
git describe --tags --abbrev=0 --exclude="*-rc*" > C:\projects\obs-studio-latest-tag.txt
|
||||
set /p OBSLatestTag=<C:\projects\obs-studio-latest-tag.txt
|
||||
git clone https://github.com/obsproject/obs-studio %OBSPath%
|
||||
cd /D %OBSPath%\
|
||||
git describe --tags --abbrev=0 --exclude="*-rc*" > "%OBSPath%\obs-studio-latest-tag.txt"
|
||||
set /p OBSLatestTag=<"%OBSPath%\obs-studio-latest-tag.txt"
|
||||
set BuildOBS=true
|
||||
)
|
||||
|
||||
REM If the needed obs-studio libs for this build_config do not exist,
|
||||
REM set the build flag.
|
||||
if not exist C:\projects\obs-studio\build32\libobs\%build_config%\obs.lib (
|
||||
if not exist %OBSPath%\build32\libobs\%build_config%\obs.lib (
|
||||
echo obs-studio\build32\libobs\%build_config%\obs.lib does not exist
|
||||
set BuildOBS=true
|
||||
)
|
||||
if not exist C:\projects\obs-studio\build32\UI\obs-frontend-api\%build_config%\obs-frontend-api.lib (
|
||||
if not exist %OBSPath%\build32\UI\obs-frontend-api\%build_config%\obs-frontend-api.lib (
|
||||
echo obs-studio\build32\UI\obs-frontend-api\%build_config%\obs-frontend-api.lib does not exist
|
||||
set BuildOBS=true
|
||||
)
|
||||
@ -95,35 +95,43 @@ echo:
|
||||
REM If the build flag is set, build obs-studio.
|
||||
if defined BuildOBS (
|
||||
echo Building obs-studio...
|
||||
cd /D %OBSPath%
|
||||
echo git checkout %OBSLatestTag%
|
||||
git checkout %OBSLatestTag%
|
||||
echo:
|
||||
|
||||
echo Removing previous build dirs...
|
||||
if exist build rmdir /s /q C:\projects\obs-studio\build
|
||||
if exist build32 rmdir /s /q C:\projects\obs-studio\build32
|
||||
if exist build64 rmdir /s /q C:\projects\obs-studio\build64
|
||||
if exist build32 rmdir /s /q "%OBSPath%\build32"
|
||||
if exist build64 rmdir /s /q "%OBSPath%\build64"
|
||||
|
||||
echo Making new build dirs...
|
||||
mkdir build
|
||||
mkdir build32
|
||||
mkdir build64
|
||||
|
||||
echo Running cmake for obs-studio %OBSLatestTag% 32-bit...
|
||||
cd ./build32
|
||||
cmake -G "Visual Studio 14 2015" -DBUILD_CAPTIONS=true -DDISABLE_PLUGINS=true -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true ..
|
||||
cd build32
|
||||
cmake -G "Visual Studio 16 2019" -A Win32 -DCMAKE_SYSTEM_VERSION=10.0 -DQTDIR="%QTDIR32%" -DDepsPath="%DepsPath32%" -DBUILD_CAPTIONS=true -DDISABLE_PLUGINS=true -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true ..
|
||||
echo:
|
||||
echo:
|
||||
|
||||
echo Running cmake for obs-studio %OBSLatestTag% 64-bit...
|
||||
cd ../build64
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DBUILD_CAPTIONS=true -DDISABLE_PLUGINS=true -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true ..
|
||||
cd ..\build64
|
||||
cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_SYSTEM_VERSION=10.0 -DQTDIR="%QTDIR64%" -DDepsPath="%DepsPath64%" -DBUILD_CAPTIONS=true -DDISABLE_PLUGINS=true -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true ..
|
||||
echo:
|
||||
echo:
|
||||
echo Building obs-studio %OBSLatestTag% 32-bit ^(Build Config: %build_config%^)...
|
||||
call msbuild /m /p:Configuration=%build_config% C:\projects\obs-studio\build32\obs-studio.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
echo Building obs-studio %OBSLatestTag% 64-bit ^(Build Config: %build_config%^)...
|
||||
call msbuild /m /p:Configuration=%build_config% C:\projects\obs-studio\build64\obs-studio.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
|
||||
REM echo Building obs-studio %OBSLatestTag% 32-bit ^(Build Config: %build_config%^)...
|
||||
REM call msbuild /m /p:Configuration=%build_config% %OBSPath%\build32\obs-studio.sln
|
||||
|
||||
REM echo Building obs-studio %OBSLatestTag% 64-bit ^(Build Config: %build_config%^)...
|
||||
REM call msbuild /m /p:Configuration=%build_config% %OBSPath%\build64\obs-studio.sln
|
||||
|
||||
cd ..
|
||||
git describe --tags --abbrev=0 > C:\projects\obs-studio-last-tag-built.txt
|
||||
set /p OBSLastTagBuilt=<C:\projects\obs-studio-last-tag-built.txt
|
||||
git describe --tags --abbrev=0 > "%OBSPath%\obs-studio-last-tag-built.txt"
|
||||
set /p OBSLastTagBuilt=<"%OBSPath%\obs-studio-last-tag-built.txt"
|
||||
) else (
|
||||
echo Last OBS tag built is: %OBSLastTagBuilt%
|
||||
echo No need to rebuild OBS.
|
||||
)
|
||||
|
||||
dir "%OBSPath%\libobs"
|
6
CI/download-obs-deps.cmd
Normal file
6
CI/download-obs-deps.cmd
Normal file
@ -0,0 +1,6 @@
|
||||
if not exist %DepsBasePath% (
|
||||
curl -o %DepsBasePath%.zip -kLO https://obsproject.com/downloads/dependencies2017.zip -f --retry 5 -C -
|
||||
7z x %DepsBasePath%.zip -o%DepsBasePath%
|
||||
) else (
|
||||
echo "OBS dependencies are already there. Download skipped."
|
||||
)
|
@ -4,6 +4,9 @@ echo "-- Generating documentation."
|
||||
echo "-- Node version: $(node -v)"
|
||||
echo "-- NPM version: $(npm -v)"
|
||||
|
||||
git fetch origin
|
||||
git checkout ${CHECKOUT_REF/refs\/heads\//}
|
||||
|
||||
cd docs
|
||||
npm install
|
||||
npm run build
|
||||
@ -15,19 +18,14 @@ if git diff --quiet; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
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."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
REMOTE_URL="$(git config remote.origin.url)"
|
||||
TARGET_REPO=${REMOTE_URL/https:\/\/github.com\//github.com/}
|
||||
GITHUB_REPO=https://${GH_TOKEN:-git}@${TARGET_REPO}
|
||||
|
||||
git config user.name "Travis CI"
|
||||
git config user.name "Azure CI"
|
||||
git config user.email "$COMMIT_AUTHOR_EMAIL"
|
||||
|
||||
git add ./generated
|
||||
git pull
|
||||
git commit -m "docs(travis): Update protocol.md - $(git rev-parse --short HEAD) [skip ci]"
|
||||
git push -q $GITHUB_REPO HEAD:$TRAVIS_BRANCH
|
||||
git commit -m "docs(ci): Update protocol.md - $(git rev-parse --short HEAD) [skip ci]"
|
||||
git push -q $GITHUB_REPO
|
||||
|
19
CI/install-dependencies-ubuntu.sh
Executable file
19
CI/install-dependencies-ubuntu.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
|
||||
sudo add-apt-repository -y ppa:obsproject/obs-studio
|
||||
sudo apt-get -qq update
|
||||
|
||||
sudo apt-get install -y \
|
||||
libc-dev-bin \
|
||||
libc6-dev git \
|
||||
build-essential \
|
||||
checkinstall \
|
||||
cmake \
|
||||
obs-studio \
|
||||
qtbase5-dev
|
||||
|
||||
# Dirty hack
|
||||
sudo wget -O /usr/include/obs/obs-frontend-api.h https://raw.githubusercontent.com/obsproject/obs-studio/25.0.0/UI/obs-frontend-api/obs-frontend-api.h
|
||||
|
||||
sudo ldconfig
|
@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
|
||||
add-apt-repository -y ppa:obsproject/obs-studio
|
||||
apt-get -qq update
|
||||
|
||||
apt-get install -y \
|
||||
libc-dev-bin \
|
||||
libc6-dev git \
|
||||
build-essential \
|
||||
checkinstall \
|
||||
cmake \
|
||||
obs-studio \
|
||||
qtbase5-dev
|
||||
|
||||
# Dirty hack
|
||||
wget -O /usr/include/obs/obs-frontend-api.h https://raw.githubusercontent.com/obsproject/obs-studio/master/UI/obs-frontend-api/obs-frontend-api.h
|
||||
|
||||
ldconfig
|
8
CI/install-qt-win.cmd
Normal file
8
CI/install-qt-win.cmd
Normal file
@ -0,0 +1,8 @@
|
||||
if not exist %QtBaseDir% (
|
||||
curl -kLO https://cdn-fastly.obsproject.com/downloads/Qt_5.10.1.7z -f --retry 5 -z Qt_5.10.1.7z
|
||||
7z x Qt_5.10.1.7z -o%QtBaseDir%
|
||||
) else (
|
||||
echo "Qt is already installed. Download skipped."
|
||||
)
|
||||
|
||||
dir %QtBaseDir%
|
@ -1,6 +0,0 @@
|
||||
@echo off
|
||||
|
||||
REM Set default values to use AppVeyor's built-in Qt.
|
||||
set QTDIR32=C:\Qt\5.10.1\msvc2015
|
||||
set QTDIR64=C:\Qt\5.10.1\msvc2015_64
|
||||
set QTCompileVersion=5.10.1
|
@ -19,7 +19,6 @@ export VERSION="$GIT_HASH-$GIT_BRANCH_OR_TAG"
|
||||
export LATEST_VERSION="$GIT_BRANCH_OR_TAG"
|
||||
|
||||
export FILENAME="obs-websocket-$VERSION.pkg"
|
||||
export LATEST_FILENAME="obs-websocket-latest-$LATEST_VERSION.pkg"
|
||||
|
||||
echo "[obs-websocket] Modifying obs-websocket.so"
|
||||
install_name_tool \
|
||||
@ -40,4 +39,3 @@ packagesbuild ./CI/macos/obs-websocket.pkgproj
|
||||
|
||||
echo "[obs-websocket] Renaming obs-websocket.pkg to $FILENAME"
|
||||
mv ./release/obs-websocket.pkg ./release/$FILENAME
|
||||
cp ./release/$FILENAME ./release/$LATEST_FILENAME
|
||||
|
23
CI/package-ubuntu.sh
Executable file
23
CI/package-ubuntu.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export GIT_HASH=$(git rev-parse --short HEAD)
|
||||
export PKG_VERSION="1-$GIT_HASH-$BRANCH_SHORT_NAME-git"
|
||||
|
||||
if [[ "$BRANCH_FULL_NAME" =~ "^refs/tags/" ]]; then
|
||||
export PKG_VERSION="$BRANCH_SHORT_NAME"
|
||||
fi
|
||||
|
||||
cd ./build
|
||||
|
||||
PAGER="cat" sudo checkinstall -y --type=debian --fstrans=no --nodoc \
|
||||
--backup=no --deldoc=yes --install=no \
|
||||
--pkgname=obs-websocket --pkgversion="$PKG_VERSION" \
|
||||
--pkglicense="GPLv2.0" --maintainer="stephane.lepin@gmail.com" \
|
||||
--pkggroup="video" \
|
||||
--pkgsource="https://github.com/Palakis/obs-websocket" \
|
||||
--requires="obs-studio,libqt5core5a,libqt5widgets5,qt5-image-formats-plugins" \
|
||||
--pakdir="../package"
|
||||
|
||||
sudo chmod ao+r ../package/*
|
12
CI/package-windows.cmd
Normal file
12
CI/package-windows.cmd
Normal file
@ -0,0 +1,12 @@
|
||||
mkdir package
|
||||
cd package
|
||||
|
||||
git rev-parse --short HEAD > package-version.txt
|
||||
set /p PackageVersion=<package-version.txt
|
||||
del package-version.txt
|
||||
|
||||
REM Package ZIP archive
|
||||
7z a "obs-websocket-%PackageVersion%-Windows.zip" "..\release\*"
|
||||
|
||||
REM Build installer
|
||||
iscc ..\installer\installer.iss /O. /F"obs-websocket-%PackageVersion%-Windows"
|
@ -1,24 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
cd /root/obs-websocket
|
||||
|
||||
export GIT_HASH=$(git rev-parse --short HEAD)
|
||||
export PKG_VERSION="1-$GIT_HASH-$TRAVIS_BRANCH-git"
|
||||
|
||||
if [ -n "${TRAVIS_TAG}" ]; then
|
||||
export PKG_VERSION="$TRAVIS_TAG"
|
||||
fi
|
||||
|
||||
cd /root/obs-websocket/build
|
||||
|
||||
PAGER=cat checkinstall -y --type=debian --fstrans=no --nodoc \
|
||||
--backup=no --deldoc=yes --install=no \
|
||||
--pkgname=obs-websocket --pkgversion="$PKG_VERSION" \
|
||||
--pkglicense="GPLv2.0" --maintainer="contact@slepin.fr" \
|
||||
--pkggroup="video" \
|
||||
--pkgsource="https://github.com/Palakis/obs-websocket" \
|
||||
--pakdir="/package"
|
||||
|
||||
chmod ao+r /package/*
|
7
CI/prepare-windows.cmd
Normal file
7
CI/prepare-windows.cmd
Normal file
@ -0,0 +1,7 @@
|
||||
mkdir build32
|
||||
mkdir build64
|
||||
|
||||
cd build32
|
||||
cmake -G "Visual Studio 16 2019" -A Win32 -DCMAKE_SYSTEM_VERSION=10.0 -DQTDIR="%QTDIR32%" -DLibObs_DIR="%OBSPath%\build32\libobs" -DLIBOBS_INCLUDE_DIR="%OBSPath%\libobs" -DLIBOBS_LIB="%OBSPath%\build32\libobs\%build_config%\obs.lib" -DOBS_FRONTEND_LIB="%OBSPath%\build32\UI\obs-frontend-api\%build_config%\obs-frontend-api.lib" ..
|
||||
cd ..\build64
|
||||
cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_SYSTEM_VERSION=10.0 -DQTDIR="%QTDIR64%" -DLibObs_DIR="%OBSPath%\build64\libobs" -DLIBOBS_INCLUDE_DIR="%OBSPath%\libobs" -DLIBOBS_LIB="%OBSPath%\build64\libobs\%build_config%\obs.lib" -DOBS_FRONTEND_LIB="%OBSPath%\build64\UI\obs-frontend-api\%build_config%\obs-frontend-api.lib" ..
|
@ -9,10 +9,6 @@ set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if (WIN32 OR APPLE)
|
||||
include(external/FindLibObs.cmake)
|
||||
endif()
|
||||
|
||||
add_definitions(-DASIO_STANDALONE)
|
||||
|
||||
if (WIN32 OR APPLE)
|
||||
@ -20,8 +16,7 @@ if (WIN32 OR APPLE)
|
||||
endif()
|
||||
|
||||
find_package(LibObs REQUIRED)
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core Widgets)
|
||||
|
||||
set(obs-websocket_SOURCES
|
||||
src/obs-websocket.cpp
|
||||
@ -89,6 +84,10 @@ if(WIN32)
|
||||
message(FATAL_ERROR "Could not find OBS Frontend API's library !")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options("/MP")
|
||||
endif()
|
||||
|
||||
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
@ -125,6 +124,16 @@ if(WIN32)
|
||||
"$<TARGET_FILE:obs-websocket>"
|
||||
"${RELEASE_DIR}/obs-plugins/${ARCH_NAME}")
|
||||
|
||||
# In Release mode, copy Qt image format plugins
|
||||
COMMAND if $<CONFIG:Release>==1 (
|
||||
"${CMAKE_COMMAND}" -E copy
|
||||
"${QTDIR}/plugins/imageformats/qjpeg.dll"
|
||||
"${RELEASE_DIR}/bin/${ARCH_NAME}/imageformats/qjpeg.dll")
|
||||
COMMAND if $<CONFIG:RelWithDebInfo>==1 (
|
||||
"${CMAKE_COMMAND}" -E copy
|
||||
"${QTDIR}/plugins/imageformats/qjpeg.dll"
|
||||
"${RELEASE_DIR}/bin/${ARCH_NAME}/imageformats/qjpeg.dll")
|
||||
|
||||
# If config is RelWithDebInfo, package release files
|
||||
COMMAND if $<CONFIG:RelWithDebInfo>==1 (
|
||||
"${CMAKE_COMMAND}" -E make_directory
|
||||
|
40
appveyor.yml
40
appveyor.yml
@ -1,40 +0,0 @@
|
||||
environment:
|
||||
CURL_VERSION: 7.39.0
|
||||
|
||||
install:
|
||||
- git submodule update --init --recursive
|
||||
- cd C:\projects\
|
||||
- if not exist dependencies2015.zip curl -kLO https://obsproject.com/downloads/dependencies2015.zip -f --retry 5 -C -
|
||||
- 7z x dependencies2015.zip -odependencies2015
|
||||
- set DepsPath32=%CD%\dependencies2015\win32
|
||||
- set DepsPath64=%CD%\dependencies2015\win64
|
||||
- call C:\projects\obs-websocket\CI\install-setup-qt.cmd
|
||||
- set build_config=RelWithDebInfo
|
||||
- call C:\projects\obs-websocket\CI\install-build-obs.cmd
|
||||
- cd C:\projects\obs-websocket\
|
||||
- mkdir build32
|
||||
- mkdir build64
|
||||
- cd ./build32
|
||||
- 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
|
||||
- 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:
|
||||
- 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\build64\obs-websocket.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
|
||||
before_deploy:
|
||||
- 7z a "C:\projects\obs-websocket\build.zip" C:\projects\obs-websocket\release\*
|
||||
- set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5"
|
||||
- iscc "C:\projects\obs-websocket\installer\installer.iss"
|
||||
|
||||
deploy_script:
|
||||
- ps: Push-AppveyorArtifact "C:\projects\obs-websocket\build.zip" -FileName "obs-websocket-$(git log --pretty=format:'%h' -n 1)-Windows.zip"
|
||||
- ps: Push-AppveyorArtifact "C:\projects\obs-websocket\installer\Output\obs-websocket-Windows-Installer.exe" -FileName "obs-websocket-$(git log --pretty=format:'%h' -n 1)-Windows-Installer.exe"
|
||||
|
||||
test: off
|
||||
|
||||
cache:
|
||||
- C:\projects\dependencies2015.zip
|
||||
- C:\projects\obs-studio-last-tag-built.txt
|
||||
- C:\projects\obs-studio\
|
@ -1,23 +1,158 @@
|
||||
pool:
|
||||
vmImage: 'macOS-10.13'
|
||||
jobs:
|
||||
- job: 'GenerateDocs'
|
||||
condition: |
|
||||
or(
|
||||
eq(variables['Build.SourceBranch'], 'refs/heads/4.x-current'),
|
||||
eq(variables['Build.SourceBranch'], 'refs/heads/master')
|
||||
)
|
||||
pool:
|
||||
vmImage: 'ubuntu-18.04'
|
||||
steps:
|
||||
- checkout: self
|
||||
submodules: false
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
- script: ./CI/generate-docs.sh
|
||||
displayName: 'Generate docs'
|
||||
env:
|
||||
CHECKOUT_REF: $(Build.SourceBranch)
|
||||
GH_TOKEN: $(GithubToken)
|
||||
|
||||
- job: 'Build_Windows'
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
variables:
|
||||
build_config: RelWithDebInfo
|
||||
DepsBasePath: 'D:\obsdependencies'
|
||||
DepsPath32: '$(DepsBasePath)\win32'
|
||||
DepsPath64: '$(DepsBasePath)\win64'
|
||||
QtBaseDir: 'D:\QtDep'
|
||||
QTDIR32: '$(QtBaseDir)\5.10.1\msvc2017'
|
||||
QTDIR64: '$(QtBaseDir)\5.10.1\msvc2017_64'
|
||||
OBSPath: 'D:\obs-studio'
|
||||
steps:
|
||||
- checkout: self
|
||||
submodules: true
|
||||
|
||||
- script: ./CI/install-dependencies-macos.sh
|
||||
displayName: 'Install Dependencies'
|
||||
- script: ./CI/install-qt-win.cmd
|
||||
displayName: 'Install Qt'
|
||||
env:
|
||||
QtBaseDir: $(QtBaseDir)
|
||||
|
||||
- script: ./CI/install-build-obs-macos.sh
|
||||
displayName: 'Build OBS'
|
||||
- task: Cache@2
|
||||
displayName: Restore cached OBS Studio dependencies
|
||||
inputs:
|
||||
key: 'obsdeps | "$(Agent.OS)"'
|
||||
restoreKeys: |
|
||||
obsdeps | "$(Agent.OS)"
|
||||
path: $(DepsBasePath)
|
||||
|
||||
- script: ./CI/build-macos.sh
|
||||
- script: ./CI/download-obs-deps.cmd
|
||||
displayName: 'Download OBS Studio dependencies'
|
||||
|
||||
- task: Cache@2
|
||||
displayName: Restore cached OBS Studio builds
|
||||
inputs:
|
||||
key: 'obs | "$(Agent.OS)"'
|
||||
restoreKeys: |
|
||||
obs | "$(Agent.OS)"
|
||||
path: $(OBSPath)
|
||||
|
||||
- script: ./CI/checkout-cmake-obs-windows.cmd
|
||||
displayName: 'Checkout & CMake OBS Studio'
|
||||
env:
|
||||
build_config: $(build_config)
|
||||
DepsPath32: $(DepsPath32)
|
||||
DepsPath64: $(DepsPath64)
|
||||
QTDIR32: $(QTDIR32)
|
||||
QTDIR64: $(QTDIR64)
|
||||
OBSPath: $(OBSPath)
|
||||
|
||||
- task: MSBuild@1
|
||||
displayName: 'Build OBS Studio 32-bit'
|
||||
inputs:
|
||||
msbuildArguments: '/m /p:Configuration=$(build_config)'
|
||||
solution: '$(OBSPath)\build32\obs-studio.sln'
|
||||
|
||||
- task: MSBuild@1
|
||||
displayName: 'Build OBS Studio 64-bit'
|
||||
inputs:
|
||||
msbuildArguments: '/m /p:Configuration=$(build_config)'
|
||||
solution: '$(OBSPath)\build64\obs-studio.sln'
|
||||
|
||||
- script: ./CI/prepare-windows.cmd
|
||||
displayName: 'CMake obs-websocket'
|
||||
env:
|
||||
build_config: $(build_config)
|
||||
QTDIR32: $(QTDIR32)
|
||||
QTDIR64: $(QTDIR64)
|
||||
OBSPath: $(OBSPath)
|
||||
|
||||
- task: MSBuild@1
|
||||
displayName: 'Build obs-websocket 32-bit'
|
||||
inputs:
|
||||
msbuildArguments: '/m /p:Configuration=$(build_config)'
|
||||
solution: '.\build32\obs-websocket.sln'
|
||||
|
||||
- task: MSBuild@1
|
||||
displayName: 'Build obs-websocket 64-bit'
|
||||
inputs:
|
||||
msbuildArguments: '/m /p:Configuration=$(build_config)'
|
||||
solution: '.\build64\obs-websocket.sln'
|
||||
|
||||
- script: ./CI/package-windows.cmd
|
||||
displayName: 'Package obs-websocket'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Upload package artifacts'
|
||||
inputs:
|
||||
pathtoPublish: './package'
|
||||
artifactName: 'windows_build'
|
||||
|
||||
- job: 'Build_Linux'
|
||||
pool:
|
||||
vmImage: 'ubuntu-18.04'
|
||||
variables:
|
||||
BUILD_REASON: $(Build.Reason)
|
||||
BRANCH_SHORT_NAME: $(Build.SourceBranchName)
|
||||
BRANCH_FULL_NAME: $(Build.SourceBranch)
|
||||
steps:
|
||||
- checkout: self
|
||||
submodules: true
|
||||
|
||||
- script: ./CI/install-dependencies-ubuntu.sh
|
||||
displayName: 'Install dependencies'
|
||||
|
||||
- script: ./CI/build-ubuntu.sh
|
||||
displayName: 'Build obs-websocket'
|
||||
|
||||
- script: ./CI/package-macos.sh
|
||||
displayName: 'Package'
|
||||
- script: ./CI/package-ubuntu.sh
|
||||
displayName: 'Package obs-websocket'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathtoPublish: './package'
|
||||
artifactName: 'deb_build'
|
||||
|
||||
- job: 'Build_macOS'
|
||||
pool:
|
||||
vmImage: 'macos-10.14'
|
||||
steps:
|
||||
- checkout: self
|
||||
submodules: true
|
||||
|
||||
- script: ./CI/install-dependencies-macos.sh
|
||||
displayName: 'Install dependencies'
|
||||
|
||||
- script: ./CI/install-build-obs-macos.sh
|
||||
displayName: 'Build OBS'
|
||||
|
||||
- script: ./CI/build-macos.sh
|
||||
displayName: 'Build obs-websocket'
|
||||
|
||||
- script: ./CI/package-macos.sh
|
||||
displayName: 'Package obs-websocket'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathtoPublish: './release'
|
||||
artifactName: 'build'
|
||||
artifactName: 'macos_build'
|
||||
|
@ -6,9 +6,11 @@
|
||||
"property": [
|
||||
"{Number} `cy`",
|
||||
"{Number} `cx`",
|
||||
"{Number} `alignment` The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis.",
|
||||
"{String} `name` The name of this Scene Item.",
|
||||
"{int} `id` Scene item ID",
|
||||
"{Boolean} `render` Whether or not this Scene Item is set to \"visible\".",
|
||||
"{Boolean} `muted` Whether or not this Scene Item is muted.",
|
||||
"{Boolean} `locked` Whether or not this Scene Item is locked and can't be moved around",
|
||||
"{Number} `source_cx`",
|
||||
"{Number} `source_cy`",
|
||||
@ -30,6 +32,11 @@
|
||||
"name": "cx",
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"type": "Number",
|
||||
"name": "alignment",
|
||||
"description": "The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis."
|
||||
},
|
||||
{
|
||||
"type": "String",
|
||||
"name": "name",
|
||||
@ -45,6 +52,11 @@
|
||||
"name": "render",
|
||||
"description": "Whether or not this Scene Item is set to \"visible\"."
|
||||
},
|
||||
{
|
||||
"type": "Boolean",
|
||||
"name": "muted",
|
||||
"description": "Whether or not this Scene Item is muted."
|
||||
},
|
||||
{
|
||||
"type": "Boolean",
|
||||
"name": "locked",
|
||||
@ -769,7 +781,7 @@
|
||||
"return": [
|
||||
"{String} `name` Transition name.",
|
||||
"{String} `type` Transition type.",
|
||||
"{int} `duration` Transition duration (in milliseconds).",
|
||||
"{int} `duration` Transition duration (in milliseconds). Will be -1 for any transition with a fixed duration, such as a Stinger, due to limitations of the OBS API.",
|
||||
"{String} `from-scene` Source scene of the transition",
|
||||
"{String} `to-scene` Destination scene of the transition"
|
||||
],
|
||||
@ -791,7 +803,7 @@
|
||||
{
|
||||
"type": "int",
|
||||
"name": "duration",
|
||||
"description": "Transition duration (in milliseconds)."
|
||||
"description": "Transition duration (in milliseconds). Will be -1 for any transition with a fixed duration, such as a Stinger, due to limitations of the OBS API."
|
||||
},
|
||||
{
|
||||
"type": "String",
|
||||
@ -829,6 +841,134 @@
|
||||
"lead": "",
|
||||
"type": "class",
|
||||
"examples": []
|
||||
},
|
||||
{
|
||||
"subheads": [],
|
||||
"description": "A transition (other than \"cut\") has ended.\nPlease note that the `from-scene` field is not available in TransitionEnd.",
|
||||
"return": [
|
||||
"{String} `name` Transition name.",
|
||||
"{String} `type` Transition type.",
|
||||
"{int} `duration` Transition duration (in milliseconds).",
|
||||
"{String} `to-scene` Destination scene of the transition"
|
||||
],
|
||||
"api": "events",
|
||||
"name": "TransitionEnd",
|
||||
"category": "transitions",
|
||||
"since": "4.8.0",
|
||||
"returns": [
|
||||
{
|
||||
"type": "String",
|
||||
"name": "name",
|
||||
"description": "Transition name."
|
||||
},
|
||||
{
|
||||
"type": "String",
|
||||
"name": "type",
|
||||
"description": "Transition type."
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"name": "duration",
|
||||
"description": "Transition duration (in milliseconds)."
|
||||
},
|
||||
{
|
||||
"type": "String",
|
||||
"name": "to-scene",
|
||||
"description": "Destination scene of the transition"
|
||||
}
|
||||
],
|
||||
"names": [
|
||||
{
|
||||
"name": "",
|
||||
"description": "TransitionEnd"
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"name": "",
|
||||
"description": "transitions"
|
||||
}
|
||||
],
|
||||
"sinces": [
|
||||
{
|
||||
"name": "",
|
||||
"description": "4.8.0"
|
||||
}
|
||||
],
|
||||
"heading": {
|
||||
"level": 2,
|
||||
"text": "TransitionEnd"
|
||||
},
|
||||
"lead": "",
|
||||
"type": "class",
|
||||
"examples": []
|
||||
},
|
||||
{
|
||||
"subheads": [],
|
||||
"description": "A stinger transition has finished playing its video.",
|
||||
"return": [
|
||||
"{String} `name` Transition name.",
|
||||
"{String} `type` Transition type.",
|
||||
"{int} `duration` Transition duration (in milliseconds).",
|
||||
"{String} `from-scene` Source scene of the transition",
|
||||
"{String} `to-scene` Destination scene of the transition"
|
||||
],
|
||||
"api": "events",
|
||||
"name": "TransitionVideoEnd",
|
||||
"category": "transitions",
|
||||
"since": "4.8.0",
|
||||
"returns": [
|
||||
{
|
||||
"type": "String",
|
||||
"name": "name",
|
||||
"description": "Transition name."
|
||||
},
|
||||
{
|
||||
"type": "String",
|
||||
"name": "type",
|
||||
"description": "Transition type."
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"name": "duration",
|
||||
"description": "Transition duration (in milliseconds)."
|
||||
},
|
||||
{
|
||||
"type": "String",
|
||||
"name": "from-scene",
|
||||
"description": "Source scene of the transition"
|
||||
},
|
||||
{
|
||||
"type": "String",
|
||||
"name": "to-scene",
|
||||
"description": "Destination scene of the transition"
|
||||
}
|
||||
],
|
||||
"names": [
|
||||
{
|
||||
"name": "",
|
||||
"description": "TransitionVideoEnd"
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"name": "",
|
||||
"description": "transitions"
|
||||
}
|
||||
],
|
||||
"sinces": [
|
||||
{
|
||||
"name": "",
|
||||
"description": "4.8.0"
|
||||
}
|
||||
],
|
||||
"heading": {
|
||||
"level": 2,
|
||||
"text": "TransitionVideoEnd"
|
||||
},
|
||||
"lead": "",
|
||||
"type": "class",
|
||||
"examples": []
|
||||
}
|
||||
],
|
||||
"profiles": [
|
||||
@ -2566,6 +2706,67 @@
|
||||
"type": "class",
|
||||
"examples": []
|
||||
},
|
||||
{
|
||||
"subheads": [],
|
||||
"description": "An item's locked status has been toggled.",
|
||||
"return": [
|
||||
"{String} `scene-name` Name of the scene.",
|
||||
"{String} `item-name` Name of the item in the scene.",
|
||||
"{int} `item-id` Scene item ID",
|
||||
"{boolean} `item-locked` New locked state of the item."
|
||||
],
|
||||
"api": "events",
|
||||
"name": "SceneItemLockChanged",
|
||||
"category": "sources",
|
||||
"since": "unreleased",
|
||||
"returns": [
|
||||
{
|
||||
"type": "String",
|
||||
"name": "scene-name",
|
||||
"description": "Name of the scene."
|
||||
},
|
||||
{
|
||||
"type": "String",
|
||||
"name": "item-name",
|
||||
"description": "Name of the item in the scene."
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"name": "item-id",
|
||||
"description": "Scene item ID"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"name": "item-locked",
|
||||
"description": "New locked state of the item."
|
||||
}
|
||||
],
|
||||
"names": [
|
||||
{
|
||||
"name": "",
|
||||
"description": "SceneItemLockChanged"
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"name": "",
|
||||
"description": "sources"
|
||||
}
|
||||
],
|
||||
"sinces": [
|
||||
{
|
||||
"name": "",
|
||||
"description": "unreleased"
|
||||
}
|
||||
],
|
||||
"heading": {
|
||||
"level": 2,
|
||||
"text": "SceneItemLockChanged"
|
||||
},
|
||||
"lead": "",
|
||||
"type": "class",
|
||||
"examples": []
|
||||
},
|
||||
{
|
||||
"subheads": [],
|
||||
"description": "An item's transform has been changed.",
|
||||
@ -2840,7 +3041,8 @@
|
||||
"{double} `version` OBSRemote compatible API version. Fixed to 1.1 for retrocompatibility.",
|
||||
"{String} `obs-websocket-version` obs-websocket plugin version.",
|
||||
"{String} `obs-studio-version` OBS Studio program version.",
|
||||
"{String} `available-requests` List of available request types, formatted as a comma-separated list string (e.g. : \"Method1,Method2,Method3\")."
|
||||
"{String} `available-requests` List of available request types, formatted as a comma-separated list string (e.g. : \"Method1,Method2,Method3\").",
|
||||
"{String} `supported-image-export-formats` List of supported formats for features that use image export (like the TakeSourceScreenshot request type) formatted as a comma-separated list string"
|
||||
],
|
||||
"api": "requests",
|
||||
"name": "GetVersion",
|
||||
@ -2866,6 +3068,11 @@
|
||||
"type": "String",
|
||||
"name": "available-requests",
|
||||
"description": "List of available request types, formatted as a comma-separated list string (e.g. : \"Method1,Method2,Method3\")."
|
||||
},
|
||||
{
|
||||
"type": "String",
|
||||
"name": "supported-image-export-formats",
|
||||
"description": "List of supported formats for features that use image export (like the TakeSourceScreenshot request type) formatted as a comma-separated list string"
|
||||
}
|
||||
],
|
||||
"names": [
|
||||
@ -3293,6 +3500,67 @@
|
||||
"lead": "",
|
||||
"type": "class",
|
||||
"examples": []
|
||||
},
|
||||
{
|
||||
"subheads": [],
|
||||
"description": "Open a projector window or create a projector on a monitor. Requires OBS v24.0.4 or newer.",
|
||||
"param": [
|
||||
"{String (Optional)} `type` Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive).",
|
||||
"{int (Optional)} `monitor` Monitor to open the projector on. If -1 or omitted, opens a window.",
|
||||
"{String (Optional)} `geometry` Size and position of the projector window (only if monitor is -1). Encoded in Base64 using Qt's geometry encoding (https://doc.qt.io/qt-5/qwidget.html#saveGeometry). Corresponds to OBS's saved projectors.",
|
||||
"{String (Optional)} `name` Name of the source or scene to be displayed (ignored for other projector types)."
|
||||
],
|
||||
"api": "requests",
|
||||
"name": "OpenProjector",
|
||||
"category": "general",
|
||||
"since": "unreleased",
|
||||
"params": [
|
||||
{
|
||||
"type": "String (Optional)",
|
||||
"name": "type",
|
||||
"description": "Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive)."
|
||||
},
|
||||
{
|
||||
"type": "int (Optional)",
|
||||
"name": "monitor",
|
||||
"description": "Monitor to open the projector on. If -1 or omitted, opens a window."
|
||||
},
|
||||
{
|
||||
"type": "String (Optional)",
|
||||
"name": "geometry",
|
||||
"description": "Size and position of the projector window (only if monitor is -1). Encoded in Base64 using Qt's geometry encoding (https://doc.qt.io/qt-5/qwidget.html#saveGeometry). Corresponds to OBS's saved projectors."
|
||||
},
|
||||
{
|
||||
"type": "String (Optional)",
|
||||
"name": "name",
|
||||
"description": "Name of the source or scene to be displayed (ignored for other projector types)."
|
||||
}
|
||||
],
|
||||
"names": [
|
||||
{
|
||||
"name": "",
|
||||
"description": "OpenProjector"
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"name": "",
|
||||
"description": "general"
|
||||
}
|
||||
],
|
||||
"sinces": [
|
||||
{
|
||||
"name": "",
|
||||
"description": "unreleased"
|
||||
}
|
||||
],
|
||||
"heading": {
|
||||
"level": 2,
|
||||
"text": "OpenProjector"
|
||||
},
|
||||
"lead": "",
|
||||
"type": "class",
|
||||
"examples": []
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
@ -4131,6 +4399,7 @@
|
||||
"{int} `crop.bottom` The number of pixels cropped off the bottom of the source before scaling.",
|
||||
"{int} `crop.left` The number of pixels cropped off the left of the source before scaling.",
|
||||
"{bool} `visible` If the source is visible.",
|
||||
"{bool} `muted` If the source is muted.",
|
||||
"{bool} `locked` If the source's transform is locked.",
|
||||
"{String} `bounds.type` Type of bounding box. Can be \"OBS_BOUNDS_STRETCH\", \"OBS_BOUNDS_SCALE_INNER\", \"OBS_BOUNDS_SCALE_OUTER\", \"OBS_BOUNDS_SCALE_TO_WIDTH\", \"OBS_BOUNDS_SCALE_TO_HEIGHT\", \"OBS_BOUNDS_MAX_ONLY\" or \"OBS_BOUNDS_NONE\".",
|
||||
"{int} `bounds.alignment` Alignment of the bounding box.",
|
||||
@ -4139,9 +4408,8 @@
|
||||
"{int} `sourceWidth` Base width (without scaling) of the source",
|
||||
"{int} `sourceHeight` Base source (without scaling) of the source",
|
||||
"{double} `width` Scene item width (base source width multiplied by the horizontal scaling factor)",
|
||||
"{double} `height` Scene item height (base source height multiplied by the vertical scaling factor)"
|
||||
],
|
||||
"property": [
|
||||
"{double} `height` Scene item height (base source height multiplied by the vertical scaling factor)",
|
||||
"{int} `alignment` The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis.",
|
||||
"{String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group)",
|
||||
"{Array<SceneItemTransform> (optional)} `groupChildren` List of children (if this item is a group)"
|
||||
],
|
||||
@ -4210,6 +4478,11 @@
|
||||
"name": "visible",
|
||||
"description": "If the source is visible."
|
||||
},
|
||||
{
|
||||
"type": "bool",
|
||||
"name": "muted",
|
||||
"description": "If the source is muted."
|
||||
},
|
||||
{
|
||||
"type": "bool",
|
||||
"name": "locked",
|
||||
@ -4254,6 +4527,21 @@
|
||||
"type": "double",
|
||||
"name": "height",
|
||||
"description": "Scene item height (base source height multiplied by the vertical scaling factor)"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"name": "alignment",
|
||||
"description": "The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis."
|
||||
},
|
||||
{
|
||||
"type": "String (optional)",
|
||||
"name": "parentGroupName",
|
||||
"description": "Name of the item's parent (if this item belongs to a group)"
|
||||
},
|
||||
{
|
||||
"type": "Array<SceneItemTransform> (optional)",
|
||||
"name": "groupChildren",
|
||||
"description": "List of children (if this item is a group)"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
@ -4268,18 +4556,6 @@
|
||||
"description": "The name of the source."
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"type": "String (optional)",
|
||||
"name": "parentGroupName",
|
||||
"description": "Name of the item's parent (if this item belongs to a group)"
|
||||
},
|
||||
{
|
||||
"type": "Array<SceneItemTransform> (optional)",
|
||||
"name": "groupChildren",
|
||||
"description": "List of children (if this item is a group)"
|
||||
}
|
||||
],
|
||||
"names": [
|
||||
{
|
||||
"name": "",
|
||||
@ -7477,9 +7753,9 @@
|
||||
"{Object (optional)} `stream.settings` Settings for the stream.",
|
||||
"{String (optional)} `stream.settings.server` The publish URL.",
|
||||
"{String (optional)} `stream.settings.key` The publish key of the stream.",
|
||||
"{boolean (optional)} `stream.settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.",
|
||||
"{String (optional)} `stream.settings.username` If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`.",
|
||||
"{String (optional)} `stream.settings.password` If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`."
|
||||
"{boolean (optional)} `stream.settings.use_auth` Indicates whether authentication should be used when connecting to the streaming server.",
|
||||
"{String (optional)} `stream.settings.username` If authentication is enabled, the username for the streaming server. Ignored if `use_auth` is not set to `true`.",
|
||||
"{String (optional)} `stream.settings.password` If authentication is enabled, the password for the streaming server. Ignored if `use_auth` is not set to `true`."
|
||||
],
|
||||
"api": "requests",
|
||||
"name": "StartStreaming",
|
||||
@ -7518,18 +7794,18 @@
|
||||
},
|
||||
{
|
||||
"type": "boolean (optional)",
|
||||
"name": "stream.settings.use-auth",
|
||||
"name": "stream.settings.use_auth",
|
||||
"description": "Indicates whether authentication should be used when connecting to the streaming server."
|
||||
},
|
||||
{
|
||||
"type": "String (optional)",
|
||||
"name": "stream.settings.username",
|
||||
"description": "If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`."
|
||||
"description": "If authentication is enabled, the username for the streaming server. Ignored if `use_auth` is not set to `true`."
|
||||
},
|
||||
{
|
||||
"type": "String (optional)",
|
||||
"name": "stream.settings.password",
|
||||
"description": "If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`."
|
||||
"description": "If authentication is enabled, the password for the streaming server. Ignored if `use_auth` is not set to `true`."
|
||||
}
|
||||
],
|
||||
"names": [
|
||||
@ -7599,7 +7875,7 @@
|
||||
"{Object} `settings` The actual settings of the stream.",
|
||||
"{String (optional)} `settings.server` The publish URL.",
|
||||
"{String (optional)} `settings.key` The publish key.",
|
||||
"{boolean (optional)} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.",
|
||||
"{boolean (optional)} `settings.use_auth` Indicates whether authentication should be used when connecting to the streaming server.",
|
||||
"{String (optional)} `settings.username` The username for the streaming service.",
|
||||
"{String (optional)} `settings.password` The password for the streaming service.",
|
||||
"{boolean} `save` Persist the settings to disk."
|
||||
@ -7631,7 +7907,7 @@
|
||||
},
|
||||
{
|
||||
"type": "boolean (optional)",
|
||||
"name": "settings.use-auth",
|
||||
"name": "settings.use_auth",
|
||||
"description": "Indicates whether authentication should be used when connecting to the streaming server."
|
||||
},
|
||||
{
|
||||
@ -7684,9 +7960,9 @@
|
||||
"{Object} `settings` Stream settings object.",
|
||||
"{String} `settings.server` The publish URL.",
|
||||
"{String} `settings.key` The publish key of the stream.",
|
||||
"{boolean} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.",
|
||||
"{String} `settings.username` The username to use when accessing the streaming server. Only present if `use-auth` is `true`.",
|
||||
"{String} `settings.password` The password to use when accessing the streaming server. Only present if `use-auth` is `true`."
|
||||
"{boolean} `settings.use_auth` Indicates whether authentication should be used when connecting to the streaming server.",
|
||||
"{String} `settings.username` The username to use when accessing the streaming server. Only present if `use_auth` is `true`.",
|
||||
"{String} `settings.password` The password to use when accessing the streaming server. Only present if `use_auth` is `true`."
|
||||
],
|
||||
"api": "requests",
|
||||
"name": "GetStreamSettings",
|
||||
@ -7715,18 +7991,18 @@
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"name": "settings.use-auth",
|
||||
"name": "settings.use_auth",
|
||||
"description": "Indicates whether authentication should be used when connecting to the streaming server."
|
||||
},
|
||||
{
|
||||
"type": "String",
|
||||
"name": "settings.username",
|
||||
"description": "The username to use when accessing the streaming server. Only present if `use-auth` is `true`."
|
||||
"description": "The username to use when accessing the streaming server. Only present if `use_auth` is `true`."
|
||||
},
|
||||
{
|
||||
"type": "String",
|
||||
"name": "settings.password",
|
||||
"description": "The password to use when accessing the streaming server. Only present if `use-auth` is `true`."
|
||||
"description": "The password to use when accessing the streaming server. Only present if `use_auth` is `true`."
|
||||
}
|
||||
],
|
||||
"names": [
|
||||
|
@ -59,6 +59,8 @@ auth_response = base64_encode(auth_response_hash)
|
||||
+ [TransitionListChanged](#transitionlistchanged)
|
||||
+ [TransitionDurationChanged](#transitiondurationchanged)
|
||||
+ [TransitionBegin](#transitionbegin)
|
||||
+ [TransitionEnd](#transitionend)
|
||||
+ [TransitionVideoEnd](#transitionvideoend)
|
||||
* [Profiles](#profiles)
|
||||
+ [ProfileChanged](#profilechanged)
|
||||
+ [ProfileListChanged](#profilelistchanged)
|
||||
@ -101,6 +103,7 @@ auth_response = base64_encode(auth_response_hash)
|
||||
+ [SceneItemAdded](#sceneitemadded)
|
||||
+ [SceneItemRemoved](#sceneitemremoved)
|
||||
+ [SceneItemVisibilityChanged](#sceneitemvisibilitychanged)
|
||||
+ [SceneItemLockChanged](#sceneitemlockchanged)
|
||||
+ [SceneItemTransformChanged](#sceneitemtransformchanged)
|
||||
+ [SceneItemSelected](#sceneitemselected)
|
||||
+ [SceneItemDeselected](#sceneitemdeselected)
|
||||
@ -118,6 +121,7 @@ auth_response = base64_encode(auth_response_hash)
|
||||
+ [GetStats](#getstats)
|
||||
+ [BroadcastCustomMessage](#broadcastcustommessage-1)
|
||||
+ [GetVideoInfo](#getvideoinfo)
|
||||
+ [OpenProjector](#openprojector)
|
||||
* [Outputs](#outputs)
|
||||
+ [ListOutputs](#listoutputs)
|
||||
+ [GetOutputInfo](#getoutputinfo)
|
||||
@ -222,9 +226,11 @@ These are complex types, such as `Source` and `Scene`, which are used as argumen
|
||||
| ---- | :---: | ------------|
|
||||
| `cy` | _Number_ | |
|
||||
| `cx` | _Number_ | |
|
||||
| `alignment` | _Number_ | The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis. |
|
||||
| `name` | _String_ | The name of this Scene Item. |
|
||||
| `id` | _int_ | Scene item ID |
|
||||
| `render` | _Boolean_ | Whether or not this Scene Item is set to "visible". |
|
||||
| `muted` | _Boolean_ | Whether or not this Scene Item is muted. |
|
||||
| `locked` | _Boolean_ | Whether or not this Scene Item is locked and can't be moved around |
|
||||
| `source_cx` | _Number_ | |
|
||||
| `source_cy` | _Number_ | |
|
||||
@ -429,6 +435,46 @@ A transition (other than "cut") has begun.
|
||||
|
||||
**Response Items:**
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | :---: | ------------|
|
||||
| `name` | _String_ | Transition name. |
|
||||
| `type` | _String_ | Transition type. |
|
||||
| `duration` | _int_ | Transition duration (in milliseconds). Will be -1 for any transition with a fixed duration, such as a Stinger, due to limitations of the OBS API. |
|
||||
| `from-scene` | _String_ | Source scene of the transition |
|
||||
| `to-scene` | _String_ | Destination scene of the transition |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### TransitionEnd
|
||||
|
||||
|
||||
- Added in v4.8.0
|
||||
|
||||
A transition (other than "cut") has ended.
|
||||
Please note that the `from-scene` field is not available in TransitionEnd.
|
||||
|
||||
**Response Items:**
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | :---: | ------------|
|
||||
| `name` | _String_ | Transition name. |
|
||||
| `type` | _String_ | Transition type. |
|
||||
| `duration` | _int_ | Transition duration (in milliseconds). |
|
||||
| `to-scene` | _String_ | Destination scene of the transition |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### TransitionVideoEnd
|
||||
|
||||
|
||||
- Added in v4.8.0
|
||||
|
||||
A stinger transition has finished playing its video.
|
||||
|
||||
**Response Items:**
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | :---: | ------------|
|
||||
| `name` | _String_ | Transition name. |
|
||||
@ -1030,6 +1076,25 @@ An item's visibility has been toggled.
|
||||
| `item-visible` | _boolean_ | New visibility state of the item. |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### SceneItemLockChanged
|
||||
|
||||
|
||||
- Unreleased
|
||||
|
||||
An item's locked status has been toggled.
|
||||
|
||||
**Response Items:**
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | :---: | ------------|
|
||||
| `scene-name` | _String_ | Name of the scene. |
|
||||
| `item-name` | _String_ | Name of the item in the scene. |
|
||||
| `item-id` | _int_ | Scene item ID |
|
||||
| `item-locked` | _boolean_ | New locked state of the item. |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### SceneItemTransformChanged
|
||||
@ -1159,6 +1224,7 @@ _No specified parameters._
|
||||
| `obs-websocket-version` | _String_ | obs-websocket plugin version. |
|
||||
| `obs-studio-version` | _String_ | OBS Studio program version. |
|
||||
| `available-requests` | _String_ | List of available request types, formatted as a comma-separated list string (e.g. : "Method1,Method2,Method3"). |
|
||||
| `supported-image-export-formats` | _String_ | List of supported formats for features that use image export (like the TakeSourceScreenshot request type) formatted as a comma-separated list string |
|
||||
|
||||
|
||||
---
|
||||
@ -1333,6 +1399,29 @@ _No specified parameters._
|
||||
| `colorRange` | _String_ | Color range (full or partial) |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### OpenProjector
|
||||
|
||||
|
||||
- Unreleased
|
||||
|
||||
Open a projector window or create a projector on a monitor. Requires OBS v24.0.4 or newer.
|
||||
|
||||
**Request Fields:**
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | :---: | ------------|
|
||||
| `type` | _String (Optional)_ | Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive). |
|
||||
| `monitor` | _int (Optional)_ | Monitor to open the projector on. If -1 or omitted, opens a window. |
|
||||
| `geometry` | _String (Optional)_ | Size and position of the projector window (only if monitor is -1). Encoded in Base64 using Qt's geometry encoding (https://doc.qt.io/qt-5/qwidget.html#saveGeometry). Corresponds to OBS's saved projectors. |
|
||||
| `name` | _String (Optional)_ | Name of the source or scene to be displayed (ignored for other projector types). |
|
||||
|
||||
|
||||
**Response Items:**
|
||||
|
||||
_No additional response items._
|
||||
|
||||
---
|
||||
|
||||
## Outputs
|
||||
@ -1791,6 +1880,7 @@ Coordinates are relative to the item's parent (the scene or group it belongs to)
|
||||
| `crop.bottom` | _int_ | The number of pixels cropped off the bottom of the source before scaling. |
|
||||
| `crop.left` | _int_ | The number of pixels cropped off the left of the source before scaling. |
|
||||
| `visible` | _bool_ | If the source is visible. |
|
||||
| `muted` | _bool_ | If the source is muted. |
|
||||
| `locked` | _bool_ | If the source's transform is locked. |
|
||||
| `bounds.type` | _String_ | Type of bounding box. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE". |
|
||||
| `bounds.alignment` | _int_ | Alignment of the bounding box. |
|
||||
@ -1800,6 +1890,9 @@ Coordinates are relative to the item's parent (the scene or group it belongs to)
|
||||
| `sourceHeight` | _int_ | Base source (without scaling) of the source |
|
||||
| `width` | _double_ | Scene item width (base source width multiplied by the horizontal scaling factor) |
|
||||
| `height` | _double_ | Scene item height (base source height multiplied by the vertical scaling factor) |
|
||||
| `alignment` | _int_ | The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis. |
|
||||
| `parentGroupName` | _String (optional)_ | Name of the item's parent (if this item belongs to a group) |
|
||||
| `groupChildren` | _Array<SceneItemTransform> (optional)_ | List of children (if this item is a group) |
|
||||
|
||||
|
||||
---
|
||||
@ -2903,9 +2996,9 @@ Will return an `error` if streaming is already active.
|
||||
| `stream.settings` | _Object (optional)_ | Settings for the stream. |
|
||||
| `stream.settings.server` | _String (optional)_ | The publish URL. |
|
||||
| `stream.settings.key` | _String (optional)_ | The publish key of the stream. |
|
||||
| `stream.settings.use-auth` | _boolean (optional)_ | Indicates whether authentication should be used when connecting to the streaming server. |
|
||||
| `stream.settings.username` | _String (optional)_ | If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`. |
|
||||
| `stream.settings.password` | _String (optional)_ | If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`. |
|
||||
| `stream.settings.use_auth` | _boolean (optional)_ | Indicates whether authentication should be used when connecting to the streaming server. |
|
||||
| `stream.settings.username` | _String (optional)_ | If authentication is enabled, the username for the streaming server. Ignored if `use_auth` is not set to `true`. |
|
||||
| `stream.settings.password` | _String (optional)_ | If authentication is enabled, the password for the streaming server. Ignored if `use_auth` is not set to `true`. |
|
||||
|
||||
|
||||
**Response Items:**
|
||||
@ -2947,7 +3040,7 @@ Sets one or more attributes of the current streaming server settings. Any option
|
||||
| `settings` | _Object_ | The actual settings of the stream. |
|
||||
| `settings.server` | _String (optional)_ | The publish URL. |
|
||||
| `settings.key` | _String (optional)_ | The publish key. |
|
||||
| `settings.use-auth` | _boolean (optional)_ | Indicates whether authentication should be used when connecting to the streaming server. |
|
||||
| `settings.use_auth` | _boolean (optional)_ | Indicates whether authentication should be used when connecting to the streaming server. |
|
||||
| `settings.username` | _String (optional)_ | The username for the streaming service. |
|
||||
| `settings.password` | _String (optional)_ | The password for the streaming service. |
|
||||
| `save` | _boolean_ | Persist the settings to disk. |
|
||||
@ -2978,9 +3071,9 @@ _No specified parameters._
|
||||
| `settings` | _Object_ | Stream settings object. |
|
||||
| `settings.server` | _String_ | The publish URL. |
|
||||
| `settings.key` | _String_ | The publish key of the stream. |
|
||||
| `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.password` | _String_ | The password to use when accessing the streaming server. Only present if `use-auth` is `true`. |
|
||||
| `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.password` | _String_ | The password to use when accessing the streaming server. Only present if `use_auth` is `true`. |
|
||||
|
||||
|
||||
---
|
||||
|
@ -104,9 +104,11 @@ obs_data_array_t* Utils::GetSceneItems(obs_source_t* source) {
|
||||
* @typedef {Object} `SceneItem` An OBS Scene Item.
|
||||
* @property {Number} `cy`
|
||||
* @property {Number} `cx`
|
||||
* @property {Number} `alignment` The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis.
|
||||
* @property {String} `name` The name of this Scene Item.
|
||||
* @property {int} `id` Scene item ID
|
||||
* @property {Boolean} `render` Whether or not this Scene Item is set to "visible".
|
||||
* @property {Boolean} `muted` Whether or not this Scene Item is muted.
|
||||
* @property {Boolean} `locked` Whether or not this Scene Item is locked and can't be moved around
|
||||
* @property {Number} `source_cx`
|
||||
* @property {Number} `source_cy`
|
||||
@ -146,6 +148,8 @@ obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) {
|
||||
obs_data_set_double(data, "y", pos.y);
|
||||
obs_data_set_int(data, "source_cx", (int)item_width);
|
||||
obs_data_set_int(data, "source_cy", (int)item_height);
|
||||
obs_data_set_bool(data, "muted", obs_source_muted(itemSource));
|
||||
obs_data_set_int(data, "alignment", (int)obs_sceneitem_get_alignment(item));
|
||||
obs_data_set_double(data, "cx", item_width * scale.x);
|
||||
obs_data_set_double(data, "cy", item_height * scale.y);
|
||||
obs_data_set_bool(data, "render", obs_sceneitem_visible(item));
|
||||
@ -387,6 +391,13 @@ int Utils::GetTransitionDuration(obs_source_t* transition) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (obs_transition_fixed(transition)) {
|
||||
// If this transition has a fixed duration (such as a Stinger),
|
||||
// we don't currently have a way of retrieving that number.
|
||||
// For now, return -1 to indicate that we don't know the actual duration.
|
||||
return -1;
|
||||
}
|
||||
|
||||
OBSSourceAutoRelease destinationScene = obs_transition_get_active_source(transition);
|
||||
OBSDataAutoRelease destinationSettings = obs_source_get_private_settings(destinationScene);
|
||||
|
||||
@ -413,6 +424,37 @@ bool Utils::SetTransitionByName(QString transitionName) {
|
||||
}
|
||||
}
|
||||
|
||||
obs_data_t* Utils::GetTransitionData(obs_source_t* transition) {
|
||||
int duration = Utils::GetTransitionDuration(transition);
|
||||
if (duration < 0) {
|
||||
blog(LOG_WARNING, "GetTransitionData: duration is negative !");
|
||||
}
|
||||
|
||||
OBSSourceAutoRelease sourceScene = obs_transition_get_source(transition, OBS_TRANSITION_SOURCE_A);
|
||||
OBSSourceAutoRelease destinationScene = obs_transition_get_active_source(transition);
|
||||
|
||||
obs_data_t* transitionData = obs_data_create();
|
||||
obs_data_set_string(transitionData, "name", obs_source_get_name(transition));
|
||||
obs_data_set_string(transitionData, "type", obs_source_get_id(transition));
|
||||
obs_data_set_int(transitionData, "duration", duration);
|
||||
|
||||
// When a transition starts and while it is running, SOURCE_A is the source scene
|
||||
// and SOURCE_B is the destination scene.
|
||||
// Before the transition_end event is triggered on a transition, the destination scene
|
||||
// goes into SOURCE_A and SOURCE_B becomes null. This means that, in transition_stop
|
||||
// we don't know what was the source scene
|
||||
// TODO fix this in libobs
|
||||
|
||||
bool isTransitionEndEvent = (sourceScene == destinationScene);
|
||||
if (!isTransitionEndEvent) {
|
||||
obs_data_set_string(transitionData, "from-scene", obs_source_get_name(sourceScene));
|
||||
}
|
||||
|
||||
obs_data_set_string(transitionData, "to-scene", obs_source_get_name(destinationScene));
|
||||
|
||||
return transitionData;
|
||||
}
|
||||
|
||||
QString Utils::OBSVersionString() {
|
||||
uint32_t version = obs_get_version();
|
||||
|
||||
@ -787,41 +829,6 @@ void getPauseRecordingFunctions(RecordingPausedFunction* recPausedFuncPtr, Pause
|
||||
if (pauseRecFuncPtr) {
|
||||
*pauseRecFuncPtr = (PauseRecordingFunction)os_dlsym(frontendApi, "obs_frontend_recording_pause");
|
||||
}
|
||||
|
||||
os_dlclose(frontendApi);
|
||||
}
|
||||
|
||||
bool Utils::RecordingPauseSupported()
|
||||
{
|
||||
RecordingPausedFunction recordingPaused = nullptr;
|
||||
PauseRecordingFunction pauseRecording = nullptr;
|
||||
getPauseRecordingFunctions(&recordingPaused, &pauseRecording);
|
||||
|
||||
return (recordingPaused && pauseRecording);
|
||||
}
|
||||
|
||||
bool Utils::RecordingPaused()
|
||||
{
|
||||
RecordingPausedFunction recordingPaused = nullptr;
|
||||
getPauseRecordingFunctions(&recordingPaused, nullptr);
|
||||
|
||||
if (recordingPaused == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return recordingPaused();
|
||||
}
|
||||
|
||||
void Utils::PauseRecording(bool pause)
|
||||
{
|
||||
PauseRecordingFunction pauseRecording = nullptr;
|
||||
getPauseRecordingFunctions(nullptr, &pauseRecording);
|
||||
|
||||
if (pauseRecording == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
pauseRecording(pause);
|
||||
}
|
||||
|
||||
QString Utils::nsToTimestamp(uint64_t ns)
|
||||
|
@ -60,6 +60,7 @@ namespace Utils {
|
||||
int GetTransitionDuration(obs_source_t* transition);
|
||||
obs_source_t* GetTransitionFromName(QString transitionName);
|
||||
bool SetTransitionByName(QString transitionName);
|
||||
obs_data_t* GetTransitionData(obs_source_t* transition);
|
||||
|
||||
QString OBSVersionString();
|
||||
|
||||
@ -82,9 +83,5 @@ namespace Utils {
|
||||
const char* GetFilenameFormatting();
|
||||
bool SetFilenameFormatting(const char* filenameFormatting);
|
||||
|
||||
bool RecordingPauseSupported();
|
||||
bool RecordingPaused();
|
||||
void PauseRecording(bool pause);
|
||||
|
||||
QString nsToTimestamp(uint64_t ns);
|
||||
};
|
||||
|
141
src/WSEvents.cpp
141
src/WSEvents.cpp
@ -122,7 +122,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private
|
||||
|
||||
switch (event) {
|
||||
case OBS_FRONTEND_EVENT_FINISHED_LOADING:
|
||||
owner->hookTransitionBeginEvent();
|
||||
owner->hookTransitionPlaybackEvents();
|
||||
break;
|
||||
|
||||
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
|
||||
@ -134,7 +134,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private
|
||||
break;
|
||||
|
||||
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED:
|
||||
owner->hookTransitionBeginEvent();
|
||||
owner->hookTransitionPlaybackEvents();
|
||||
owner->OnSceneCollectionChange();
|
||||
break;
|
||||
|
||||
@ -147,7 +147,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private
|
||||
break;
|
||||
|
||||
case OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED:
|
||||
owner->hookTransitionBeginEvent();
|
||||
owner->hookTransitionPlaybackEvents();
|
||||
owner->OnTransitionListChange();
|
||||
break;
|
||||
|
||||
@ -231,7 +231,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private
|
||||
break;
|
||||
|
||||
case OBS_FRONTEND_EVENT_EXIT:
|
||||
owner->unhookTransitionBeginEvent();
|
||||
owner->unhookTransitionPlaybackEvents();
|
||||
owner->OnExit();
|
||||
break;
|
||||
}
|
||||
@ -282,6 +282,8 @@ void WSEvents::connectSourceSignals(obs_source_t* source) {
|
||||
signal_handler_connect(sh, "item_remove", OnSceneItemDelete, this);
|
||||
signal_handler_connect(sh,
|
||||
"item_visible", OnSceneItemVisibilityChanged, this);
|
||||
signal_handler_connect(sh,
|
||||
"item_locked", OnSceneItemLockChanged, this);
|
||||
signal_handler_connect(sh, "item_transform", OnSceneItemTransform, this);
|
||||
signal_handler_connect(sh, "item_select", OnSceneItemSelected, this);
|
||||
signal_handler_connect(sh, "item_deselect", OnSceneItemDeselected, this);
|
||||
@ -311,11 +313,15 @@ void WSEvents::disconnectSourceSignals(obs_source_t* source) {
|
||||
signal_handler_disconnect(sh, "item_remove", OnSceneItemDelete, this);
|
||||
signal_handler_disconnect(sh,
|
||||
"item_visible", OnSceneItemVisibilityChanged, this);
|
||||
signal_handler_disconnect(sh,
|
||||
"item_locked", OnSceneItemLockChanged, this);
|
||||
signal_handler_disconnect(sh, "item_transform", OnSceneItemTransform, this);
|
||||
signal_handler_disconnect(sh, "item_select", OnSceneItemSelected, this);
|
||||
signal_handler_disconnect(sh, "item_deselect", OnSceneItemDeselected, this);
|
||||
|
||||
signal_handler_disconnect(sh, "transition_start", OnTransitionBegin, this);
|
||||
signal_handler_disconnect(sh, "transition_stop", OnTransitionEnd, this);
|
||||
signal_handler_disconnect(sh, "transition_video_stop", OnTransitionVideoEnd, this);
|
||||
}
|
||||
|
||||
void WSEvents::connectFilterSignals(obs_source_t* filter) {
|
||||
@ -338,7 +344,7 @@ void WSEvents::disconnectFilterSignals(obs_source_t* filter) {
|
||||
signal_handler_disconnect(sh, "enable", OnSourceFilterVisibilityChanged, this);
|
||||
}
|
||||
|
||||
void WSEvents::hookTransitionBeginEvent() {
|
||||
void WSEvents::hookTransitionPlaybackEvents() {
|
||||
obs_frontend_source_list transitions = {};
|
||||
obs_frontend_get_transitions(&transitions);
|
||||
|
||||
@ -347,12 +353,16 @@ void WSEvents::hookTransitionBeginEvent() {
|
||||
signal_handler_t* sh = obs_source_get_signal_handler(transition);
|
||||
signal_handler_disconnect(sh, "transition_start", OnTransitionBegin, this);
|
||||
signal_handler_connect(sh, "transition_start", OnTransitionBegin, this);
|
||||
signal_handler_disconnect(sh, "transition_stop", OnTransitionEnd, this);
|
||||
signal_handler_connect(sh, "transition_stop", OnTransitionEnd, this);
|
||||
signal_handler_disconnect(sh, "transition_video_stop", OnTransitionVideoEnd, this);
|
||||
signal_handler_connect(sh, "transition_video_stop", OnTransitionVideoEnd, this);
|
||||
}
|
||||
|
||||
obs_frontend_source_list_free(&transitions);
|
||||
}
|
||||
|
||||
void WSEvents::unhookTransitionBeginEvent() {
|
||||
void WSEvents::unhookTransitionPlaybackEvents() {
|
||||
obs_frontend_source_list transitions = {};
|
||||
obs_frontend_get_transitions(&transitions);
|
||||
|
||||
@ -360,6 +370,8 @@ void WSEvents::unhookTransitionBeginEvent() {
|
||||
obs_source_t* transition = transitions.sources.array[i];
|
||||
signal_handler_t* sh = obs_source_get_signal_handler(transition);
|
||||
signal_handler_disconnect(sh, "transition_start", OnTransitionBegin, this);
|
||||
signal_handler_disconnect(sh, "transition_stop", OnTransitionEnd, this);
|
||||
signal_handler_disconnect(sh, "transition_video_stop", OnTransitionVideoEnd, this);
|
||||
}
|
||||
|
||||
obs_frontend_source_list_free(&transitions);
|
||||
@ -742,7 +754,7 @@ void WSEvents::OnExit() {
|
||||
void WSEvents::StreamStatus() {
|
||||
bool streamingActive = obs_frontend_streaming_active();
|
||||
bool recordingActive = obs_frontend_recording_active();
|
||||
bool recordingPaused = Utils::RecordingPaused();
|
||||
bool recordingPaused = obs_frontend_recording_paused();
|
||||
bool replayBufferActive = obs_frontend_replay_buffer_active();
|
||||
|
||||
OBSOutputAutoRelease streamOutput = obs_frontend_get_streaming_output();
|
||||
@ -826,7 +838,7 @@ void WSEvents::Heartbeat() {
|
||||
|
||||
bool streamingActive = obs_frontend_streaming_active();
|
||||
bool recordingActive = obs_frontend_recording_active();
|
||||
bool recordingPaused = Utils::RecordingPaused();
|
||||
bool recordingPaused = obs_frontend_recording_paused();
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
OBSOutputAutoRelease recordOutput = obs_frontend_get_recording_output();
|
||||
@ -886,6 +898,8 @@ void WSEvents::TransitionDurationChanged(int ms) {
|
||||
* @return {String} `name` Transition name.
|
||||
* @return {String} `type` Transition type.
|
||||
* @return {int} `duration` Transition duration (in milliseconds).
|
||||
* Will be -1 for any transition with a fixed duration,
|
||||
* such as a Stinger, due to limitations of the OBS API.
|
||||
* @return {String} `from-scene` Source scene of the transition
|
||||
* @return {String} `to-scene` Destination scene of the transition
|
||||
*
|
||||
@ -902,29 +916,62 @@ void WSEvents::OnTransitionBegin(void* param, calldata_t* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
int duration = Utils::GetTransitionDuration(transition);
|
||||
if (duration < 0) {
|
||||
blog(LOG_WARNING, "OnTransitionBegin: duration is negative !");
|
||||
}
|
||||
|
||||
OBSDataAutoRelease fields = obs_data_create();
|
||||
obs_data_set_string(fields, "name", obs_source_get_name(transition));
|
||||
obs_data_set_string(fields, "type", obs_source_get_id(transition));
|
||||
obs_data_set_int(fields, "duration", duration);
|
||||
|
||||
OBSSourceAutoRelease sourceScene = obs_transition_get_source(transition, OBS_TRANSITION_SOURCE_A);
|
||||
if (sourceScene) {
|
||||
obs_data_set_string(fields, "from-scene", obs_source_get_name(sourceScene));
|
||||
}
|
||||
|
||||
OBSSourceAutoRelease destinationScene = obs_transition_get_active_source(transition);
|
||||
if (destinationScene) {
|
||||
obs_data_set_string(fields, "to-scene", obs_source_get_name(destinationScene));
|
||||
}
|
||||
|
||||
OBSDataAutoRelease fields = Utils::GetTransitionData(transition);
|
||||
instance->broadcastUpdate("TransitionBegin", fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* A transition (other than "cut") has ended.
|
||||
* Please note that the `from-scene` field is not available in TransitionEnd.
|
||||
*
|
||||
* @return {String} `name` Transition name.
|
||||
* @return {String} `type` Transition type.
|
||||
* @return {int} `duration` Transition duration (in milliseconds).
|
||||
* @return {String} `to-scene` Destination scene of the transition
|
||||
*
|
||||
* @api events
|
||||
* @name TransitionEnd
|
||||
* @category transitions
|
||||
* @since 4.8.0
|
||||
*/
|
||||
void WSEvents::OnTransitionEnd(void* param, calldata_t* data) {
|
||||
auto instance = reinterpret_cast<WSEvents*>(param);
|
||||
|
||||
OBSSource transition = calldata_get_pointer<obs_source_t>(data, "source");
|
||||
if (!transition) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease fields = Utils::GetTransitionData(transition);
|
||||
instance->broadcastUpdate("TransitionEnd", fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* A stinger transition has finished playing its video.
|
||||
*
|
||||
* @return {String} `name` Transition name.
|
||||
* @return {String} `type` Transition type.
|
||||
* @return {int} `duration` Transition duration (in milliseconds).
|
||||
* @return {String} `from-scene` Source scene of the transition
|
||||
* @return {String} `to-scene` Destination scene of the transition
|
||||
*
|
||||
* @api events
|
||||
* @name TransitionVideoEnd
|
||||
* @category transitions
|
||||
* @since 4.8.0
|
||||
*/
|
||||
void WSEvents::OnTransitionVideoEnd(void* param, calldata_t* data) {
|
||||
auto instance = reinterpret_cast<WSEvents*>(param);
|
||||
|
||||
OBSSource transition = calldata_get_pointer<obs_source_t>(data, "source");
|
||||
if (!transition) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease fields = Utils::GetTransitionData(transition);
|
||||
instance->broadcastUpdate("TransitionVideoEnd", fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* A source has been created. A source can be an input, a scene or a transition.
|
||||
*
|
||||
@ -1435,6 +1482,44 @@ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) {
|
||||
instance->broadcastUpdate("SceneItemVisibilityChanged", fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* An item's locked status has been toggled.
|
||||
*
|
||||
* @return {String} `scene-name` Name of the scene.
|
||||
* @return {String} `item-name` Name of the item in the scene.
|
||||
* @return {int} `item-id` Scene item ID
|
||||
* @return {boolean} `item-locked` New locked state of the item.
|
||||
*
|
||||
* @api events
|
||||
* @name SceneItemLockChanged
|
||||
* @category sources
|
||||
* @since unreleased
|
||||
*/
|
||||
void WSEvents::OnSceneItemLockChanged(void* param, calldata_t* data) {
|
||||
auto instance = reinterpret_cast<WSEvents*>(param);
|
||||
|
||||
obs_scene_t* scene = nullptr;
|
||||
calldata_get_ptr(data, "scene", &scene);
|
||||
|
||||
obs_sceneitem_t* sceneItem = nullptr;
|
||||
calldata_get_ptr(data, "item", &sceneItem);
|
||||
|
||||
bool locked = false;
|
||||
calldata_get_bool(data, "locked", &locked);
|
||||
|
||||
const char* sceneName =
|
||||
obs_source_get_name(obs_scene_get_source(scene));
|
||||
const char* sceneItemName =
|
||||
obs_source_get_name(obs_sceneitem_get_source(sceneItem));
|
||||
|
||||
OBSDataAutoRelease fields = obs_data_create();
|
||||
obs_data_set_string(fields, "scene-name", sceneName);
|
||||
obs_data_set_string(fields, "item-name", sceneItemName);
|
||||
obs_data_set_int(fields, "item-id", obs_sceneitem_get_id(sceneItem));
|
||||
obs_data_set_bool(fields, "item-locked", locked);
|
||||
instance->broadcastUpdate("SceneItemLockChanged", fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* An item's transform has been changed.
|
||||
*
|
||||
|
@ -43,8 +43,8 @@ public:
|
||||
void connectFilterSignals(obs_source_t* filter);
|
||||
void disconnectFilterSignals(obs_source_t* filter);
|
||||
|
||||
void hookTransitionBeginEvent();
|
||||
void unhookTransitionBeginEvent();
|
||||
void hookTransitionPlaybackEvents();
|
||||
void unhookTransitionPlaybackEvents();
|
||||
|
||||
uint64_t getStreamingTime();
|
||||
uint64_t getRecordingTime();
|
||||
@ -116,6 +116,8 @@ private:
|
||||
enum obs_frontend_event event, void* privateData);
|
||||
|
||||
static void OnTransitionBegin(void* param, calldata_t* data);
|
||||
static void OnTransitionEnd(void* param, calldata_t* data);
|
||||
static void OnTransitionVideoEnd(void* param, calldata_t* data);
|
||||
|
||||
static void OnSourceCreate(void* param, calldata_t* data);
|
||||
static void OnSourceDestroy(void* param, calldata_t* data);
|
||||
@ -136,6 +138,7 @@ private:
|
||||
static void OnSceneItemAdd(void* param, calldata_t* data);
|
||||
static void OnSceneItemDelete(void* param, calldata_t* data);
|
||||
static void OnSceneItemVisibilityChanged(void* param, calldata_t* data);
|
||||
static void OnSceneItemLockChanged(void* param, calldata_t* data);
|
||||
static void OnSceneItemTransform(void* param, calldata_t* data);
|
||||
static void OnSceneItemSelected(void* param, calldata_t* data);
|
||||
static void OnSceneItemDeselected(void* param, calldata_t* data);
|
||||
|
@ -36,6 +36,7 @@ const QHash<QString, RpcMethodHandler> WSRequestHandler::messageMap {
|
||||
{ "GetStats", &WSRequestHandler::GetStats },
|
||||
{ "SetHeartbeat", &WSRequestHandler::SetHeartbeat },
|
||||
{ "GetVideoInfo", &WSRequestHandler::GetVideoInfo },
|
||||
{ "OpenProjector", &WSRequestHandler::OpenProjector },
|
||||
|
||||
{ "SetFilenameFormatting", &WSRequestHandler::SetFilenameFormatting },
|
||||
{ "GetFilenameFormatting", &WSRequestHandler::GetFilenameFormatting },
|
||||
|
@ -54,6 +54,7 @@ class WSRequestHandler {
|
||||
RpcResponse GetStats(const RpcRequest&);
|
||||
RpcResponse SetHeartbeat(const RpcRequest&);
|
||||
RpcResponse GetVideoInfo(const RpcRequest&);
|
||||
RpcResponse OpenProjector(const RpcRequest&);
|
||||
|
||||
RpcResponse SetFilenameFormatting(const RpcRequest&);
|
||||
RpcResponse GetFilenameFormatting(const RpcRequest&);
|
||||
|
@ -1,10 +1,13 @@
|
||||
#include "WSRequestHandler.h"
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtGui/QImageWriter>
|
||||
|
||||
#include "obs-websocket.h"
|
||||
#include "Config.h"
|
||||
#include "Utils.h"
|
||||
#include "WSEvents.h"
|
||||
|
||||
#include "WSRequestHandler.h"
|
||||
|
||||
#define CASE(x) case x: return #x;
|
||||
const char *describe_output_format(int format) {
|
||||
switch (format) {
|
||||
@ -60,6 +63,7 @@ const char *describe_scale_type(int scale) {
|
||||
* @return {String} `obs-websocket-version` obs-websocket plugin version.
|
||||
* @return {String} `obs-studio-version` OBS Studio program version.
|
||||
* @return {String} `available-requests` List of available request types, formatted as a comma-separated list string (e.g. : "Method1,Method2,Method3").
|
||||
* @return {String} `supported-image-export-formats` List of supported formats for features that use image export (like the TakeSourceScreenshot request type) formatted as a comma-separated list string
|
||||
*
|
||||
* @api requests
|
||||
* @name GetVersion
|
||||
@ -70,20 +74,28 @@ RpcResponse WSRequestHandler::GetVersion(const RpcRequest& request) {
|
||||
QString obsVersion = Utils::OBSVersionString();
|
||||
|
||||
QList<QString> names = messageMap.keys();
|
||||
names.sort(Qt::CaseInsensitive);
|
||||
QList<QByteArray> imageWriterFormats = QImageWriter::supportedImageFormats();
|
||||
|
||||
// (Palakis) OBS' data arrays only support object arrays, so I improvised.
|
||||
QString requests;
|
||||
names.sort(Qt::CaseInsensitive);
|
||||
requests += names.takeFirst();
|
||||
for (QString reqName : names) {
|
||||
for (const QString& reqName : names) {
|
||||
requests += ("," + reqName);
|
||||
}
|
||||
|
||||
QString supportedImageExportFormats;
|
||||
supportedImageExportFormats += QString::fromUtf8(imageWriterFormats.takeFirst());
|
||||
for (const QByteArray& format : imageWriterFormats) {
|
||||
supportedImageExportFormats += ("," + QString::fromUtf8(format));
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_double(data, "version", 1.1);
|
||||
obs_data_set_string(data, "obs-websocket-version", OBS_WEBSOCKET_VERSION);
|
||||
obs_data_set_string(data, "obs-studio-version", obsVersion.toUtf8());
|
||||
obs_data_set_string(data, "available-requests", requests.toUtf8());
|
||||
obs_data_set_string(data, "supported-image-export-formats", supportedImageExportFormats.toUtf8());
|
||||
|
||||
return request.success(data);
|
||||
}
|
||||
@ -304,3 +316,31 @@ RpcResponse WSRequestHandler::GetVideoInfo(const RpcRequest& request) {
|
||||
|
||||
return request.success(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a projector window or create a projector on a monitor. Requires OBS v24.0.4 or newer.
|
||||
*
|
||||
* @param {String (Optional)} `type` Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive).
|
||||
* @param {int (Optional)} `monitor` Monitor to open the projector on. If -1 or omitted, opens a window.
|
||||
* @param {String (Optional)} `geometry` Size and position of the projector window (only if monitor is -1). Encoded in Base64 using Qt's geometry encoding (https://doc.qt.io/qt-5/qwidget.html#saveGeometry). Corresponds to OBS's saved projectors.
|
||||
* @param {String (Optional)} `name` Name of the source or scene to be displayed (ignored for other projector types).
|
||||
*
|
||||
* @api requests
|
||||
* @name OpenProjector
|
||||
* @category general
|
||||
* @since unreleased
|
||||
*/
|
||||
RpcResponse WSRequestHandler::OpenProjector(const RpcRequest& request) {
|
||||
const char* type = obs_data_get_string(request.parameters(), "type");
|
||||
|
||||
int monitor = -1;
|
||||
if (request.hasField("monitor")) {
|
||||
monitor = obs_data_get_int(request.parameters(), "monitor");
|
||||
}
|
||||
|
||||
const char* geometry = obs_data_get_string(request.parameters(), "geometry");
|
||||
const char* name = obs_data_get_string(request.parameters(), "name");
|
||||
|
||||
obs_frontend_open_projector(type, monitor, geometry, name);
|
||||
return request.success();
|
||||
}
|
||||
|
@ -10,10 +10,6 @@ RpcResponse ifCanPause(const RpcRequest& request, std::function<RpcResponse()> c
|
||||
return request.failed("recording is not active");
|
||||
}
|
||||
|
||||
if (!Utils::RecordingPauseSupported()) {
|
||||
return request.failed("recording pauses are not available in this version of OBS Studio");
|
||||
}
|
||||
|
||||
return callback();
|
||||
}
|
||||
|
||||
@ -77,11 +73,11 @@ RpcResponse WSRequestHandler::StartRecording(const RpcRequest& request) {
|
||||
*/
|
||||
RpcResponse WSRequestHandler::PauseRecording(const RpcRequest& request) {
|
||||
return ifCanPause(request, [request]() {
|
||||
if (Utils::RecordingPaused()) {
|
||||
if (obs_frontend_recording_paused()) {
|
||||
return request.failed("recording already paused");
|
||||
}
|
||||
|
||||
Utils::PauseRecording(true);
|
||||
obs_frontend_recording_pause(true);
|
||||
return request.success();
|
||||
});
|
||||
}
|
||||
@ -97,11 +93,11 @@ RpcResponse WSRequestHandler::PauseRecording(const RpcRequest& request) {
|
||||
*/
|
||||
RpcResponse WSRequestHandler::ResumeRecording(const RpcRequest& request) {
|
||||
return ifCanPause(request, [request]() {
|
||||
if (!Utils::RecordingPaused()) {
|
||||
if (!obs_frontend_recording_paused()) {
|
||||
return request.failed("recording is not paused");
|
||||
}
|
||||
|
||||
Utils::PauseRecording(false);
|
||||
obs_frontend_recording_pause(false);
|
||||
return request.success();
|
||||
});
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
* @return {int} `crop.bottom` The number of pixels cropped off the bottom of the source before scaling.
|
||||
* @return {int} `crop.left` The number of pixels cropped off the left of the source before scaling.
|
||||
* @return {bool} `visible` If the source is visible.
|
||||
* @return {bool} `muted` If the source is muted.
|
||||
* @return {bool} `locked` If the source's transform is locked.
|
||||
* @return {String} `bounds.type` Type of bounding box. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE".
|
||||
* @return {int} `bounds.alignment` Alignment of the bounding box.
|
||||
@ -30,8 +31,9 @@
|
||||
* @return {int} `sourceHeight` Base source (without scaling) of the source
|
||||
* @return {double} `width` Scene item width (base source width multiplied by the horizontal scaling factor)
|
||||
* @return {double} `height` Scene item height (base source height multiplied by the vertical scaling factor)
|
||||
* @property {String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group)
|
||||
* @property {Array<SceneItemTransform> (optional)} `groupChildren` List of children (if this item is a group)
|
||||
* @return {int} `alignment` The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis.
|
||||
* @return {String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group)
|
||||
* @return {Array<SceneItemTransform> (optional)} `groupChildren` List of children (if this item is a group)
|
||||
*
|
||||
* @api requests
|
||||
* @name GetSceneItemProperties
|
||||
|
@ -335,7 +335,7 @@ RpcResponse WSRequestHandler::SetSyncOffset(const RpcRequest& request)
|
||||
QString sourceName = obs_data_get_string(request.parameters(), "source");
|
||||
int64_t sourceSyncOffset = (int64_t)obs_data_get_int(request.parameters(), "offset");
|
||||
|
||||
if (sourceName.isEmpty() || sourceSyncOffset < 0) {
|
||||
if (sourceName.isEmpty()) {
|
||||
return request.failed("invalid request parameters");
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ RpcResponse WSRequestHandler::GetStreamingStatus(const RpcRequest& request) {
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_bool(data, "streaming", obs_frontend_streaming_active());
|
||||
obs_data_set_bool(data, "recording", obs_frontend_recording_active());
|
||||
obs_data_set_bool(data, "recording-paused", Utils::RecordingPaused());
|
||||
obs_data_set_bool(data, "recording-paused", obs_frontend_recording_paused());
|
||||
obs_data_set_bool(data, "preview-only", false);
|
||||
|
||||
if (obs_frontend_streaming_active()) {
|
||||
@ -67,9 +67,9 @@ RpcResponse WSRequestHandler::StartStopStreaming(const RpcRequest& request) {
|
||||
* @param {Object (optional)} `stream.settings` Settings for the stream.
|
||||
* @param {String (optional)} `stream.settings.server` The publish URL.
|
||||
* @param {String (optional)} `stream.settings.key` The publish key of the stream.
|
||||
* @param {boolean (optional)} `stream.settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.
|
||||
* @param {String (optional)} `stream.settings.username` If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`.
|
||||
* @param {String (optional)} `stream.settings.password` If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`.
|
||||
* @param {boolean (optional)} `stream.settings.use_auth` Indicates whether authentication should be used when connecting to the streaming server.
|
||||
* @param {String (optional)} `stream.settings.username` If authentication is enabled, the username for the streaming server. Ignored if `use_auth` is not set to `true`.
|
||||
* @param {String (optional)} `stream.settings.password` If authentication is enabled, the password for the streaming server. Ignored if `use_auth` is not set to `true`.
|
||||
*
|
||||
* @api requests
|
||||
* @name StartStreaming
|
||||
@ -188,7 +188,7 @@ RpcResponse WSRequestHandler::StopStreaming(const RpcRequest& request) {
|
||||
* @param {Object} `settings` The actual settings of the stream.
|
||||
* @param {String (optional)} `settings.server` The publish URL.
|
||||
* @param {String (optional)} `settings.key` The publish key.
|
||||
* @param {boolean (optional)} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.
|
||||
* @param {boolean (optional)} `settings.use_auth` Indicates whether authentication should be used when connecting to the streaming server.
|
||||
* @param {String (optional)} `settings.username` The username for the streaming service.
|
||||
* @param {String (optional)} `settings.password` The password for the streaming service.
|
||||
* @param {boolean} `save` Persist the settings to disk.
|
||||
@ -213,6 +213,7 @@ RpcResponse WSRequestHandler::SetStreamSettings(const RpcRequest& request) {
|
||||
OBSDataAutoRelease hotkeys = obs_hotkeys_save_service(service);
|
||||
service = obs_service_create(
|
||||
requestedType.toUtf8(), STREAM_SERVICE_ID, requestSettings, hotkeys);
|
||||
obs_frontend_set_streaming_service(service);
|
||||
} else {
|
||||
// If type isn't changing, we should overlay the settings we got
|
||||
// to the existing settings. By doing so, you can send a request that
|
||||
@ -235,10 +236,12 @@ RpcResponse WSRequestHandler::SetStreamSettings(const RpcRequest& request) {
|
||||
obs_frontend_save_streaming_service();
|
||||
}
|
||||
|
||||
OBSDataAutoRelease serviceSettings = obs_service_get_settings(service);
|
||||
OBSService responseService = obs_frontend_get_streaming_service();
|
||||
OBSDataAutoRelease serviceSettings = obs_service_get_settings(responseService);
|
||||
const char* responseType = obs_service_get_type(responseService);
|
||||
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_string(response, "type", requestedType.toUtf8());
|
||||
obs_data_set_string(response, "type", responseType);
|
||||
obs_data_set_obj(response, "settings", serviceSettings);
|
||||
|
||||
return request.success(response);
|
||||
@ -251,9 +254,9 @@ RpcResponse WSRequestHandler::SetStreamSettings(const RpcRequest& request) {
|
||||
* @return {Object} `settings` Stream settings object.
|
||||
* @return {String} `settings.server` The publish URL.
|
||||
* @return {String} `settings.key` The publish key of the stream.
|
||||
* @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.password` The password to use when accessing the streaming server. Only present if `use-auth` is `true`.
|
||||
* @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.password` The password to use when accessing the streaming server. Only present if `use_auth` is `true`.
|
||||
*
|
||||
* @api requests
|
||||
* @name GetStreamSettings
|
||||
|
@ -133,7 +133,11 @@ RpcResponse WSRequestHandler::TransitionToProgram(const RpcRequest& request) {
|
||||
* @since 4.1.0
|
||||
*/
|
||||
RpcResponse WSRequestHandler::EnableStudioMode(const RpcRequest& request) {
|
||||
obs_queue_task(OBS_TASK_UI, [](void* param) {
|
||||
obs_frontend_set_preview_program_mode(true);
|
||||
|
||||
UNUSED_PARAMETER(param);
|
||||
}, nullptr, true);
|
||||
return request.success();
|
||||
}
|
||||
|
||||
@ -146,7 +150,12 @@ RpcResponse WSRequestHandler::EnableStudioMode(const RpcRequest& request) {
|
||||
* @since 4.1.0
|
||||
*/
|
||||
RpcResponse WSRequestHandler::DisableStudioMode(const RpcRequest& request) {
|
||||
obs_queue_task(OBS_TASK_UI, [](void* param) {
|
||||
obs_frontend_set_preview_program_mode(false);
|
||||
|
||||
UNUSED_PARAMETER(param);
|
||||
}, nullptr, true);
|
||||
|
||||
return request.success();
|
||||
}
|
||||
|
||||
@ -159,7 +168,12 @@ RpcResponse WSRequestHandler::DisableStudioMode(const RpcRequest& request) {
|
||||
* @since 4.1.0
|
||||
*/
|
||||
RpcResponse WSRequestHandler::ToggleStudioMode(const RpcRequest& request) {
|
||||
obs_queue_task(OBS_TASK_UI, [](void* param) {
|
||||
bool previewProgramMode = obs_frontend_preview_program_mode_active();
|
||||
obs_frontend_set_preview_program_mode(!previewProgramMode);
|
||||
|
||||
UNUSED_PARAMETER(param);
|
||||
}, nullptr, true);
|
||||
|
||||
return request.success();
|
||||
}
|
||||
|
@ -56,6 +56,6 @@ ConfigPtr GetConfig();
|
||||
WSServerPtr GetServer();
|
||||
WSEventsPtr GetEventsSystem();
|
||||
|
||||
#define OBS_WEBSOCKET_VERSION "4.7.0"
|
||||
#define OBS_WEBSOCKET_VERSION "4.8.0"
|
||||
|
||||
#define blog(level, msg, ...) blog(level, "[obs-websocket] " msg, ##__VA_ARGS__)
|
||||
|
Reference in New Issue
Block a user