Compare commits

..

56 Commits

Author SHA1 Message Date
WarmUpTill
10d3c8c268 add handling of window title of metro apps 2020-10-24 14:43:10 +02:00
WarmUpTill
bc3fcde12d remove unnecessary nullptr checks 2020-10-23 23:57:45 +02:00
WarmUpTill
8b9c93f76c workaround / fixes on media tab
fix memory leaks due to not clearing signal handlers
add workaround for VLC source states during playlists item change
2020-10-23 23:45:04 +02:00
WarmUpTill
89f0449fcd Merge branch 'master' into UI 2020-10-22 22:02:45 +02:00
WarmUpTill
babe8b5c28 rename title tab and only show windows specific hints on windows 2020-10-22 21:25:59 +02:00
WarmUpTill
b1179f4e50 fix mem leaks which could occur with new UI 2020-10-22 21:00:41 +02:00
WarmUpTill
017664b8e0 Merge branch 'master' into UI 2020-10-22 20:02:13 +02:00
WarmUpTill
161588e43b allow WS_EX_TOOLWINDOW as valid window to match 'Task Switching' 2020-10-22 19:40:21 +02:00
WarmUpTill
3dd1138f31 separate idle from file data 2020-10-21 22:15:25 +02:00
WarmUpTill
54aaeed7d7 adjust media switch handling to support vlc source 2020-10-21 21:48:21 +02:00
WarmUpTill
7df6d59c06 more include cleanup 2020-10-20 21:22:24 +02:00
WarmUpTill
b05115a7bb clean up includes 2020-10-19 21:06:35 +02:00
WarmUpTill
58acdb8f79 set process selection editable so processes can be displayed / entered which are not currently running 2020-10-18 22:42:28 +02:00
WarmUpTill
5dd3cf1945 make destructor virtual just in case 2020-10-18 20:12:41 +02:00
WarmUpTill
793e5edf01 add media state 'any' 2020-10-18 20:05:10 +02:00
WarmUpTill
6b1a01de5e move transition warning label and change default transition only once per scene change 2020-10-18 19:21:52 +02:00
WarmUpTill
0b7faee84f fix match log only printing previous scene 2020-10-18 17:43:28 +02:00
WarmUpTill
fd3be07024 fix previous scene handling 2020-10-18 17:37:33 +02:00
WarmUpTill
986422ca83 rename main SceneSwitcher widget to AdvSceneSwitcher 2020-10-18 17:18:21 +02:00
WarmUpTill
6c5c861514 update transitions UI 2020-10-18 16:22:45 +02:00
WarmUpTill
02a8dd87ca adjust log 2020-10-18 16:22:09 +02:00
WarmUpTill
a1266f71f2 fix pulse on sequence and adjust log 2020-10-18 16:21:38 +02:00
WarmUpTill
c7ad2f6ec1 rename sceneSequences widget to sceneSequenceSwitches 2020-10-18 02:03:20 +02:00
WarmUpTill
51612d9e7f do not switch if entry is uninitialized for window, time, region, random 2020-10-18 01:52:19 +02:00
WarmUpTill
491108678e update UI of scene sequence tab 2020-10-18 01:51:07 +02:00
WarmUpTill
3ac795fc72 silence warning 2020-10-18 00:01:44 +02:00
WarmUpTill
96746b3507 update screen region UI and add helper frame 2020-10-17 23:58:08 +02:00
WarmUpTill
7a1104884a change pulse default specifizer to QLabel 2020-10-16 19:42:32 +02:00
WarmUpTill
c6e2c9dcc3 add tooltips to selection entries and do not allow scrolling to them 2020-10-15 21:17:23 +02:00
WarmUpTill
a33c0905c9 allow regex entry for window switch and limit window selection size 2020-10-15 21:16:34 +02:00
WarmUpTill
7f85cdb500 update UI of window tab 2020-10-15 20:59:59 +02:00
WarmUpTill
f643ec10fd add option to disable UI hints 2020-10-14 22:03:12 +02:00
WarmUpTill
abab9f70b5 update Random Tab UI 2020-10-14 21:46:35 +02:00
WarmUpTill
8ecc197805 remove previous scene entry on time tab and unnecessary populate calls 2020-10-14 21:45:42 +02:00
WarmUpTill
0fc6c60d49 add new UI for Time tab 2020-10-14 20:55:11 +02:00
WarmUpTill
255432f3b2 clean up unused signal 2020-10-14 20:18:39 +02:00
WarmUpTill
5c38996d41 add add pulse for media/exec/audio and move inactive pluse to general 2020-10-14 20:17:51 +02:00
WarmUpTill
4d76206452 add generic PulseWidget function to highlight widgets 2020-10-13 22:12:00 +02:00
WarmUpTill
7c561797af clean up setup of audio/exe/media and fix slight leak in media 2020-10-13 20:37:02 +02:00
WarmUpTill
26697faa9f Merge branch 'master' into UI 2020-10-12 21:48:30 +02:00
WarmUpTill
f22da7ff31 fix audio valid(), skip uninit exec switches, skip setting scene and transition for audio / exec as this is done in generic switch 2020-10-12 21:48:08 +02:00
WarmUpTill
5ad820d6cd add new UI for media tab 2020-10-12 21:46:16 +02:00
WarmUpTill
a0a272f49e fix include path and warning 2020-10-11 20:02:37 +02:00
WarmUpTill
5b315d0574 add generic switch widget and setup new UI for exec switching 2020-10-11 19:12:31 +02:00
WarmUpTill
bc3a7cd9be move functions 2020-10-11 15:50:00 +02:00
WarmUpTill
39067f6157 fix up / down audio 2020-10-11 15:18:55 +02:00
WarmUpTill
085225bdcc audio up / down draft (signals still not working) 2020-10-11 00:32:38 +02:00
WarmUpTill
e3dc2c5f26 Merge branch 'master' into UI 2020-10-10 01:58:21 +02:00
WarmUpTill
50545e7f83 audio delete 2020-10-10 01:57:59 +02:00
WarmUpTill
616ce0c737 even more logging 2020-10-10 01:57:38 +02:00
WarmUpTill
ece2d61e0a more logging 2020-10-10 01:50:10 +02:00
WarmUpTill
62d54f7206 slightly adjust logging 2020-10-10 01:43:43 +02:00
WarmUpTill
611c478eb3 adjust audio add to new UI 2020-10-10 00:18:29 +02:00
WarmUpTill
3ff7a848b1 add option to add 'select ...' entry to populate functions 2020-10-10 00:17:19 +02:00
WarmUpTill
36b4d15a17 add edit in place for audio 2020-10-06 21:51:05 +02:00
WarmUpTill
02e797a3db first draft of UI improvements
group settings of the general tab
highlight if the scene switcher is inactive
add draft of allowing editing in place
define additional populate functions for audio and media
2020-10-04 16:28:36 +02:00
25 changed files with 194 additions and 790 deletions

View File

