New upstream version 25.0.8+dfsg1

This commit is contained in:
Sebastian Ramacher 2020-05-27 22:57:19 +02:00
parent 8b2e5f2130
commit 8e020cdacb
115 changed files with 1767 additions and 10949 deletions

View file

@ -13,7 +13,7 @@ task:
freetype2 jackit jansson luajit mbedtls pulseaudio speexdsp freetype2 jackit jansson luajit mbedtls pulseaudio speexdsp
libsysinfo libudev-devd libv4l libx264 cmake ninja libsysinfo libudev-devd libv4l libx264 cmake ninja
mesa-libs lua52 pkgconf mesa-libs lua52 pkgconf
qt5-svg qt5-qmake qt5-buildtools qt5-x11extras qt5-svg qt5-qmake qt5-buildtools qt5-x11extras qt5-xml
script: script:
- mkdir build - mkdir build
- cd build - cd build

48
.github/workflows/clang-format.yml vendored Normal file
View file

@ -0,0 +1,48 @@
name: Clang Format Check
on: [push, pull_request]
jobs:
ubuntu64:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Install clang format
run: |
# gets us newer clang
sudo bash -c "cat >> /etc/apt/sources.list" << LLVMAPT
# 3.8
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
LLVMAPT
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
sudo apt-get -qq update
sudo apt-get install -y clang-format-8
- name: Check the Formatting
run: |
./formatcode.sh
./CI/check-format.sh
macos64:
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Install clang-format
run: |
brew install clang-format
- name: Check the Formatting
run: |
./formatcode.sh
./CI/check-format.sh

348
.github/workflows/main.yml vendored Normal file
View file

@ -0,0 +1,348 @@
name: 'CI Multiplatform Build'
on:
push:
branches:
- master
pull_request:
paths-ignore:
- '**.md'
branches:
- master
env:
CEF_BUILD_VERSION: '3770'
CEF_VERSION: '75.1.16+g16a67c4+chromium-75.0.3770.100'
jobs:
macos64:
name: 'macOS 64-bit'
runs-on: [macos-latest]
env:
MACOS_DEPS_VERSION: '2020-04-24'
VLC_VERSION: '3.0.8'
SPARKLE_VERSION: '1.23.0'
QT_VERSION: '5.14.1'
steps:
- name: 'Checkout'
uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: 'Fetch Git Tags'
run: |
git fetch --prune --unshallow
echo ::set-env name=OBS_GIT_BRANCH::$(git rev-parse --abbrev-ref HEAD)
echo ::set-env name=OBS_GIT_HASH::$(git rev-parse --short HEAD)
echo ::set-env name=OBS_GIT_TAG::$(git describe --tags --abbrev=0)
- name: 'Install prerequisites (Homebrew)'
shell: bash
run: |
brew bundle --file ./CI/scripts/macos/Brewfile
- name: 'Install prerequisite: Pre-built dependencies'
shell: bash
run: |
curl -L -O https://github.com/obsproject/obs-deps/releases/download/${{ env.MACOS_DEPS_VERSION }}/osx-deps-${{ env.MACOS_DEPS_VERSION }}.tar.gz
tar -xf ./osx-deps-${{ env.MACOS_DEPS_VERSION }}.tar.gz -C "/tmp"
- name: 'Install prerequisite: VLC'
shell: bash
run: |
curl -L -O https://downloads.videolan.org/vlc/${{ env.VLC_VERSION }}/vlc-${{ env.VLC_VERSION }}.tar.xz
if [ ! -d "${{ github.workspace }}/cmbuild" ]; then mkdir "${{ github.workspace }}/cmbuild"; fi
tar -xf ./vlc-${{ env.VLC_VERSION }}.tar.xz -C "${{ github.workspace }}/cmbuild"
- name: 'Install prerequisite: Sparkle'
shell: bash
run: |
curl -L -o sparkle.tar.bz2 https://github.com/sparkle-project/Sparkle/releases/download/${{ env.SPARKLE_VERSION }}/Sparkle-${{ env.SPARKLE_VERSION }}.tar.bz2
mkdir ${{ github.workspace }}/cmbuild/sparkle
tar -xf ./sparkle.tar.bz2 -C ${{ github.workspace }}/cmbuild/sparkle
sudo cp -R ${{ github.workspace }}/cmbuild/sparkle/Sparkle.framework /Library/Frameworks/Sparkle.framework
- name: 'Restore Chromium Embedded Framework from cache'
id: cef-cache
uses: actions/cache@v1
env:
CACHE_NAME: 'cef-cache'
with:
path: ${{ github.workspace }}/cmbuild/cef_binary_${{ env.CEF_BUILD_VERSION }}_macosx64
key: ${{ runner.os }}-pr-${{ env.CACHE_NAME }}-${{ env.CEF_BUILD_VERSION }}
restore-keys: |
${{ runner.os }}-pr-${{ env.CACHE_NAME }}-
- name: 'Install prerequisite: Chromium Embedded Framework'
if: steps.cef-cache.outputs.cache-hit != 'true'
shell: bash
run: |
curl -L -O https://obs-nightly.s3-us-west-2.amazonaws.com/cef_binary_${{ env.CEF_BUILD_VERSION }}_macosx64.tar.bz2
tar -xf ./cef_binary_${{ env.CEF_BUILD_VERSION }}_macosx64.tar.bz2 -C ${{ github.workspace }}/cmbuild/
cd ${{ github.workspace }}/cmbuild/cef_binary_${{ env.CEF_BUILD_VERSION }}_macosx64
sed -i '.orig' '/add_subdirectory(tests\/ceftests)/d' ./CMakeLists.txt
# target 10.11
sed -i '.orig' s/\"10.9\"/\"10.11\"/ ./cmake/cef_variables.cmake
mkdir build && cd build
cmake -DCMAKE_CXX_FLAGS="-std=c++11 -stdlib=libc++" -DCMAKE_EXE_LINKER_FLAGS="-std=c++11 -stdlib=libc++" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 ..
make -j4
mkdir libcef_dll
cd ../../
- name: 'Configure'
shell: bash
run: |
mkdir ./build
cd ./build
cmake -DENABLE_SPARKLE_UPDATER=ON -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 -DQTDIR="/usr/local/Cellar/qt/${{ env.QT_VERSION }}" -DDepsPath="/tmp/obsdeps" -DVLCPath="${{ github.workspace }}/cmbuild/vlc-${{ env.VLC_VERSION }}" -DBUILD_BROWSER=ON -DBROWSER_DEPLOY=ON -DBUILD_CAPTIONS=ON -DWITH_RTMPS=ON -DCEF_ROOT_DIR="${{ github.workspace }}/cmbuild/cef_binary_${{ env.CEF_BUILD_VERSION }}_macosx64" ..
- name: 'Build'
shell: bash
working-directory: ${{ github.workspace }}/build
run: make -j4
- name: 'Install prerequisite: Packages app'
if: success() && (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'Seeking Testers'))
shell: bash
run: |
curl -L -O https://s3-us-west-2.amazonaws.com/obs-nightly/Packages.pkg
sudo installer -pkg ./Packages.pkg -target /
- name: 'Install prerequisite: DMGbuild'
if: success() && (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'Seeking Testers'))
shell: bash
run: |
pip3 install dmgbuild
- name: 'Package'
if: success() && (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'Seeking Testers'))
shell: bash
run: |
FILE_DATE=$(date +%Y-%m-%d)
FILE_NAME=$FILE_DATE-${{ env.OBS_GIT_HASH }}-${{ env.OBS_GIT_TAG }}-osx.dmg
echo "::set-env name=FILE_NAME::${FILE_NAME}"
./CI/scripts/macos/prepareApp.sh
dmgbuild -s ./CI/scripts/macos/package/settings.json "OBS" OBS.dmg
mkdir ./nightly
sudo mv ./OBS.dmg ./nightly/${FILE_NAME}
- name: 'Publish'
if: success() && (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'Seeking Testers'))
uses: actions/upload-artifact@v2-preview
with:
name: '${{ env.FILE_NAME }}'
path: ./nightly/*.dmg
ubuntu64:
name: 'Linux/Ubuntu 64-bit'
runs-on: [ubuntu-latest]
steps:
- name: 'Checkout'
uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: 'Fetch Git Tags'
run: |
git fetch --prune --unshallow
echo ::set-env name=OBS_GIT_BRANCH::$(git rev-parse --abbrev-ref HEAD)
echo ::set-env name=OBS_GIT_HASH::$(git rev-parse --short HEAD)
echo ::set-env name=OBS_GIT_TAG::$(git describe --tags --abbrev=0)
- name: Install prerequisites (Apt)
shell: bash
run: |
sudo dpkg --add-architecture amd64
sudo apt-get -qq update
sudo apt-get install -y \
build-essential \
checkinstall \
cmake \
libasound2-dev \
libavcodec-dev \
libavdevice-dev \
libavfilter-dev \
libavformat-dev \
libavutil-dev \
libcurl4-openssl-dev \
libfdk-aac-dev \
libfontconfig-dev \
libfreetype6-dev \
libgl1-mesa-dev \
libjack-jackd2-dev \
libjansson-dev \
libluajit-5.1-dev \
libpulse-dev \
libqt5x11extras5-dev \
libspeexdsp-dev \
libswresample-dev \
libswscale-dev \
libudev-dev \
libv4l-dev \
libva-dev \
libvlc-dev \
libx11-dev \
libx264-dev \
libxcb-randr0-dev \
libxcb-shm0-dev \
libxcb-xinerama0-dev \
libxcomposite-dev \
libxinerama-dev \
libmbedtls-dev \
pkg-config \
python3-dev \
qtbase5-dev \
libqt5svg5-dev \
swig
- name: 'Install prerequisite: Chromium Embedded Framework'
shell: bash
run: |
curl -kL https://cdn-fastly.obsproject.com/downloads/cef_binary_${{ env.CEF_BUILD_VERSION }}_linux64.tar.bz2 -f --retry 5 -o cef.tar.bz2
if [ ! -d "${{ github.workspace }}/cmbuild" ]; then mkdir "${{ github.workspace }}/cmbuild"; fi
tar -C"${{ github.workspace }}/cmbuild" -xjf cef.tar.bz2
- name: 'Configure'
shell: bash
run: |
mkdir ./build
cd ./build
cmake -DUNIX_STRUCTURE=0 -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/obs-studio-portable" -DBUILD_CAPTIONS=ON -DWITH_RTMPS=ON -DBUILD_BROWSER=ON -DCEF_ROOT_DIR="${{ github.workspace }}/cmbuild/cef_binary_${{ env.CEF_BUILD_VERSION }}_linux64" ..
- name: 'Build'
shell: bash
working-directory: ${{ github.workspace }}/build
run: make -j4
- name: 'Package'
if: success() && (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'Seeking Testers'))
shell: bash
run: |
FILE_DATE=$(date +%Y-%m-%d)
FILE_NAME=$FILE_DATE-${{ env.OBS_GIT_HASH }}-${{ env.OBS_GIT_TAG }}-linux64.tar.gz
echo "::set-env name=FILE_NAME::${FILE_NAME}"
cd ./build
sudo checkinstall --default --install=no --pkgname=obs-studio --fstrans=yes --backup=no --pkgversion="$(date +%Y%m%d)-git" --deldoc=yes
mkdir ../nightly
tar -cvzf "${FILE_NAME}" *.deb
mv "${FILE_NAME}" ../nightly/
cd -
- name: 'Publish'
if: success() && (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'Seeking Testers'))
uses: actions/upload-artifact@v2-preview
with:
name: '${{ env.FILE_NAME }}'
path: './nightly/*.tar.gz'
win64:
name: 'Windows 64-bit'
runs-on: [windows-latest]
env:
QT_VERSION: '5.10.1'
CMAKE_GENERATOR: "Visual Studio 16 2019"
CMAKE_SYSTEM_VERSION: "10.0.18363.657"
WINDOWS_DEPS_VERSION: '2017'
TWITCH-CLIENTID: ${{ secrets.TWITCH_CLIENTID }}
TWITCH-HASH: ${{ secrets.TWITCH_HASH }}
MIXER-CLIENTID: ${{ secrets.MIXER_CLIENTID }}
MIXER-HASH: ${{ secrets.MIXER_HASH }}
RESTREAM-CLIENTID: ${{ secrets.RESTREAM-CLIENTID }}
RESTREAM-HASH: ${{ secrets.RESTREAM-HASH }}
steps:
- name: 'Add msbuild to PATH'
uses: microsoft/setup-msbuild@v1.0.0
- name: 'Checkout'
uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: 'Fetch Git Tags'
shell: bash
run: |
git fetch --prune --unshallow
echo ::set-env name=OBS_GIT_BRANCH::$(git rev-parse --abbrev-ref HEAD)
echo ::set-env name=OBS_GIT_HASH::$(git rev-parse --short HEAD)
echo ::set-env name=OBS_GIT_TAG::$(git describe --tags --abbrev=0)
- name: 'Install prerequisite: QT'
run: |
curl -kLO https://cdn-fastly.obsproject.com/downloads/Qt_${{ env.QT_VERSION }}.7z -f --retry 5 -C -
7z x Qt_${{ env.QT_VERSION }}.7z -o"${{ github.workspace }}/cmbuild/QT"
- name: 'Install prerequisite: Pre-built dependencies'
run: |
curl -kLO https://cdn-fastly.obsproject.com/downloads/dependencies${{ env.WINDOWS_DEPS_VERSION }}.zip -f --retry 5 -C -
7z x dependencies${{ env.WINDOWS_DEPS_VERSION }}.zip -o"${{ github.workspace }}/cmbuild/deps"
- name: 'Install prerequisite: VLC'
run: |
curl -kL https://cdn-fastly.obsproject.com/downloads/vlc.zip -f --retry 5 -o vlc.zip
7z x vlc.zip -o"${{ github.workspace }}/cmbuild/vlc"
- name: 'Install prerequisite: Chromium Embedded Framework'
run: |
curl -kL https://cdn-fastly.obsproject.com/downloads/cef_binary_${{ env.CEF_VERSION }}_windows64_minimal.zip -f --retry 5 -o cef.zip
7z x cef.zip -o"${{ github.workspace }}/cmbuild"
- name: 'Configure'
run: |
mkdir ./build
mkdir ./build64
cd ./build64
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"x64" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=true -DBUILD_CAPTIONS=true -DCOMPILE_D3D12_HOOK=true -DDepsPath="${{ github.workspace }}/cmbuild/deps/win64" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017_64" -DCEF_ROOT_DIR="${{ github.workspace }}/cmdbuild/cef_binary_${{ env.CEF_VERSION }}_windows64_minimal" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
- name: 'Build'
run: msbuild /m /p:Configuration=RelWithDebInfo .\build64\obs-studio.sln
- name: 'Package'
if: success() && (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'Seeking Testers'))
run: |
$env:FILE_DATE=(Get-Date -UFormat "%F")
$env:FILE_NAME="${env:FILE_DATE}-${{ env.OBS_GIT_HASH }}-${{ env.OBS_GIT_TAG }}-win64.zip"
echo "::set-env name=FILE_NAME::${env:FILE_NAME}"
robocopy .\build64\rundir\RelWithDebInfo .\build\ /E /XF .gitignore
7z a ${env:FILE_NAME} .\build\*
- name: 'Publish'
if: success() && (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'Seeking Testers'))
uses: actions/upload-artifact@v2-preview
with:
name: '${{ env.FILE_NAME }}'
path: '*-win64.zip'
win32:
name: 'Windows 32-bit'
runs-on: [windows-latest]
env:
QT_VERSION: '5.10.1'
CMAKE_GENERATOR: "Visual Studio 16 2019"
CMAKE_SYSTEM_VERSION: "10.0.18363.657"
WINDOWS_DEPS_VERSION: '2017'
TWITCH-CLIENTID: ${{ secrets.TWITCH_CLIENTID }}
TWITCH-HASH: ${{ secrets.TWITCH_HASH }}
MIXER-CLIENTID: ${{ secrets.MIXER_CLIENTID }}
MIXER-HASH: ${{ secrets.MIXER_HASH }}
RESTREAM-CLIENTID: ${{ secrets.RESTREAM-CLIENTID }}
RESTREAM-HASH: ${{ secrets.RESTREAM-HASH }}
steps:
- name: 'Add msbuild to PATH'
uses: microsoft/setup-msbuild@v1.0.0
- name: 'Checkout'
uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: 'Fetch Git Tags'
shell: bash
run: |
git fetch --prune --unshallow
echo ::set-env name=OBS_GIT_BRANCH::$(git rev-parse --abbrev-ref HEAD)
echo ::set-env name=OBS_GIT_HASH::$(git rev-parse --short HEAD)
echo ::set-env name=OBS_GIT_TAG::$(git describe --tags --abbrev=0)
- name: 'Install prerequisite: QT'
run: |
curl -kLO https://cdn-fastly.obsproject.com/downloads/Qt_${{ env.QT_VERSION }}.7z -f --retry 5 -C -
7z x Qt_${{ env.QT_VERSION }}.7z -o"${{ github.workspace }}/cmbuild/QT"
- name: 'Install prerequisite: Pre-built dependencies'
run: |
curl -kLO https://cdn-fastly.obsproject.com/downloads/dependencies${{ env.WINDOWS_DEPS_VERSION }}.zip -f --retry 5 -C -
7z x dependencies${{ env.WINDOWS_DEPS_VERSION }}.zip -o"${{ github.workspace }}/cmbuild/deps"
- name: 'Install prerequisite: VLC'
run: |
curl -kL https://cdn-fastly.obsproject.com/downloads/vlc.zip -f --retry 5 -o vlc.zip
7z x vlc.zip -o"${{ github.workspace }}/cmbuild/vlc"
- name: 'Install prerequisite: Chromium Embedded Framework'
run: |
curl -kL https://cdn-fastly.obsproject.com/downloads/cef_binary_${{ env.CEF_VERSION }}_windows32_minimal.zip -f --retry 5 -o cef.zip
7z x cef.zip -o"${{ github.workspace }}/cmbuild"
- name: 'Configure'
run: |
mkdir ./build
mkdir ./build32
cd ./build32
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"Win32" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=true -DBUILD_CAPTIONS=true -DCOMPILE_D3D12_HOOK=true -DDepsPath="${{ github.workspace }}/cmbuild/deps/win32" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017" -DCEF_ROOT_DIR="${{ github.workspace }}/cmdbuild/cef_binary_${{ env.CEF_VERSION }}_windows32_minimal" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
- name: 'Build'
run: msbuild /m /p:Configuration=RelWithDebInfo .\build32\obs-studio.sln
- name: 'Package'
if: success() && (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'Seeking Testers'))
run: |
$env:FILE_DATE=(Get-Date -UFormat "%F")
$env:FILE_NAME="${env:FILE_DATE}-${{ env.OBS_GIT_HASH }}-${{ env.OBS_GIT_TAG }}-win32.zip"
echo "::set-env name=FILE_NAME::${env:FILE_NAME}"
robocopy .\build32\rundir\RelWithDebInfo .\build\ /E /XF .gitignore
7z a ${env:FILE_NAME} .\build\*
- name: 'Publish'
if: success() && (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'Seeking Testers'))
uses: actions/upload-artifact@v2-preview
with:
name: '${{ env.FILE_NAME }}'
path: '*-win32.zip'

View file

@ -37,7 +37,7 @@ fi
../CI/install/osx/packageApp.sh ../CI/install/osx/packageApp.sh
# fix obs outputs # fix obs outputs plugin it doesn't play nicely with dylibBundler at the moment
cp /usr/local/opt/mbedtls/lib/libmbedtls.12.dylib ./OBS.app/Contents/Frameworks/ cp /usr/local/opt/mbedtls/lib/libmbedtls.12.dylib ./OBS.app/Contents/Frameworks/
cp /usr/local/opt/mbedtls/lib/libmbedcrypto.3.dylib ./OBS.app/Contents/Frameworks/ cp /usr/local/opt/mbedtls/lib/libmbedcrypto.3.dylib ./OBS.app/Contents/Frameworks/
cp /usr/local/opt/mbedtls/lib/libmbedx509.0.dylib ./OBS.app/Contents/Frameworks/ cp /usr/local/opt/mbedtls/lib/libmbedx509.0.dylib ./OBS.app/Contents/Frameworks/
@ -45,11 +45,12 @@ chmod +w ./OBS.app/Contents/Frameworks/*.dylib
install_name_tool -id @executable_path/../Frameworks/libmbedtls.12.dylib ./OBS.app/Contents/Frameworks/libmbedtls.12.dylib install_name_tool -id @executable_path/../Frameworks/libmbedtls.12.dylib ./OBS.app/Contents/Frameworks/libmbedtls.12.dylib
install_name_tool -id @executable_path/../Frameworks/libmbedcrypto.3.dylib ./OBS.app/Contents/Frameworks/libmbedcrypto.3.dylib install_name_tool -id @executable_path/../Frameworks/libmbedcrypto.3.dylib ./OBS.app/Contents/Frameworks/libmbedcrypto.3.dylib
install_name_tool -id @executable_path/../Frameworks/libmbedx509.0.dylib ./OBS.app/Contents/Frameworks/libmbedx509.0.dylib install_name_tool -id @executable_path/../Frameworks/libmbedx509.0.dylib ./OBS.app/Contents/Frameworks/libmbedx509.0.dylib
install_name_tool -change /usr/local/opt/mbedtls/lib/libmbedtls.12.dylib @executable_path/../Frameworks/libmbedtls.12.dylib ./OBS.app/Contents/Plugins/obs-outputs.so install_name_tool -change libmbedtls.12.dylib @executable_path/../Frameworks/libmbedtls.12.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
install_name_tool -change /usr/local/opt/mbedtls/lib/libmbedcrypto.3.dylib @executable_path/../Frameworks/libmbedcrypto.3.dylib ./OBS.app/Contents/Plugins/obs-outputs.so install_name_tool -change libmbedcrypto.3.dylib @executable_path/../Frameworks/libmbedcrypto.3.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
install_name_tool -change /usr/local/opt/mbedtls/lib/libmbedx509.0.dylib @executable_path/../Frameworks/libmbedx509.0.dylib ./OBS.app/Contents/Plugins/obs-outputs.so install_name_tool -change libmbedx509.0.dylib @executable_path/../Frameworks/libmbedx509.0.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
install_name_tool -change /usr/local/opt/curl/lib/libcurl.4.dylib @executable_path/../Frameworks/libcurl.4.dylib ./OBS.app/Contents/Plugins/obs-outputs.so install_name_tool -change /usr/local/opt/curl/lib/libcurl.4.dylib @executable_path/../Frameworks/libcurl.4.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
install_name_tool -change @rpath/libobs.0.dylib @executable_path/../Frameworks/libobs.0.dylib ./OBS.app/Contents/Plugins/obs-outputs.so install_name_tool -change @rpath/libobs.0.dylib @executable_path/../Frameworks/libobs.0.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
install_name_tool -change /tmp/obsdeps/bin/libjansson.4.dylib @executable_path/../Frameworks/libjansson.4.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
# copy sparkle into the app # copy sparkle into the app
hr "Copying Sparkle.framework" hr "Copying Sparkle.framework"

View file

@ -1,10 +1,5 @@
#!/bin/bash #!/bin/bash
./formatcode.sh
if ! ./CI/check-format.sh; then
exit 1
fi
set -ex set -ex
ccache -s || echo "CCache is not available." ccache -s || echo "CCache is not available."
mkdir build && cd build mkdir build && cd build

View file

@ -3,19 +3,15 @@ export PATH=/usr/local/opt/ccache/libexec:$PATH
git fetch --tags git fetch --tags
./formatcode.sh
if ! ./CI/check-format.sh; then
exit 1
fi
mkdir build mkdir build
cd build cd build
cmake -DENABLE_SPARKLE_UPDATER=ON \ cmake -DENABLE_SPARKLE_UPDATER=ON \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 \ -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 \
-DQTDIR=/usr/local/Cellar/qt/5.14.1 \ -DQTDIR=/usr/local/Cellar/qt/5.14.1 \
-DDepsPath=/tmp/obsdeps \ -DDepsPath=/tmp/obsdeps \
-DVLCPath=$PWD/../../vlc-3.0.4 \ -DVLCPath=$PWD/../../vlc-3.0.8 \
-DBUILD_BROWSER=ON \ -DBUILD_BROWSER=ON \
-DBROWSER_DEPLOY=ON \ -DBROWSER_DEPLOY=ON \
-DBUILD_CAPTIONS=ON \ -DBUILD_CAPTIONS=ON \
-DWITH_RTMPS=ON \
-DCEF_ROOT_DIR=$PWD/../../cef_binary_${CEF_BUILD_VERSION}_macosx64 .. -DCEF_ROOT_DIR=$PWD/../../cef_binary_${CEF_BUILD_VERSION}_macosx64 ..

View file

@ -3,15 +3,6 @@ set -ex
curl -L https://packagecloud.io/github/git-lfs/gpgkey | sudo apt-key add - curl -L https://packagecloud.io/github/git-lfs/gpgkey | sudo apt-key add -
# gets us newer clang
sudo bash -c "cat >> /etc/apt/sources.list" << LLVMAPT
# 3.8
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
LLVMAPT
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
sudo apt-get -qq update sudo apt-get -qq update
sudo apt-get install -y \ sudo apt-get install -y \
build-essential \ build-essential \
@ -52,8 +43,7 @@ sudo apt-get install -y \
python3-dev \ python3-dev \
qtbase5-dev \ qtbase5-dev \
libqt5svg5-dev \ libqt5svg5-dev \
swig \ swig
clang-format-8
# build cef # build cef
wget --quiet --retry-connrefused --waitretry=1 https://cdn-fastly.obsproject.com/downloads/cef_binary_${CEF_BUILD_VERSION}_linux64.tar.bz2 wget --quiet --retry-connrefused --waitretry=1 https://cdn-fastly.obsproject.com/downloads/cef_binary_${CEF_BUILD_VERSION}_linux64.tar.bz2

View file

@ -28,9 +28,11 @@ sudo installer -pkg ./Packages.pkg -target /
brew update brew update
#Base OBS Deps and ccache #Base OBS Deps and ccache
brew install jack speexdsp ccache mbedtls clang-format freetype fdk-aac brew install jack speexdsp ccache mbedtls freetype fdk-aac
brew install https://gist.githubusercontent.com/DDRBoxman/9c7a2b08933166f4b61ed9a44b242609/raw/ef4de6c587c6bd7f50210eccd5bd51ff08e6de13/qt.rb brew install https://gist.githubusercontent.com/DDRBoxman/9c7a2b08933166f4b61ed9a44b242609/raw/ef4de6c587c6bd7f50210eccd5bd51ff08e6de13/qt.rb
brew unlink swig if [ -d "$(brew --cellar)/swig" ]; then
brew unlink swig
fi
brew install https://gist.githubusercontent.com/DDRBoxman/4cada55c51803a2f963fa40ce55c9d3e/raw/572c67e908bfbc1bcb8c476ea77ea3935133f5b5/swig.rb brew install https://gist.githubusercontent.com/DDRBoxman/4cada55c51803a2f963fa40ce55c9d3e/raw/572c67e908bfbc1bcb8c476ea77ea3935133f5b5/swig.rb
pip install dmgbuild pip install dmgbuild
@ -40,17 +42,17 @@ ccache -s || echo "CCache is not available."
# Fetch and untar prebuilt OBS deps that are compatible with older versions of OSX # Fetch and untar prebuilt OBS deps that are compatible with older versions of OSX
hr "Downloading OBS deps" hr "Downloading OBS deps"
wget --quiet --retry-connrefused --waitretry=1 https://obs-nightly.s3.amazonaws.com/osx-deps-2018-08-09.tar.gz wget --quiet --retry-connrefused --waitretry=1 https://github.com/obsproject/obs-deps/releases/download/2020-04-24/osx-deps-2020-04-24.tar.gz
tar -xf ./osx-deps-2018-08-09.tar.gz -C /tmp tar -xf ./osx-deps-2020-04-24.tar.gz -C /tmp
# Fetch vlc codebase # Fetch vlc codebase
hr "Downloading VLC repo" hr "Downloading VLC repo"
wget --quiet --retry-connrefused --waitretry=1 https://downloads.videolan.org/vlc/3.0.4/vlc-3.0.4.tar.xz wget --quiet --retry-connrefused --waitretry=1 https://downloads.videolan.org/vlc/3.0.8/vlc-3.0.8.tar.xz
tar -xf vlc-3.0.4.tar.xz tar -xf vlc-3.0.8.tar.xz
# Get sparkle # Get sparkle
hr "Downloading Sparkle framework" hr "Downloading Sparkle framework"
wget --quiet --retry-connrefused --waitretry=1 -O sparkle.tar.bz2 https://github.com/sparkle-project/Sparkle/releases/download/1.20.0/Sparkle-1.20.0.tar.bz2 wget --quiet --retry-connrefused --waitretry=1 -O sparkle.tar.bz2 https://github.com/sparkle-project/Sparkle/releases/download/1.23.0/Sparkle-1.23.0.tar.bz2
mkdir ./sparkle mkdir ./sparkle
tar -xf ./sparkle.tar.bz2 -C ./sparkle tar -xf ./sparkle.tar.bz2 -C ./sparkle
sudo cp -R ./sparkle/Sparkle.framework /Library/Frameworks/Sparkle.framework sudo cp -R ./sparkle/Sparkle.framework /Library/Frameworks/Sparkle.framework

View file

@ -0,0 +1,8 @@
brew "jack"
brew "speexdsp"
brew "cmake"
brew "freetype"
brew "fdk-aac"
brew "https://gist.githubusercontent.com/DDRBoxman/9c7a2b08933166f4b61ed9a44b242609/raw/ef4de6c587c6bd7f50210eccd5bd51ff08e6de13/qt.rb"
brew "swig", link: false
brew "https://gist.githubusercontent.com/DDRBoxman/4cada55c51803a2f963fa40ce55c9d3e/raw/572c67e908bfbc1bcb8c476ea77ea3935133f5b5/swig.rb"

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIconFile</key>
<string>obs.icns</string>
<key>CFBundleName</key>
<string>OBS</string>
<key>CFBundleGetInfoString</key>
<string>OBS - Free and Open Source Streaming/Recording Software</string>
<key>CFBundleExecutable</key>
<string>obs</string>
<key>CFBundleIdentifier</key>
<string>com.obsproject.obs-studio</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>LSMinimumSystemVersion</key>
<string>10.8.5</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>LSAppNapIsDisabled</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>OBS needs to access the camera to enable camera sources to work.</string>
<key>NSMicrophoneUsageDescription</key>
<string>OBS needs to access the microphone to enable audio input.</string>
</dict>
</plist>

View file

@ -0,0 +1,36 @@
-----BEGIN PUBLIC KEY-----
MIIGPDCCBC4GByqGSM44BAEwggQhAoICAQCZZZ2y7H2GJmMfP4KQihJTJOoiGNUw
mue6sqMbH+utRykRnSKBZux6R665eRFMpNgrgFO1TLLGbdD2U31KiGtCvFJOmOl3
+QP055BuXjEG36NU7AWEFLAlbDlr/2D3oumq3Ib3iMnnr9RrVztJ2VFOvVio1eWr
ZxboVwKPK8D6BqsWiv15vbYlJnTC4Fls6ySmdjVBxwoPlTaMu1ysi5DfbIZ93s5u
aQt1FvXuWtPBWjyVUORcNbcWf49E5R2pV0OSBK95Hw2/wXz4vmj+w92dTePGnVaW
Me4CoF5PIeZILwp6DCLStX4eW2WG1NChJTC8zeQ/3bMMoGyKM/MadyvrDqMywsKY
caxkIwHrDKOEdXXGo80dIwZMMLipPA8DKhx5ojphfkeXjIhKSx+49knXT3ED5okE
Wai7tGUXj/8D8sGh+7b+AVsdujvr4v8WQaZiKUOZ2IIHOg3VLz9T9v0zet1Yt987
KNymFcp2CHeJ6KnDP/ZGQ6Nl0HsPxUgscsXV+R2FEc8Q1j0Ukkuxnopa0E4/huUu
gjyRzpXD734qFMDf7LcXca6qNjBor6gVj5sRyRKCpZ+KQfMUlr8jp506ztYSyeJu
dxJV30tQgztwkbrs02CqOt4Z3Peo6sdht7hWKSPVwmja3tq8/TfUSSoo6wKYN9/w
Mf3dVeRF8hCzJQIVAJnzuzmzQhCKPiQnl3jh5qGII2XfAoICAQCCVATAff89ceHj
ROHEbHTQFpVxJ/kRZPfxnU46DSw79Tih7tthV68oakPSOTP3cx/Tga0GwogarZ9N
F2VVan5w9OQSSewXsr5UDT5bnmJF+h+JB7TMy+sXZBYobUqjlUd5VtKc8RsN86P4
s7xbK0mA+hfe+27r18JT81/eH3xUfh7UOUGSdMN2Ch9f7RFSMZIgUAZUzu2K3ODp
hPgtc2QJ8QVAp7GLvQgw8ZUME/ChZslyBIyJvYgUIxfxlgRWYro5pQT7/ngkgdXo
wlghHKkldwMuY3zaFdhPnFNuEUEtc18ILsbz0+AnagCUd6n+3safskCRqLIHMOY6
iLBSZPX9hJQhVCqSqz1VNDDww8FNa/fojJ1Lr/TI0I+0Ib2pCiY2LChXUqGY5SLZ
2KNs5qFsyZP+I0L8YsGwqvUYyFwk7Ok224n0NtaOwqpLCrtXd/i6DaDNiaoJuwJC
1ELCfaZivorgkC5rhBt2H7qWUAR+EtrFE/gb0k/G5EIhjYql7onGbX+G2re38vQA
fg1pzguhig2dafP/BxMLZrn1Gg61xzmEYPuS9gclktaf675srv8GVb46VkOxXL+D
YvTmpJPP7UUOVlmAMCo4j4y09MW3jq9TDp42VTLeZVubyjslGnavlnq1O+ZyXUye
1FMeby65sIbSHHHwoFnRv3hLSEXI5gOCAgYAAoICAQCUkYnZkPfHfOJZI403xUYP
CE/bLpkza074Xo6EXElsWRnpQgNTx+JFOvItgj3v0OkIqDin9UredKOwfkiftslV
jxUVKA6I5kwnGvCpvTpQMLyLjq+VQr+J2D6eId6tV/iajhdu5r4JThU8KllT7Ywb
NAur34ftLNCVAMRUaDNeEoHfePgderW384e+lbvpmtifmBluammGSxxRtUsdjvJZ
BFkhaJu86CKxcU7D1lbPVOtV/jaxz6d16VdGcfBdi2LzXZzZtYpT9XGPX3NF+xii
spAURWsoe11LTRXF+eJhgCm5iIDN3kh1HEQKYKAVpmrcM0aFzk/NpS+tFyU72vaq
IRSSJw/aa1oELOAakG5oPldc4RcYWl32sbnVwXHO7TZvgTrBSC10o65MAC5CHP/s
b07heDYAIt7re7szvOYq+c/9zAMAlu3pcO8MqaXYMmybdHBXHQ2b+DdJWHmIUWcX
CbUzr09vzGkJAvqsXqbmJPr8aixrO75DhT0iDTILLWe/GWK51nf+Tg0pNxVgGyAl
BqvRqqo7SSDu9FMkwQesFFHhuoHLyEHwVPJ+sMQTNwQcm9c6YuW8EYDRSkeKLWYk
3fkjG+Pe9uVE8a1taDg3FjSY0UqjUT6XMw+i0Lajyus2L6wFBwrrGM6E4xa6x1CC
MGjmuSOlPA1umQsToIcO4g==
-----END PUBLIC KEY-----

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,14 @@
{
"title": "OBS",
"background": "./CI/scripts/macos/package/background.tiff",
"icon": "./CI/scripts/macos/app/obs.icns",
"format": "UDZO",
"compression-level": 9,
"window": { "position": { "x": 100, "y": 100 },
"size": { "width": 540, "height": 380 } },
"contents": [
{ "x": 120, "y": 180, "type": "file",
"path": "./OBS.app" },
{ "x": 420, "y": 180, "type": "link", "path": "/Applications" }
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View file

@ -0,0 +1 @@
tiffutil -cathidpicheck background.png background@2x.png -out background.tiff

78
CI/scripts/macos/packageApp.sh Executable file
View file

@ -0,0 +1,78 @@
#!/usr/bin/env bash
# Exit if something fails
set -e
rm -rf ./OBS.app
mkdir OBS.app
mkdir OBS.app/Contents
mkdir OBS.app/Contents/MacOS
mkdir OBS.app/Contents/PlugIns
mkdir OBS.app/Contents/Resources
cp -R rundir/RelWithDebInfo/bin/ ./OBS.app/Contents/MacOS
cp -R rundir/RelWithDebInfo/data ./OBS.app/Contents/Resources
cp ../CI/scripts/macos/app/obs.icns ./OBS.app/Contents/Resources
cp -R rundir/RelWithDebInfo/obs-plugins/ ./OBS.app/Contents/PlugIns
cp ../CI/scripts/macos/app/Info.plist ./OBS.app/Contents
../CI/scripts/macos/package/dylibBundler -b -cd -d ./OBS.app/Contents/Frameworks -p @executable_path/../Frameworks/ \
-s ./OBS.app/Contents/MacOS \
-x ./OBS.app/Contents/PlugIns/coreaudio-encoder.so \
-x ./OBS.app/Contents/PlugIns/decklink-ouput-ui.so \
-x ./OBS.app/Contents/PlugIns/frontend-tools.so \
-x ./OBS.app/Contents/PlugIns/image-source.so \
-x ./OBS.app/Contents/PlugIns/linux-jack.so \
-x ./OBS.app/Contents/PlugIns/mac-avcapture.so \
-x ./OBS.app/Contents/PlugIns/mac-capture.so \
-x ./OBS.app/Contents/PlugIns/mac-decklink.so \
-x ./OBS.app/Contents/PlugIns/mac-syphon.so \
-x ./OBS.app/Contents/PlugIns/mac-vth264.so \
-x ./OBS.app/Contents/PlugIns/obs-browser.so \
-x ./OBS.app/Contents/PlugIns/obs-browser-page \
-x ./OBS.app/Contents/PlugIns/obs-ffmpeg.so \
-x ./OBS.app/Contents/PlugIns/obs-filters.so \
-x ./OBS.app/Contents/PlugIns/obs-transitions.so \
-x ./OBS.app/Contents/PlugIns/obs-vst.so \
-x ./OBS.app/Contents/PlugIns/rtmp-services.so \
-x ./OBS.app/Contents/MacOS/obs \
-x ./OBS.app/Contents/MacOS/obs-ffmpeg-mux \
-x ./OBS.app/Contents/MacOS/obslua.so \
-x ./OBS.app/Contents/MacOS/_obspython.so \
-x ./OBS.app/Contents/PlugIns/obs-x264.so \
-x ./OBS.app/Contents/PlugIns/text-freetype2.so \
-x ./OBS.app/Contents/PlugIns/obs-libfdk.so
# -x ./OBS.app/Contents/PlugIns/obs-outputs.so \
/usr/local/Cellar/qt/${QT_VERSION}/bin/macdeployqt ./OBS.app
mv ./OBS.app/Contents/MacOS/libobs-opengl.so ./OBS.app/Contents/Frameworks
rm -f -r ./OBS.app/Contents/Frameworks/QtNetwork.framework
# put qt network in here becasuse streamdeck uses it
cp -R /usr/local/opt/qt/lib/QtNetwork.framework ./OBS.app/Contents/Frameworks
chmod -R +w ./OBS.app/Contents/Frameworks/QtNetwork.framework
rm -r ./OBS.app/Contents/Frameworks/QtNetwork.framework/Headers
rm -r ./OBS.app/Contents/Frameworks/QtNetwork.framework/Versions/5/Headers/
chmod 644 ./OBS.app/Contents/Frameworks/QtNetwork.framework/Versions/5/Resources/Info.plist
install_name_tool -id @executable_path/../Frameworks/QtNetwork.framework/Versions/5/QtNetwork ./OBS.app/Contents/Frameworks/QtNetwork.framework/Versions/5/QtNetwork
install_name_tool -change /usr/local/Cellar/qt/${QT_VERSION}/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ./OBS.app/Contents/Frameworks/QtNetwork.framework/Versions/5/QtNetwork
# decklink ui qt
install_name_tool -change /usr/local/opt/qt/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui ./OBS.app/Contents/PlugIns/decklink-ouput-ui.so
install_name_tool -change /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ./OBS.app/Contents/PlugIns/decklink-ouput-ui.so
install_name_tool -change /usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets ./OBS.app/Contents/PlugIns/decklink-ouput-ui.so
# frontend tools qt
install_name_tool -change /usr/local/opt/qt/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui ./OBS.app/Contents/PlugIns/frontend-tools.so
install_name_tool -change /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ./OBS.app/Contents/PlugIns/frontend-tools.so
install_name_tool -change /usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets ./OBS.app/Contents/PlugIns/frontend-tools.so
# vst qt
install_name_tool -change /usr/local/opt/qt/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui ./OBS.app/Contents/PlugIns/obs-vst.so
install_name_tool -change /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ./OBS.app/Contents/PlugIns/obs-vst.so
install_name_tool -change /usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets ./OBS.app/Contents/PlugIns/obs-vst.so
install_name_tool -change /usr/local/opt/qt/lib/QtMacExtras.framework/Versions/5/QtMacExtras @executable_path/../Frameworks/QtMacExtras.framework/Versions/5/QtMacExtras ./OBS.app/Contents/PlugIns/obs-vst.so

41
CI/scripts/macos/prepareApp.sh Executable file
View file

@ -0,0 +1,41 @@
#!/usr/bin/env bash
# Exit if something fails
set -e
cd ./build
mv ./rundir/RelWithDebInfo/data/obs-scripting/obslua.so ./rundir/RelWithDebInfo/bin/
mv ./rundir/RelWithDebInfo/data/obs-scripting/_obspython.so ./rundir/RelWithDebInfo/bin/
mv ./rundir/RelWithDebInfo/data/obs-scripting/obspython.py ./rundir/RelWithDebInfo/bin/
../CI/scripts/macos/packageApp.sh
# fix obs outputs plugin it doesn't play nicely with dylibBundler at the moment
chmod +w ./OBS.app/Contents/Frameworks/*.dylib
install_name_tool -change libmbedtls.12.dylib @executable_path/../Frameworks/libmbedtls.12.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
install_name_tool -change libmbedcrypto.3.dylib @executable_path/../Frameworks/libmbedcrypto.3.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
install_name_tool -change libmbedx509.0.dylib @executable_path/../Frameworks/libmbedx509.0.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
install_name_tool -change /usr/local/opt/curl/lib/libcurl.4.dylib @executable_path/../Frameworks/libcurl.4.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
install_name_tool -change @rpath/libobs.0.dylib @executable_path/../Frameworks/libobs.0.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
install_name_tool -change /tmp/obsdeps/bin/libjansson.4.dylib @executable_path/../Frameworks/libjansson.4.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
cp -R ${GITHUB_WORKSPACE}/cmbuild/sparkle/Sparkle.framework ./OBS.app/Contents/Frameworks/
install_name_tool -change @rpath/Sparkle.framework/Versions/A/Sparkle @executable_path/../Frameworks/Sparkle.framework/Versions/A/Sparkle ./OBS.app/Contents/MacOS/obs
sudo mkdir -p ./OBS.app/Contents/Frameworks
sudo cp -R ${GITHUB_WORKSPACE}/cmbuild/cef_binary_${CEF_BUILD_VERSION}_macosx64/Release/Chromium\ Embedded\ Framework.framework ./OBS.app/Contents/Frameworks/
install_name_tool -change /usr/local/opt/qt/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui ./OBS.app/Contents/Plugins/obs-browser.so
install_name_tool -change /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ./OBS.app/Contents/Plugins/obs-browser.so
install_name_tool -change /usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets ./OBS.app/Contents/Plugins/obs-browser.so
cp ../CI/scripts/macos/app/OBSPublicDSAKey.pem ./OBS.app/Contents/Resources
plutil -insert CFBundleVersion -string $(basename ${GITHUB_REF}) ./OBS.app/Contents/Info.plist
plutil -insert CFBundleShortVersionString -string $(basename ${GITHUB_REF}) ./OBS.app/Contents/Info.plist
plutil -insert OBSFeedsURL -string https://obsproject.com/osx_update/feeds.xml ./OBS.app/Contents/Info.plist
plutil -insert SUFeedURL -string https://obsproject.com/osx_update/stable/updates.xml ./OBS.app/Contents/Info.plist
plutil -insert SUPublicDSAKeyFile -string OBSPublicDSAKey.pem ./OBS.app/Contents/Info.plist
mv ./OBS.app ../OBS.app
cd -

View file

@ -86,6 +86,11 @@ if(WIN32)
list(GET UI_VERSION_SEMANTIC 0 UI_VERSION_MAJOR) list(GET UI_VERSION_SEMANTIC 0 UI_VERSION_MAJOR)
list(GET UI_VERSION_SEMANTIC 1 UI_VERSION_MINOR) list(GET UI_VERSION_SEMANTIC 1 UI_VERSION_MINOR)
list(GET UI_VERSION_SEMANTIC 2 UI_VERSION_PATCH) list(GET UI_VERSION_SEMANTIC 2 UI_VERSION_PATCH)
set(OBS_COMPANY_NAME "OBS")
set(OBS_PRODUCT_NAME "OBS Studio")
set(OBS_COMMENTS "Free and open source software for video recording and live streaming")
set(OBS_LEGAL_COPYRIGHT "(C) Hugh Bailey")
set(MODULE_DESCRIPTION "OBS Studio")
configure_file(UI/obs.rc.in ${PROJECT_BINARY_DIR}/obs.rc) configure_file(UI/obs.rc.in ${PROJECT_BINARY_DIR}/obs.rc)
endif() endif()

View file

@ -52,8 +52,8 @@ Untitled="Untitled"
New="New" New="New"
Duplicate="Duplicate" Duplicate="Duplicate"
Enable="Enable" Enable="Enable"
DisableOSXVSync="Disable OSX V-Sync" DisableOSXVSync="Disable macOS V-Sync"
ResetOSXVSyncOnExit="Reset OSX V-Sync on Exit" ResetOSXVSyncOnExit="Reset macOS V-Sync on Exit"
HighResourceUsage="Encoding overloaded! Consider turning down video settings or using a faster encoding preset." HighResourceUsage="Encoding overloaded! Consider turning down video settings or using a faster encoding preset."
Transition="Transition" Transition="Transition"
QuickTransitions="Quick Transitions" QuickTransitions="Quick Transitions"
@ -324,8 +324,6 @@ Output.RecordNoSpace.Msg="There is not sufficient disk space to continue recordi
Output.RecordError.Title="Recording error" Output.RecordError.Title="Recording error"
Output.RecordError.Msg="An unspecified error occurred while recording." Output.RecordError.Msg="An unspecified error occurred while recording."
Output.RecordError.EncodeErrorMsg="An encoder error occurred while recording." Output.RecordError.EncodeErrorMsg="An encoder error occurred while recording."
Output.ReplayBuffer.NoHotkey.Title="No hotkey set!"
Output.ReplayBuffer.NoHotkey.Msg="No save hotkey set for replay buffer. Please set the \"Save\" hotkey to use for saving replay recordings."
# output recording messages # output recording messages
Output.BadPath.Title="Bad File Path" Output.BadPath.Title="Bad File Path"
@ -715,7 +713,6 @@ Basic.Settings.Output.ReplayBuffer.SecondsMax="Maximum Replay Time"
Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maximum Memory (Megabytes)" Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maximum Memory (Megabytes)"
Basic.Settings.Output.ReplayBuffer.Estimate="Estimated memory usage: %1 MB" Basic.Settings.Output.ReplayBuffer.Estimate="Estimated memory usage: %1 MB"
Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Cannot estimate memory usage. Please set maximum memory limit." Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Cannot estimate memory usage. Please set maximum memory limit."
Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Note: Make sure to set a hotkey for the replay buffer in the hotkeys section)"
Basic.Settings.Output.ReplayBuffer.Prefix="Replay Buffer Filename Prefix" Basic.Settings.Output.ReplayBuffer.Prefix="Replay Buffer Filename Prefix"
Basic.Settings.Output.ReplayBuffer.Suffix="Suffix" Basic.Settings.Output.ReplayBuffer.Suffix="Suffix"
Basic.Settings.Output.Simple.SavePath="Recording Path" Basic.Settings.Output.Simple.SavePath="Recording Path"

View file

@ -154,6 +154,11 @@ QListWidget QLineEdit {
} }
/* Dock stuff */ /* Dock stuff */
QDockWidget {
titlebar-close-icon: url('./Dark/Close.svg');
titlebar-normal-icon: url('./Dark/Popout.svg');
}
QDockWidget { QDockWidget {
background: #181819; background: #181819;
border: none; border: none;
@ -182,6 +187,7 @@ QDockWidget::float-button {
subcontrol-position: top right; subcontrol-position: top right;
subcontrol-origin: padding; subcontrol-origin: padding;
right: 0px; right: 0px;
margin: 0px;
} }
QDockWidget::float-button { QDockWidget::float-button {

View file

@ -119,6 +119,11 @@ SourceTree QLineEdit {
/* Dock Widget */ /* Dock Widget */
QDockWidget {
titlebar-close-icon: url('./Dark/Close.svg');
titlebar-normal-icon: url('./Dark/Popout.svg');
}
QDockWidget::title { QDockWidget::title {
text-align: center; text-align: center;
background-color: rgb(70,69,70); background-color: rgb(70,69,70);

View file

@ -0,0 +1 @@
<svg class="feather feather-plus" fill="none" stroke="#FFF" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" version="1.1" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"><line x1="2" x2="28" y1="2" y2="28" /><line x1="2" x2="28" y1="28" y2="2" /></svg>

After

Width:  |  Height:  |  Size: 276 B

View file

@ -0,0 +1 @@
<svg class="feather feather-plus" fill="none" stroke="#FFF" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" version="1.1" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="24" height="20" /><rect x="2" y="2" width="24" height="4" style="fill:#fff" /><rect x="14" y="18" width="24" height="20" /><rect x="14" y="18" width="24" height="4" style="fill:#fff" /></svg>

After

Width:  |  Height:  |  Size: 410 B

View file

@ -188,6 +188,11 @@ QListWidget::item:hover:!active {
/* --- Dock widget --- */ /* --- Dock widget --- */
/***********************/ /***********************/
QDockWidget {
titlebar-close-icon: url('./Dark/Close.svg');
titlebar-normal-icon: url('./Dark/Popout.svg');
}
QDockWidget { QDockWidget {
background: rgb(49, 54, 59); /* Blue-gray */ background: rgb(49, 54, 59); /* Blue-gray */
border: 1px solid rgb(58, 64, 69); /* Light Blue-gray */ border: 1px solid rgb(58, 64, 69); /* Light Blue-gray */

View file

@ -38,6 +38,21 @@
</property> </property>
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
@ -853,19 +868,19 @@
<widget class="QWidget" name="transitionsContainer" native="true"> <widget class="QWidget" name="transitionsContainer" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing"> <property name="spacing">
<number>4</number> <number>2</number>
</property> </property>
<property name="leftMargin"> <property name="leftMargin">
<number>1</number> <number>0</number>
</property> </property>
<property name="topMargin"> <property name="topMargin">
<number>1</number> <number>0</number>
</property> </property>
<property name="rightMargin"> <property name="rightMargin">
<number>1</number> <number>0</number>
</property> </property>
<property name="bottomMargin"> <property name="bottomMargin">
<number>2</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="QComboBox" name="transitions"> <widget class="QComboBox" name="transitions">

View file

@ -958,6 +958,12 @@
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QStackedWidget" name="serverStackedWidget"> <widget class="QStackedWidget" name="serverStackedWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex"> <property name="currentIndex">
<number>1</number> <number>1</number>
</property> </property>
@ -1760,13 +1766,6 @@
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="QLabel" name="label_45">
<property name="text">
<string>Basic.Settings.Output.ReplayBuffer.HotkeyMessage</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="simpleRBEstimate"> <widget class="QLabel" name="simpleRBEstimate">
<property name="text"> <property name="text">
<string notr="true"/> <string notr="true"/>
@ -3670,13 +3669,6 @@
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="QLabel" name="advRBHotkeyLabel">
<property name="text">
<string>Basic.Settings.Output.ReplayBuffer.HotkeyMessage</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="advRBEstimate"> <widget class="QLabel" name="advRBEstimate">
<property name="text"> <property name="text">
<string notr="true"/> <string notr="true"/>

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 2.1166666 2.1166667"
height="8"
width="8">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-294.88332)"
id="layer1">
<circle
r="0.52916664"
cy="295.94165"
cx="1.0583333"
id="path4544"
style="fill:#d40000;fill-opacity:1;stroke:none;stroke-width:0.06614584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 2.1166666 2.1166667"
height="8"
width="8">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-294.88332)"
id="layer1">
<circle
r="0.52916664"
cy="295.94165"
cx="1.0583333"
id="path4544"
style="fill:#999999;fill-opacity:1;stroke:none;stroke-width:0.06614584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 5.2916665 5.2916668"
height="20"
width="20">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-291.70832)"
id="layer1">
<rect
y="293.03125"
x="1.3229166"
height="2.6458333"
width="1.0583333"
id="rect822"
style="fill:#999999;fill-opacity:1;stroke:none;stroke-width:0.5020116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<rect
y="293.03125"
x="2.9104166"
height="2.6458333"
width="1.0583333"
id="rect822-1"
style="fill:#999999;fill-opacity:1;stroke:none;stroke-width:0.5020116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 5.2916665 5.2916668"
height="20"
width="20">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-291.70832)"
id="layer1">
<rect
y="293.03125"
x="1.3229166"
height="2.6458333"
width="1.0583333"
id="rect822"
style="fill:#d4ae00;fill-opacity:1;stroke:none;stroke-width:0.5020116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<rect
y="293.03125"
x="2.9104166"
height="2.6458333"
width="1.0583333"
id="rect822-1"
style="fill:#d4ae00;fill-opacity:1;stroke:none;stroke-width:0.5020116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 2.1166666 2.1166667"
height="8"
width="8">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-294.88332)"
id="layer1">
<circle
r="0.39687499"
cy="295.94165"
cx="1.0582843"
id="path4544-3"
style="fill:#5079cc;fill-opacity:1;stroke:none;stroke-width:0.13229169;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<path
d="M 0.41577997,296.5497 A 0.79374999,0.79374999 0 0 1 0.13224262,295.94165 0.79374999,0.79374999 0 0 1 0.41577996,295.3336"
id="path4546-7"
style="fill:none;fill-opacity:1;stroke:#5079cc;stroke-width:0.15875001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<path
transform="scale(-1,1)"
d="m -1.7008867,296.5497 a 0.79374999,0.79374999 0 0 1 -0.2835374,-0.60805 0.79374999,0.79374999 0 0 1 0.2835374,-0.60805"
id="path4546-1-3"
style="fill:none;fill-opacity:1;stroke:#5079cc;stroke-width:0.15875001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<path
d="M 0.63239977,296.41847 A 0.62244385,0.62244385 0 0 1 0.4100551,295.94165 0.62244385,0.62244385 0 0 1 0.63239977,295.46483"
id="path4546-5-7"
style="fill:none;fill-opacity:1;stroke:#5079cc;stroke-width:0.15875001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<path
transform="scale(-1,1)"
d="m -1.484193,296.41847 a 0.62244391,0.62244391 0 0 1 -0.2223447,-0.47682 0.62244391,0.62244391 0 0 1 0.2223447,-0.47682"
id="path4546-5-4-2"
style="fill:none;fill-opacity:1;stroke:#5079cc;stroke-width:0.15875001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 2.1166666 2.1166667"
height="8"
width="8">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-294.88332)"
id="layer1">
<circle
r="0.39687499"
cy="295.94165"
cx="1.0583333"
id="path4544"
style="fill:#7f7d7f;fill-opacity:1;stroke:none;stroke-width:0.13229167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<path
d="M 0.41582902,296.5497 A 0.79374999,0.79374999 0 0 1 0.13229167,295.94165 0.79374999,0.79374999 0 0 1 0.41582902,295.3336"
id="path4546"
style="fill:none;fill-opacity:1;stroke:#7f7d7f;stroke-width:0.15875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<path
transform="scale(-1,1)"
d="m -1.7009357,296.5497 a 0.79374999,0.79374999 0 0 1 -0.2835373,-0.60805 0.79374999,0.79374999 0 0 1 0.2835373,-0.60805"
id="path4546-1"
style="fill:none;fill-opacity:1;stroke:#7f7d7f;stroke-width:0.15875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<path
d="M 0.6324488,296.41847 A 0.6224438,0.6224438 0 0 1 0.41010416,295.94165 0.6224438,0.6224438 0 0 1 0.6324488,295.46483"
id="path4546-5"
style="fill:none;fill-opacity:1;stroke:#7f7d7f;stroke-width:0.15875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<path
transform="scale(-1,1)"
d="m -1.484242,296.41847 a 0.62244385,0.62244385 0 0 1 -0.2223447,-0.47682 0.62244385,0.62244385 0 0 1 0.2223447,-0.47682"
id="path4546-5-4"
style="fill:none;fill-opacity:1;stroke:#7f7d7f;stroke-width:0.15875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -34,6 +34,12 @@
<file>images/sources/text.svg</file> <file>images/sources/text.svg</file>
<file>images/sources/window.svg</file> <file>images/sources/window.svg</file>
<file>images/sources/default.svg</file> <file>images/sources/default.svg</file>
<file>images/recording-active.svg</file>
<file>images/recording-inactive.svg</file>
<file>images/recording-pause.svg</file>
<file>images/recording-pause-inactive.svg</file>
<file>images/streaming-active.svg</file>
<file>images/streaming-inactive.svg</file>
</qresource> </qresource>
<qresource prefix="/settings"> <qresource prefix="/settings">
<file>images/settings/output.svg</file> <file>images/settings/output.svg</file>

View file

@ -39,6 +39,13 @@ set(decklink-ouput-ui_UI
forms/output.ui forms/output.ui
) )
if(WIN32)
set(MODULE_DESCRIPTION "OBS DeckLink Output UI")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in decklink-ouput-ui.rc)
list(APPEND decklink-ouput-ui_SOURCES
decklink-ouput-ui.rc)
endif()
if(APPLE) if(APPLE)
set(decklink-ouput-ui_PLATFORM_LIBS set(decklink-ouput-ui_PLATFORM_LIBS
${COCOA}) ${COCOA})

View file

@ -71,8 +71,11 @@ if(SCRIPTING_ENABLED)
endif() endif()
if(WIN32) if(WIN32)
set(MODULE_DESCRIPTION "OBS Frontend Tools")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in frontend-tools.rc)
set(frontend-tools_PLATFORM_SOURCES set(frontend-tools_PLATFORM_SOURCES
auto-scene-switcher-win.cpp) auto-scene-switcher-win.cpp
frontend-tools.rc)
if(BUILD_CAPTIONS) if(BUILD_CAPTIONS)
set(frontend-tools_PLATFORM_SOURCES set(frontend-tools_PLATFORM_SOURCES

View file

@ -298,15 +298,8 @@ static int attempt_import(const Json &root, const string &name, Json &res)
Json::array filter_items = in_filters["items"].array_items(); Json::array filter_items = in_filters["items"].array_items();
Json in_settings = scene["settings"]; Json in_settings = scene["settings"];
Json in_sync = scene["syncOffset"];
int sync = (int)(in_sync["sec"].number_value() * 1000000000 +
in_sync["nsec"].number_value());
double vol = scene["volume"].number_value();
bool muted = scene["muted"].bool_value();
string name = scene["name"].string_value(); string name = scene["name"].string_value();
int monitoring = scene["monitoringType"].int_value();
Json::object out_hotkeys = Json::object{}; Json::object out_hotkeys = Json::object{};
get_hotkey_bindings(out_hotkeys, hotkey_items, ""); get_hotkey_bindings(out_hotkeys, hotkey_items, "");
@ -336,11 +329,8 @@ static int attempt_import(const Json &root, const string &name, Json &res)
{"id", "scene"}, {"id", "scene"},
{"sl_id", sl_id}, {"sl_id", sl_id},
{"settings", in_settings}, {"settings", in_settings},
{"sync", sync}, {"volume", 1.0},
{"volume", vol},
{"muted", muted},
{"name", out_name}, {"name", out_name},
{"monitoring_type", monitoring},
{"private_settings", Json::object{}}}; {"private_settings", Json::object{}}};
Json in_items = scene["sceneItems"]; Json in_items = scene["sceneItems"];