@@ -19,12 +19,12 @@ jobs:
MACOS_DEPS_VERSION: '2020-08-30'
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
uses: actions/checkout@v2
with:
repository: obsproject/obs-studio
submodules: 'recursive'
- name: "Checkout plugin"
uses: actions/checkout@v2.3.4
uses: actions/checkout@v2
with:
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
- name: Fetch Git Tags
@@ -34,15 +34,12 @@ jobs:
- name: 'Install prerequisites (Homebrew)'
shell: bash
run: |
if [ -d /usr/local/opt/openssl@1.0.2t ]; then
brew uninstall openssl@1.0.2t
brew untap local/openssl
fi
if [ -d /usr/local/opt/python@2.7.17 ]; then
brew uninstall python@2.7.17
brew untap local/python2
fi
brew bundle --file ./CI/scripts/macos/Brewfile
cd UI/frontend-plugins/${{ env.PLUGIN_NAME }}/CI/macos
brew untap local/openssl
brew untap local/python2
brew update
brew bundle
cd -
- name: 'Install prerequisite: Pre-built dependencies'
if: steps.deps-cache.outputs.cache-hit != 'true'
shell: bash
@@ -62,7 +59,7 @@ jobs:
echo "add_subdirectory(${{ env.PLUGIN_NAME }})" >> UI/frontend-plugins/CMakeLists.txt
mkdir ./build
cd ./build
cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DDISABLE_PYTHON=ON -DDepsPath="/tmp/obsdeps" -DQTDIR="/tmp/obsdeps" ..
cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 -DDISABLE_PYTHON=ON -DDepsPath="/tmp/obsdeps" -DQTDIR="/tmp/obsdeps" ..
cd -
- name: Build
shell: bash
@@ -89,14 +86,14 @@ jobs:
install_name_tool -change /tmp/obsdeps/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ../../../build/UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
FILE_DATE=$(date +%Y-%m-%d)
FILE_NAME=${{ env.PLUGIN_NAME }}-$FILE_DATE-${{ github.sha }}-macos.pkg
echo "FILE_NAME=${FILE_NAME}" >> $GITHUB_ENV
echo "::set-env name=FILE_NAME::${FILE_NAME}"
packagesbuild ./CI/macos/${{ env.PLUGIN_NAME }}.pkgproj
cd -
mkdir ./nightly
mv UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.PLUGIN_NAME }}.pkg ./nightly/${FILE_NAME}
- name: Publish
if: success()
uses: actions/upload-artifact@v2.2.1
uses: actions/upload-artifact@v2-preview
with:
name: '${{ env.FILE_NAME }}'
path: ./nightly/*.pkg
@@ -105,12 +102,12 @@ jobs:
runs-on: [ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
uses: actions/checkout@v2
with:
repository: obsproject/obs-studio
submodules: 'recursive'
- name: "Checkout plugin"
uses: actions/checkout@v2.3.4
uses: actions/checkout@v2
with:
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
- name: Add plugin to obs cmake
@@ -169,7 +166,7 @@ jobs:
run: |
mkdir ./build
cd ./build
cmake -DUNIX_STRUCTURE=0 -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/obs-studio-portable" -DWITH_RTMPS=OFF -DBUILD_BROWSER=OFF ..
cmake -DUNIX_STRUCTURE=0 -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/obs-studio-portable" -DBUILD_CAPTIONS=OFF -DWITH_RTMPS=OFF -DBUILD_BROWSER=OFF ..
- name: 'Build'
shell: bash
working-directory: ${{ github.workspace }}/build
@@ -179,12 +176,12 @@ jobs:
run: |
FILE_DATE=$(date +%Y-%m-%d)
FILE_NAME=${{ env.PLUGIN_NAME }}-$FILE_DATE-${{ github.sha }}-linux64.tar.gz
echo "FILE_NAME=${FILE_NAME}" >> $GITHUB_ENV
echo "::set-env name=FILE_NAME::${FILE_NAME}"
mkdir -p ./${{ env.PLUGIN_NAME }}/bin/64bit/
mv ./build/UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.LIB_NAME }}.so ./${{ env.PLUGIN_NAME }}/bin/64bit/${{ env.LIB_NAME }}.so
tar -cvzf "${FILE_NAME}" ${{ env.PLUGIN_NAME }}
- name: 'Publish'
uses: actions/upload-artifact@v2.2.1
uses: actions/upload-artifact@v2-preview
with:
name: '${{ env.FILE_NAME }}'
path: '*.tar.gz'
@@ -197,14 +194,14 @@ jobs:
CMAKE_SYSTEM_VERSION: "10.0.18363.657"
steps:
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.2
uses: microsoft/setup-msbuild@v1.0.0
- name: Checkout obs
uses: actions/checkout@v2.3.4
uses: actions/checkout@v2
with:
repository: obsproject/obs-studio
submodules: 'recursive'
- name: Checkout plugin
uses: actions/checkout@v2.3.4
uses: actions/checkout@v2
with:
path: UI/frontend-plugins/${{ env.PLUGIN_NAME}}
- name: Add plugin to obs cmake
@@ -225,7 +222,7 @@ jobs:
mkdir ./build
mkdir ./build64
cd ./build64
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"x64" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win64" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017_64" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"x64" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DBUILD_CAPTIONS=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win64" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017_64" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
- name: Build
run: msbuild /m /p:Configuration=RelWithDebInfo .\build64\obs-studio.sln
- name: Package
@@ -233,12 +230,12 @@ jobs:
run: |
$env:FILE_DATE=(Get-Date -UFormat "%F")
$env:FILE_NAME="${{ env.PLUGIN_NAME }}-${env:FILE_DATE}-${{ github.sha }}-win64.zip"
echo "FILE_NAME=${env:FILE_NAME}" >> ${env:GITHUB_ENV}
echo "::set-env name=FILE_NAME::${env:FILE_NAME}"
robocopy .\build64\rundir\RelWithDebInfo\obs-plugins\64bit\ .\build\obs-plugins\64bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
7z a ${env:FILE_NAME} .\build\*
- name: Publish
if: success()
uses: actions/upload-artifact@v2.2.1
uses: actions/upload-artifact@v2-preview
with:
name: '${{ env.FILE_NAME }}'
path: '*-win64.zip'
@@ -251,14 +248,14 @@ jobs:
CMAKE_SYSTEM_VERSION: "10.0.18363.657"
steps:
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.2
uses: microsoft/setup-msbuild@v1.0.0
- name: Checkout obs
uses: actions/checkout@v2.3.4
uses: actions/checkout@v2
with:
repository: obsproject/obs-studio
submodules: 'recursive'
- name: Checkout plugin
uses: actions/checkout@v2.3.4
uses: actions/checkout@v2
with:
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
- name: Add plugin to obs cmake
@@ -279,7 +276,7 @@ jobs:
mkdir ./build
mkdir ./build32
cd ./build32
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"Win32" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win32" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"Win32" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DBUILD_CAPTIONS=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win32" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
- name: Build
run: msbuild /m /p:Configuration=RelWithDebInfo .\build32\obs-studio.sln
- name: Package
@@ -287,12 +284,12 @@ jobs:
run: |
$env:FILE_DATE=(Get-Date -UFormat "%F")
$env:FILE_NAME="${{ env.PLUGIN_NAME }}-${env:FILE_DATE}-${{ github.sha }}-win32.zip"
echo "FILE_NAME=${env:FILE_NAME}" >> ${env:GITHUB_ENV}
echo "::set-env name=FILE_NAME::${env:FILE_NAME}"
robocopy .\build32\rundir\RelWithDebInfo\obs-plugins\32bit\ .\build\obs-plugins\32bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
7z a ${env:FILE_NAME} .\build\*
- name: Publish
if: success()
uses: actions/upload-artifact@v2.2.1
uses: actions/upload-artifact@v2-preview
with:
name: '${{ env.FILE_NAME }}'
path: '*-win32.zip'

View File

@@ -1,32 +0,0 @@
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: |
./CI/formatcode.sh
./CI/check-format.sh

View File

@@ -1,11 +0,0 @@
#!/bin/bash
dirty=$(git ls-files --modified)
set +x
if [[ $dirty ]]; then
echo "================================="
echo "Files were not formatted properly"
echo "$dirty"
echo "================================="
exit 1
fi

View File

@@ -1,31 +0,0 @@
#!/usr/bin/env bash
# Original source https://github.com/Project-OSRM/osrm-backend/blob/master/scripts/format.sh
set +x
set -o errexit
set -o pipefail
set -o nounset
# Runs the Clang Formatter in parallel on the code base.
# Return codes:
# - 1 there are files to be formatted
# - 0 everything looks fine
# Get CPU count
OS=$(uname)
NPROC=1
if [[ $OS = "Linux" || $OS = "Darwin" ]] ; then
NPROC=$(getconf _NPROCESSORS_ONLN)
fi
# Discover clang-format
if type clang-format-8 2> /dev/null ; then
CLANG_FORMAT=clang-format-8
else
CLANG_FORMAT=clang-format
fi
find .. -type d \( -path ./deps \
-o -path ./cmake \
-o -path ./build \) -prune -type f -o -name '*.h' -or -name '*.hpp' -or -name '*.m' -or -name '*.mm' -or -name '*.c' -or -name '*.cpp' \
| xargs -L100 -P${NPROC} ${CLANG_FORMAT} -i -style=file -fallback-style=none

View File

@@ -2,12 +2,6 @@ cmake_minimum_required(VERSION 3.5)
project(advanced-scene-switcher)
# generate version info
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/version.cpp" @ONLY)
if(BUILD_OUT_OF_TREE)
# out of tree builds
# credits to c3r1c3
@@ -54,7 +48,6 @@ if(BUILD_OUT_OF_TREE)
src/headers/switch-window.hpp
src/headers/switch-sequence.hpp
src/headers/switch-generic.hpp
src/headers/version.h
)
set(advanced-scene-switcher_SOURCES
@@ -80,7 +73,6 @@ if(BUILD_OUT_OF_TREE)
src/switch-generic.cpp
src/curl-helper.cpp
src/volume-control.cpp
src/version.cpp
)
set(advanced-scene-switcher_UI
@@ -206,7 +198,6 @@ else ()
src/headers/switch-window.hpp
src/headers/switch-sequence.hpp
src/headers/switch-generic.hpp
src/headers/version.h
)
set(advanced-scene-switcher_SOURCES
@@ -232,7 +223,6 @@ else ()
src/switch-generic.cpp
src/curl-helper.cpp
src/volume-control.cpp
src/version.cpp
)
set(advanced-scene-switcher_UI

View File

@@ -3,7 +3,7 @@ An automated scene switcher for OBS Studio
More information can be found on https://obsproject.com/forum/resources/automatic-scene-switching.395/
## Compiling in tree (recommended)
## Compiling in tree
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
```
cd obs-studio/UI/frontend-plugins/

View File

@@ -1,279 +0,0 @@
# - Returns a version string from Git
#
# These functions force a re-configure on each git commit so that you can
# trust the values of the variables in your build system.
#
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
#
# Returns the refspec and sha hash of the current head revision
#
# git_describe(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe on the source tree, and adjusting
# the output so that it tests false if an error occurs.
#
# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe on the working tree (--dirty option),
# and adjusting the output so that it tests false if an error occurs.
#
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe --exact-match on the source tree,
# and adjusting the output so that it tests false if there was no exact
# matching tag.
#
# git_local_changes(<var>)
#
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
# Uses the return code of "git diff-index --quiet HEAD --".
# Does not regard untracked files.
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
# http://academic.cleardefinition.com
#
# Copyright 2009-2013, Iowa State University.
# Copyright 2013-2020, Ryan Pavlik
# Copyright 2013-2020, Contributors
# SPDX-License-Identifier: BSL-1.0
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
if(__get_git_revision_description)
return()
endif()
set(__get_git_revision_description YES)
# We must run the following at "include" time, not at function call time,
# to find the path to this module rather than the path to a calling list file
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
# Function _git_find_closest_git_dir finds the next closest .git directory
# that is part of any directory in the path defined by _start_dir.
# The result is returned in the parent scope variable whose name is passed
# as variable _git_dir_var. If no .git directory can be found, the
# function returns an empty string via _git_dir_var.
#
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
# neither foo nor bar contain a file/directory .git. This wil return
# C:/bla/.git
#
function(_git_find_closest_git_dir _start_dir _git_dir_var)
set(cur_dir "${_start_dir}")
set(git_dir "${_start_dir}/.git")
while(NOT EXISTS "${git_dir}")
# .git dir not found, search parent directories
set(git_previous_parent "${cur_dir}")
get_filename_component(cur_dir ${cur_dir} DIRECTORY)
if(cur_dir STREQUAL git_previous_parent)
# We have reached the root directory, we are not in git
set(${_git_dir_var}
""
PARENT_SCOPE)
return()
endif()
set(git_dir "${cur_dir}/.git")
endwhile()
set(${_git_dir_var}
"${git_dir}"
PARENT_SCOPE)
endfunction()
function(get_git_head_revision _refspecvar _hashvar)
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
if(NOT "${GIT_DIR}" STREQUAL "")
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
"${GIT_DIR}")
if("${_relative_to_source_dir}" MATCHES "[.][.]")
# We've gone above the CMake root dir.
set(GIT_DIR "")
endif()
endif()
if("${GIT_DIR}" STREQUAL "")
set(${_refspecvar}
"GITDIR-NOTFOUND"
PARENT_SCOPE)
set(${_hashvar}
"GITDIR-NOTFOUND"
PARENT_SCOPE)
return()
endif()
# Check if the current source dir is a git submodule or a worktree.
# In both cases .git is a file instead of a directory.
#
if(NOT IS_DIRECTORY ${GIT_DIR})
# The following git command will return a non empty string that
# points to the super project working tree if the current
# source dir is inside a git submodule.
# Otherwise the command will return an empty string.
#
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse
--show-superproject-working-tree
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT "${out}" STREQUAL "")
# If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
file(READ ${GIT_DIR} submodule)
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
${submodule})
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
ABSOLUTE)
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
else()
# GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
file(READ ${GIT_DIR} worktree_ref)
# The .git directory contains a path to the worktree information directory
# inside the parent git repo of the worktree.
#
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
${worktree_ref})
string(STRIP ${git_worktree_dir} git_worktree_dir)
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
endif()
else()
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}")
endif()
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
return()
endif()
set(HEAD_FILE "${GIT_DATA}/HEAD")
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
"${GIT_DATA}/grabRef.cmake" @ONLY)
include("${GIT_DATA}/grabRef.cmake")
set(${_refspecvar}
"${HEAD_REF}"
PARENT_SCOPE)
set(${_hashvar}
"${HEAD_HASH}"
PARENT_SCOPE)
endfunction()
function(git_describe _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
# TODO sanitize
#if((${ARGN}" MATCHES "&&") OR
# (ARGN MATCHES "||") OR
# (ARGN MATCHES "\\;"))
# message("Please report the following error to the project!")
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
#endif()
#message(STATUS "Arguments to execute_process: ${ARGN}")
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_describe_working_tree _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)
git_describe(out --exact-match ${ARGN})
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_local_changes _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(res EQUAL 0)
set(${_var}
"CLEAN"
PARENT_SCOPE)
else()
set(${_var}
"DIRTY"
PARENT_SCOPE)
endif()
endfunction()

View File

@@ -1,41 +0,0 @@
#
# Internal file for GetGitRevisionDescription.cmake
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
set(HEAD_HASH)
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
if(HEAD_CONTENTS MATCHES "ref")
# named branch
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
else()
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
set(HEAD_HASH "${CMAKE_MATCH_1}")
endif()
endif()
else()
# detached HEAD
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
endif()
if(NOT HEAD_HASH)
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
string(STRIP "${HEAD_HASH}" HEAD_HASH)
endif()

View File

@@ -1,3 +0,0 @@
#include "src/headers/version.h"
#define GIT_SHA1 "@GIT_SHA1@"
const char g_GIT_SHA1[] = GIT_SHA1;

View File

@@ -289,23 +289,13 @@
</sizepolicy>
</property>
<property name="text">
<string>If no switch condition is met for</string>
<string>If no switch condition is met</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="noMatchDelay">
<property name="suffix">
<string>s</string>
</property>
<property name="maximum">
<double>999999.989999999990687</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@@ -596,6 +586,13 @@
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="close">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="transitionsTab">
@@ -1175,7 +1172,7 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="windowTitleTab">
<widget class="QWidget" name="titleTab">
<attribute name="title">
<string notr="true">Title</string>
</attribute>
@@ -2627,7 +2624,7 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="idleTab">
<widget class="QWidget" name="IdleTab">
<attribute name="title">
<string notr="true">Idle</string>
</attribute>
@@ -3179,13 +3176,6 @@
</widget>
</widget>
</item>
<item>
<widget class="QPushButton" name="close">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>

View File

@@ -9,7 +9,6 @@
#include "headers/advanced-scene-switcher.hpp"
#include "headers/curl-helper.hpp"
#include "headers/version.h"
SwitcherData *switcher = nullptr;
@@ -329,49 +328,34 @@ void SwitcherData::Thread()
{
blog(LOG_INFO, "started");
int sleep = 0;
std::chrono::milliseconds duration;
auto startTime = std::chrono::high_resolution_clock::now();
auto endTime = std::chrono::high_resolution_clock::now();
while (true) {
startLoop:
std::unique_lock<std::mutex> lock(m);
bool match = false;
OBSWeakSource scene;
OBSWeakSource transition;
bool defTransitionMatch = false;
OBSWeakSource defTransition;
endTime = std::chrono::high_resolution_clock::now();
auto runTime =
std::chrono::duration_cast<std::chrono::milliseconds>(
endTime - startTime);
if (sleep) {
std::chrono::milliseconds duration;
if (sleep > interval) {
duration = std::chrono::milliseconds(sleep);
if (verbose)
blog(LOG_INFO, "sleep for %d", sleep);
} else {
duration =
std::chrono::milliseconds(interval) - runTime;
if (duration.count() < 0)
duration = std::chrono::milliseconds(0);
duration = std::chrono::milliseconds(interval);
if (verbose)
blog(LOG_INFO, "sleep for %d", interval);
}
//sleep for a bit
if (verbose)
blog(LOG_INFO, "sleep for %d", duration.count());
cv.wait_for(lock, duration);
startTime = std::chrono::high_resolution_clock::now();
sleep = 0;
switcher->Prune();
writeSceneInfoToFile();
//sleep for a bit
cv.wait_for(lock, duration);
if (switcher->stop) {
break;
}
setDefaultSceneTransitions();
if (autoStopEnable) {
autoStopStreamAndRecording();
}
@@ -384,8 +368,6 @@ void SwitcherData::Thread()
continue;
}
checkDefaultSceneTransitions(defTransitionMatch, defTransition);
for (int switchFuncName : functionNamesByPriority) {
switch (switchFuncName) {
case read_file_func:
@@ -399,6 +381,7 @@ void SwitcherData::Thread()
case exe_func:
checkExeSwitch(match, scene, transition);
break;
case screen_region_func:
checkScreenRegionSwitch(match, scene,
transition);
@@ -410,6 +393,10 @@ void SwitcherData::Thread()
case round_trip_func:
checkSceneSequence(match, scene, transition,
lock);
if (sceneChangedDuringWait()) //scene might have changed during the sleep
{
goto startLoop;
}
break;
case media_func:
checkMediaSwitch(match, scene, transition);
@@ -430,44 +417,44 @@ void SwitcherData::Thread()
}
}
checkNoMatchSwitch(match, scene, transition, sleep);
// After this point we will call frontend functions
// obs_frontend_set_current_scene() and
// obs_frontend_set_current_transition()
//
// During this time SaveSceneSwitcher() could be called
// leading to a deadlock, so we have to unlock()
lock.unlock();
if (!match && defTransitionMatch) {
setCurrentDefTransition(defTransition);
if (!match && switchIfNotMatching == SWITCH &&
nonMatchingScene) {
match = true;
scene = nonMatchingScene;
transition = nullptr;
}
if (!match && switchIfNotMatching == RANDOM_SWITCH) {
checkRandom(match, scene, transition, sleep);
}
if (match) {
switchScene(scene, transition,
tansitionOverrideOverride);
tansitionOverrideOverride, lock);
}
writeSceneInfoToFile();
}
endLoop:
blog(LOG_INFO, "stopped");
}
void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
bool &transitionOverrideOverride)
bool &transitionOverrideOverride,
std::unique_lock<std::mutex> &lock)
{
obs_source_t *source = obs_weak_source_get_source(scene);
obs_source_t *currentSource = obs_frontend_get_current_scene();
if (source && source != currentSource) {
// this call might block when OBS_FRONTEND_EVENT_SCENE_CHANGED is active and mutex is held
// thus unlock mutex to avoid deadlock
lock.unlock();
transitionData td;
setNextTransition(scene, currentSource, transition,
transitionOverrideOverride, td);
obs_frontend_set_current_scene(source);
if (transitionOverrideOverride)
restoreTransitionOverride(source, td);
lock.lock();
if (switcher->verbose)
blog(LOG_INFO, "switched scene");
@@ -476,6 +463,18 @@ void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
obs_source_release(source);
}
bool SwitcherData::sceneChangedDuringWait()
{
bool r = false;
obs_source_t *currentSource = obs_frontend_get_current_scene();
if (!currentSource)
return true;
obs_source_release(currentSource);
if (waitScene && currentSource != waitScene)
r = true;
return r;
}
void SwitcherData::Start()
{
if (!(th && th->isRunning())) {
@@ -498,15 +497,6 @@ void SwitcherData::Stop()
}
}
bool SwitcherData::sceneChangedDuringWait()
{
obs_source_t *currentSource = obs_frontend_get_current_scene();
if (!currentSource)
return true;
obs_source_release(currentSource);
return (waitScene && currentSource != waitScene);
}
/********************************************************************************
* OBS module setup
********************************************************************************/
@@ -525,6 +515,7 @@ extern "C" void FreeSceneSwitcher()
void handleSceneChange(SwitcherData *s)
{
std::lock_guard<std::mutex> lock(s->m);
//stop waiting if scene was manually changed
if (s->sceneChangedDuringWait())
s->cv.notify_one();
@@ -534,18 +525,14 @@ void handleSceneChange(SwitcherData *s)
obs_weak_source_t *ws = obs_source_get_weak_source(source);
obs_source_release(source);
obs_weak_source_release(ws);
if (source && s->previousScene2 != ws) {
s->previousScene = s->previousScene2;
s->previousScene2 = ws;
if (source && s->PreviousScene2 != ws) {
s->previousScene = s->PreviousScene2;
s->PreviousScene2 = ws;
}
//reset events only hanled on scene change
s->autoStartedRecently = false;
}
void handleTransitionStop(SwitcherData *s)
{
s->checkedDefTransition = false;
s->changedDefTransitionRecently = false;
}
void setLiveTime(SwitcherData *s)
@@ -558,9 +545,6 @@ void resetLiveTime(SwitcherData *s)
s->liveTime = QDateTime();
}
// Note to future self:
// be careful using switcher->m here as there is potential for deadlocks when using
// frontend functions such as obs_frontend_set_current_scene()
static void OBSEvent(enum obs_frontend_event event, void *switcher)
{
switch (event) {
@@ -570,9 +554,6 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
handleSceneChange((SwitcherData *)switcher);
break;
case OBS_FRONTEND_EVENT_TRANSITION_STOPPED:
handleTransitionStop((SwitcherData *)switcher);
break;
case OBS_FRONTEND_EVENT_RECORDING_STARTED:
case OBS_FRONTEND_EVENT_STREAMING_STARTED:
setLiveTime((SwitcherData *)switcher);
@@ -588,8 +569,6 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
extern "C" void InitSceneSwitcher()
{
blog(LOG_INFO, "version: %s", g_GIT_SHA1);
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
"Advanced Scene Switcher");

View File

@@ -43,8 +43,7 @@ bool loadCurl()
#endif
for (QString path : locations) {
blog(LOG_INFO, "[adv-ss] trying '%s'",
path.toUtf8().constData());
blog(LOG_INFO, "[adv-ss] trying '%s'", path.toUtf8().constData());
QFileInfo libPath(
QDir(path).absoluteFilePath(curl_library_name));

View File

@@ -56,14 +56,6 @@ void AdvSceneSwitcher::on_noMatchRandomSwitch_clicked()
ui->randomDisabledWarning->setVisible(false);
}
void AdvSceneSwitcher::on_noMatchDelay_valueChanged(double i)
{
if (loading)
return;
std::lock_guard<std::mutex> lock(switcher->m);
switcher->noMatchDelay = i;
}
void AdvSceneSwitcher::on_startupBehavior_currentIndexChanged(int index)
{
if (loading)
@@ -166,18 +158,10 @@ void SwitcherData::autoStopStreamAndRecording()
obs_weak_source_t *ws = obs_source_get_weak_source(currentSource);
if (ws && autoStopScene == ws) {
if (obs_frontend_streaming_active()) {
blog(LOG_INFO,
"Stopping stream because scene '%s' is active",
obs_source_get_name(currentSource));
if (obs_frontend_streaming_active())
obs_frontend_streaming_stop();
}
if (obs_frontend_recording_active()) {
blog(LOG_INFO,
"Stopping record because scene '%s' is active",
obs_source_get_name(currentSource));
if (obs_frontend_recording_active())
obs_frontend_recording_stop();
}
}
obs_source_release(currentSource);
obs_weak_source_release(ws);
@@ -242,20 +226,12 @@ void SwitcherData::autoStartStreamRecording()
if (ws && autoStartScene == ws) {
if ((switcher->autoStartType == STREAMING ||
switcher->autoStartType == RECORINDGSTREAMING) &&
!obs_frontend_streaming_active()) {
blog(LOG_INFO,
"Starting stream because scene '%s' is active",
obs_source_get_name(currentSource));
!obs_frontend_streaming_active())
obs_frontend_streaming_start();
}
if ((switcher->autoStartType == RECORDING ||
switcher->autoStartType == RECORINDGSTREAMING) &&
!obs_frontend_recording_active()) {
blog(LOG_INFO,
"Starting record because scene '%s' is active",
obs_source_get_name(currentSource));
!obs_frontend_recording_active())
obs_frontend_recording_start();
}
}
obs_source_release(currentSource);
obs_weak_source_release(ws);
@@ -361,56 +337,58 @@ void AdvSceneSwitcher::on_importSettings_clicked()
close();
}
int findTabIndex(QTabWidget *tabWidget, int pos)
int findTabIndex(QTabBar *bar, int pos)
{
int at = -1;
QString tabName = "";
switch (pos) {
case 0:
tabName = "generalTab";
tabName = "General";
break;
case 1:
tabName = "transitionsTab";
tabName = "Transition";
break;
case 2:
tabName = "pauseScenesTab";
tabName = "Pause";
break;
case 3:
tabName = "windowTitleTab";
tabName = "Title";
break;
case 4:
tabName = "executableTab";
tabName = "Executable";
break;
case 5:
tabName = "screenRegionTab";
tabName = "Region";
break;
case 6:
tabName = "mediaTab";
tabName = "Media";
break;
case 7:
tabName = "fileTab";
tabName = "File";
break;
case 8:
tabName = "randomTab";
tabName = "Random";
break;
case 9:
tabName = "timeTab";
tabName = "Time";
break;
case 10:
tabName = "idleTab";
tabName = "Idle";
break;
case 11:
tabName = "sceneSequenceTab";
tabName = "Sequence";
break;
case 12:
tabName = "audioTab";
tabName = "Audio";
break;
}
QWidget *page = tabWidget->findChild<QWidget *>(tabName);
if (page) {
at = tabWidget->indexOf(page);
for (int i = 0; i < bar->count(); ++i) {
if (bar->tabText(i).compare(tabName) == 0) {
at = i;
break;
}
}
if (at == -1)
blog(LOG_INFO, "failed to find tab %s",
@@ -423,7 +401,7 @@ void AdvSceneSwitcher::setTabOrder()
{
QTabBar *bar = ui->tabWidget->tabBar();
for (int i = 0; i < bar->count(); ++i) {
int curPos = findTabIndex(ui->tabWidget, switcher->tabOrder[i]);
int curPos = findTabIndex(bar, switcher->tabOrder[i]);
if (i != curPos && curPos != -1)
bar->moveTab(curPos, i);
@@ -439,15 +417,6 @@ void AdvSceneSwitcher::on_tabMoved(int from, int to)
std::swap(switcher->tabOrder[from], switcher->tabOrder[to]);
}
void AdvSceneSwitcher::on_tabWidget_currentChanged(int index)
{
UNUSED_PARAMETER(index);
switcher->showFrame = false;
clearFrames(ui->screenRegionSwitches);
SetShowFrames();
}
void SwitcherData::saveGeneralSettings(obs_data_t *obj)
{
obs_data_set_int(obj, "interval", switcher->interval);
@@ -458,7 +427,6 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
nonMatchingSceneName.c_str());
obs_data_set_int(obj, "switch_if_not_matching",
switcher->switchIfNotMatching);
obs_data_set_double(obj, "noMatchDelay", switcher->noMatchDelay);
obs_data_set_bool(obj, "active", !switcher->stop);
obs_data_set_int(obj, "startup_behavior", switcher->startupBehavior);
@@ -500,14 +468,6 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
obs_data_set_int(obj, "threadPriority", switcher->threadPriority);
// After fresh install of OBS the vector can be empty
// as save() might be called before first load()
if (switcher->tabOrder.size() < 13) {
switcher->tabOrder = std::vector<int>(13);
std::iota(switcher->tabOrder.begin(), switcher->tabOrder.end(),
0);
}
obs_data_set_int(obj, "generalTabPos", switcher->tabOrder[0]);
obs_data_set_int(obj, "transitionTabPos", switcher->tabOrder[1]);
obs_data_set_int(obj, "pauseTabPos", switcher->tabOrder[2]);
@@ -535,7 +495,6 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
obs_data_get_string(obj, "non_matching_scene");
switcher->nonMatchingScene =
GetWeakSourceByName(nonMatchingScene.c_str());
switcher->noMatchDelay = obs_data_get_double(obj, "noMatchDelay");
switcher->stop = !obs_data_get_bool(obj, "active");
switcher->startupBehavior =
@@ -646,29 +605,6 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
(int)(obs_data_get_int(obj, "audioTabPos")));
}
void SwitcherData::checkNoMatchSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition, int &sleep)
{
if (match) {
noMatchCount = 0;
return;
}
if ((noMatchCount * interval) / 1000.0 < noMatchDelay) {
noMatchCount++;
return;
}
if (switchIfNotMatching == SWITCH && nonMatchingScene) {
match = true;
scene = nonMatchingScene;
transition = nullptr;
}
if (switchIfNotMatching == RANDOM_SWITCH) {
checkRandom(match, scene, transition, sleep);
}
}
void AdvSceneSwitcher::setupGeneralTab()
{
populateSceneSelection(ui->noMatchSwitchScene, false);
@@ -687,9 +623,6 @@ void AdvSceneSwitcher::setupGeneralTab()
}
ui->noMatchSwitchScene->setCurrentText(
GetWeakSourceName(switcher->nonMatchingScene).c_str());
ui->noMatchDelay->setValue(switcher->noMatchDelay);
ui->noMatchDelay->setToolTip(
"Will only ever be as accurate as the configured check interval.");
ui->checkInterval->setValue(switcher->interval);
ui->autoStopSceneCheckBox->setChecked(switcher->autoStopEnable);

View File

@@ -27,10 +27,6 @@ public:
void SetStarted();
void SetStopped();
void SetShowFrames();
void SetHideFrames();
void clearFrames(QListWidget *list);
int PauseScenesFindByData(const QString &scene);
int PauseWindowsFindByData(const QString &window);
int IgnoreWindowsFindByData(const QString &window);
@@ -86,13 +82,11 @@ public slots:
void on_noMatchDontSwitch_clicked();
void on_noMatchSwitch_clicked();
void on_noMatchRandomSwitch_clicked();
void on_noMatchDelay_valueChanged(double i);
void on_startupBehavior_currentIndexChanged(int index);
void on_noMatchSwitchScene_currentTextChanged(const QString &text);
void on_checkInterval_valueChanged(int value);
void on_toggleStartButton_clicked();
void on_tabMoved(int from, int to);
void on_tabWidget_currentChanged(int index);
void on_screenRegionSwitches_currentRowChanged(int idx);
void on_showFrame_clicked();
@@ -227,6 +221,13 @@ bool isInFocus(const QString &executable);
/********************************************************************************
* Sceneswitch helper
********************************************************************************/
struct obs_weak_source;
typedef struct obs_weak_source obs_weak_source_t;
typedef struct transitionData {
std::string name = "";
int duration = 0;
} transitionData;
void setNextTransition(OBSWeakSource &targetScene, obs_source_t *currentSource,
OBSWeakSource &transition,
@@ -234,8 +235,10 @@ void setNextTransition(OBSWeakSource &targetScene, obs_source_t *currentSource,
void overwriteTransitionOverride(obs_weak_source_t *sceneWs,
obs_source_t *transition, transitionData &td);
void restoreTransitionOverride(obs_source_t *scene, transitionData td);
void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
bool &transitionOverrideOverride);
bool &transitionOverrideOverride,
std::unique_lock<std::mutex> &lock);
/********************************************************************************
* Main SwitcherData

View File

@@ -18,18 +18,12 @@ struct MediaSwitch : SceneSwitcherEntry {
bool anyState = false;
time_restriction restriction = TIME_RESTRICTION_NONE;
int64_t time = 0;
// trigger scene change only once even if media state might trigger repeatedly
bool matched = false;
std::atomic<bool> stopped = false;
std::atomic<bool> ended = false;
// workaround to enable use of "ended" to specify end of VLC playlist
bool previousStateEnded = false;
bool playedToEnd = false;
const char *getType() { return "media"; }
bool initialized();
bool valid();

View File

@@ -30,12 +30,6 @@ typedef enum {
RECORINDGSTREAMING = 2
} AutoStartType;
typedef struct transitionData {
std::string name = "";
int duration = 0;
} transitionData;
class SwitcherThread;
/********************************************************************************
@@ -57,14 +51,12 @@ struct SwitcherData {
int interval = default_interval;
obs_source_t *waitScene = nullptr;
OBSWeakSource previousScene = nullptr;
OBSWeakSource previousScene2 = nullptr;
obs_source_t *waitScene = NULL;
OBSWeakSource previousScene = NULL;
OBSWeakSource PreviousScene2 = NULL;
OBSWeakSource lastRandomScene;
OBSWeakSource nonMatchingScene;
NoMatch switchIfNotMatching = NO_SWITCH;
double noMatchDelay;
double noMatchCount = 0;
StartupBehavior startupBehavior = PERSIST;
std::deque<WindowSwitch> windowSwitches;
@@ -101,7 +93,7 @@ struct SwitcherData {
std::deque<SceneTransition> sceneTransitions;
std::deque<DefaultSceneTransition> defaultSceneTransitions;
bool checkedDefTransition = false;
bool changedDefTransitionRecently = false;
std::deque<MediaSwitch> mediaSwitches;
@@ -145,9 +137,9 @@ struct SwitcherData {
std::vector<int> tabOrder;
bool hotkeysRegistered = false;
obs_hotkey_id startHotkey = 0;
obs_hotkey_id stopHotkey = 0;
obs_hotkey_id toggleHotkey = 0;
obs_hotkey_id startHotkey;
obs_hotkey_id stopHotkey;
obs_hotkey_id toggleHotkey;
void Thread();
void Start();
@@ -156,12 +148,10 @@ struct SwitcherData {
bool sceneChangedDuringWait();
bool prioFuncsValid();
void writeSceneInfoToFile();
void setDefaultSceneTransitions();
void autoStopStreamAndRecording();
void autoStartStreamRecording();
bool checkPause();
void checkDefaultSceneTransitions(bool &match,
OBSWeakSource &transition);
void setCurrentDefTransition(OBSWeakSource &transition);
void checkSceneSequence(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition,
std::unique_lock<std::mutex> &lock);
@@ -185,8 +175,6 @@ struct SwitcherData {
OBSWeakSource &transition);
void checkAudioSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition);
void checkNoMatchSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition, int &sleep);
void saveWindowTitleSwitches(obs_data_t *obj);
void saveScreenRegionSwitches(obs_data_t *obj);
@@ -219,7 +207,6 @@ struct SwitcherData {
void loadHotkeys(obs_data_t *obj);
void Prune();
inline ~SwitcherData() { Stop(); }
};

View File

@@ -1 +0,0 @@
extern const char g_GIT_SHA1[];

View File

@@ -17,16 +17,15 @@ void GetWindowList(std::vector<std::string> &windows)
for (NSDictionary *app in apps) {
// Construct string from NSString accounting for nil
std::string name([[app objectForKey:@"kCGWindowName"]
UTF8String],
[[app objectForKey:@"kCGWindowName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
std::string owner(
[[app objectForKey:@"kCGWindowOwnerName"]
UTF8String],
[[app objectForKey:@"kCGWindowOwnerName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
UTF8String],
[[app objectForKey:@"kCGWindowName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
std::string owner([[app objectForKey:@"kCGWindowOwnerName"]
UTF8String],
[[app objectForKey:@"kCGWindowOwnerName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
// Check if name exists
if (!name.empty() &&
@@ -54,16 +53,15 @@ void GetWindowList(QStringList &windows)
for (NSDictionary *app in apps) {
// Construct string from NSString accounting for nil
std::string name([[app objectForKey:@"kCGWindowName"]
UTF8String],
[[app objectForKey:@"kCGWindowName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
std::string owner(
[[app objectForKey:@"kCGWindowOwnerName"]
UTF8String],
[[app objectForKey:@"kCGWindowOwnerName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
UTF8String],
[[app objectForKey:@"kCGWindowName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
std::string owner([[app objectForKey:@"kCGWindowOwnerName"]
UTF8String],
[[app objectForKey:@"kCGWindowOwnerName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
// Check if name exists
if (!name.empty() &&
@@ -146,16 +144,15 @@ bool isFullscreen(std::string &title)
for (NSDictionary *app in apps) {
// Construct string from NSString accounting for nil
std::string name([[app objectForKey:@"kCGWindowName"]
UTF8String],
[[app objectForKey:@"kCGWindowName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
std::string owner(
[[app objectForKey:@"kCGWindowOwnerName"]
UTF8String],
[[app objectForKey:@"kCGWindowOwnerName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
UTF8String],
[[app objectForKey:@"kCGWindowName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
std::string owner([[app objectForKey:@"kCGWindowOwnerName"]
UTF8String],
[[app objectForKey:@"kCGWindowOwnerName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
// True if switch equals app
bool equals = (title == name || title == owner);

View File

@@ -17,9 +17,8 @@ void SceneSwitcherEntry::logMatch()
{
const char *sceneName = previous_scene_name;
if (!usePreviousScene) {
obs_source_t *s = obs_weak_source_get_source(scene);
OBSSource s = obs_weak_source_get_source(scene);
sceneName = obs_source_get_name(s);
obs_source_release(s);
}
blog(LOG_INFO, "match for '%s' - switch to scene '%s'", getType(),
sceneName);
@@ -75,8 +74,6 @@ void SwitchWidget::SceneChanged(const QString &text)
return;
std::lock_guard<std::mutex> lock(switcher->m);
switchData->usePreviousScene = text.compare(previous_scene_name) == 0;
if (switchData->usePreviousScene)
return;
switchData->scene = GetWeakSourceByQString(text);
}

View File

@@ -3,9 +3,6 @@
static QMetaObject::Connection addPulse;
constexpr auto media_played_to_end_idx = 8;
constexpr auto media_any_idx = 9;
void AdvSceneSwitcher::on_mediaAdd_clicked()
{
ui->mediaAdd->disconnect(addPulse);
@@ -113,41 +110,22 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
// bool matchedEnded = mediaSwitch.state == OBS_MEDIA_STATE_ENDED &&
// mediaSwitch.ended;
bool ended = false;
bool matchedEnded = false;
if (state == OBS_MEDIA_STATE_ENDED) {
ended = mediaSwitch.previousStateEnded;
matchedEnded = mediaSwitch.previousStateEnded;
mediaSwitch.previousStateEnded = true;
} else {
mediaSwitch.previousStateEnded = false;
}
bool matchedEnded =
ended && (mediaSwitch.state == OBS_MEDIA_STATE_ENDED);
// match if playedToEnd was true in last interval
// and playback is currently ended
bool matchedPlayedToEnd = mediaSwitch.state ==
media_played_to_end_idx &&
mediaSwitch.playedToEnd && ended;
// interval * 2 to make sure not to miss any state changes
// which happened during check of the conditions
mediaSwitch.playedToEnd = mediaSwitch.playedToEnd ||
(duration - time <= interval * 2);
// reset
if (ended)
mediaSwitch.playedToEnd = false;
// reset for next check
mediaSwitch.stopped = false;
mediaSwitch.ended = false;
bool matchedState = ((state == mediaSwitch.state) ||
mediaSwitch.anyState) ||
matchedStopped || matchedEnded ||
matchedPlayedToEnd;
matchedStopped || matchedEnded;
bool matchedTimeNone =
(mediaSwitch.restriction == TIME_RESTRICTION_NONE);
@@ -173,7 +151,7 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
bool matched = matchedState && matchedTime;
if (matched && !mediaSwitch.matched) {
if (matched) {
match = true;
scene = (mediaSwitch.usePreviousScene)
? previousScene
@@ -182,12 +160,8 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
if (verbose)
mediaSwitch.logMatch();
}
mediaSwitch.matched = matched;
if (match)
break;
}
}
}
@@ -330,7 +304,7 @@ inline MediaSwitch::MediaSwitch(OBSWeakSource scene_, OBSWeakSource source_,
restriction(restriction_),
time(time_)
{
anyState = state == media_any_idx;
anyState = state > 7;
obs_source_t *mediasource = obs_weak_source_get_source(source);
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
signal_handler_connect(sh, "media_stopped", MediaStopped, this);
@@ -346,7 +320,7 @@ MediaSwitch::MediaSwitch(const MediaSwitch &other)
restriction(other.restriction),
time(other.time)
{
anyState = state == media_any_idx;
anyState = state > 7;
obs_source_t *mediasource = obs_weak_source_get_source(source);
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
signal_handler_connect(sh, "media_stopped", MediaStopped, this);
@@ -359,9 +333,9 @@ MediaSwitch::MediaSwitch(MediaSwitch &&other)
other.usePreviousScene),
source(other.source),
state(other.state),
anyState(other.anyState),
restriction(other.restriction),
time(other.time)
time(other.time),
anyState(other.anyState)
{
}
@@ -422,7 +396,6 @@ void populateMediaStates(QComboBox *list)
list->addItem("Stopped");
list->addItem("Ended");
list->addItem("Error");
list->addItem("Played to end");
list->addItem("Any");
}
@@ -536,7 +509,7 @@ void MediaSwitchWidget::StateChanged(int index)
return;
std::lock_guard<std::mutex> lock(switcher->m);
switchData->state = (obs_media_state)index;
switchData->anyState = switchData->state == media_any_idx;
switchData->anyState = switchData->state > 7;
}
void MediaSwitchWidget::TimeRestrictionChanged(int index)

View File

@@ -51,7 +51,7 @@ void SwitcherData::checkRandom(bool &match, OBSWeakSource &scene,
if (!r.initialized())
continue;
if (r.scene == lastRandomScene && randomSwitches.size() != 1)
if (r.scene == lastRandomScene)
continue;
scene = r.scene;
transition = r.transition;

View File

@@ -5,7 +5,7 @@
static QMetaObject::Connection addPulse;
void AdvSceneSwitcher::clearFrames(QListWidget *list)
void clearFrames(QListWidget *list)
{
for (int i = 0; i < list->count(); ++i) {
ScreenRegionWidget *sw =
@@ -25,32 +25,23 @@ void showCurrentFrame(QListWidget *list)
sw->showFrame();
}
void AdvSceneSwitcher::SetShowFrames()
{
ui->showFrame->setText("Show guide frames");
}
void AdvSceneSwitcher::SetHideFrames()
{
ui->showFrame->setText("Hide guide frames");
}
void AdvSceneSwitcher::on_showFrame_clicked()
{
switcher->showFrame = !switcher->showFrame;
if (switcher->showFrame) {
SetHideFrames();
ui->showFrame->setText("Hide guide frames");
showCurrentFrame(ui->screenRegionSwitches);
} else {
SetShowFrames();
ui->showFrame->setText("Show guide frames");
clearFrames(ui->screenRegionSwitches);
}
}
void AdvSceneSwitcher::on_screenRegionSwitches_currentRowChanged(int idx)
{
if (loading || idx == -1)
UNUSED_PARAMETER(idx);
if (loading)
return;
if (switcher->showFrame) {

View File

@@ -30,19 +30,10 @@ void AdvSceneSwitcher::on_sceneSequenceRemove_clicked()
return;
{
// might be in waiting state of sequence
// causing invalid access after wakeup
// thus we need to stop the main thread before delete
bool wasRunning = !switcher->stop;
switcher->Stop();
std::lock_guard<std::mutex> lock(switcher->m);
int idx = ui->sceneSequenceSwitches->currentRow();
auto &switches = switcher->sceneSequenceSwitches;
switches.erase(switches.begin() + idx);
if (wasRunning)
switcher->Start();
}
delete item;
@@ -108,6 +99,8 @@ void AdvSceneSwitcher::on_sceneSequenceSave_clicked()
void AdvSceneSwitcher::on_sceneSequenceLoad_clicked()
{
std::lock_guard<std::mutex> lock(switcher->m);
QString directory = QFileDialog::getOpenFileName(
this, tr("Select a file to read Scene Sequence from ..."),
QDir::currentPath(), tr("Text files (*.txt)"));
@@ -128,18 +121,7 @@ void AdvSceneSwitcher::on_sceneSequenceLoad_clicked()
Msgbox.exec();
return;
}
// might be in waiting state of sequence
// causing invalid access after wakeup
// thus we need to stop the main thread before delete
bool wasRunning = !switcher->stop;
switcher->Stop();
switcher->loadSceneSequenceSwitches(obj);
if (wasRunning)
switcher->Start();
obs_data_release(obj);
QMessageBox Msgbox;
@@ -183,10 +165,7 @@ void SwitcherData::checkSceneSequence(bool &match, OBSWeakSource &scene,
transition = s.transition;
if (verbose)
s.logMatch();
} else if (verbose) {
blog(LOG_INFO, "sequence canceled");
}
obs_source_release(currentSource2);
break;
}

View File

@@ -143,10 +143,9 @@ void AdvSceneSwitcher::on_defaultTransitionsDown_clicked()
switcher->defaultSceneTransitions[index + 1]);
}
void SwitcherData::checkDefaultSceneTransitions(bool &match,
OBSWeakSource &transition)
void SwitcherData::setDefaultSceneTransitions()
{
if (checkedDefTransition)
if (changedDefTransitionRecently)
return;
obs_source_t *currentSource = obs_frontend_get_current_scene();
@@ -157,25 +156,22 @@ void SwitcherData::checkDefaultSceneTransitions(bool &match,
if (!s.initialized())
continue;
match = true;
transition = s.transition;
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
//This might cancel the current transition
//There is no way to be sure when the previous transition finished
obs_frontend_set_current_transition(transition);
if (verbose)
s.logMatch();
obs_source_release(transition);
break;
}
}
obs_source_release(currentSource);
obs_weak_source_release(ws);
checkedDefTransition = true;
}
void SwitcherData::setCurrentDefTransition(OBSWeakSource &transition)
{
obs_source_t *transitionSource = obs_weak_source_get_source(transition);
obs_frontend_set_current_transition(transitionSource);
obs_source_release(transitionSource);
changedDefTransitionRecently = true;
}
void AdvSceneSwitcher::on_transitionOverridecheckBox_stateChanged(int state)

View File

@@ -89,9 +89,6 @@ void GetWindowList(QStringList &windows)
for (auto window : w) {
windows << QString::fromStdString(window);
}
// Add entry for OBS Studio itself, see GetCurrentWindowTitle
windows << QString("OBS");
}
void GetCurrentWindowTitle(std::string &title)
@@ -100,10 +97,10 @@ void GetCurrentWindowTitle(std::string &title)
DWORD pid;
DWORD thid;
thid = GetWindowThreadProcessId(window, &pid);
// GetWindowText will freeze if the control it is reading was created in another thread.
// It does not directly read the control.
// Instead it waits for the thread that created the control to process a WM_GETTEXT message.
// So if that thread is frozen in a WaitFor... call you have a deadlock.
/*GetWindowText will freeze if the control it is reading was created in another thread.
It does not directly read the control.Instead,
it waits for the thread that created the control to process a WM_GETTEXT message.
So if that thread is frozen in a WaitFor... call you have a deadlock.*/
if (GetCurrentProcessId() == pid) {
title = "OBS";
return;