View file

@ -7,6 +7,12 @@ add_definitions(-DLIBOBS_EXPORTS)
set(obs-frontend-api_SOURCES set(obs-frontend-api_SOURCES
obs-frontend-api.cpp) obs-frontend-api.cpp)
if(WIN32)
set(MODULE_DESCRIPTION "OBS Frontend API")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in ./obs-frontend-api.rc)
list(APPEND obs-frontend-api_SOURCES
obs-frontend-api.rc)
endif()
set(obs-frontend-api_HEADERS set(obs-frontend-api_HEADERS
obs-frontend-internal.hpp obs-frontend-internal.hpp
obs-frontend-api.h) obs-frontend-api.h)

View file

@ -1694,7 +1694,7 @@ bool WidgetInfo::ColorChanged(const char *setting)
* other open QDialogs on exit, and * other open QDialogs on exit, and
* https://bugreports.qt-project.org/browse/QTBUG-34532 * https://bugreports.qt-project.org/browse/QTBUG-34532
*/ */
#ifdef __APPLE__ #ifndef _WIN32
options |= QColorDialog::DontUseNativeDialog; options |= QColorDialog::DontUseNativeDialog;
#endif #endif
@ -1728,7 +1728,7 @@ bool WidgetInfo::FontChanged(const char *setting)
QFontDialog::FontDialogOptions options; QFontDialog::FontDialogOptions options;
#ifdef __APPLE__ #ifndef _WIN32
options = QFontDialog::DontUseNativeDialog; options = QFontDialog::DontUseNativeDialog;
#endif #endif

View file

@ -6,6 +6,7 @@
#include <QStackedWidget> #include <QStackedWidget>
#include <QWidget> #include <QWidget>
#include <obs.h>
#include <media-io/frame-rate.h> #include <media-io/frame-rate.h>
#include <vector> #include <vector>

View file

@ -8,6 +8,8 @@
#include <QStaticText> #include <QStaticText>
#include <QSvgRenderer> #include <QSvgRenderer>
#include <QAbstractListModel> #include <QAbstractListModel>
#include <obs.hpp>
#include <obs-frontend-api.h>
class QLabel; class QLabel;
class QCheckBox; class QCheckBox;

View file

@ -169,6 +169,12 @@ void OBSBasic::AddDropSource(const char *data, DropType image)
void OBSBasic::dragEnterEvent(QDragEnterEvent *event) void OBSBasic::dragEnterEvent(QDragEnterEvent *event)
{ {
// refuse drops of our own widgets
if (event->source() != nullptr) {
event->setDropAction(Qt::IgnoreAction);
return;
}
event->acceptProposedAction(); event->acceptProposedAction();
} }

View file

@ -1346,7 +1346,7 @@ void OBSBasic::SetPreviewProgramMode(bool enabled)
RefreshQuickTransitions(); RefreshQuickTransitions();
programLabel = new QLabel(QTStr("StudioMode.Program")); programLabel = new QLabel(QTStr("StudioMode.Program"), this);
programLabel->setSizePolicy(QSizePolicy::Preferred, programLabel->setSizePolicy(QSizePolicy::Preferred,
QSizePolicy::Preferred); QSizePolicy::Preferred);
programLabel->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); programLabel->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);

View file

@ -385,6 +385,7 @@ OBSBasic::OBSBasic(QWidget *parent)
statsDock->move(newPos); statsDock->move(newPos);
ui->previewLabel->setProperty("themeID", "previewProgramLabels"); ui->previewLabel->setProperty("themeID", "previewProgramLabels");
ui->previewLabel->style()->polish(ui->previewLabel);
bool labels = config_get_bool(GetGlobalConfig(), "BasicWindow", bool labels = config_get_bool(GetGlobalConfig(), "BasicWindow",
"StudioModeLabels"); "StudioModeLabels");
@ -670,6 +671,8 @@ void OBSBasic::DeferSaveEnd()
} }
} }
static void LogFilter(obs_source_t *, obs_source_t *filter, void *v_val);
static void LoadAudioDevice(const char *name, int channel, obs_data_t *parent) static void LoadAudioDevice(const char *name, int channel, obs_data_t *parent)
{ {
obs_data_t *data = obs_data_get_obj(parent, name); obs_data_t *data = obs_data_get_obj(parent, name);
@ -679,6 +682,10 @@ static void LoadAudioDevice(const char *name, int channel, obs_data_t *parent)
obs_source_t *source = obs_load_source(data); obs_source_t *source = obs_load_source(data);
if (source) { if (source) {
obs_set_output_source(channel, source); obs_set_output_source(channel, source);
const char *name = obs_source_get_name(source);
blog(LOG_INFO, "[Loaded global audio device]: '%s'", name);
obs_source_enum_filters(source, LogFilter, (void *)(intptr_t)1);
obs_source_release(source); obs_source_release(source);
} }
@ -3915,6 +3922,7 @@ void OBSBasic::ClearSceneData()
return true; return true;
}; };
obs_enum_scenes(cb, nullptr);
obs_enum_sources(cb, nullptr); obs_enum_sources(cb, nullptr);
if (api) if (api)
@ -5719,9 +5727,6 @@ void OBSBasic::RecordingStop(int code, QString last_error)
UpdatePause(false); UpdatePause(false);
} }
#define RP_NO_HOTKEY_TITLE QTStr("Output.ReplayBuffer.NoHotkey.Title")
#define RP_NO_HOTKEY_TEXT QTStr("Output.ReplayBuffer.NoHotkey.Msg")
void OBSBasic::ShowReplayBufferPauseWarning() void OBSBasic::ShowReplayBufferPauseWarning()
{ {
auto msgBox = []() { auto msgBox = []() {
@ -5773,21 +5778,6 @@ void OBSBasic::StartReplayBuffer()
return; return;
} }
obs_output_t *output = outputHandler->replayBuffer;
obs_data_t *hotkeys = obs_hotkeys_save_output(output);
obs_data_array_t *bindings =
obs_data_get_array(hotkeys, "ReplayBuffer.Save");
size_t count = obs_data_array_count(bindings);
obs_data_array_release(bindings);
obs_data_release(hotkeys);
if (!count) {
OBSMessageBox::information(this, RP_NO_HOTKEY_TITLE,
RP_NO_HOTKEY_TEXT);
replayBufferButton->setChecked(false);
return;
}
if (api) if (api)
api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING); api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING);
@ -6225,6 +6215,9 @@ void OBSBasic::on_actionEditTransform_triggered()
if (transformWindow) if (transformWindow)
transformWindow->close(); transformWindow->close();
if (!GetCurrentSceneItem())
return;
transformWindow = new OBSBasicTransform(this); transformWindow = new OBSBasicTransform(this);
transformWindow->show(); transformWindow->show();
transformWindow->setAttribute(Qt::WA_DeleteOnClose, true); transformWindow->setAttribute(Qt::WA_DeleteOnClose, true);
@ -7264,7 +7257,7 @@ void OBSBasic::on_actionCopySource_triggered()
copyVisible = obs_sceneitem_visible(item); copyVisible = obs_sceneitem_visible(item);
uint32_t output_flags = obs_source_get_output_flags(source); uint32_t output_flags = obs_source_get_output_flags(source);
if (!(output_flags & OBS_SOURCE_DO_NOT_DUPLICATE) == 0) if (output_flags & OBS_SOURCE_DO_NOT_DUPLICATE)
allowPastingDuplicate = false; allowPastingDuplicate = false;
} }
@ -7482,7 +7475,7 @@ void OBSBasic::ColorChange()
obs_data_get_string(curPrivData, "color"); obs_data_get_string(curPrivData, "color");
const char *customColor = *oldColor != 0 ? oldColor const char *customColor = *oldColor != 0 ? oldColor
: "#55FF0000"; : "#55FF0000";
#ifdef __APPLE__ #ifndef _WIN32
options |= QColorDialog::DontUseNativeDialog; options |= QColorDialog::DontUseNativeDialog;
#endif #endif
@ -7703,6 +7696,8 @@ void OBSBasic::PauseRecording()
pause->setChecked(true); pause->setChecked(true);
pause->blockSignals(false); pause->blockSignals(false);
ui->statusbar->RecordingPaused();
if (trayIcon) if (trayIcon)
trayIcon->setIcon(QIcon(":/res/images/obs_paused.png")); trayIcon->setIcon(QIcon(":/res/images/obs_paused.png"));
@ -7730,6 +7725,8 @@ void OBSBasic::UnpauseRecording()
pause->setChecked(false); pause->setChecked(false);
pause->blockSignals(false); pause->blockSignals(false);
ui->statusbar->RecordingUnpaused();
if (trayIcon) if (trayIcon)
trayIcon->setIcon( trayIcon->setIcon(
QIcon(":/res/images/tray_active.png")); QIcon(":/res/images/tray_active.png"));

View file

@ -2,6 +2,7 @@
#include <obs.hpp> #include <obs.hpp>
#include <util/platform.h> #include <util/platform.h>
#include <obs-frontend-api.h>
#include <QPointer> #include <QPointer>
#include <QWidget> #include <QWidget>
#include <QTimer> #include <QTimer>

View file

@ -11,18 +11,36 @@ OBSBasicStatusBar::OBSBasicStatusBar(QWidget *parent)
: QStatusBar(parent), : QStatusBar(parent),
delayInfo(new QLabel), delayInfo(new QLabel),
droppedFrames(new QLabel), droppedFrames(new QLabel),
streamIcon(new QLabel),
streamTime(new QLabel), streamTime(new QLabel),
recordIcon(new QLabel),
recordTime(new QLabel), recordTime(new QLabel),
cpuUsage(new QLabel), cpuUsage(new QLabel),
transparentPixmap(20, 20), transparentPixmap(20, 20),
greenPixmap(20, 20), greenPixmap(20, 20),
grayPixmap(20, 20), grayPixmap(20, 20),
redPixmap(20, 20) redPixmap(20, 20),
recordingActivePixmap(QIcon(":/res/images/recording-active.svg")
.pixmap(QSize(20, 20))),
recordingPausePixmap(QIcon(":/res/images/recording-pause.svg")
.pixmap(QSize(20, 20))),
recordingPauseInactivePixmap(
QIcon(":/res/images/recording-pause-inactive.svg")
.pixmap(QSize(20, 20))),
recordingInactivePixmap(QIcon(":/res/images/recording-inactive.svg")
.pixmap(QSize(20, 20))),
streamingActivePixmap(QIcon(":/res/images/streaming-active.svg")
.pixmap(QSize(20, 20))),
streamingInactivePixmap(QIcon(":/res/images/streaming-inactive.svg")
.pixmap(QSize(20, 20)))
{ {
streamTime->setText(QString("LIVE: 00:00:00")); streamTime->setText(QString("LIVE: 00:00:00"));
recordTime->setText(QString("REC: 00:00:00")); recordTime->setText(QString("REC: 00:00:00"));
cpuUsage->setText(QString("CPU: 0.0%, 0.00 fps")); cpuUsage->setText(QString("CPU: 0.0%, 0.00 fps"));
streamIcon->setPixmap(streamingInactivePixmap);
recordIcon->setPixmap(recordingInactivePixmap);
QWidget *brWidget = new QWidget(this); QWidget *brWidget = new QWidget(this);
QHBoxLayout *brLayout = new QHBoxLayout(brWidget); QHBoxLayout *brLayout = new QHBoxLayout(brWidget);
brLayout->setContentsMargins(0, 0, 0, 0); brLayout->setContentsMargins(0, 0, 0, 0);
@ -39,8 +57,12 @@ OBSBasicStatusBar::OBSBasicStatusBar(QWidget *parent)
delayInfo->setAlignment(Qt::AlignVCenter); delayInfo->setAlignment(Qt::AlignVCenter);
droppedFrames->setAlignment(Qt::AlignRight); droppedFrames->setAlignment(Qt::AlignRight);
droppedFrames->setAlignment(Qt::AlignVCenter); droppedFrames->setAlignment(Qt::AlignVCenter);
streamIcon->setAlignment(Qt::AlignRight);
streamIcon->setAlignment(Qt::AlignVCenter);
streamTime->setAlignment(Qt::AlignRight); streamTime->setAlignment(Qt::AlignRight);
streamTime->setAlignment(Qt::AlignVCenter); streamTime->setAlignment(Qt::AlignVCenter);
recordIcon->setAlignment(Qt::AlignRight);
recordIcon->setAlignment(Qt::AlignVCenter);
recordTime->setAlignment(Qt::AlignRight); recordTime->setAlignment(Qt::AlignRight);
recordTime->setAlignment(Qt::AlignVCenter); recordTime->setAlignment(Qt::AlignVCenter);
cpuUsage->setAlignment(Qt::AlignRight); cpuUsage->setAlignment(Qt::AlignRight);
@ -50,13 +72,15 @@ OBSBasicStatusBar::OBSBasicStatusBar(QWidget *parent)
delayInfo->setIndent(20); delayInfo->setIndent(20);
droppedFrames->setIndent(20); droppedFrames->setIndent(20);
streamTime->setIndent(20); streamIcon->setIndent(20);
recordTime->setIndent(20); recordIcon->setIndent(20);
cpuUsage->setIndent(20); cpuUsage->setIndent(20);
kbps->setIndent(10); kbps->setIndent(10);
addPermanentWidget(droppedFrames); addPermanentWidget(droppedFrames);
addPermanentWidget(streamIcon);
addPermanentWidget(streamTime); addPermanentWidget(streamTime);
addPermanentWidget(recordIcon);
addPermanentWidget(recordTime); addPermanentWidget(recordTime);
addPermanentWidget(cpuUsage); addPermanentWidget(cpuUsage);
addPermanentWidget(delayInfo); addPermanentWidget(delayInfo);
@ -93,6 +117,14 @@ void OBSBasicStatusBar::Activate()
statusSquare->setPixmap(grayPixmap); statusSquare->setPixmap(grayPixmap);
} }
} }
if (streamOutput) {
streamIcon->setPixmap(streamingActivePixmap);
}
if (recordOutput) {
recordIcon->setPixmap(recordingActivePixmap);
}
} }
void OBSBasicStatusBar::Deactivate() void OBSBasicStatusBar::Deactivate()
@ -103,11 +135,13 @@ void OBSBasicStatusBar::Deactivate()
if (!streamOutput) { if (!streamOutput) {
streamTime->setText(QString("LIVE: 00:00:00")); streamTime->setText(QString("LIVE: 00:00:00"));
streamIcon->setPixmap(streamingInactivePixmap);
totalStreamSeconds = 0; totalStreamSeconds = 0;
} }
if (!recordOutput) { if (!recordOutput) {
recordTime->setText(QString("REC: 00:00:00")); recordTime->setText(QString("REC: 00:00:00"));
recordIcon->setPixmap(recordingInactivePixmap);
totalRecordSeconds = 0; totalRecordSeconds = 0;
} }
@ -247,25 +281,26 @@ void OBSBasicStatusBar::UpdateRecordTime()
{ {
bool paused = os_atomic_load_bool(&recording_paused); bool paused = os_atomic_load_bool(&recording_paused);
if (!paused) if (!paused) {
totalRecordSeconds++; totalRecordSeconds++;
QString text;
if (paused) {
text = QStringLiteral("REC: PAUSED");
} else {
int seconds = totalRecordSeconds % 60; int seconds = totalRecordSeconds % 60;
int totalMinutes = totalRecordSeconds / 60; int totalMinutes = totalRecordSeconds / 60;
int minutes = totalMinutes % 60; int minutes = totalMinutes % 60;
int hours = totalMinutes / 60; int hours = totalMinutes / 60;
text = QString::asprintf("REC: %02d:%02d:%02d", hours, minutes, QString text = QString::asprintf("REC: %02d:%02d:%02d", hours,
seconds); minutes, seconds);
}
recordTime->setText(text); recordTime->setText(text);
recordTime->setMinimumWidth(recordTime->width()); recordTime->setMinimumWidth(recordTime->width());
} else {
recordIcon->setPixmap(streamPauseIconToggle
? recordingPauseInactivePixmap
: recordingPausePixmap);
streamPauseIconToggle = !streamPauseIconToggle;
}
} }
void OBSBasicStatusBar::UpdateDroppedFrames() void OBSBasicStatusBar::UpdateDroppedFrames()
@ -483,3 +518,22 @@ void OBSBasicStatusBar::RecordingStopped()
recordOutput = nullptr; recordOutput = nullptr;
Deactivate(); Deactivate();
} }
void OBSBasicStatusBar::RecordingPaused()
{
QString text = QStringLiteral("REC: PAUSED");
recordTime->setText(text);
recordTime->setMinimumWidth(recordTime->width());
if (recordOutput) {
recordIcon->setPixmap(recordingPausePixmap);
streamPauseIconToggle = true;
}
}
void OBSBasicStatusBar::RecordingUnpaused()
{
if (recordOutput) {
recordIcon->setPixmap(recordingActivePixmap);
}
}

View file

@ -14,8 +14,10 @@ class OBSBasicStatusBar : public QStatusBar {
private: private:
QLabel *delayInfo; QLabel *delayInfo;
QLabel *droppedFrames; QLabel *droppedFrames;
QLabel *streamIcon;
QLabel *streamTime; QLabel *streamTime;
QLabel *recordTime; QLabel *recordTime;
QLabel *recordIcon;
QLabel *cpuUsage; QLabel *cpuUsage;
QLabel *kbps; QLabel *kbps;
QLabel *statusSquare; QLabel *statusSquare;
@ -24,6 +26,7 @@ private:
obs_output_t *recordOutput = nullptr; obs_output_t *recordOutput = nullptr;
bool active = false; bool active = false;
bool overloadedNotify = true; bool overloadedNotify = true;
bool streamPauseIconToggle = false;
int retries = 0; int retries = 0;
int totalStreamSeconds = 0; int totalStreamSeconds = 0;
@ -48,6 +51,13 @@ private:
QPixmap grayPixmap; QPixmap grayPixmap;
QPixmap redPixmap; QPixmap redPixmap;
QPixmap recordingActivePixmap;
QPixmap recordingPausePixmap;
QPixmap recordingPauseInactivePixmap;
QPixmap recordingInactivePixmap;
QPixmap streamingActivePixmap;
QPixmap streamingInactivePixmap;
float lastCongestion = 0.0f; float lastCongestion = 0.0f;
QPointer<QTimer> refreshTimer; QPointer<QTimer> refreshTimer;
@ -81,6 +91,8 @@ public:
void StreamStopped(); void StreamStopped();
void RecordingStarted(obs_output_t *output); void RecordingStarted(obs_output_t *output);
void RecordingStopped(); void RecordingStopped();
void RecordingPaused();
void RecordingUnpaused();
void ReconnectClear(); void ReconnectClear();
}; };

View file

@ -92,6 +92,9 @@ QWidget *ImporterEntryPathItemDelegate::createEditor(
QSizePolicy::ControlType::LineEdit)); QSizePolicy::ControlType::LineEdit));
layout->addWidget(text); layout->addWidget(text);
QObject::connect(text, SIGNAL(editingFinished()), this,
SLOT(updateText()));
QToolButton *browseButton = new QToolButton(); QToolButton *browseButton = new QToolButton();
browseButton->setText("..."); browseButton->setText("...");
browseButton->setSizePolicy(buttonSizePolicy); browseButton->setSizePolicy(buttonSizePolicy);
@ -121,8 +124,6 @@ void ImporterEntryPathItemDelegate::setEditorData(
{ {
QLineEdit *text = editor->findChild<QLineEdit *>(); QLineEdit *text = editor->findChild<QLineEdit *>();
text->setText(index.data().toString()); text->setText(index.data().toString());
QObject::connect(text, SIGNAL(textEdited(QString)), this,
SLOT(updateText()));
editor->setProperty(PATH_LIST_PROP, QVariant()); editor->setProperty(PATH_LIST_PROP, QVariant());
} }

View file

@ -58,9 +58,6 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor,
connect(this, &OBSQTDisplay::DisplayCreated, addDrawCallback); connect(this, &OBSQTDisplay::DisplayCreated, addDrawCallback);
if (isFullScreen())
SetHideCursor();
if (type == ProjectorType::Multiview) { if (type == ProjectorType::Multiview) {
obs_enter_graphics(); obs_enter_graphics();
@ -169,8 +166,9 @@ void OBSProjector::SetMonitor(int monitor)
{ {
savedMonitor = monitor; savedMonitor = monitor;
QScreen *screen = QGuiApplication::screens()[monitor]; QScreen *screen = QGuiApplication::screens()[monitor];
showFullScreen();
setGeometry(screen->geometry()); setGeometry(screen->geometry());
showFullScreen();
SetHideCursor();
} }
void OBSProjector::SetHideCursor() void OBSProjector::SetHideCursor()
@ -1034,7 +1032,6 @@ void OBSProjector::OpenFullScreenProjector()
int monitor = sender()->property("monitor").toInt(); int monitor = sender()->property("monitor").toInt();
SetMonitor(monitor); SetMonitor(monitor);
SetHideCursor();
UpdateProjectorTitle(QT_UTF8(obs_source_get_name(source))); UpdateProjectorTitle(QT_UTF8(obs_source_get_name(source)));
} }

View file

@ -112,6 +112,9 @@ QWidget *RemuxEntryPathItemDelegate::createEditor(
QSizePolicy::ControlType::LineEdit)); QSizePolicy::ControlType::LineEdit));
layout->addWidget(text); layout->addWidget(text);
QObject::connect(text, SIGNAL(editingFinished()), this,
SLOT(updateText()));
QToolButton *browseButton = new QToolButton(); QToolButton *browseButton = new QToolButton();
browseButton->setText("..."); browseButton->setText("...");
browseButton->setSizePolicy(buttonSizePolicy); browseButton->setSizePolicy(buttonSizePolicy);
@ -143,8 +146,6 @@ void RemuxEntryPathItemDelegate::setEditorData(QWidget *editor,
{ {
QLineEdit *text = editor->findChild<QLineEdit *>(); QLineEdit *text = editor->findChild<QLineEdit *>();
text->setText(index.data().toString()); text->setText(index.data().toString());
QObject::connect(text, SIGNAL(textEdited(QString)), this,
SLOT(updateText()));
editor->setProperty(PATH_LIST_PROP, QVariant()); editor->setProperty(PATH_LIST_PROP, QVariant());
} }

View file

@ -55,7 +55,7 @@ jobs:
condition: or(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['prHasCILabel'], true)) condition: or(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['prHasCILabel'], true))
inputs: inputs:
pathtoPublish: './nightly' pathtoPublish: './nightly'
artifactName: build artifactName: macbuild
- job: 'Build_Windows32' - job: 'Build_Windows32'
dependsOn: Prebuild dependsOn: Prebuild

View file

@ -0,0 +1,24 @@
1 VERSIONINFO
FILEVERSION ${UI_VERSION_MAJOR},${UI_VERSION_MINOR},${UI_VERSION_PATCH},0
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0"
BEGIN
VALUE "CompanyName", "${OBS_COMPANY_NAME}"
VALUE "FileDescription", "${MODULE_DESCRIPTION}"
VALUE "FileVersion", "${UI_VERSION}"
VALUE "ProductName", "${OBS_PRODUCT_NAME}"
VALUE "ProductVersion", "${UI_VERSION}"
VALUE "Comments", "${OBS_COMMENTS}"
VALUE "LegalCopyright", "${OBS_LEGAL_COPYRIGHT}"
VALUE "InternalName", "${PROJECT_NAME}"
VALUE "OriginalFilename", "${PROJECT_NAME}"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 0x04B0
END
END

View file

@ -11,9 +11,12 @@ set(glad_SOURCES
include/glad/glad.h) include/glad/glad.h)
if(WIN32) if(WIN32)
set(MODULE_DESCRIPTION "Glad OpenGL Loading Library")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in obsglad.rc)
set(glad_PLATFORM_SOURCES set(glad_PLATFORM_SOURCES
src/glad_wgl.c src/glad_wgl.c
include/glad/glad_wgl.h) include/glad/glad_wgl.h
obsglad.rc)
elseif(NOT APPLE) elseif(NOT APPLE)
set(glad_PLATFORM_SOURCES set(glad_PLATFORM_SOURCES
src/glad_glx.c src/glad_glx.c

View file

@ -158,6 +158,13 @@ set(obs-scripting_HEADERS
cstrcache.h cstrcache.h
) )
if(WIN32)
set(MODULE_DESCRIPTION "OBS Studio scripting module")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in obs-scripting.rc)
list(APPEND obs-scripting_SOURCES
obs-scripting.rc)
endif()
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/swig) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/swig)
if(PYTHONLIBS_FOUND) if(PYTHONLIBS_FOUND)

View file

@ -4,8 +4,11 @@ if(NOT WIN32)
return() return()
endif() endif()
set(MODULE_DESCRIPTION "POSIX Threads for Windows")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in w32-pthreads.rc)
set(w32-pthreads_SOURCES set(w32-pthreads_SOURCES
pthread.c) pthread.c
w32-pthreads.rc)
set(w32-pthreads_HEADERS set(w32-pthreads_HEADERS
implement.h implement.h

View file

@ -57,9 +57,9 @@ author = 'Hugh Bailey'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '20.1.0' version = '25.0.0'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '20.1.0' release = '25.0.0'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View file

@ -71,6 +71,10 @@ General Functions
--------------------- ---------------------
.. function:: obs_properties_t *obs_properties_get_parent(obs_properties_t *props)
---------------------
Property Object Functions Property Object Functions
------------------------- -------------------------
@ -276,6 +280,29 @@ Property Object Functions
--------------------- ---------------------
.. function:: obs_property_t *obs_properties_add_group(obs_properties_t *props, const char *name, const char *description, enum obs_group_type type, obs_properties_t *group)
Adds a property group.
:param name: Setting identifier string
:param description: Localized name shown to user
:param type: Can be one of the following values:
- **OBS_GROUP_NORMAL** - A normal group with just a name and content.
- **OBS_GROUP_CHECKABLE** - A checkable group with a checkbox, name and content.
:param group: Group to add
:return: The property
Important Related Functions:
- :c:func:`obs_property_group_type`
- :c:func:`obs_property_group_content`
- :c:func:`obs_properties_get_parent`
---------------------
Property Enumeration Functions Property Enumeration Functions
------------------------------ ------------------------------
@ -340,6 +367,7 @@ Property Enumeration Functions
- OBS_PROPERTY_FONT - OBS_PROPERTY_FONT
- OBS_PROPERTY_EDITABLE_LIST - OBS_PROPERTY_EDITABLE_LIST
- OBS_PROPERTY_FRAME_RATE - OBS_PROPERTY_FRAME_RATE
- OBS_PROPERTY_GROUP
--------------------- ---------------------
@ -467,6 +495,20 @@ Property Enumeration Functions
--------------------- ---------------------
.. function:: enum obs_group_type obs_property_group_type(obs_property_t *p)
:return: One of the following values:
- OBS_COMBO_INVALID
- OBS_GROUP_NORMAL
- OBS_GROUP_CHECKABLE
---------------------
.. function:: obs_properties_t *obs_property_group_content(obs_property_t *p)
---------------------
Property Modification Functions Property Modification Functions
------------------------------- -------------------------------

View file

@ -14,10 +14,8 @@ set -o nounset
# Get CPU count # Get CPU count
OS=$(uname) OS=$(uname)
NPROC=1 NPROC=1
if [[ $OS = "Linux" ]] ; then if [[ $OS = "Linux" || $OS = "Darwin" ]] ; then
NPROC=$(nproc) NPROC=$(getconf _NPROCESSORS_ONLN)
elif [[ ${OS} = "Darwin" ]] ; then
NPROC=$(sysctl -n hw.physicalcpu)
fi fi
# Discover clang-format # Discover clang-format

View file

@ -4,6 +4,9 @@ include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/libobs")
add_definitions(-DLIBOBS_EXPORTS) add_definitions(-DLIBOBS_EXPORTS)
set(MODULE_DESCRIPTION "OBS Library D3D11 wrapper")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in libobs-d3d11.rc)
if(NOT DEFINED GPU_PRIORITY_VAL OR "${GPU_PRIORITY_VAL}" STREQUAL "" OR if(NOT DEFINED GPU_PRIORITY_VAL OR "${GPU_PRIORITY_VAL}" STREQUAL "" OR
"${GPU_PRIORITY_VAL}" STREQUAL "0") "${GPU_PRIORITY_VAL}" STREQUAL "0")
set(USE_GPU_PRIORITY FALSE) set(USE_GPU_PRIORITY FALSE)
@ -30,7 +33,8 @@ set(libobs-d3d11_SOURCES
d3d11-vertexbuffer.cpp d3d11-vertexbuffer.cpp
d3d11-duplicator.cpp d3d11-duplicator.cpp
d3d11-rebuild.cpp d3d11-rebuild.cpp
d3d11-zstencilbuffer.cpp) d3d11-zstencilbuffer.cpp
libobs-d3d11.rc)
set(libobs-d3d11_HEADERS set(libobs-d3d11_HEADERS
${CMAKE_CURRENT_BINARY_DIR}/d3d11-config.h ${CMAKE_CURRENT_BINARY_DIR}/d3d11-config.h

View file

@ -7,8 +7,11 @@ include_directories(${OPENGL_INCLUDE_DIR})
add_definitions(-DLIBOBS_EXPORTS) add_definitions(-DLIBOBS_EXPORTS)
if(WIN32) if(WIN32)
set(MODULE_DESCRIPTION "OBS Library OpenGL wrapper")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in libobs-opengl.rc)
set(libobs-opengl_PLATFORM_SOURCES set(libobs-opengl_PLATFORM_SOURCES
gl-windows.c) gl-windows.c
libobs-opengl.rc)
elseif(APPLE) elseif(APPLE)
set(libobs-opengl_PLATFORM_SOURCES set(libobs-opengl_PLATFORM_SOURCES
gl-cocoa.m) gl-cocoa.m)

View file

@ -270,6 +270,7 @@ static inline void gl_write_structs(struct gl_shader_parser *glsp)
* mul -> (change to operator) * mul -> (change to operator)
* rsqrt -> inversesqrt * rsqrt -> inversesqrt
* saturate -> (use clamp) * saturate -> (use clamp)
* sincos -> (map to manual sin/cos calls)
* tex* -> texture * tex* -> texture
* tex*grad -> textureGrad * tex*grad -> textureGrad
* tex*lod -> textureLod * tex*lod -> textureLod
@ -301,6 +302,51 @@ static bool gl_write_mul(struct gl_shader_parser *glsp,
return true; return true;
} }
static bool gl_write_sincos(struct gl_shader_parser *glsp,
struct cf_token **p_token)
{
struct cf_parser *cfp = &glsp->parser.cfp;
struct dstr var = {0};
bool success = false;
cfp->cur_token = *p_token;
if (!cf_next_token(cfp))
return false;
if (!cf_token_is(cfp, "("))
return false;
dstr_printf(&var, "sincos_var_internal_%d", glsp->sincos_counter++);
dstr_cat(&glsp->gl_string, "float ");
dstr_cat_dstr(&glsp->gl_string, &var);
dstr_cat(&glsp->gl_string, " = ");
gl_write_function_contents(glsp, &cfp->cur_token, ",");
dstr_cat(&glsp->gl_string, "); ");
if (!cf_next_token(cfp))
goto fail;
gl_write_function_contents(glsp, &cfp->cur_token, ",");
dstr_cat(&glsp->gl_string, " = sin(");
dstr_cat_dstr(&glsp->gl_string, &var);
dstr_cat(&glsp->gl_string, "); ");
if (!cf_next_token(cfp))
goto fail;
gl_write_function_contents(glsp, &cfp->cur_token, ")");
dstr_cat(&glsp->gl_string, " = cos(");
dstr_cat_dstr(&glsp->gl_string, &var);
dstr_cat(&glsp->gl_string, ")");
success = true;
fail:
dstr_free(&var);
*p_token = cfp->cur_token;
return success;
}
static bool gl_write_saturate(struct gl_shader_parser *glsp, static bool gl_write_saturate(struct gl_shader_parser *glsp,
struct cf_token **p_token) struct cf_token **p_token)
{ {
@ -404,7 +450,7 @@ static bool gl_write_intrinsic(struct gl_shader_parser *glsp,
bool written = true; bool written = true;
if (strref_cmp(&token->str, "atan2") == 0) { if (strref_cmp(&token->str, "atan2") == 0) {
dstr_cat(&glsp->gl_string, "atan2"); dstr_cat(&glsp->gl_string, "atan");
} else if (strref_cmp(&token->str, "ddx") == 0) { } else if (strref_cmp(&token->str, "ddx") == 0) {
dstr_cat(&glsp->gl_string, "dFdx"); dstr_cat(&glsp->gl_string, "dFdx");
} else if (strref_cmp(&token->str, "ddy") == 0) { } else if (strref_cmp(&token->str, "ddy") == 0) {
@ -421,6 +467,8 @@ static bool gl_write_intrinsic(struct gl_shader_parser *glsp,
written = gl_write_saturate(glsp, &token); written = gl_write_saturate(glsp, &token);
} else if (strref_cmp(&token->str, "mul") == 0) { } else if (strref_cmp(&token->str, "mul") == 0) {
written = gl_write_mul(glsp, &token); written = gl_write_mul(glsp, &token);
} else if (strref_cmp(&token->str, "sincos") == 0) {
written = gl_write_sincos(glsp, &token);
} else { } else {
struct shader_var *var = sp_getparam(glsp, token); struct shader_var *var = sp_getparam(glsp, token);
if (var && astrcmp_n(var->type, "texture", 7) == 0) if (var && astrcmp_n(var->type, "texture", 7) == 0)

View file

@ -48,6 +48,7 @@ struct gl_shader_parser {
const char *output_prefix; const char *output_prefix;
struct shader_parser parser; struct shader_parser parser;
struct dstr gl_string; struct dstr gl_string;
int sincos_counter;
DARRAY(uint32_t) texture_samplers; DARRAY(uint32_t) texture_samplers;
DARRAY(struct gl_parser_attrib) attribs; DARRAY(struct gl_parser_attrib) attribs;
@ -70,6 +71,7 @@ static inline void gl_shader_parser_init(struct gl_shader_parser *glsp,
dstr_init(&glsp->gl_string); dstr_init(&glsp->gl_string);
da_init(glsp->texture_samplers); da_init(glsp->texture_samplers);
da_init(glsp->attribs); da_init(glsp->attribs);
glsp->sincos_counter = 1;
} }
static inline void gl_shader_parser_free(struct gl_shader_parser *glsp) static inline void gl_shader_parser_free(struct gl_shader_parser *glsp)

View file

@ -1264,7 +1264,6 @@ void device_set_viewport(gs_device_t *device, int x, int y, int width,
int height) int height)
{ {
uint32_t base_height = 0; uint32_t base_height = 0;
int gl_y = 0;
/* GL uses bottom-up coordinates for viewports. We want top-down */ /* GL uses bottom-up coordinates for viewports. We want top-down */
if (device->cur_render_target) { if (device->cur_render_target) {
@ -1274,7 +1273,8 @@ void device_set_viewport(gs_device_t *device, int x, int y, int width,
gl_getclientsize(device->cur_swap, &dw, &base_height); gl_getclientsize(device->cur_swap, &dw, &base_height);
} }
if (base_height) GLint gl_y = y;
if (base_height && !device->cur_fbo)
gl_y = base_height - y - height; gl_y = base_height - y - height;
glViewport(x, gl_y, width, height); glViewport(x, gl_y, width, height);

View file

@ -18,10 +18,14 @@ try {
return winrt::Windows::Foundation::Metadata::ApiInformation:: return winrt::Windows::Foundation::Metadata::ApiInformation::
IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", IsApiContractPresent(L"Windows.Foundation.UniversalApiContract",
8); 8);
} catch (winrt::hresult_error &err) { } catch (const winrt::hresult_error &err) {
blog(LOG_ERROR, "winrt_capture_supported (0x%08X): %ls", err.to_abi(), blog(LOG_ERROR, "winrt_capture_supported (0x%08X): %ls", err.to_abi(),
err.message().c_str()); err.message().c_str());
return false; return false;
} catch (...) {
blog(LOG_ERROR, "winrt_capture_supported (0x%08X)",
winrt::to_hresult());
return false;
} }
extern "C" EXPORT BOOL winrt_capture_cursor_toggle_supported() extern "C" EXPORT BOOL winrt_capture_cursor_toggle_supported()
@ -34,10 +38,14 @@ try {
#else #else
return false; return false;
#endif #endif
} catch (winrt::hresult_error &err) { } catch (const winrt::hresult_error &err) {
blog(LOG_ERROR, "winrt_capture_cursor_toggle_supported (0x%08X): %ls", blog(LOG_ERROR, "winrt_capture_cursor_toggle_supported (0x%08X): %ls",
err.to_abi(), err.message().c_str()); err.to_abi(), err.message().c_str());
return false; return false;
} catch (...) {
blog(LOG_ERROR, "winrt_capture_cursor_toggle_supported (0x%08X)",
winrt::to_hresult());
return false;
} }
template<typename T> template<typename T>
@ -353,6 +361,10 @@ try {
blog(LOG_ERROR, "CreateForWindow (0x%08X): %ls", err.to_abi(), blog(LOG_ERROR, "CreateForWindow (0x%08X): %ls", err.to_abi(),
err.message().c_str()); err.message().c_str());
return nullptr; return nullptr;
} catch (...) {
blog(LOG_ERROR, "CreateForWindow (0x%08X)",
winrt::to_hresult());
return nullptr;
} }
const winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice const winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice
@ -406,10 +418,13 @@ try {
return capture; return capture;
} catch (winrt::hresult_error &err) { } catch (const winrt::hresult_error &err) {
blog(LOG_ERROR, "winrt_capture_init (0x%08X): %ls", err.to_abi(), blog(LOG_ERROR, "winrt_capture_init (0x%08X): %ls", err.to_abi(),
err.message().c_str()); err.message().c_str());
return nullptr; return nullptr;
} catch (...) {
blog(LOG_ERROR, "winrt_capture_init (0x%08X)", winrt::to_hresult());
return nullptr;
} }
extern "C" EXPORT void winrt_capture_free(struct winrt_capture *capture) extern "C" EXPORT void winrt_capture_free(struct winrt_capture *capture)

View file

@ -81,12 +81,22 @@ add_definitions(-DLIBOBS_EXPORTS)
include_directories(${OBS_JANSSON_INCLUDE_DIRS}) include_directories(${OBS_JANSSON_INCLUDE_DIRS})
if(WIN32) if(WIN32)
set(MODULE_DESCRIPTION "OBS Library")
file(STRINGS obs-config.h _version_parse REGEX "^.*(MAJOR|MINOR|PATCH)_VER[ \t]+[0-9]+[ \t]*$")
string(REGEX REPLACE ".*MAJOR_VER[ \t]+([0-9]+).*" "\\1" UI_VERSION_MAJOR "${_version_parse}")
string(REGEX REPLACE ".*MINOR_VER[ \t]+([0-9]+).*" "\\1" UI_VERSION_MINOR "${_version_parse}")
string(REGEX REPLACE ".*PATCH_VER[ \t]+([0-9]+).*" "\\1" UI_VERSION_PATCH "${_version_parse}")
set(UI_VERSION "${UI_VERSION_MAJOR}.${UI_VERSION_MINOR}.${UI_VERSION_PATCH}")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in libobs.rc)
set(libobs_PLATFORM_SOURCES set(libobs_PLATFORM_SOURCES
obs-win-crash-handler.c obs-win-crash-handler.c
obs-windows.c obs-windows.c
util/threading-windows.c util/threading-windows.c
util/pipe-windows.c util/pipe-windows.c
util/platform-windows.c) util/platform-windows.c
libobs.rc)
set(libobs_PLATFORM_HEADERS set(libobs_PLATFORM_HEADERS
util/threading-windows.h util/threading-windows.h
util/windows/win-registry.h util/windows/win-registry.h

View file

@ -65,7 +65,7 @@ void add_default_module_paths(void)
[NSRunningApplication currentApplication]; [NSRunningApplication currentApplication];
NSURL *bundleURL = [app bundleURL]; NSURL *bundleURL = [app bundleURL];
NSURL *pluginsURL = [bundleURL NSURL *pluginsURL = [bundleURL
URLByAppendingPathComponent:@"Contents/Plugins"]; URLByAppendingPathComponent:@"Contents/PlugIns"];
NSURL *dataURL = [bundleURL NSURL *dataURL = [bundleURL
URLByAppendingPathComponent: URLByAppendingPathComponent:
@"Contents/Resources/data/obs-plugins/%module%"]; @"Contents/Resources/data/obs-plugins/%module%"];
@ -175,6 +175,8 @@ static void log_os_name(id pi, SEL UTF8StringSel)
blog(LOG_INFO, "OS Name: %s", name ? name : "Unknown"); blog(LOG_INFO, "OS Name: %s", name ? name : "Unknown");
} }
static bool using_10_15_or_above = true;
static void log_os_version(id pi, SEL UTF8StringSel) static void log_os_version(id pi, SEL UTF8StringSel)
{ {
typedef id (*version_func)(id, SEL); typedef id (*version_func)(id, SEL);
@ -186,6 +188,16 @@ static void log_os_version(id pi, SEL UTF8StringSel)
const char *version = UTF8String(vs, UTF8StringSel); const char *version = UTF8String(vs, UTF8StringSel);
blog(LOG_INFO, "OS Version: %s", version ? version : "Unknown"); blog(LOG_INFO, "OS Version: %s", version ? version : "Unknown");
if (version) {
int major;
int minor;
int count = sscanf(version, "Version %d.%d", &major, &minor);
if (count == 2 && major == 10) {
using_10_15_or_above = minor >= 15;
}
}
} }
static void log_os(void) static void log_os(void)
@ -239,6 +251,7 @@ static bool dstr_from_cfstring(struct dstr *str, CFStringRef ref)
struct obs_hotkeys_platform { struct obs_hotkeys_platform {
volatile long refs; volatile long refs;
bool secure_input_activated;
TISInputSourceRef tis; TISInputSourceRef tis;
CFDataRef layout_data; CFDataRef layout_data;
UCKeyboardLayout *layout; UCKeyboardLayout *layout;
@ -1749,6 +1762,14 @@ bool obs_hotkeys_platform_is_pressed(obs_hotkeys_platform_t *plat,
if (key >= OBS_KEY_LAST_VALUE) if (key >= OBS_KEY_LAST_VALUE)
return false; return false;
/* if secure input is activated, kill hotkeys.
*
* TODO: rewrite all mac hotkey code, suspect there's a bug in 10.15
* causing the crash internally. */
if (plat->secure_input_activated) {
return false;
}
for (size_t i = 0; i < plat->keys[key].num;) { for (size_t i = 0; i < plat->keys[key].num;) {
IOHIDElementRef element = plat->keys[key].array[i]; IOHIDElementRef element = plat->keys[key].array[i];
IOHIDValueRef value = 0; IOHIDValueRef value = 0;
@ -1758,6 +1779,11 @@ bool obs_hotkeys_platform_is_pressed(obs_hotkeys_platform_t *plat,
continue; continue;
} }
if (using_10_15_or_above && IsSecureEventInputEnabled()) {
plat->secure_input_activated = true;
return false;
}
if (IOHIDDeviceGetValue(device, element, &value) != if (IOHIDDeviceGetValue(device, element, &value) !=
kIOReturnSuccess) { kIOReturnSuccess) {
i += 1; i += 1;

View file

@ -41,7 +41,7 @@
* *
* Reset to zero each major or minor version * Reset to zero each major or minor version
*/ */
#define LIBOBS_API_PATCH_VER 3 #define LIBOBS_API_PATCH_VER 8
#define MAKE_SEMANTIC_VERSION(major, minor, patch) \ #define MAKE_SEMANTIC_VERSION(major, minor, patch) \
((major << 24) | (minor << 16) | patch) ((major << 24) | (minor << 16) | patch)

View file

@ -276,6 +276,8 @@ static void obs_encoder_actually_destroy(obs_encoder_t *encoder)
obs_context_data_free(&encoder->context); obs_context_data_free(&encoder->context);
if (encoder->owns_info_id) if (encoder->owns_info_id)
bfree((void *)encoder->info.id); bfree((void *)encoder->info.id);
if (encoder->last_error_message)
bfree(encoder->last_error_message);
bfree(encoder); bfree(encoder);
} }
} }
@ -521,6 +523,7 @@ void obs_encoder_shutdown(obs_encoder_t *encoder)
encoder->offset_usec = 0; encoder->offset_usec = 0;
encoder->start_ts = 0; encoder->start_ts = 0;
} }
obs_encoder_set_last_error(encoder, NULL);
pthread_mutex_unlock(&encoder->init_mutex); pthread_mutex_unlock(&encoder->init_mutex);
} }
@ -1484,3 +1487,25 @@ bool obs_encoder_paused(const obs_encoder_t *encoder)
? os_atomic_load_bool(&encoder->paused) ? os_atomic_load_bool(&encoder->paused)
: false; : false;
} }
const char *obs_encoder_get_last_error(obs_encoder_t *encoder)
{
if (!obs_encoder_valid(encoder, "obs_encoder_get_last_error"))
return NULL;
return encoder->last_error_message;
}
void obs_encoder_set_last_error(obs_encoder_t *encoder, const char *message)
{
if (!obs_encoder_valid(encoder, "obs_encoder_set_last_error"))
return;
if (encoder->last_error_message)
bfree(encoder->last_error_message);
if (message)
encoder->last_error_message = bstrdup(message);
else
encoder->last_error_message = NULL;
}

View file

@ -1076,6 +1076,7 @@ struct obs_encoder {
struct pause_data pause; struct pause_data pause;
const char *profile_encoder_encode_name; const char *profile_encoder_encode_name;
char *last_error_message;
}; };
extern struct obs_encoder_info *find_encoder(const char *id); extern struct obs_encoder_info *find_encoder(const char *id);

View file

@ -1979,6 +1979,9 @@ static inline bool initialize_audio_encoders(obs_output_t *output,
{ {
for (size_t i = 0; i < num_mixes; i++) { for (size_t i = 0; i < num_mixes; i++) {
if (!obs_encoder_initialize(output->audio_encoders[i])) { if (!obs_encoder_initialize(output->audio_encoders[i])) {
obs_output_set_last_error(
output, obs_encoder_get_last_error(
output->audio_encoders[i]));
return false; return false;
} }
} }
@ -2038,8 +2041,12 @@ bool obs_output_initialize_encoders(obs_output_t *output, uint32_t flags)
if (!encoded) if (!encoded)
return false; return false;
if (has_video && !obs_encoder_initialize(output->video_encoder)) if (has_video && !obs_encoder_initialize(output->video_encoder)) {
obs_output_set_last_error(
output,
obs_encoder_get_last_error(output->video_encoder));
return false; return false;
}
if (has_audio && !initialize_audio_encoders(output, num_mixes)) if (has_audio && !initialize_audio_encoders(output, num_mixes))
return false; return false;

View file

@ -2108,7 +2108,8 @@ obs_data_array_t *obs_save_sources_filtered(obs_save_source_filter_cb cb,
while (source) { while (source) {
if ((source->info.type != OBS_SOURCE_TYPE_FILTER) != 0 && if ((source->info.type != OBS_SOURCE_TYPE_FILTER) != 0 &&
!source->context.private && cb(data_, source)) { !source->context.private && !source->removed &&
cb(data_, source)) {
obs_data_t *source_data = obs_save_source(source); obs_data_t *source_data = obs_save_source(source);
obs_data_array_push_back(array, source_data); obs_data_array_push_back(array, source_data);

View file

@ -2102,6 +2102,10 @@ EXPORT void *obs_encoder_create_rerouted(obs_encoder_t *encoder,
/** Returns whether encoder is paused */ /** Returns whether encoder is paused */
EXPORT bool obs_encoder_paused(const obs_encoder_t *output); EXPORT bool obs_encoder_paused(const obs_encoder_t *output);
EXPORT const char *obs_encoder_get_last_error(obs_encoder_t *encoder);
EXPORT void obs_encoder_set_last_error(obs_encoder_t *encoder,
const char *message);
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* Stream Services */ /* Stream Services */

View file

@ -275,7 +275,20 @@ char *os_get_program_data_path_ptr(const char *name)
char *os_get_executable_path_ptr(const char *name) char *os_get_executable_path_ptr(const char *name)
{ {
char exe[PATH_MAX]; char exe[PATH_MAX];
#if defined(__FreeBSD__) || defined(__DragonFly__)
int sysctlname[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
size_t pathlen = PATH_MAX;
ssize_t count;
if (sysctl(sysctlname, nitems(sysctlname), exe, &pathlen, NULL, 0) ==
-1) {
blog(LOG_ERROR, "sysctl(KERN_PROC_PATHNAME) failed, errno %d",
errno);
return NULL;
}
count = pathlen;
#else
ssize_t count = readlink("/proc/self/exe", exe, PATH_MAX); ssize_t count = readlink("/proc/self/exe", exe, PATH_MAX);
#endif
const char *path_out = NULL; const char *path_out = NULL;
struct dstr path; struct dstr path;

View file

@ -1,258 +0,0 @@
/* Check (assertions)
* Portable Snippets - https://gitub.com/nemequ/portable-snippets
* Created by Evan Nemerson <evan@nemerson.com>
*
* To the extent possible under law, the authors have waived all
* copyright and related or neighboring rights to this code. For
* details, see the Creative Commons Zero 1.0 Universal license at
* https://creativecommons.org/publicdomain/zero/1.0/
*/
#if !defined(SIMDE_CHECK_H)
#define SIMDE_CHECK_H
#if !defined(SIMDE_NDEBUG) && !defined(SIMDE_DEBUG)
#define SIMDE_NDEBUG 1
#endif
#include <stdint.h>
#if !defined(_WIN32)
#define SIMDE_SIZE_MODIFIER "z"
#define SIMDE_CHAR_MODIFIER "hh"
#define SIMDE_SHORT_MODIFIER "h"
#else
#if defined(_M_X64) || defined(__amd64__)
#define SIMDE_SIZE_MODIFIER "I64"
#else
#define SIMDE_SIZE_MODIFIER ""
#endif
#define SIMDE_CHAR_MODIFIER ""
#define SIMDE_SHORT_MODIFIER ""
#endif
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
#define SIMDE__PUSH_DISABLE_MSVC_C4127 \
__pragma(warning(push)) __pragma(warning(disable : 4127))
#define SIMDE__POP_DISABLE_MSVC_C4127 __pragma(warning(pop))
#else
#define SIMDE__PUSH_DISABLE_MSVC_C4127
#define SIMDE__POP_DISABLE_MSVC_C4127
#endif
#if !defined(simde_errorf)
#include <stdio.h>
#include <stdlib.h>
#define simde_errorf(format, ...) \
(fprintf(stderr, format, __VA_ARGS__), abort())
#endif
#define simde_error(msg) simde_errorf("%s", msg)
#if defined(SIMDE_NDEBUG)
#if defined(SIMDE_CHECK_FAIL_DEFINED)
#define simde_assert(expr)
#else
#if defined(HEDLEY_ASSUME)
#define simde_assert(expr) HEDLEY_ASSUME(expr)
#elif HEDLEY_GCC_VERSION_CHECK(4, 5, 0)
#define simde_assert(expr) ((void)(!!(expr) ? 1 : (__builtin_unreachable(), 1)))
#elif HEDLEY_MSVC_VERSION_CHECK(13, 10, 0)
#define simde_assert(expr) __assume(expr)
#else
#define simde_assert(expr)
#endif
#endif
#define simde_assert_true(expr) simde_assert(expr)
#define simde_assert_false(expr) simde_assert(!(expr))
#define simde_assert_type_full(prefix, suffix, T, fmt, a, op, b) \
simde_assert(((a)op(b)))
#define simde_assert_double_equal(a, b, precision)
#define simde_assert_string_equal(a, b)
#define simde_assert_string_not_equal(a, b)
#define simde_assert_memory_equal(size, a, b)
#define simde_assert_memory_not_equal(size, a, b)
#else
#define simde_assert(expr) \
do { \
if (!HEDLEY_LIKELY(expr)) { \
simde_error("assertion failed: " #expr "\n"); \
} \
SIMDE__PUSH_DISABLE_MSVC_C4127 \
} while (0) SIMDE__POP_DISABLE_MSVC_C4127
#define simde_assert_true(expr) \
do { \
if (!HEDLEY_LIKELY(expr)) { \
simde_error("assertion failed: " #expr \
" is not true\n"); \
} \
SIMDE__PUSH_DISABLE_MSVC_C4127 \
} while (0) SIMDE__POP_DISABLE_MSVC_C4127
#define simde_assert_false(expr) \
do { \
if (!HEDLEY_LIKELY(!(expr))) { \
simde_error("assertion failed: " #expr \
" is not false\n"); \
} \
SIMDE__PUSH_DISABLE_MSVC_C4127 \
} while (0) SIMDE__POP_DISABLE_MSVC_C4127
#define simde_assert_type_full(prefix, suffix, T, fmt, a, op, b) \
do { \
T simde_tmp_a_ = (a); \
T simde_tmp_b_ = (b); \
if (!(simde_tmp_a_ op simde_tmp_b_)) { \
simde_errorf("assertion failed: %s %s %s (" prefix \
"%" fmt suffix " %s " prefix \
"%" fmt suffix ")\n", \
#a, #op, #b, simde_tmp_a_, #op, \
simde_tmp_b_); \
} \
SIMDE__PUSH_DISABLE_MSVC_C4127 \
} while (0) SIMDE__POP_DISABLE_MSVC_C4127
#define simde_assert_double_equal(a, b, precision) \
do { \
const double simde_tmp_a_ = (a); \
const double simde_tmp_b_ = (b); \
const double simde_tmp_diff_ = \
((simde_tmp_a_ - simde_tmp_b_) < 0) \
? -(simde_tmp_a_ - simde_tmp_b_) \
: (simde_tmp_a_ - simde_tmp_b_); \
if (HEDLEY_UNLIKELY(simde_tmp_diff_ > 1e-##precision)) { \
simde_errorf( \
"assertion failed: %s == %s (%0." #precision \
"g == %0." #precision "g)\n", \
#a, #b, simde_tmp_a_, simde_tmp_b_); \
} \
SIMDE__PUSH_DISABLE_MSVC_C4127 \
} while (0) SIMDE__POP_DISABLE_MSVC_C4127
#include <string.h>
#define simde_assert_string_equal(a, b) \
do { \
const char *simde_tmp_a_ = a; \
const char *simde_tmp_b_ = b; \
if (HEDLEY_UNLIKELY(strcmp(simde_tmp_a_, simde_tmp_b_) != \
0)) { \
simde_errorf( \
"assertion failed: string %s == %s (\"%s\" == \"%s\")\n", \
#a, #b, simde_tmp_a_, simde_tmp_b_); \
} \
SIMDE__PUSH_DISABLE_MSVC_C4127 \
} while (0) SIMDE__POP_DISABLE_MSVC_C4127
#define simde_assert_string_not_equal(a, b) \
do { \
const char *simde_tmp_a_ = a; \
const char *simde_tmp_b_ = b; \
if (HEDLEY_UNLIKELY(strcmp(simde_tmp_a_, simde_tmp_b_) == \
0)) { \
simde_errorf( \
"assertion failed: string %s != %s (\"%s\" == \"%s\")\n", \
#a, #b, simde_tmp_a_, simde_tmp_b_); \
} \
SIMDE__PUSH_DISABLE_MSVC_C4127 \
} while (0) SIMDE__POP_DISABLE_MSVC_C4127
#define simde_assert_memory_equal(size, a, b) \
do { \
const unsigned char *simde_tmp_a_ = \
(const unsigned char *)(a); \
const unsigned char *simde_tmp_b_ = \
(const unsigned char *)(b); \
const size_t simde_tmp_size_ = (size); \
if (HEDLEY_UNLIKELY(memcmp(simde_tmp_a_, simde_tmp_b_, \
simde_tmp_size_)) != 0) { \
size_t simde_tmp_pos_; \
for (simde_tmp_pos_ = 0; \
simde_tmp_pos_ < simde_tmp_size_; \
simde_tmp_pos_++) { \
if (simde_tmp_a_[simde_tmp_pos_] != \
simde_tmp_b_[simde_tmp_pos_]) { \
simde_errorf( \
"assertion failed: memory %s == %s, at offset %" SIMDE_SIZE_MODIFIER \
"u\n", \
#a, #b, simde_tmp_pos_); \
break; \
} \
} \
} \
SIMDE__PUSH_DISABLE_MSVC_C4127 \
} while (0) SIMDE__POP_DISABLE_MSVC_C4127
#define simde_assert_memory_not_equal(size, a, b) \
do { \
const unsigned char *simde_tmp_a_ = \
(const unsigned char *)(a); \
const unsigned char *simde_tmp_b_ = \
(const unsigned char *)(b); \
const size_t simde_tmp_size_ = (size); \
if (HEDLEY_UNLIKELY(memcmp(simde_tmp_a_, simde_tmp_b_, \
simde_tmp_size_)) == 0) { \
simde_errorf( \
"assertion failed: memory %s != %s (%" SIMDE_SIZE_MODIFIER \
"u bytes)\n", \
#a, #b, simde_tmp_size_); \
} \
SIMDE__PUSH_DISABLE_MSVC_C4127 \
} while (0) SIMDE__POP_DISABLE_MSVC_C4127
#endif
#define simde_assert_type(T, fmt, a, op, b) \
simde_assert_type_full("", "", T, fmt, a, op, b)
#define simde_assert_char(a, op, b) \
simde_assert_type_full("'\\x", "'", char, \
"02" SIMDE_CHAR_MODIFIER "x", a, op, b)
#define simde_assert_uchar(a, op, b) \
simde_assert_type_full("'\\x", "'", unsigned char, \
"02" SIMDE_CHAR_MODIFIER "x", a, op, b)
#define simde_assert_short(a, op, b) \
simde_assert_type(short, SIMDE_SHORT_MODIFIER "d", a, op, b)
#define simde_assert_ushort(a, op, b) \
simde_assert_type(unsigned short, SIMDE_SHORT_MODIFIER "u", a, op, b)
#define simde_assert_int(a, op, b) simde_assert_type(int, "d", a, op, b)
#define simde_assert_uint(a, op, b) \
simde_assert_type(unsigned int, "u", a, op, b)
#define simde_assert_long(a, op, b) simde_assert_type(long int, "ld", a, op, b)
#define simde_assert_ulong(a, op, b) \
simde_assert_type(unsigned long int, "lu", a, op, b)
#define simde_assert_llong(a, op, b) \
simde_assert_type(long long int, "lld", a, op, b)
#define simde_assert_ullong(a, op, b) \
simde_assert_type(unsigned long long int, "llu", a, op, b)
#define simde_assert_size(a, op, b) \
simde_assert_type(size_t, SIMDE_SIZE_MODIFIER "u", a, op, b)
#define simde_assert_float(a, op, b) simde_assert_type(float, "f", a, op, b)
#define simde_assert_double(a, op, b) simde_assert_type(double, "g", a, op, b)
#define simde_assert_ptr(a, op, b) \
simde_assert_type(const void *, "p", a, op, b)
#define simde_assert_int8(a, op, b) simde_assert_type(int8_t, PRIi8, a, op, b)
#define simde_assert_uint8(a, op, b) simde_assert_type(uint8_t, PRIu8, a, op, b)
#define simde_assert_int16(a, op, b) \
simde_assert_type(int16_t, PRIi16, a, op, b)
#define simde_assert_uint16(a, op, b) \
simde_assert_type(uint16_t, PRIu16, a, op, b)
#define simde_assert_int32(a, op, b) \
simde_assert_type(int32_t, PRIi32, a, op, b)
#define simde_assert_uint32(a, op, b) \
simde_assert_type(uint32_t, PRIu32, a, op, b)
#define simde_assert_int64(a, op, b) \
simde_assert_type(int64_t, PRIi64, a, op, b)
#define simde_assert_uint64(a, op, b) \
simde_assert_type(uint64_t, PRIu64, a, op, b)
#define simde_assert_ptr_equal(a, b) simde_assert_ptr(a, ==, b)
#define simde_assert_ptr_not_equal(a, b) simde_assert_ptr(a, !=, b)
#define simde_assert_null(ptr) simde_assert_ptr(ptr, ==, NULL)
#define simde_assert_not_null(ptr) simde_assert_ptr(ptr, !=, NULL)
#define simde_assert_ptr_null(ptr) simde_assert_ptr(ptr, ==, NULL)
#define simde_assert_ptr_not_null(ptr) simde_assert_ptr(ptr, !=, NULL)
#endif /* !defined(SIMDE_CHECK_H) */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,355 +0,0 @@
/* Architecture detection
* Created by Evan Nemerson <evan@nemerson.com>
*
* To the extent possible under law, the authors have waived all
* copyright and related or neighboring rights to this code. For
* details, see the Creative Commons Zero 1.0 Universal license at
* <https://creativecommons.org/publicdomain/zero/1.0/>
*
* Different compilers define different preprocessor macros for the
* same architecture. This is an attempt to provide a single
* interface which is usable on any compiler.
*
* In general, a macro named SIMDE_ARCH_* is defined for each
* architecture the CPU supports. When there are multiple possible
* versions, we try to define the macro to the target version. For
* example, if you want to check for i586+, you could do something
* like:
*
* #if defined(SIMDE_ARCH_X86) && (SIMDE_ARCH_X86 >= 5)
* ...
* #endif
*
* You could also just check that SIMDE_ARCH_X86 >= 5 without checking
* if it's defined first, but some compilers may emit a warning about
* an undefined macro being used (e.g., GCC with -Wundef).
*
* This was originally created for SIMDe
* <https://github.com/nemequ/simde> (hence the prefix), but this
* header has no dependencies and may be used anywhere. It is
* originally based on information from
* <https://sourceforge.net/p/predef/wiki/Architectures/>, though it
* has been enhanced with additional information.
*
* If you improve this file, or find a bug, please file the issue at
* <https://github.com/nemequ/simde/issues>. If you copy this into
* your project, even if you change the prefix, please keep the links
* to SIMDe intact so others know where to report issues, submit
* enhancements, and find the latest version. */
#if !defined(SIMDE_ARCH_H)
#define SIMDE_ARCH_H
/* Alpha
<https://en.wikipedia.org/wiki/DEC_Alpha> */
#if defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
#if defined(__alpha_ev6__)
#define SIMDE_ARCH_ALPHA 6
#elif defined(__alpha_ev5__)
#define SIMDE_ARCH_ALPHA 5
#elif defined(__alpha_ev4__)
#define SIMDE_ARCH_ALPHA 4
#else
#define SIMDE_ARCH_ALPHA 1
#endif
#endif
/* Atmel AVR
<https://en.wikipedia.org/wiki/Atmel_AVR> */
#if defined(__AVR_ARCH__)
#define SIMDE_ARCH_AVR __AVR_ARCH__
#endif
/* AMD64 / x86_64
<https://en.wikipedia.org/wiki/X86-64> */
#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || \
defined(__x86_64) || defined(_M_X66) || defined(_M_AMD64)
#define SIMDE_ARCH_AMD64 1
#endif
/* ARM
<https://en.wikipedia.org/wiki/ARM_architecture> */
#if defined(__ARM_ARCH_8A__)
#define SIMDE_ARCH_ARM 82
#elif defined(__ARM_ARCH_8R__)
#define SIMDE_ARCH_ARM 81
#elif defined(__ARM_ARCH_8__)
#define SIMDE_ARCH_ARM 80
#elif defined(__ARM_ARCH_7S__)
#define SIMDE_ARCH_ARM 74
#elif defined(__ARM_ARCH_7M__)
#define SIMDE_ARCH_ARM 73
#elif defined(__ARM_ARCH_7R__)
#define SIMDE_ARCH_ARM 72
#elif defined(__ARM_ARCH_7A__)
#define SIMDE_ARCH_ARM 71
#elif defined(__ARM_ARCH_7__)
#define SIMDE_ARCH_ARM 70
#elif defined(__ARM_ARCH)
#define SIMDE_ARCH_ARM (__ARM_ARCH * 10)
#elif defined(_M_ARM)
#define SIMDE_ARCH_ARM (_M_ARM * 10)
#elif defined(__arm__) || defined(__thumb__) || defined(__TARGET_ARCH_ARM) || \
defined(_ARM) || defined(_M_ARM) || defined(_M_ARM)
#define SIMDE_ARCH_ARM 1
#endif
/* AArch64
<https://en.wikipedia.org/wiki/ARM_architecture> */
#if defined(__aarch64__) || defined(_M_ARM64)
#define SIMDE_ARCH_AARCH64 10
#endif
/* Blackfin
<https://en.wikipedia.org/wiki/Blackfin> */
#if defined(__bfin) || defined(__BFIN__) || defined(__bfin__)
#define SIMDE_ARCH_BLACKFIN 1
#endif
/* CRIS
<https://en.wikipedia.org/wiki/ETRAX_CRIS> */
#if defined(__CRIS_arch_version)
#define SIMDE_ARCH_CRIS __CRIS_arch_version
#elif defined(__cris__) || defined(__cris) || defined(__CRIS) || \
defined(__CRIS__)
#define SIMDE_ARCH_CRIS 1
#endif
/* Convex
<https://en.wikipedia.org/wiki/Convex_Computer> */
#if defined(__convex_c38__)
#define SIMDE_ARCH_CONVEX 38
#elif defined(__convex_c34__)
#define SIMDE_ARCH_CONVEX 34
#elif defined(__convex_c32__)
#define SIMDE_ARCH_CONVEX 32
#elif defined(__convex_c2__)
#define SIMDE_ARCH_CONVEX 2
#elif defined(__convex__)
#define SIMDE_ARCH_CONVEX 1
#endif
/* Adapteva Epiphany
<https://en.wikipedia.org/wiki/Adapteva_Epiphany> */
#if defined(__epiphany__)
#define SIMDE_ARCH_EPIPHANY 1
#endif
/* Fujitsu FR-V
<https://en.wikipedia.org/wiki/FR-V_(microprocessor)> */
#if defined(__frv__)
#define SIMDE_ARCH_FRV 1
#endif
/* H8/300
<https://en.wikipedia.org/wiki/H8_Family> */
#if defined(__H8300__)
#define SIMDE_ARCH_H8300
#endif
/* HP/PA / PA-RISC
<https://en.wikipedia.org/wiki/PA-RISC> */
#if defined(__PA8000__) || defined(__HPPA20__) || defined(__RISC2_0__) || \
defined(_PA_RISC2_0)
#define SIMDE_ARCH_HPPA 20
#elif defined(__PA7100__) || defined(__HPPA11__) || defined(_PA_RISC1_1)
#define SIMDE_ARCH_HPPA 11
#elif defined(_PA_RISC1_0)
#define SIMDE_ARCH_HPPA 10
#elif defined(__hppa__) || defined(__HPPA__) || defined(__hppa)
#define SIMDE_ARCH_HPPA 1
#endif
/* x86
<https://en.wikipedia.org/wiki/X86> */
#if defined(_M_IX86)
#define SIMDE_ARCH_X86 (_M_IX86 / 100)
#elif defined(__I86__)
#define SIMDE_ARCH_X86 __I86__
#elif defined(i686) || defined(__i686) || defined(__i686__)
#define SIMDE_ARCH_X86 6
#elif defined(i586) || defined(__i586) || defined(__i586__)
#define SIMDE_ARCH_X86 5
#elif defined(i486) || defined(__i486) || defined(__i486__)
#define SIMDE_ARCH_X86 4
#elif defined(i386) || defined(__i386) || defined(__i386__)
#define SIMDE_ARCH_X86 3
#elif defined(_X86_) || defined(__X86__) || defined(__THW_INTEL__)
#define SIMDE_ARCH_X86 3
#endif
/* Itanium
<https://en.wikipedia.org/wiki/Itanium> */
#if defined(__ia64__) || defined(_IA64) || defined(__IA64__) || \
defined(__ia64) || defined(_M_IA64) || defined(__itanium__)
#define SIMDE_ARCH_IA64 1
#endif
/* Renesas M32R
<https://en.wikipedia.org/wiki/M32R> */
#if defined(__m32r__) || defined(__M32R__)
#define SIMDE_ARCH_M32R
#endif
/* Motorola 68000
<https://en.wikipedia.org/wiki/Motorola_68000> */
#if defined(__mc68060__) || defined(__MC68060__)
#define SIMDE_ARCH_M68K 68060
#elif defined(__mc68040__) || defined(__MC68040__)
#define SIMDE_ARCH_M68K 68040
#elif defined(__mc68030__) || defined(__MC68030__)
#define SIMDE_ARCH_M68K 68030
#elif defined(__mc68020__) || defined(__MC68020__)
#define SIMDE_ARCH_M68K 68020
#elif defined(__mc68010__) || defined(__MC68010__)
#define SIMDE_ARCH_M68K 68010
#elif defined(__mc68000__) || defined(__MC68000__)
#define SIMDE_ARCH_M68K 68000
#endif
/* Xilinx MicroBlaze
<https://en.wikipedia.org/wiki/MicroBlaze> */
#if defined(__MICROBLAZE__) || defined(__microblaze__)
#define SIMDE_ARCH_MICROBLAZE
#endif
/* MIPS
<https://en.wikipedia.org/wiki/MIPS_architecture> */
#if defined(_MIPS_ISA_MIPS64R2)
#define SIMDE_ARCH_MIPS 642
#elif defined(_MIPS_ISA_MIPS64)
#define SIMDE_ARCH_MIPS 640
#elif defined(_MIPS_ISA_MIPS32R2)
#define SIMDE_ARCH_MIPS 322
#elif defined(_MIPS_ISA_MIPS32)
#define SIMDE_ARCH_MIPS 320
#elif defined(_MIPS_ISA_MIPS4)
#define SIMDE_ARCH_MIPS 4
#elif defined(_MIPS_ISA_MIPS3)
#define SIMDE_ARCH_MIPS 3
#elif defined(_MIPS_ISA_MIPS2)
#define SIMDE_ARCH_MIPS 2
#elif defined(_MIPS_ISA_MIPS1)
#define SIMDE_ARCH_MIPS 1
#elif defined(_MIPS_ISA_MIPS) || defined(__mips) || defined(__MIPS__)
#define SIMDE_ARCH_MIPS 1
#endif
/* Matsushita MN10300
<https://en.wikipedia.org/wiki/MN103> */
#if defined(__MN10300__) || defined(__mn10300__)
#define SIMDE_ARCH_MN10300 1
#endif
/* POWER
<https://en.wikipedia.org/wiki/IBM_POWER_Instruction_Set_Architecture> */
#if defined(_M_PPC)
#define SIMDE_ARCH_POWER _M_PPC
#elif defined(_ARCH_PWR8)
#define SIMDE_ARCH_POWER 800
#elif defined(_ARCH_PWR7)
#define SIMDE_ARCH_POWER 700
#elif defined(_ARCH_PWR6)
#define SIMDE_ARCH_POWER 600
#elif defined(_ARCH_PWR5)
#define SIMDE_ARCH_POWER 500
#elif defined(_ARCH_PWR4)
#define SIMDE_ARCH_POWER 400
#elif defined(_ARCH_440) || defined(__ppc440__)
#define SIMDE_ARCH_POWER 440
#elif defined(_ARCH_450) || defined(__ppc450__)
#define SIMDE_ARCH_POWER 450
#elif defined(_ARCH_601) || defined(__ppc601__)
#define SIMDE_ARCH_POWER 601
#elif defined(_ARCH_603) || defined(__ppc603__)
#define SIMDE_ARCH_POWER 603
#elif defined(_ARCH_604) || defined(__ppc604__)
#define SIMDE_ARCH_POWER 604
#elif defined(_ARCH_605) || defined(__ppc605__)
#define SIMDE_ARCH_POWER 605
#elif defined(_ARCH_620) || defined(__ppc620__)
#define SIMDE_ARCH_POWER 620
#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || \
defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC) || \
defined(__ppc)
#define SIMDE_ARCH_POWER 1
#endif
/* SPARC
<https://en.wikipedia.org/wiki/SPARC> */
#if defined(__sparc_v9__) || defined(__sparcv9)
#define SIMDE_ARCH_SPARC 9
#elif defined(__sparc_v8__) || defined(__sparcv8)
#define SIMDE_ARCH_SPARC 8
#elif defined(__sparc_v7__) || defined(__sparcv7)
#define SIMDE_ARCH_SPARC 7
#elif defined(__sparc_v6__) || defined(__sparcv6)
#define SIMDE_ARCH_SPARC 6
#elif defined(__sparc_v5__) || defined(__sparcv5)
#define SIMDE_ARCH_SPARC 5
#elif defined(__sparc_v4__) || defined(__sparcv4)
#define SIMDE_ARCH_SPARC 4
#elif defined(__sparc_v3__) || defined(__sparcv3)
#define SIMDE_ARCH_SPARC 3
#elif defined(__sparc_v2__) || defined(__sparcv2)
#define SIMDE_ARCH_SPARC 2
#elif defined(__sparc_v1__) || defined(__sparcv1)
#define SIMDE_ARCH_SPARC 1
#elif defined(__sparc__) || defined(__sparc)
#define SIMDE_ARCH_SPARC 1
#endif
/* SuperH
<https://en.wikipedia.org/wiki/SuperH> */
#if defined(__sh5__) || defined(__SH5__)
#define SIMDE_ARCH_SUPERH 5
#elif defined(__sh4__) || defined(__SH4__)
#define SIMDE_ARCH_SUPERH 4
#elif defined(__sh3__) || defined(__SH3__)
#define SIMDE_ARCH_SUPERH 3
#elif defined(__sh2__) || defined(__SH2__)
#define SIMDE_ARCH_SUPERH 2
#elif defined(__sh1__) || defined(__SH1__)
#define SIMDE_ARCH_SUPERH 1
#elif defined(__sh__) || defined(__SH__)
#define SIMDE_ARCH_SUPERH 1
#endif
/* IBM System z
<https://en.wikipedia.org/wiki/IBM_System_z> */
#if defined(__370__) || defined(__THW_370__) || defined(__s390__) || \
defined(__s390x__) || defined(__zarch__) || defined(__SYSC_ZARCH__)
#define SIMDE_ARCH_SYSTEMZ
#endif
/* TMS320 DSP
<https://en.wikipedia.org/wiki/Texas_Instruments_TMS320> */
#if defined(_TMS320C6740) || defined(__TMS320C6740__)
#define SIMDE_ARCH_TMS320 6740
#elif defined(_TMS320C6700_PLUS) || defined(__TMS320C6700_PLUS__)
#define SIMDE_ARCH_TMS320 6701
#elif defined(_TMS320C6700) || defined(__TMS320C6700__)
#define SIMDE_ARCH_TMS320 6700
#elif defined(_TMS320C6600) || defined(__TMS320C6600__)
#define SIMDE_ARCH_TMS320 6600
#elif defined(_TMS320C6400_PLUS) || defined(__TMS320C6400_PLUS__)
#define SIMDE_ARCH_TMS320 6401
#elif defined(_TMS320C6400) || defined(__TMS320C6400__)
#define SIMDE_ARCH_TMS320 6400
#elif defined(_TMS320C6200) || defined(__TMS320C6200__)
#define SIMDE_ARCH_TMS320 6200
#elif defined(_TMS320C55X) || defined(__TMS320C55X__)
#define SIMDE_ARCH_TMS320 550
#elif defined(_TMS320C54X) || defined(__TMS320C54X__)
#define SIMDE_ARCH_TMS320 540
#elif defined(_TMS320C28X) || defined(__TMS320C28X__)
#define SIMDE_ARCH_TMS320 280
#endif
/* Xtensa
<https://en.wikipedia.org/wiki/> */
#if defined(__xtensa__) || defined(__XTENSA__)
#define SIMDE_ARCH_XTENSA 1
#endif
#endif /* !defined(SIMDE_ARCH_H) */

View file

@ -1,278 +0,0 @@
/* Copyright (c) 2017-2019 Evan Nemerson <evan@nemerson.com>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#if !defined(SIMDE_COMMON_H)
#define SIMDE_COMMON_H
#include "hedley.h"
#include "check.h"
#include "simde-arch.h"
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
#define SIMDE_ALIGN(alignment) _Alignas(alignment)
#elif (defined(__cplusplus) && (__cplusplus >= 201103L))
#define SIMDE_ALIGN(alignment) alignas(alignment)
#elif HEDLEY_GCC_VERSION_CHECK(2, 95, 0) || \
HEDLEY_CRAY_VERSION_CHECK(8, 4, 0) || \
HEDLEY_IBM_VERSION_CHECK(11, 1, 0) || \
HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \
HEDLEY_PGI_VERSION_CHECK(19, 4, 0) || \
HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \
HEDLEY_TINYC_VERSION_CHECK(0, 9, 24) || \
HEDLEY_TI_VERSION_CHECK(8, 1, 0)
#define SIMDE_ALIGN(alignment) __attribute__((aligned(alignment)))
#elif defined(_MSC_VER) && (!defined(_M_IX86) || defined(_M_AMD64))
#define SIMDE_ALIGN(alignment) __declspec(align(alignment))
#else
#define SIMDE_ALIGN(alignment)
#endif
#define simde_assert_aligned(alignment, val) \
simde_assert_int(((uintptr_t)(val)) % (alignment), ==, 0)
#if HEDLEY_GCC_HAS_ATTRIBUTE(vector_size, 4, 6, 0)
#define SIMDE__ENABLE_GCC_VEC_EXT
#endif
#if !defined(SIMDE_ENABLE_OPENMP) && \
((defined(_OPENMP) && (_OPENMP >= 201307L)) || \
(defined(_OPENMP_SIMD) && (_OPENMP_SIMD >= 201307L)))
#define SIMDE_ENABLE_OPENMP
#endif
#if !defined(SIMDE_ENABLE_CILKPLUS) && defined(__cilk)
#define SIMDE_ENABLE_CILKPLUS
#endif
#if defined(SIMDE_ENABLE_OPENMP)
#define SIMDE__VECTORIZE _Pragma("omp simd")
#define SIMDE__VECTORIZE_SAFELEN(l) HEDLEY_PRAGMA(omp simd safelen(l))
#define SIMDE__VECTORIZE_REDUCTION(r) HEDLEY_PRAGMA(omp simd reduction(r))
#define SIMDE__VECTORIZE_ALIGNED(a) HEDLEY_PRAGMA(omp simd aligned(a))
#elif defined(SIMDE_ENABLE_CILKPLUS)
#define SIMDE__VECTORIZE _Pragma("simd")
#define SIMDE__VECTORIZE_SAFELEN(l) HEDLEY_PRAGMA(simd vectorlength(l))
#define SIMDE__VECTORIZE_REDUCTION(r) HEDLEY_PRAGMA(simd reduction(r))
#define SIMDE__VECTORIZE_ALIGNED(a) HEDLEY_PRAGMA(simd aligned(a))
#elif defined(__INTEL_COMPILER)
#define SIMDE__VECTORIZE _Pragma("simd")
#define SIMDE__VECTORIZE_SAFELEN(l) HEDLEY_PRAGMA(simd vectorlength(l))
#define SIMDE__VECTORIZE_REDUCTION(r) HEDLEY_PRAGMA(simd reduction(r))
#define SIMDE__VECTORIZE_ALIGNED(a)
#elif defined(__clang__)
#define SIMDE__VECTORIZE _Pragma("clang loop vectorize(enable)")
#define SIMDE__VECTORIZE_SAFELEN(l) HEDLEY_PRAGMA(clang loop vectorize_width(l))
#define SIMDE__VECTORIZE_REDUCTION(r) SIMDE__VECTORIZE
#define SIMDE__VECTORIZE_ALIGNED(a)
#elif HEDLEY_GCC_VERSION_CHECK(4, 9, 0)
#define SIMDE__VECTORIZE _Pragma("GCC ivdep")
#define SIMDE__VECTORIZE_SAFELEN(l) SIMDE__VECTORIZE
#define SIMDE__VECTORIZE_REDUCTION(r) SIMDE__VECTORIZE
#define SIMDE__VECTORIZE_ALIGNED(a)
#elif HEDLEY_CRAY_VERSION_CHECK(5, 0, 0)
#define SIMDE__VECTORIZE _Pragma("_CRI ivdep")
#define SIMDE__VECTORIZE_SAFELEN(l) SIMDE__VECTORIZE
#define SIMDE__VECTORIZE_REDUCTION(r) SIMDE__VECTORIZE
#define SIMDE__VECTORIZE_ALIGNED(a)
#else
#define SIMDE__VECTORIZE
#define SIMDE__VECTORIZE_SAFELEN(l)
#define SIMDE__VECTORIZE_REDUCTION(r)
#define SIMDE__VECTORIZE_ALIGNED(a)
#endif
#if HEDLEY_GCC_HAS_ATTRIBUTE(unused, 3, 1, 0)
#define SIMDE__UNUSED __attribute__((__unused__))
#else
#define SIMDE__UNUSED
#endif
#if HEDLEY_GCC_HAS_ATTRIBUTE(artificial, 4, 3, 0)
#define SIMDE__ARTIFICIAL __attribute__((__artificial__))
#else
#define SIMDE__ARTIFICIAL
#endif
/* Intended for checking coverage, you should never use this in
production. */
#if defined(SIMDE_NO_INLINE)
#define SIMDE__FUNCTION_ATTRIBUTES HEDLEY_NEVER_INLINE SIMDE__UNUSED static
#else
#define SIMDE__FUNCTION_ATTRIBUTES HEDLEY_INLINE SIMDE__ARTIFICIAL static
#endif
#if defined(_MSC_VER)
#define SIMDE__BEGIN_DECLS \
HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(disable : 4996 4204)) \
HEDLEY_BEGIN_C_DECLS
#define SIMDE__END_DECLS HEDLEY_DIAGNOSTIC_POP HEDLEY_END_C_DECLS
#else
#define SIMDE__BEGIN_DECLS HEDLEY_BEGIN_C_DECLS
#define SIMDE__END_DECLS HEDLEY_END_C_DECLS
#endif
#if defined(__SIZEOF_INT128__)
#define SIMDE__HAVE_INT128
typedef __int128 simde_int128;
typedef unsigned __int128 simde_uint128;
#endif
/* TODO: we should at least make an attempt to detect the correct
types for simde_float32/float64 instead of just assuming float and
double. */
#if !defined(SIMDE_FLOAT32_TYPE)
#define SIMDE_FLOAT32_TYPE float
#define SIMDE_FLOAT32_C(value) value##f
#else
#define SIMDE_FLOAT32_C(value) ((SIMDE_FLOAT32_TYPE)value)
#endif
typedef SIMDE_FLOAT32_TYPE simde_float32;
HEDLEY_STATIC_ASSERT(sizeof(simde_float32) == 4,
"Unable to find 32-bit floating-point type.");
#if !defined(SIMDE_FLOAT64_TYPE)
#define SIMDE_FLOAT64_TYPE double
#define SIMDE_FLOAT64_C(value) value
#else
#define SIMDE_FLOAT32_C(value) ((SIMDE_FLOAT64_TYPE)value)
#endif
typedef SIMDE_FLOAT64_TYPE simde_float64;
HEDLEY_STATIC_ASSERT(sizeof(simde_float64) == 8,
"Unable to find 64-bit floating-point type.");
/* Whether to assume that the compiler can auto-vectorize reasonably
well. This will cause SIMDe to attempt to compose vector
operations using more simple vector operations instead of minimize
serial work.
As an example, consider the _mm_add_ss(a, b) function from SSE,
which returns { a0 + b0, a1, a2, a3 }. This pattern is repeated
for other operations (sub, mul, etc.).
The naïve implementation would result in loading a0 and b0, adding
them into a temporary variable, then splicing that value into a new
vector with the remaining elements from a.
On platforms which support vectorization, it's generally faster to
simply perform the operation on the entire vector to avoid having
to move data between SIMD registers and non-SIMD registers.
Basically, instead of the temporary variable being (a0 + b0) it
would be a vector of (a + b), which is then combined with a to form
the result.
By default, SIMDe will prefer the pure-vector versions if we detect
a vector ISA extension, but this can be overridden by defining
SIMDE_NO_ASSUME_VECTORIZATION. You can also define
SIMDE_ASSUME_VECTORIZATION if you want to force SIMDe to use the
vectorized version. */
#if !defined(SIMDE_NO_ASSUME_VECTORIZATION) && \
!defined(SIMDE_ASSUME_VECTORIZATION)
#if defined(__SSE__) || defined(__ARM_NEON) || defined(__mips_msa) || \
defined(__ALTIVEC__)
#define SIMDE_ASSUME_VECTORIZATION
#endif
#endif
/* GCC and clang have built-in functions to handle shuffling of
vectors, but the implementations are slightly different. This
macro is just an abstraction over them. Note that elem_size is in
bits but vec_size is in bytes. */
#if HEDLEY_CLANG_HAS_BUILTIN(__builtin_shufflevector)
#define SIMDE__SHUFFLE_VECTOR(elem_size, vec_size, a, b, ...) \
__builtin_shufflevector(a, b, __VA_ARGS__)
#elif HEDLEY_GCC_HAS_BUILTIN(__builtin_shuffle, 4, 7, 0) && \
!defined(__INTEL_COMPILER)
#define SIMDE__SHUFFLE_VECTOR(elem_size, vec_size, a, b, ...) \
__builtin_shuffle(a, b, \
(int##elem_size##_t __attribute__( \
(__vector_size__(vec_size)))){__VA_ARGS__})
#endif
/* Some algorithms are iterative, and fewer iterations means less
accuracy. Lower values here will result in faster, but less
accurate, calculations for some functions. */
#if !defined(SIMDE_ACCURACY_ITERS)
#define SIMDE_ACCURACY_ITERS 2
#endif
/* This will probably move into Hedley at some point, but I'd like to
more thoroughly check for other compilers which define __GNUC__
first. */
#if defined(SIMDE__REALLY_GCC)
#undef SIMDE__REALLY_GCC
#endif
#if !defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)
#define SIMDE__REALLY_GCC 0
#else
#define SIMDE__REALLY_GCC 1
#endif
#if defined(SIMDE__ASSUME_ALIGNED)
#undef SIMDE__ASSUME_ALIGNED
#endif
#if HEDLEY_INTEL_VERSION_CHECK(9, 0, 0)
#define SIMDE__ASSUME_ALIGNED(ptr, align) __assume_aligned(ptr, align)
#elif HEDLEY_MSVC_VERSION_CHECK(13, 10, 0)
#define SIMDE__ASSUME_ALIGNED(ptr, align) \
__assume((((char *)ptr) - ((char *)0)) % (align) == 0)
#elif HEDLEY_GCC_HAS_BUILTIN(__builtin_assume_aligned, 4, 7, 0)
#define SIMDE__ASSUME_ALIGNED(ptr, align) \
(ptr = (__typeof__(ptr))__builtin_assume_aligned((ptr), align))
#elif HEDLEY_CLANG_HAS_BUILTIN(__builtin_assume)
#define SIMDE__ASSUME_ALIGNED(ptr, align) \
__builtin_assume((((char *)ptr) - ((char *)0)) % (align) == 0)
#elif HEDLEY_GCC_HAS_BUILTIN(__builtin_unreachable, 4, 5, 0)
#define SIMDE__ASSUME_ALIGNED(ptr, align) \
((((char *)ptr) - ((char *)0)) % (align) == 0) \
? (1) \
: (__builtin_unreachable(), 0)
#else
#define SIMDE__ASSUME_ALIGNED(ptr, align)
#endif
/* Sometimes we run into problems with specific versions of compilers
which make the native versions unusable for us. Often this is due
to missing functions, sometimes buggy implementations, etc. These
macros are how we check for specific bugs. As they are fixed we'll
start only defining them for problematic compiler versions. */
#if !defined(SIMDE_IGNORE_COMPILER_BUGS)
#if SIMDE__REALLY_GCC
#if !HEDLEY_GCC_VERSION_CHECK(4, 9, 0)
#define SIMDE_BUG_GCC_REV_208793
#endif
#if !HEDLEY_GCC_VERSION_CHECK(5, 0, 0)
#define SIMDE_BUG_GCC_BAD_MM_SRA_EPI32 /* TODO: find relevant bug or commit */
#endif
#if !HEDLEY_GCC_VERSION_CHECK(4, 6, 0)
#define SIMDE_BUG_GCC_BAD_MM_EXTRACT_EPI8 /* TODO: find relevant bug or commit */
#endif
#endif
#if defined(__EMSCRIPTEN__)
#define SIMDE_BUG_EMSCRIPTEN_MISSING_IMPL /* Placeholder for (as yet) unfiled issues. */
#define SIMDE_BUG_EMSCRIPTEN_5242
#endif
#endif
#endif /* !defined(SIMDE_COMMON_H) */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -46,6 +46,7 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
add_subdirectory(linux-pulseaudio) add_subdirectory(linux-pulseaudio)
add_subdirectory(linux-v4l2) add_subdirectory(linux-v4l2)
add_subdirectory(linux-jack) add_subdirectory(linux-jack)
add_subdirectory(linux-alsa)
endif() endif()
option(BUILD_BROWSER "Build browser plugin" OFF) option(BUILD_BROWSER "Build browser plugin" OFF)

View file

@ -4,6 +4,10 @@ set(coreaudio-encoder_SOURCES
encoder.cpp) encoder.cpp)
if (WIN32) if (WIN32)
set(MODULE_DESCRIPTION "OBS Core Audio encoder")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in coreaudio-encoder.rc)
list(APPEND coreaudio-encoder_SOURCES
coreaudio-encoder.rc)
set(coreaudio-encoder_HEADERS windows-imports.h) set(coreaudio-encoder_HEADERS windows-imports.h)
set(coreaudio-encoder_LIBS ) set(coreaudio-encoder_LIBS )

View file

@ -60,6 +60,9 @@ static bool decklink_output_start(void *data)
device.Set(deviceEnum->FindByHash(decklink->deviceHash)); device.Set(deviceEnum->FindByHash(decklink->deviceHash));
if (!device)
return false;
DeckLinkDeviceMode *mode = device->FindOutputMode(decklink->modeID); DeckLinkDeviceMode *mode = device->FindOutputMode(decklink->modeID);
decklink->SetSize(mode->GetWidth(), mode->GetHeight()); decklink->SetSize(mode->GetWidth(), mode->GetHeight());

View file

@ -31,6 +31,8 @@ set(win-decklink_HEADERS
../util.hpp ../util.hpp
) )
set(MODULE_DESCRIPTION "OBS DeckLink Windows module")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in win-decklink.rc)
set(win-decklink_SOURCES set(win-decklink_SOURCES
../plugin-main.cpp ../plugin-main.cpp
../decklink-devices.cpp ../decklink-devices.cpp
@ -46,7 +48,7 @@ set(win-decklink_SOURCES
../audio-repack.c ../audio-repack.c
platform.cpp platform.cpp
../util.cpp ../util.cpp
) win-decklink.rc)
add_idl_files(win-decklink-sdk_GENERATED_FILES add_idl_files(win-decklink-sdk_GENERATED_FILES
${win-decklink-sdk_IDLS} ${win-decklink-sdk_IDLS}

View file

@ -10,6 +10,13 @@ set(image-source_SOURCES
color-source.c color-source.c
obs-slideshow.c) obs-slideshow.c)
if(WIN32)
set(MODULE_DESCRIPTION "OBS image module")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in image-source.rc)
list(APPEND image-source_SOURCES
image-source.rc)
endif()
add_library(image-source MODULE add_library(image-source MODULE
${image-source_SOURCES}) ${image-source_SOURCES})
target_link_libraries(image-source target_link_libraries(image-source

View file

@ -43,6 +43,8 @@ static enum speaker_layout jack_channels_to_obs_speakers(uint_fast32_t channels)
return SPEAKERS_STEREO; return SPEAKERS_STEREO;
case 3: case 3:
return SPEAKERS_2POINT1; return SPEAKERS_2POINT1;
case 4:
return SPEAKERS_4POINT0;
case 5: case 5:
return SPEAKERS_4POINT1; return SPEAKERS_4POINT1;
case 6: case 6:

View file

@ -95,7 +95,7 @@ static inline bool valid_control(struct v4l2_queryctrl *qctrl)
return (qctrl->flags & INVALID_CONTROL_FLAGS) == 0; return (qctrl->flags & INVALID_CONTROL_FLAGS) == 0;
} }
static inline bool add_control_property(obs_properties_t *props, static inline void add_control_property(obs_properties_t *props,
obs_data_t *settings, int_fast32_t dev, obs_data_t *settings, int_fast32_t dev,
struct v4l2_queryctrl *qctrl) struct v4l2_queryctrl *qctrl)
{ {

View file

@ -6,6 +6,7 @@
struct cocoa_window { struct cocoa_window {
CGWindowID window_id; CGWindowID window_id;
int owner_pid;
pthread_mutex_t name_lock; pthread_mutex_t name_lock;
NSString *owner_name; NSString *owner_name;

View file

@ -60,8 +60,11 @@ bool find_window(cocoa_window_t cw, obs_data_t *settings, bool force)
NSNumber *window_id = (NSNumber *)dict[WINDOW_NUMBER]; NSNumber *window_id = (NSNumber *)dict[WINDOW_NUMBER];
cw->window_id = window_id.intValue; cw->window_id = window_id.intValue;
NSNumber *owner_pid = (NSNumber *)dict[OWNER_PID];
cw->owner_pid = owner_pid.intValue;
obs_data_set_int(settings, "window", cw->window_id); obs_data_set_int(settings, "window", cw->window_id);
obs_data_set_int(settings, "owner_pid", cw->owner_pid);
return true; return true;
} }
@ -78,7 +81,41 @@ void init_window(cocoa_window_t cw, obs_data_t *settings)
cw->window_name = @(obs_data_get_string(settings, "window_name")); cw->window_name = @(obs_data_get_string(settings, "window_name"));
[cw->owner_name retain]; [cw->owner_name retain];
[cw->window_name retain]; [cw->window_name retain];
find_window(cw, settings, true);
// Find initial window.
pthread_mutex_lock(&cw->name_lock);
if (!cw->window_name.length && !cw->owner_name.length)
goto invalid_name;
NSNumber *owner_pid = @(obs_data_get_int(settings, "owner_pid"));
NSNumber *window_id = @(obs_data_get_int(settings, "window"));
for (NSDictionary *dict in enumerate_windows()) {
bool owner_names_match =
[cw->owner_name isEqualToString:dict[OWNER_NAME]];
bool ids_match =
[owner_pid isEqualToNumber:dict[OWNER_PID]] &&
[window_id isEqualToNumber:dict[WINDOW_NUMBER]];
bool window_names_match =
[cw->window_name isEqualToString:dict[WINDOW_NAME]];
if (owner_names_match && (ids_match || window_names_match)) {
pthread_mutex_unlock(&cw->name_lock);
NSNumber *window_id = (NSNumber *)dict[WINDOW_NUMBER];
cw->window_id = window_id.intValue;
NSNumber *owner_pid = (NSNumber *)dict[OWNER_PID];
cw->owner_pid = owner_pid.intValue;
obs_data_set_int(settings, "window", cw->window_id);
obs_data_set_int(settings, "owner_pid", cw->owner_pid);
return;
}
}
invalid_name:
pthread_mutex_unlock(&cw->name_lock);
return;
} }
void destroy_window(cocoa_window_t cw) void destroy_window(cocoa_window_t cw)
@ -99,6 +136,7 @@ void update_window(cocoa_window_t cw, obs_data_t *settings)
[cw->window_name retain]; [cw->window_name retain];
pthread_mutex_unlock(&cw->name_lock); pthread_mutex_unlock(&cw->name_lock);
cw->owner_pid = obs_data_get_int(settings, "owner_pid");
cw->window_id = obs_data_get_int(settings, "window"); cw->window_id = obs_data_get_int(settings, "window");
} }

View file

@ -55,6 +55,9 @@ set(syphon_SOURCES
syphon-framework/SyphonServerDirectory.m syphon-framework/SyphonServerDirectory.m
) )
add_library(syphon-framework ${syphon_HEADERS}
${syphon_SOURCES})
set(mac-syphon_HEADERS set(mac-syphon_HEADERS
) )
@ -70,15 +73,17 @@ add_definitions(-DSYPHON_UNIQUE_CLASS_NAME_PREFIX=OBS_ -include
add_library(mac-syphon MODULE add_library(mac-syphon MODULE
${mac-syphon_SOURCES} ${mac-syphon_SOURCES}
${mac-syphon_HEADERS} ${mac-syphon_HEADERS})
${syphon_HEADERS}
${syphon_SOURCES})
target_link_libraries(mac-syphon target_link_libraries(mac-syphon
libobs libobs
syphon-framework
${COCOA} ${COCOA}
${IOSURF} ${IOSURF}
${SCRIPTINGBRIDGE} ${SCRIPTINGBRIDGE}
${OPENGL_gl_LIBRARY}) ${OPENGL_gl_LIBRARY})
set_property (TARGET mac-syphon APPEND_STRING PROPERTY
COMPILE_FLAGS "-fobjc-arc")
install_obs_plugin_with_data(mac-syphon data) install_obs_plugin_with_data(mac-syphon data)

View file

@ -41,12 +41,6 @@ struct syphon {
}; };
typedef struct syphon *syphon_t; typedef struct syphon *syphon_t;
static inline void objc_release(NSObject **obj)
{
[*obj release];
*obj = nil;
}
static inline void update_properties(syphon_t s) static inline void update_properties(syphon_t s)
{ {
obs_source_update_properties(s->source); obs_source_update_properties(s->source);
@ -101,10 +95,7 @@ static void stop_client(syphon_t s)
obs_enter_graphics(); obs_enter_graphics();
if (s->client) { if (s->client) {
@autoreleasepool {
[s->client stop]; [s->client stop];
objc_release(&s->client);
}
} }
if (s->tex) { if (s->tex) {
@ -178,16 +169,6 @@ static inline void check_description(syphon_t s, NSDictionary *desc)
surfaces_string.UTF8String); surfaces_string.UTF8String);
} }
static inline bool update_string(NSString **str, NSString *new)
{
if (!new)
return false;
[*str release];
*str = [new retain];
return true;
}
static inline void handle_new_frame(syphon_t s, static inline void handle_new_frame(syphon_t s,
SYPHON_CLIENT_UNIQUE_CLASS_NAME *client) SYPHON_CLIENT_UNIQUE_CLASS_NAME *client)
{ {
@ -233,35 +214,26 @@ static void create_client(syphon_t s)
NSDictionary *desc = find_by_uuid(servers, s->uuid); NSDictionary *desc = find_by_uuid(servers, s->uuid);
if (!desc) { if (!desc) {
desc = servers[0]; desc = servers[0];
if (update_string(&s->uuid, if (![s->uuid isEqualToString:
desc[SyphonServerDescriptionUUIDKey])) desc[SyphonServerDescriptionUUIDKey]]) {
s->uuid_changed = true; s->uuid_changed = true;
} }
}
check_version(s, desc); check_version(s, desc);
check_description(s, desc); check_description(s, desc);
@autoreleasepool {
s->client = [[SYPHON_CLIENT_UNIQUE_CLASS_NAME alloc] s->client = [[SYPHON_CLIENT_UNIQUE_CLASS_NAME alloc]
initWithServerDescription:desc initWithServerDescription:desc
options:nil options:nil
newFrameHandler:^( newFrameHandler:^(
SYPHON_CLIENT_UNIQUE_CLASS_NAME SYPHON_CLIENT_UNIQUE_CLASS_NAME *client) {
*client) {
handle_new_frame(s, client); handle_new_frame(s, client);
}]; }];
}
s->active = true; s->active = true;
} }
static inline void release_settings(syphon_t s)
{
[s->app_name release];
[s->name release];
[s->uuid release];
}
static inline bool load_syphon_settings(syphon_t s, obs_data_t *settings) static inline bool load_syphon_settings(syphon_t s, obs_data_t *settings)
{ {
NSString *app_name = @(obs_data_get_string(settings, "app_name")); NSString *app_name = @(obs_data_get_string(settings, "app_name"));
@ -275,10 +247,9 @@ static inline bool load_syphon_settings(syphon_t s, obs_data_t *settings)
if ([uuid isEqual:s->uuid] && equal_names) if ([uuid isEqual:s->uuid] && equal_names)
return false; return false;
release_settings(s); s->app_name = app_name;
s->app_name = [app_name retain]; s->name = name;
s->name = [name retain]; s->uuid = uuid;
s->uuid = [uuid retain];
s->uuid_changed = false; s->uuid_changed = false;
return true; return true;
} }
@ -299,10 +270,12 @@ static inline void update_from_announce(syphon_t s, NSDictionary *info)
!([app_name isEqual:s->app_name] && [name isEqual:s->name])) !([app_name isEqual:s->app_name] && [name isEqual:s->name]))
return; return;
update_string(&s->app_name, app_name); s->app_name = app_name;
update_string(&s->name, name); s->name = name;
if (update_string(&s->uuid, uuid)) if (![s->uuid isEqualToString:uuid]) {
s->uuid = uuid;
s->uuid_changed = true; s->uuid_changed = true;
}
create_client(s); create_client(s);
} }
@ -324,8 +297,6 @@ static inline void update_inject_state(syphon_t s, NSDictionary *info,
if (!(s->inject_server_found = announce)) { if (!(s->inject_server_found = announce)) {
s->inject_wait_time = 0.f; s->inject_wait_time = 0.f;
objc_release(&s->inject_uuid);
LOG(LOG_INFO, LOG(LOG_INFO,
"Injected server retired: " "Injected server retired: "
"[%s] InjectedSyphon (%s)", "[%s] InjectedSyphon (%s)",
@ -336,7 +307,7 @@ static inline void update_inject_state(syphon_t s, NSDictionary *info,
if (s->inject_uuid) //TODO: track multiple injected instances? if (s->inject_uuid) //TODO: track multiple injected instances?
return; return;
s->inject_uuid = [uuid retain]; s->inject_uuid = uuid;
LOG(LOG_INFO, "Injected server found: [%s] %s (%s)", LOG(LOG_INFO, "Injected server found: [%s] %s (%s)",
app_name.UTF8String, name.UTF8String, uuid.UTF8String); app_name.UTF8String, name.UTF8String, uuid.UTF8String);
} }
@ -487,26 +458,31 @@ static void *syphon_create_internal(obs_data_t *settings, obs_source_t *source)
s->source = source; s->source = source;
if (!init_obs_graphics_objects(s)) if (!init_obs_graphics_objects(s)) {
goto fail; syphon_destroy_internal(s);
return NULL;
}
if (!load_syphon_settings(s, settings)) if (!load_syphon_settings(s, settings)) {
goto fail; syphon_destroy_internal(s);
return NULL;
}
const char *inject_info = obs_data_get_string(settings, "application"); const char *inject_info = obs_data_get_string(settings, "application");
s->inject_info = obs_data_create_from_json(inject_info); s->inject_info = obs_data_create_from_json(inject_info);
s->inject_active = obs_data_get_bool(settings, "inject"); s->inject_active = obs_data_get_bool(settings, "inject");
s->inject_app = @(obs_data_get_string(s->inject_info, "name")); s->inject_app = @(obs_data_get_string(s->inject_info, "name"));
if (s->inject_app) if (!create_syphon_listeners(s)) {
[s->inject_app retain]; syphon_destroy_internal(s);
return NULL;
if (!create_syphon_listeners(s)) }
goto fail;
NSWorkspace *ws = [NSWorkspace sharedWorkspace]; NSWorkspace *ws = [NSWorkspace sharedWorkspace];
if (!create_applications_observer(s, ws)) if (!create_applications_observer(s, ws)) {
goto fail; syphon_destroy_internal(s);
return NULL;
}
if (s->inject_active) if (s->inject_active)
find_and_inject_target(s, ws.runningApplications, false); find_and_inject_target(s, ws.runningApplications, false);
@ -519,10 +495,6 @@ static void *syphon_create_internal(obs_data_t *settings, obs_source_t *source)
obs_data_get_bool(settings, "allow_transparency"); obs_data_get_bool(settings, "allow_transparency");
return s; return s;
fail:
syphon_destroy_internal(s);
return NULL;
} }
static void *syphon_create(obs_data_t *settings, obs_source_t *source) static void *syphon_create(obs_data_t *settings, obs_source_t *source)
@ -550,15 +522,9 @@ static inline void syphon_destroy_internal(syphon_t s)
[ws removeObserver:s->launch_listener [ws removeObserver:s->launch_listener
forKeyPath:NSStringFromSelector(@selector forKeyPath:NSStringFromSelector(@selector
(runningApplications))]; (runningApplications))];
objc_release(&s->launch_listener);
objc_release(&s->inject_app);
objc_release(&s->inject_uuid);
obs_data_release(s->inject_info); obs_data_release(s->inject_info);
release_settings(s);
obs_enter_graphics(); obs_enter_graphics();
stop_client(s); stop_client(s);
@ -1198,11 +1164,7 @@ static inline void update_inject(syphon_t s, obs_data_t *settings)
obs_data_t *prev = s->inject_info; obs_data_t *prev = s->inject_info;
s->inject_info = obs_data_create_from_json(inject_str); s->inject_info = obs_data_create_from_json(inject_str);
NSString *prev_app = s->inject_app; s->inject_app = @(obs_data_get_string(s->inject_info, "name"));
s->inject_app = [@(obs_data_get_string(s->inject_info, "name")) retain];
[prev_app release];
objc_release(&s->inject_uuid);
SyphonServerDirectory *ssd = [SyphonServerDirectory sharedDirectory]; SyphonServerDirectory *ssd = [SyphonServerDirectory sharedDirectory];
NSArray *servers = [ssd serversMatchingName:@"InjectedSyphon" NSArray *servers = [ssd serversMatchingName:@"InjectedSyphon"

View file

@ -46,9 +46,12 @@ if(ENABLE_FFMPEG_LOGGING)
endif() endif()
if(WIN32) if(WIN32)
set(MODULE_DESCRIPTION "OBS FFmpeg module")
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in obs-ffmpeg.rc)
list(APPEND obs-ffmpeg_SOURCES list(APPEND obs-ffmpeg_SOURCES
jim-nvenc.c jim-nvenc.c
jim-nvenc-helpers.c) jim-nvenc-helpers.c
obs-ffmpeg.rc)
list(APPEND obs-ffmpeg_HEADERS list(APPEND obs-ffmpeg_HEADERS
jim-nvenc.h) jim-nvenc.h)
endif() endif()

View file

@ -58,3 +58,11 @@ ReplayBuffer.Save="Save Replay"
HelperProcessFailed="Unable to start the recording helper process. Check that OBS files have not been blocked or removed by any 3rd party antivirus / security software." HelperProcessFailed="Unable to start the recording helper process. Check that OBS files have not been blocked or removed by any 3rd party antivirus / security software."
UnableToWritePath="Unable to write to %1. Make sure you're using a recording path which your user account is allowed to write to and that there is sufficient disk space." UnableToWritePath="Unable to write to %1. Make sure you're using a recording path which your user account is allowed to write to and that there is sufficient disk space."
WarnWindowsDefender="If Windows 10 Ransomware Protection is enabled it can also cause this error. Try turning off controlled folder access in Windows Security / Virus & threat protection settings." WarnWindowsDefender="If Windows 10 Ransomware Protection is enabled it can also cause this error. Try turning off controlled folder access in Windows Security / Virus & threat protection settings."
NVENC.Error="Failed to open NVENC codec: %1"
NVENC.GenericError="Check your video drivers are up to date. Try closing other recording software which might be using NVENC such as NVIDIA Shadowplay or Windows 10 Game DVR."
NVENC.BadGPUIndex="You have selected GPU %1 in your output encoder settings. Set this back to 0 and try again."
NVENC.OutdatedDriver="Your current video card driver does not support this NVENC version, please update your drivers."
NVENC.UnsupportedDevice="NVENC Error: Unsupported device. Check your video card supports NVENC and that the drivers are up to date."
NVENC.TooManySessions="NVENC Error: Too many concurrent sessions. Try closing other recording software which might be using NVENC such as NVIDIA Shadowplay or Windows 10 Game DVR."
NVENC.CheckDrivers="Please check your video drivers are up to date."

View file

@ -1,6 +1,7 @@
#include "jim-nvenc.h" #include "jim-nvenc.h"
#include <util/platform.h> #include <util/platform.h>
#include <util/threading.h> #include <util/threading.h>
#include <util/dstr.h>
static void *nvenc_lib = NULL; static void *nvenc_lib = NULL;
static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
@ -9,18 +10,40 @@ NV_CREATE_INSTANCE_FUNC nv_create_instance = NULL;
#define error(format, ...) blog(LOG_ERROR, "[jim-nvenc] " format, ##__VA_ARGS__) #define error(format, ...) blog(LOG_ERROR, "[jim-nvenc] " format, ##__VA_ARGS__)
static inline bool nv_failed(NVENCSTATUS err, const char *func, bool nv_failed(obs_encoder_t *encoder, NVENCSTATUS err, const char *func,
const char *call) const char *call)
{ {
if (err == NV_ENC_SUCCESS) struct dstr error_message = {0};
switch (err) {
case NV_ENC_SUCCESS:
return false; return false;
case NV_ENC_ERR_OUT_OF_MEMORY:
obs_encoder_set_last_error(
encoder, obs_module_text("NVENC.TooManySessions"));
break;
case NV_ENC_ERR_UNSUPPORTED_DEVICE:
obs_encoder_set_last_error(
encoder, obs_module_text("NVENC.UnsupportedDevice"));
break;
default:
dstr_printf(&error_message,
"NVENC Error: %s: %s failed: %d (%s)", func, call,
(int)err, nv_error_name(err));
obs_encoder_set_last_error(encoder, error_message.array);
dstr_free(&error_message);
break;
}
error("%s: %s failed: %d (%s)", func, call, (int)err, error("%s: %s failed: %d (%s)", func, call, (int)err,
nv_error_name(err)); nv_error_name(err));
return true; return true;
} }
#define NV_FAILED(x) nv_failed(x, __FUNCTION__, #x) #define NV_FAILED(e, x) nv_failed(e, x, __FUNCTION__, #x)
bool load_nvenc_lib(void) bool load_nvenc_lib(void)
{ {
@ -83,7 +106,7 @@ const char *nv_error_name(NVENCSTATUS err)
return "Unknown Error"; return "Unknown Error";
} }
static inline bool init_nvenc_internal(void) static inline bool init_nvenc_internal(obs_encoder_t *encoder)
{ {
static bool initialized = false; static bool initialized = false;
static bool success = false; static bool success = false;
@ -95,17 +118,24 @@ static inline bool init_nvenc_internal(void)
NV_MAX_VER_FUNC nv_max_ver = (NV_MAX_VER_FUNC)load_nv_func( NV_MAX_VER_FUNC nv_max_ver = (NV_MAX_VER_FUNC)load_nv_func(
"NvEncodeAPIGetMaxSupportedVersion"); "NvEncodeAPIGetMaxSupportedVersion");
if (!nv_max_ver) { if (!nv_max_ver) {
obs_encoder_set_last_error(
encoder,
"Missing NvEncodeAPIGetMaxSupportedVersion, check "
"your video card drivers are up to date.");
return false; return false;
} }
uint32_t ver = 0; uint32_t ver = 0;
if (NV_FAILED(nv_max_ver(&ver))) { if (NV_FAILED(encoder, nv_max_ver(&ver))) {
return false; return false;
} }
uint32_t cur_ver = (NVENCAPI_MAJOR_VERSION << 4) | uint32_t cur_ver = (NVENCAPI_MAJOR_VERSION << 4) |
NVENCAPI_MINOR_VERSION; NVENCAPI_MINOR_VERSION;
if (cur_ver > ver) { if (cur_ver > ver) {
obs_encoder_set_last_error(
encoder, obs_module_text("NVENC.OutdatedDriver"));
error("Current driver version does not support this NVENC " error("Current driver version does not support this NVENC "
"version, please upgrade your driver"); "version, please upgrade your driver");
return false; return false;
@ -114,10 +144,13 @@ static inline bool init_nvenc_internal(void)
nv_create_instance = (NV_CREATE_INSTANCE_FUNC)load_nv_func( nv_create_instance = (NV_CREATE_INSTANCE_FUNC)load_nv_func(
"NvEncodeAPICreateInstance"); "NvEncodeAPICreateInstance");
if (!nv_create_instance) { if (!nv_create_instance) {
obs_encoder_set_last_error(
encoder, "Missing NvEncodeAPICreateInstance, check "
"your video card drivers are up to date.");
return false; return false;
} }
if (NV_FAILED(nv_create_instance(&nv))) { if (NV_FAILED(encoder, nv_create_instance(&nv))) {
return false; return false;
} }
@ -125,12 +158,12 @@ static inline bool init_nvenc_internal(void)
return true; return true;
} }
bool init_nvenc(void) bool init_nvenc(obs_encoder_t *encoder)
{ {
bool success; bool success;
pthread_mutex_lock(&init_mutex); pthread_mutex_lock(&init_mutex);
success = init_nvenc_internal(); success = init_nvenc_internal(encoder);
pthread_mutex_unlock(&init_mutex); pthread_mutex_unlock(&init_mutex);
return success; return success;

View file

@ -81,18 +81,7 @@ struct nv_bitstream {
HANDLE event; HANDLE event;
}; };
static inline bool nv_failed(struct nvenc_data *enc, NVENCSTATUS err, #define NV_FAILED(x) nv_failed(enc->encoder, x, __FUNCTION__, #x)
const char *func, const char *call)
{
if (err == NV_ENC_SUCCESS)
return false;
error("%s: %s failed: %d (%s)", func, call, (int)err,
nv_error_name(err));
return true;
}
#define NV_FAILED(x) nv_failed(enc, x, __FUNCTION__, #x)
static bool nv_bitstream_init(struct nvenc_data *enc, struct nv_bitstream *bs) static bool nv_bitstream_init(struct nvenc_data *enc, struct nv_bitstream *bs)
{ {
@ -400,7 +389,8 @@ static bool init_encoder(struct nvenc_data *enc, obs_data_t *settings)
err = nv.nvEncGetEncodePresetConfig(enc->session, err = nv.nvEncGetEncodePresetConfig(enc->session,
NV_ENC_CODEC_H264_GUID, nv_preset, NV_ENC_CODEC_H264_GUID, nv_preset,
&preset_config); &preset_config);
if (nv_failed(enc, err, __FUNCTION__, "nvEncGetEncodePresetConfig")) { if (nv_failed(enc->encoder, err, __FUNCTION__,
"nvEncGetEncodePresetConfig")) {
return false; return false;
} }
@ -578,16 +568,19 @@ static void *nvenc_create(obs_data_t *settings, obs_encoder_t *encoder)
* gpu other than the one OBS is currently running on. */ * gpu other than the one OBS is currently running on. */
int gpu = (int)obs_data_get_int(settings, "gpu"); int gpu = (int)obs_data_get_int(settings, "gpu");
if (gpu != 0) { if (gpu != 0) {
info("different GPU selected by user, falling back to ffmpeg");
goto fail; goto fail;
} }
if (obs_encoder_scaling_enabled(encoder)) { if (obs_encoder_scaling_enabled(encoder)) {
info("scaling enabled, falling back to ffmpeg");
goto fail; goto fail;
} }
if (!obs_nv12_tex_active()) { if (!obs_nv12_tex_active()) {
info("nv12 not active, falling back to ffmpeg");
goto fail; goto fail;
} }
if (!init_nvenc()) { if (!init_nvenc(encoder)) {
goto fail; goto fail;
} }
if (NV_FAILED(nv_create_instance(&init))) { if (NV_FAILED(nv_create_instance(&init))) {
@ -766,7 +759,8 @@ static bool get_encoded_packet(struct nvenc_data *enc, bool finalize)
if (nvtex->mapped_res) { if (nvtex->mapped_res) {
NVENCSTATUS err; NVENCSTATUS err;
err = nv.nvEncUnmapInputResource(s, nvtex->mapped_res); err = nv.nvEncUnmapInputResource(s, nvtex->mapped_res);
if (nv_failed(enc, err, __FUNCTION__, "unmap")) { if (nv_failed(enc->encoder, err, __FUNCTION__,
"unmap")) {
return false; return false;
} }
nvtex->mapped_res = NULL; nvtex->mapped_res = NULL;
@ -859,7 +853,8 @@ static bool nvenc_encode_tex(void *data, uint32_t handle, int64_t pts,
err = nv.nvEncEncodePicture(enc->session, &params); err = nv.nvEncEncodePicture(enc->session, &params);
if (err != NV_ENC_SUCCESS && err != NV_ENC_ERR_NEED_MORE_INPUT) { if (err != NV_ENC_SUCCESS && err != NV_ENC_ERR_NEED_MORE_INPUT) {
nv_failed(enc, err, __FUNCTION__, "nvEncEncodePicture"); nv_failed(enc->encoder, err, __FUNCTION__,
"nvEncEncodePicture");
return false; return false;
} }

View file

@ -12,4 +12,6 @@ typedef NVENCSTATUS(NVENCAPI *NV_CREATE_INSTANCE_FUNC)(
extern const char *nv_error_name(NVENCSTATUS err); extern const char *nv_error_name(NVENCSTATUS err);
extern NV_ENCODE_API_FUNCTION_LIST nv; extern NV_ENCODE_API_FUNCTION_LIST nv;
extern NV_CREATE_INSTANCE_FUNC nv_create_instance; extern NV_CREATE_INSTANCE_FUNC nv_create_instance;
extern bool init_nvenc(void); extern bool init_nvenc(obs_encoder_t *encoder);
bool nv_failed(obs_encoder_t *encoder, NVENCSTATUS err, const char *func,
const char *call);

View file

@ -18,6 +18,7 @@
#include <util/base.h> #include <util/base.h>
#include <util/circlebuf.h> #include <util/circlebuf.h>
#include <util/darray.h> #include <util/darray.h>
#include <util/dstr.h>
#include <obs-module.h> #include <obs-module.h>
#include <libavutil/opt.h> #include <libavutil/opt.h>
@ -143,6 +144,11 @@ static bool initialize_codec(struct enc_encoder *enc)
ret = avcodec_open2(enc->context, enc->codec, NULL); ret = avcodec_open2(enc->context, enc->codec, NULL);
if (ret < 0) { if (ret < 0) {
struct dstr error_message = {0};
dstr_printf(&error_message, "Failed to open AAC codec: %s",
av_err2str(ret));
obs_encoder_set_last_error(enc->encoder, error_message.array);
dstr_free(&error_message);
warn("Failed to open AAC codec: %s", av_err2str(ret)); warn("Failed to open AAC codec: %s", av_err2str(ret));
return false; return false;
} }

View file

@ -88,8 +88,50 @@ static bool nvenc_init_codec(struct nvenc_encoder *enc)
{ {
int ret; int ret;
// avcodec_open2 will overwrite priv_data, we call this to get a
// local copy of the "gpu" setting for improved error messages.
int64_t gpu;
if (av_opt_get_int(enc->context->priv_data, "gpu", 0, &gpu) < 0) {
gpu = -1;
}
ret = avcodec_open2(enc->context, enc->nvenc, NULL); ret = avcodec_open2(enc->context, enc->nvenc, NULL);
if (ret < 0) { if (ret < 0) {
// if we were a fallback from jim-nvenc, there may already be a
// more useful error returned from that, so don't overwrite.
// this can be removed if / when ffmpeg fallback is removed.
if (!obs_encoder_get_last_error(enc->encoder)) {
struct dstr error_message = {0};
dstr_copy(&error_message,
obs_module_text("NVENC.Error"));
dstr_replace(&error_message, "%1", av_err2str(ret));
dstr_cat(&error_message, "\r\n\r\n");
if (gpu > 0) {
// if a non-zero GPU failed, almost always
// user error. tell then to fix it.
char gpu_str[16];
snprintf(gpu_str, sizeof(gpu_str) - 1, "%d",
(int)gpu);
gpu_str[sizeof(gpu_str) - 1] = 0;
dstr_cat(&error_message,
obs_module_text("NVENC.BadGPUIndex"));
dstr_replace(&error_message, "%1", gpu_str);
} else if (ret == AVERROR_EXTERNAL) {
// special case for common NVENC error
dstr_cat(&error_message,
obs_module_text("NVENC.GenericError"));
} else {
dstr_cat(&error_message,
obs_module_text("NVENC.CheckDrivers"));
}
obs_encoder_set_last_error(enc->encoder,
error_message.array);
dstr_free(&error_message);
}
warn("Failed to open NVENC codec: %s", av_err2str(ret)); warn("Failed to open NVENC codec: %s", av_err2str(ret));
return false; return false;
} }
@ -296,6 +338,8 @@ static void *nvenc_create(obs_data_t *settings, obs_encoder_t *encoder)
blog(LOG_INFO, "---------------------------------"); blog(LOG_INFO, "---------------------------------");
if (!enc->nvenc) { if (!enc->nvenc) {
obs_encoder_set_last_error(encoder,
"Couldn't find NVENC encoder");
warn("Couldn't find encoder"); warn("Couldn't find encoder");
goto fail; goto fail;
} }

Some files were not shown because too many files have changed in this diff Show more