mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-09-07 09:05:57 -05:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d023ee385 | ||
|
|
3fd3801e56 | ||
|
|
3ec1e99f4b | ||
|
|
21a788b48b | ||
|
|
a5c8d776f3 | ||
|
|
95261ce9bb |
16
.github/workflows/build.yml
vendored
16
.github/workflows/build.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
runs-on: [macos-latest]
|
runs-on: [macos-latest]
|
||||||
env:
|
env:
|
||||||
QT_VERSION: 5.14.1
|
QT_VERSION: 5.14.1
|
||||||
OSX_DEPS_VERSION: '2020-04-07'
|
MACOS_DEPS_VERSION: '2020-08-30'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
@@ -39,17 +39,25 @@ jobs:
|
|||||||
brew bundle
|
brew bundle
|
||||||
cd -
|
cd -
|
||||||
- name: 'Install prerequisite: Pre-built dependencies'
|
- name: 'Install prerequisite: Pre-built dependencies'
|
||||||
|
if: steps.deps-cache.outputs.cache-hit != 'true'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
curl -L -O https://github.com/obsproject/obs-deps/releases/download/${{ env.OSX_DEPS_VERSION }}/osx-deps-${{ env.OSX_DEPS_VERSION }}.tar.gz
|
curl -L -O https://github.com/obsproject/obs-deps/releases/download/${{ env.MACOS_DEPS_VERSION }}/macos-deps-${{ env.MACOS_DEPS_VERSION }}.tar.gz
|
||||||
tar -xf ./osx-deps-${{ env.OSX_DEPS_VERSION }}.tar.gz -C "/tmp"
|
tar -xf ./macos-deps-${{ env.MACOS_DEPS_VERSION }}.tar.gz -C "/tmp"
|
||||||
|
- name: 'Install prerequisite: Pre-built dependency Qt'
|
||||||
|
if: steps.deps-qt-cache.outputs.cache-hit != 'true'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
curl -L -O https://github.com/obsproject/obs-deps/releases/download/${{ env.MACOS_DEPS_VERSION }}/macos-qt-${{ env.QT_VERSION }}-${{ env.MACOS_DEPS_VERSION }}.tar.gz
|
||||||
|
tar -xf ./macos-qt-${{ env.QT_VERSION }}-${{ env.MACOS_DEPS_VERSION }}.tar.gz -C "/tmp"
|
||||||
|
xattr -r -d com.apple.quarantine /tmp/obsdeps
|
||||||
- name: Configure
|
- name: Configure
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
echo "add_subdirectory(${{ env.PLUGIN_NAME }})" >> UI/frontend-plugins/CMakeLists.txt
|
echo "add_subdirectory(${{ env.PLUGIN_NAME }})" >> UI/frontend-plugins/CMakeLists.txt
|
||||||
mkdir ./build
|
mkdir ./build
|
||||||
cd ./build
|
cd ./build
|
||||||
cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 -DDepsPath="/tmp/obsdeps" -DQTDIR="/usr/local/Cellar/qt/${{ env.QT_VERSION }}" ..
|
cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 -DDISABLE_PYTHON=ON -DDepsPath="/tmp/obsdeps" -DQTDIR="/tmp/obsdeps" ..
|
||||||
cd -
|
cd -
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -3,4 +3,3 @@ brew "speexdsp"
|
|||||||
brew "cmake"
|
brew "cmake"
|
||||||
brew "freetype"
|
brew "freetype"
|
||||||
brew "fdk-aac"
|
brew "fdk-aac"
|
||||||
brew "https://gist.githubusercontent.com/DDRBoxman/9c7a2b08933166f4b61ed9a44b242609/raw/ef4de6c587c6bd7f50210eccd5bd51ff08e6de13/qt.rb"
|
|
||||||
@@ -35,6 +35,7 @@ if(BUILD_OUT_OF_TREE)
|
|||||||
src/headers/advanced-scene-switcher.hpp
|
src/headers/advanced-scene-switcher.hpp
|
||||||
src/headers/switcher-data-structs.hpp
|
src/headers/switcher-data-structs.hpp
|
||||||
src/headers/utility.hpp
|
src/headers/utility.hpp
|
||||||
|
src/headers/curl-helper.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(advanced-scene-switcher_SOURCES
|
set(advanced-scene-switcher_SOURCES
|
||||||
@@ -55,6 +56,7 @@ if(BUILD_OUT_OF_TREE)
|
|||||||
src/pause-switch.cpp
|
src/pause-switch.cpp
|
||||||
src/random.cpp
|
src/random.cpp
|
||||||
src/time-switch.cpp
|
src/time-switch.cpp
|
||||||
|
src/curl-helper.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(advanced-scene-switcher_UI
|
set(advanced-scene-switcher_UI
|
||||||
@@ -105,8 +107,7 @@ if(BUILD_OUT_OF_TREE)
|
|||||||
${LIBOBS_LIB}
|
${LIBOBS_LIB}
|
||||||
${LIBOBS_FRONTEND_API_LIB}
|
${LIBOBS_FRONTEND_API_LIB}
|
||||||
Qt5::Core
|
Qt5::Core
|
||||||
Qt5::Widgets
|
Qt5::Widgets)
|
||||||
${LIBCURL_LIBRARIES})
|
|
||||||
|
|
||||||
# Additional commands to install the module in the correct place.
|
# Additional commands to install the module in the correct place.
|
||||||
# Find all the translation files so we can copy them to the correct
|
# Find all the translation files so we can copy them to the correct
|
||||||
@@ -167,6 +168,8 @@ else ()
|
|||||||
src/headers/advanced-scene-switcher.hpp
|
src/headers/advanced-scene-switcher.hpp
|
||||||
src/headers/switcher-data-structs.hpp
|
src/headers/switcher-data-structs.hpp
|
||||||
src/headers/utility.hpp
|
src/headers/utility.hpp
|
||||||
|
src/headers/curl-helper.hpp
|
||||||
|
src/headers/volume-control.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(advanced-scene-switcher_SOURCES
|
set(advanced-scene-switcher_SOURCES
|
||||||
@@ -187,6 +190,9 @@ else ()
|
|||||||
src/pause-switch.cpp
|
src/pause-switch.cpp
|
||||||
src/random.cpp
|
src/random.cpp
|
||||||
src/time-switch.cpp
|
src/time-switch.cpp
|
||||||
|
src/audio-switch.cpp
|
||||||
|
src/curl-helper.cpp
|
||||||
|
src/volume-control.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(advanced-scene-switcher_UI
|
set(advanced-scene-switcher_UI
|
||||||
@@ -227,8 +233,7 @@ else ()
|
|||||||
${advanced-scene-switcher_PLATFORM_LIBS}
|
${advanced-scene-switcher_PLATFORM_LIBS}
|
||||||
obs-frontend-api
|
obs-frontend-api
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
libobs
|
libobs)
|
||||||
${LIBCURL_LIBRARIES})
|
|
||||||
|
|
||||||
install_obs_plugin(advanced-scene-switcher data)
|
install_obs_plugin(advanced-scene-switcher data)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -438,6 +438,69 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_50">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="autoStartSceneCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Automatically start</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="autoStartType">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_65">
|
||||||
|
<property name="text">
|
||||||
|
<string>on scene</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="autoStartScenes">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_55">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line_10">
|
<widget class="Line" name="line_10">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@@ -2341,7 +2404,7 @@
|
|||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string notr="true">File</string>
|
<string notr="true">File</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_14">
|
<layout class="QHBoxLayout" name="horizontalLayout_14">
|
||||||
<item>
|
<item>
|
||||||
@@ -2474,6 +2537,22 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="libcurlWarning">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Failed to load libcurl! Accesssing remote files will not be possible!</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPlainTextEdit" name="fileTextEdit"/>
|
<widget class="QPlainTextEdit" name="fileTextEdit"/>
|
||||||
</item>
|
</item>
|
||||||
@@ -2854,13 +2933,23 @@
|
|||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string notr="true">Time</string>
|
<string notr="true">Time</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_42">
|
<layout class="QHBoxLayout" name="horizontalLayout_42">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="timeTrigger">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_55">
|
<widget class="QLabel" name="label_55">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>At</string>
|
<string>at</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -2926,12 +3015,12 @@
|
|||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="sortingEnabled">
|
<property name="sortingEnabled">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_99">
|
<layout class="QHBoxLayout" name="horizontalLayout_51">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="timeAdd">
|
<widget class="QPushButton" name="timeAdd">
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
@@ -2964,6 +3053,91 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_110">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>5</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_36">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_111">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>5</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="timeUp">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>22</width>
|
||||||
|
<height>22</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>../../../forms/images/up.svg</normaloff>../../../forms/images/up.svg</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string>upArrowIconSmall</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="timeDown">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>22</width>
|
||||||
|
<height>22</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>../../../forms/images/down.svg</normaloff>../../../forms/images/down.svg</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string>downArrowIconSmall</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_39">
|
<spacer name="horizontalSpacer_39">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@@ -3483,6 +3657,257 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="audioTab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Audio</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="audioControlLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_52">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_66">
|
||||||
|
<property name="text">
|
||||||
|
<string>When the volume of</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="audioSources">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_67">
|
||||||
|
<property name="text">
|
||||||
|
<string>is above</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="audioVolumeThreshold">
|
||||||
|
<property name="suffix">
|
||||||
|
<string>%</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_68">
|
||||||
|
<property name="text">
|
||||||
|
<string>switch to</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="audioScenes">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_69">
|
||||||
|
<property name="text">
|
||||||
|
<string>using</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="audioTransitions"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_54">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="audioPlaceholder" native="true"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="audioSwitches">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_53">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="audioAdd">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>22</width>
|
||||||
|
<height>22</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">addIconSmall</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="audioRemove">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>22</width>
|
||||||
|
<height>22</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">removeIconSmall</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_114">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>5</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_38">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_115">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>5</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="audioUp">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>22</width>
|
||||||
|
<height>22</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>../../../forms/images/up.svg</normaloff>../../../forms/images/up.svg</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string>upArrowIconSmall</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="audioDown">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>22</width>
|
||||||
|
<height>22</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>../../../forms/images/down.svg</normaloff>../../../forms/images/down.svg</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string>downArrowIconSmall</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_56">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "headers/switcher-data-structs.hpp"
|
#include "headers/switcher-data-structs.hpp"
|
||||||
#include "headers/advanced-scene-switcher.hpp"
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
#include "headers/utility.hpp"
|
#include "headers/utility.hpp"
|
||||||
|
#include "headers/curl-helper.hpp"
|
||||||
|
|
||||||
SwitcherData *switcher = nullptr;
|
SwitcherData *switcher = nullptr;
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ void SceneSwitcher::populateSceneSelection(QComboBox *sel, bool addPrevious)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (addPrevious)
|
if (addPrevious)
|
||||||
sel->addItem(PREVIOUS_SCENE_NAME);
|
sel->addItem(previous_scene_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneSwitcher::populateTransitionSelection(QComboBox *sel)
|
void SceneSwitcher::populateTransitionSelection(QComboBox *sel)
|
||||||
@@ -89,6 +90,7 @@ void SceneSwitcher::loadUI()
|
|||||||
setupMediaTab();
|
setupMediaTab();
|
||||||
setupFileTab();
|
setupFileTab();
|
||||||
setupTimeTab();
|
setupTimeTab();
|
||||||
|
setupAudioTab();
|
||||||
|
|
||||||
setTabOrder();
|
setTabOrder();
|
||||||
|
|
||||||
@@ -118,6 +120,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||||||
switcher->saveFileSwitches(obj);
|
switcher->saveFileSwitches(obj);
|
||||||
switcher->saveMediaSwitches(obj);
|
switcher->saveMediaSwitches(obj);
|
||||||
switcher->saveTimeSwitches(obj);
|
switcher->saveTimeSwitches(obj);
|
||||||
|
switcher->saveAudioSwitches(obj);
|
||||||
switcher->saveGeneralSettings(obj);
|
switcher->saveGeneralSettings(obj);
|
||||||
|
|
||||||
obs_data_set_obj(save_data, "advanced-scene-switcher", obj);
|
obs_data_set_obj(save_data, "advanced-scene-switcher", obj);
|
||||||
@@ -143,6 +146,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||||||
switcher->loadFileSwitches(obj);
|
switcher->loadFileSwitches(obj);
|
||||||
switcher->loadMediaSwitches(obj);
|
switcher->loadMediaSwitches(obj);
|
||||||
switcher->loadTimeSwitches(obj);
|
switcher->loadTimeSwitches(obj);
|
||||||
|
switcher->loadAudioSwitches(obj);
|
||||||
switcher->loadGeneralSettings(obj);
|
switcher->loadGeneralSettings(obj);
|
||||||
|
|
||||||
obs_data_release(obj);
|
obs_data_release(obj);
|
||||||
@@ -195,37 +199,44 @@ void SwitcherData::Thread()
|
|||||||
if (switcher->stop) {
|
if (switcher->stop) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
setDefaultSceneTransitions();
|
setDefaultSceneTransitions();
|
||||||
|
|
||||||
if (autoStopEnable) {
|
if (autoStopEnable) {
|
||||||
autoStopStreamAndRecording();
|
autoStopStreamAndRecording();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (autoStartEnable) {
|
||||||
|
autoStartStreamRecording();
|
||||||
|
}
|
||||||
|
|
||||||
if (checkPause()) {
|
if (checkPause()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int switchFuncName : functionNamesByPriority) {
|
for (int switchFuncName : functionNamesByPriority) {
|
||||||
switch (switchFuncName) {
|
switch (switchFuncName) {
|
||||||
case READ_FILE_FUNC:
|
case read_file_func:
|
||||||
checkSwitchInfoFromFile(match, scene,
|
checkSwitchInfoFromFile(match, scene,
|
||||||
transition);
|
transition);
|
||||||
checkFileContent(match, scene, transition);
|
checkFileContent(match, scene, transition);
|
||||||
break;
|
break;
|
||||||
case IDLE_FUNC:
|
case idle_func:
|
||||||
checkIdleSwitch(match, scene, transition);
|
checkIdleSwitch(match, scene, transition);
|
||||||
break;
|
break;
|
||||||
case EXE_FUNC:
|
case exe_func:
|
||||||
checkExeSwitch(match, scene, transition);
|
checkExeSwitch(match, scene, transition);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCREEN_REGION_FUNC:
|
case screen_region_func:
|
||||||
checkScreenRegionSwitch(match, scene,
|
checkScreenRegionSwitch(match, scene,
|
||||||
transition);
|
transition);
|
||||||
break;
|
break;
|
||||||
case WINDOW_TITLE_FUNC:
|
case window_title_func:
|
||||||
checkWindowTitleSwitch(match, scene,
|
checkWindowTitleSwitch(match, scene,
|
||||||
transition);
|
transition);
|
||||||
break;
|
break;
|
||||||
case ROUND_TRIP_FUNC:
|
case round_trip_func:
|
||||||
checkSceneRoundTrip(match, scene, transition,
|
checkSceneRoundTrip(match, scene, transition,
|
||||||
lock);
|
lock);
|
||||||
if (sceneChangedDuringWait()) //scene might have changed during the sleep
|
if (sceneChangedDuringWait()) //scene might have changed during the sleep
|
||||||
@@ -233,12 +244,15 @@ void SwitcherData::Thread()
|
|||||||
goto startLoop;
|
goto startLoop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MEDIA_FUNC:
|
case media_func:
|
||||||
checkMediaSwitch(match, scene, transition);
|
checkMediaSwitch(match, scene, transition);
|
||||||
break;
|
break;
|
||||||
case TIME_FUNC:
|
case time_func:
|
||||||
checkTimeSwitch(match, scene, transition);
|
checkTimeSwitch(match, scene, transition);
|
||||||
break;
|
break;
|
||||||
|
case audio_func:
|
||||||
|
checkAudioSwitch(match, scene, transition);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switcher->stop) {
|
if (switcher->stop) {
|
||||||
@@ -335,6 +349,13 @@ void SwitcherData::Stop()
|
|||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
extern "C" void FreeSceneSwitcher()
|
extern "C" void FreeSceneSwitcher()
|
||||||
{
|
{
|
||||||
|
if (loaded_curl_lib) {
|
||||||
|
if (switcher->curl && f_curl_cleanup)
|
||||||
|
f_curl_cleanup(switcher->curl);
|
||||||
|
delete loaded_curl_lib;
|
||||||
|
loaded_curl_lib = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
delete switcher;
|
delete switcher;
|
||||||
switcher = nullptr;
|
switcher = nullptr;
|
||||||
}
|
}
|
||||||
@@ -355,6 +376,19 @@ void handleSceneChange(SwitcherData *s)
|
|||||||
s->previousScene = s->PreviousScene2;
|
s->previousScene = s->PreviousScene2;
|
||||||
s->PreviousScene2 = ws;
|
s->PreviousScene2 = ws;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//reset autostart
|
||||||
|
s->autoStartedRecently = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLiveTime(SwitcherData *s)
|
||||||
|
{
|
||||||
|
s->liveTime = QDateTime::currentDateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetLiveTime(SwitcherData *s)
|
||||||
|
{
|
||||||
|
s->liveTime = QDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
||||||
@@ -366,6 +400,14 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
|||||||
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
|
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
|
||||||
handleSceneChange((SwitcherData *)switcher);
|
handleSceneChange((SwitcherData *)switcher);
|
||||||
break;
|
break;
|
||||||
|
case OBS_FRONTEND_EVENT_RECORDING_STARTED:
|
||||||
|
case OBS_FRONTEND_EVENT_STREAMING_STARTED:
|
||||||
|
setLiveTime((SwitcherData *)switcher);
|
||||||
|
break;
|
||||||
|
case OBS_FRONTEND_EVENT_RECORDING_STOPPED:
|
||||||
|
case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
|
||||||
|
resetLiveTime((SwitcherData *)switcher);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -378,6 +420,10 @@ extern "C" void InitSceneSwitcher()
|
|||||||
|
|
||||||
switcher = new SwitcherData;
|
switcher = new SwitcherData;
|
||||||
|
|
||||||
|
if (loadCurl() && f_curl_init) {
|
||||||
|
switcher->curl = f_curl_init();
|
||||||
|
}
|
||||||
|
|
||||||
auto cb = []() {
|
auto cb = []() {
|
||||||
QMainWindow *window =
|
QMainWindow *window =
|
||||||
(QMainWindow *)obs_frontend_get_main_window();
|
(QMainWindow *)obs_frontend_get_main_window();
|
||||||
@@ -402,13 +448,13 @@ extern "C" void InitSceneSwitcher()
|
|||||||
"startStopToggleSwitcherHotkey",
|
"startStopToggleSwitcherHotkey",
|
||||||
"Toggle Start/Stop for the Advanced Scene Switcher",
|
"Toggle Start/Stop for the Advanced Scene Switcher",
|
||||||
startStopToggleHotkeyFunc, NULL);
|
startStopToggleHotkeyFunc, NULL);
|
||||||
loadKeybinding(toggleHotkeyId, TOGGLE_HOTKEY_PATH);
|
loadKeybinding(toggleHotkeyId, toggle_hotkey_path);
|
||||||
obs_hotkey_id startHotkeyId = obs_hotkey_register_frontend(
|
obs_hotkey_id startHotkeyId = obs_hotkey_register_frontend(
|
||||||
"startSwitcherHotkey", "Start the Advanced Scene Switcher",
|
"startSwitcherHotkey", "Start the Advanced Scene Switcher",
|
||||||
startHotkeyFunc, NULL);
|
startHotkeyFunc, NULL);
|
||||||
loadKeybinding(startHotkeyId, START_HOTKEY_PATH);
|
loadKeybinding(startHotkeyId, start_hotkey_path);
|
||||||
obs_hotkey_id stopHotkeyId = obs_hotkey_register_frontend(
|
obs_hotkey_id stopHotkeyId = obs_hotkey_register_frontend(
|
||||||
"stopSwitcherHotkey", "Stop the Advanced Scene Switcher",
|
"stopSwitcherHotkey", "Stop the Advanced Scene Switcher",
|
||||||
stopHotkeyFunc, NULL);
|
stopHotkeyFunc, NULL);
|
||||||
loadKeybinding(stopHotkeyId, STOP_HOTKEY_PATH);
|
loadKeybinding(stopHotkeyId, stop_hotkey_path);
|
||||||
}
|
}
|
||||||
|
|||||||
327
src/audio-switch.cpp
Normal file
327
src/audio-switch.cpp
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
|
|
||||||
|
#include "headers/volume-control.hpp"
|
||||||
|
|
||||||
|
void SceneSwitcher::on_audioSwitches_currentRowChanged(int idx)
|
||||||
|
{
|
||||||
|
if (loading)
|
||||||
|
return;
|
||||||
|
if (idx == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QListWidgetItem *item = ui->audioSwitches->item(idx);
|
||||||
|
|
||||||
|
QString audioScenestr = item->data(Qt::UserRole).toString();
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
for (auto &s : switcher->audioSwitches) {
|
||||||
|
if (audioScenestr.compare(s.audioSwitchStr.c_str()) == 0) {
|
||||||
|
QString sceneName = GetWeakSourceName(s.scene).c_str();
|
||||||
|
QString audioSrouceName =
|
||||||
|
GetWeakSourceName(s.audioSource).c_str();
|
||||||
|
QString transitionName =
|
||||||
|
GetWeakSourceName(s.transition).c_str();
|
||||||
|
ui->audioScenes->setCurrentText(sceneName);
|
||||||
|
ui->audioTransitions->setCurrentText(transitionName);
|
||||||
|
ui->audioSources->setCurrentText(audioSrouceName);
|
||||||
|
ui->audioVolumeThreshold->setValue(s.volumeThreshold);
|
||||||
|
volMeter->GetSlider()->setValue(s.volumeThreshold);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::on_audioSources_currentTextChanged(const QString &text)
|
||||||
|
{
|
||||||
|
SetAudioVolumeMeter(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::SetAudioVolumeMeter(const QString &name)
|
||||||
|
{
|
||||||
|
obs_source_t *soruce =
|
||||||
|
obs_get_source_by_name(name.toUtf8().constData());
|
||||||
|
if (!soruce) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volMeter) {
|
||||||
|
ui->audioControlLayout->removeWidget(volMeter);
|
||||||
|
delete volMeter;
|
||||||
|
}
|
||||||
|
|
||||||
|
volMeter = new VolControl(soruce);
|
||||||
|
ui->audioControlLayout->addWidget(volMeter);
|
||||||
|
obs_source_release(soruce);
|
||||||
|
|
||||||
|
QWidget::connect(volMeter->GetSlider(), SIGNAL(valueChanged(int)),
|
||||||
|
ui->audioVolumeThreshold, SLOT(setValue(int)));
|
||||||
|
QWidget::connect(ui->audioVolumeThreshold, SIGNAL(valueChanged(int)),
|
||||||
|
volMeter->GetSlider(), SLOT(setValue(int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int SceneSwitcher::audioFindByData(const QString &source, const int &volume)
|
||||||
|
{
|
||||||
|
QRegExp rx(MakeAudioSwitchName(QStringLiteral(".*"),
|
||||||
|
QStringLiteral(".*"), source, volume));
|
||||||
|
int count = ui->audioSwitches->count();
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
QListWidgetItem *item = ui->audioSwitches->item(i);
|
||||||
|
QString str = item->data(Qt::UserRole).toString();
|
||||||
|
|
||||||
|
if (rx.exactMatch(str))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::on_audioAdd_clicked()
|
||||||
|
{
|
||||||
|
QString sceneName = ui->audioScenes->currentText();
|
||||||
|
QString transitionName = ui->audioTransitions->currentText();
|
||||||
|
QString audioSourceName = ui->audioSources->currentText();
|
||||||
|
int vol = ui->audioVolumeThreshold->value();
|
||||||
|
|
||||||
|
if (sceneName.isEmpty() || audioSourceName.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
OBSWeakSource source = GetWeakSourceByQString(sceneName);
|
||||||
|
OBSWeakSource audioSource = GetWeakSourceByQString(audioSourceName);
|
||||||
|
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
|
||||||
|
|
||||||
|
QString text = MakeAudioSwitchName(sceneName, transitionName,
|
||||||
|
audioSourceName, vol);
|
||||||
|
QVariant v = QVariant::fromValue(text);
|
||||||
|
|
||||||
|
int idx = audioFindByData(audioSourceName, vol);
|
||||||
|
|
||||||
|
if (idx == -1) {
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
switcher->audioSwitches.emplace_back(
|
||||||
|
source, transition, audioSource, vol,
|
||||||
|
(sceneName == QString(previous_scene_name)),
|
||||||
|
text.toUtf8().constData());
|
||||||
|
QListWidgetItem *item =
|
||||||
|
new QListWidgetItem(text, ui->audioSwitches);
|
||||||
|
item->setData(Qt::UserRole, v);
|
||||||
|
} else {
|
||||||
|
QListWidgetItem *item = ui->audioSwitches->item(idx);
|
||||||
|
item->setText(text);
|
||||||
|
item->setData(Qt::UserRole, v);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
for (auto &s : switcher->audioSwitches) {
|
||||||
|
if (s.audioSource == audioSource &&
|
||||||
|
s.volumeThreshold == vol) {
|
||||||
|
s.scene = source;
|
||||||
|
s.transition = transition;
|
||||||
|
s.usePreviousScene =
|
||||||
|
(sceneName ==
|
||||||
|
QString(previous_scene_name));
|
||||||
|
s.audioSwitchStr =
|
||||||
|
text.toUtf8().constData();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::on_audioRemove_clicked()
|
||||||
|
{
|
||||||
|
QListWidgetItem *item = ui->audioSwitches->currentItem();
|
||||||
|
if (!item)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string text =
|
||||||
|
item->data(Qt::UserRole).toString().toUtf8().constData();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
auto &switches = switcher->audioSwitches;
|
||||||
|
|
||||||
|
for (auto it = switches.begin(); it != switches.end(); ++it) {
|
||||||
|
auto &s = *it;
|
||||||
|
|
||||||
|
if (s.audioSwitchStr == text) {
|
||||||
|
switches.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::on_audioUp_clicked()
|
||||||
|
{
|
||||||
|
int index = ui->audioSwitches->currentRow();
|
||||||
|
if (index != -1 && index != 0) {
|
||||||
|
ui->audioSwitches->insertItem(
|
||||||
|
index - 1, ui->audioSwitches->takeItem(index));
|
||||||
|
ui->audioSwitches->setCurrentRow(index - 1);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
|
||||||
|
iter_swap(switcher->audioSwitches.begin() + index,
|
||||||
|
switcher->audioSwitches.begin() + index - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::on_audioDown_clicked()
|
||||||
|
{
|
||||||
|
int index = ui->audioSwitches->currentRow();
|
||||||
|
if (index != -1 && index != ui->audioSwitches->count() - 1) {
|
||||||
|
ui->audioSwitches->insertItem(
|
||||||
|
index + 1, ui->audioSwitches->takeItem(index));
|
||||||
|
ui->audioSwitches->setCurrentRow(index + 1);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
|
||||||
|
iter_swap(switcher->audioSwitches.begin() + index,
|
||||||
|
switcher->audioSwitches.begin() + index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwitcherData::checkAudioSwitch(bool &match, OBSWeakSource &scene,
|
||||||
|
OBSWeakSource &transition)
|
||||||
|
{
|
||||||
|
if (audioSwitches.size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (AudioSwitch &s : audioSwitches) {
|
||||||
|
obs_source_t *as = obs_weak_source_get_source(s.audioSource);
|
||||||
|
const char *name = obs_source_get_name(as);
|
||||||
|
bool audioActive = obs_source_active(as);
|
||||||
|
obs_source_release(as);
|
||||||
|
|
||||||
|
// peak will have a value from -60 db to 0 db
|
||||||
|
bool volumeThresholdreached = (s.peak + 60) * 1.7 >
|
||||||
|
s.volumeThreshold;
|
||||||
|
|
||||||
|
if (volumeThresholdreached && audioActive) {
|
||||||
|
scene = (s.usePreviousScene) ? previousScene : s.scene;
|
||||||
|
transition = s.transition;
|
||||||
|
match = true;
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
blog(LOG_INFO,
|
||||||
|
"Advanced Scene Switcher audio match for %s",
|
||||||
|
name);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwitcherData::saveAudioSwitches(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
obs_data_array_t *audioArray = obs_data_array_create();
|
||||||
|
for (AudioSwitch &s : switcher->audioSwitches) {
|
||||||
|
obs_data_t *array_obj = obs_data_create();
|
||||||
|
|
||||||
|
obs_source_t *sceneSource = obs_weak_source_get_source(s.scene);
|
||||||
|
obs_source_t *transition =
|
||||||
|
obs_weak_source_get_source(s.transition);
|
||||||
|
obs_source_t *audioSrouce =
|
||||||
|
obs_weak_source_get_source(s.audioSource);
|
||||||
|
if ((s.usePreviousScene || sceneSource) && transition) {
|
||||||
|
const char *sceneName =
|
||||||
|
obs_source_get_name(sceneSource);
|
||||||
|
const char *transitionName =
|
||||||
|
obs_source_get_name(transition);
|
||||||
|
const char *audioSourceName =
|
||||||
|
obs_source_get_name(audioSrouce);
|
||||||
|
obs_data_set_string(array_obj, "scene",
|
||||||
|
s.usePreviousScene
|
||||||
|
? previous_scene_name
|
||||||
|
: sceneName);
|
||||||
|
obs_data_set_string(array_obj, "transition",
|
||||||
|
transitionName);
|
||||||
|
obs_data_set_string(array_obj, "audioSource",
|
||||||
|
audioSourceName);
|
||||||
|
obs_data_set_int(array_obj, "volume",
|
||||||
|
s.volumeThreshold);
|
||||||
|
obs_data_array_push_back(audioArray, array_obj);
|
||||||
|
}
|
||||||
|
obs_source_release(sceneSource);
|
||||||
|
obs_source_release(transition);
|
||||||
|
obs_source_release(audioSrouce);
|
||||||
|
|
||||||
|
obs_data_release(array_obj);
|
||||||
|
}
|
||||||
|
obs_data_set_array(obj, "audioSwitches", audioArray);
|
||||||
|
obs_data_array_release(audioArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwitcherData::loadAudioSwitches(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
switcher->audioSwitches.clear();
|
||||||
|
|
||||||
|
obs_data_array_t *audioArray = obs_data_get_array(obj, "audioSwitches");
|
||||||
|
size_t count = obs_data_array_count(audioArray);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
obs_data_t *array_obj = obs_data_array_item(audioArray, i);
|
||||||
|
|
||||||
|
const char *scene = obs_data_get_string(array_obj, "scene");
|
||||||
|
const char *transition =
|
||||||
|
obs_data_get_string(array_obj, "transition");
|
||||||
|
const char *audioSource =
|
||||||
|
obs_data_get_string(array_obj, "audioSource");
|
||||||
|
int vol = obs_data_get_int(array_obj, "volume");
|
||||||
|
|
||||||
|
std::string audioSwitchStr =
|
||||||
|
MakeAudioSwitchName(scene, transition, audioSource, vol)
|
||||||
|
.toUtf8()
|
||||||
|
.constData();
|
||||||
|
|
||||||
|
switcher->audioSwitches.emplace_back(
|
||||||
|
GetWeakSourceByName(scene),
|
||||||
|
GetWeakTransitionByName(transition),
|
||||||
|
GetWeakSourceByName(audioSource), vol,
|
||||||
|
(strcmp(scene, previous_scene_name) == 0),
|
||||||
|
audioSwitchStr);
|
||||||
|
|
||||||
|
obs_data_release(array_obj);
|
||||||
|
}
|
||||||
|
obs_data_array_release(audioArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::setupAudioTab()
|
||||||
|
{
|
||||||
|
populateSceneSelection(ui->audioScenes, true);
|
||||||
|
populateTransitionSelection(ui->audioTransitions);
|
||||||
|
|
||||||
|
auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */
|
||||||
|
{
|
||||||
|
QComboBox *combo = reinterpret_cast<QComboBox *>(data);
|
||||||
|
uint32_t flags = obs_source_get_output_flags(source);
|
||||||
|
|
||||||
|
if ((flags & OBS_SOURCE_AUDIO) != 0) {
|
||||||
|
const char *name = obs_source_get_name(source);
|
||||||
|
combo->addItem(name);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
obs_enum_sources(sourceEnum, ui->audioSources);
|
||||||
|
|
||||||
|
for (auto &s : switcher->audioSwitches) {
|
||||||
|
std::string sceneName = (s.usePreviousScene)
|
||||||
|
? previous_scene_name
|
||||||
|
: GetWeakSourceName(s.scene);
|
||||||
|
std::string transitionName = GetWeakSourceName(s.transition);
|
||||||
|
std::string audioSourceName = GetWeakSourceName(s.audioSource);
|
||||||
|
QString listText = MakeAudioSwitchName(sceneName.c_str(),
|
||||||
|
transitionName.c_str(),
|
||||||
|
audioSourceName.c_str(),
|
||||||
|
s.volumeThreshold);
|
||||||
|
|
||||||
|
QListWidgetItem *item =
|
||||||
|
new QListWidgetItem(listText, ui->audioSwitches);
|
||||||
|
item->setData(Qt::UserRole, listText);
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/curl-helper.cpp
Normal file
65
src/curl-helper.cpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <obs.hpp>
|
||||||
|
|
||||||
|
#include "headers/curl-helper.hpp"
|
||||||
|
|
||||||
|
initFunction f_curl_init = nullptr;
|
||||||
|
setOptFunction f_curl_setopt = nullptr;
|
||||||
|
performFunction f_curl_perform = nullptr;
|
||||||
|
cleanupFunction f_curl_cleanup = nullptr;
|
||||||
|
|
||||||
|
QLibrary *loaded_curl_lib = nullptr;
|
||||||
|
|
||||||
|
bool resolveCurl()
|
||||||
|
{
|
||||||
|
f_curl_init = (initFunction)loaded_curl_lib->resolve("curl_easy_init");
|
||||||
|
f_curl_setopt = (setOptFunction)loaded_curl_lib->resolve("curl_easy_setopt");
|
||||||
|
f_curl_perform =
|
||||||
|
(performFunction)loaded_curl_lib->resolve("curl_easy_perform");
|
||||||
|
f_curl_cleanup =
|
||||||
|
(cleanupFunction)loaded_curl_lib->resolve("curl_easy_cleanup");
|
||||||
|
|
||||||
|
if (f_curl_init && f_curl_setopt && f_curl_perform && f_curl_cleanup) {
|
||||||
|
blog(LOG_INFO, "curl loaded successfully");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
blog(LOG_INFO, "curl symbols not resolved");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadCurl()
|
||||||
|
{
|
||||||
|
QStringList locations;
|
||||||
|
locations << QDir::currentPath();
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
locations << "/usr/lib";
|
||||||
|
locations << "/usr/local/lib";
|
||||||
|
locations << "/usr/lib/x86_64-linux-gnu";
|
||||||
|
locations << "/usr/local/opt/curl/lib";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (QString path : locations) {
|
||||||
|
blog(LOG_INFO, "trying '%s'", path.toUtf8().constData());
|
||||||
|
QFileInfo libPath(QDir(path).absoluteFilePath(CURL_LIBRARY_NAME));
|
||||||
|
|
||||||
|
if (libPath.exists() && libPath.isFile()) {
|
||||||
|
QString libFilePath = libPath.absoluteFilePath();
|
||||||
|
blog(LOG_INFO, "found curl library at '%s'",
|
||||||
|
libFilePath.toUtf8().constData());
|
||||||
|
|
||||||
|
loaded_curl_lib = new QLibrary(libFilePath, nullptr);
|
||||||
|
if (resolveCurl())
|
||||||
|
return true;
|
||||||
|
else {
|
||||||
|
delete loaded_curl_lib;
|
||||||
|
loaded_curl_lib = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blog(LOG_ERROR, "can't find the curl library");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include "headers/advanced-scene-switcher.hpp"
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
|
#include "headers/curl-helper.hpp"
|
||||||
|
|
||||||
#define LOCAL_FILE_IDX 0
|
#define LOCAL_FILE_IDX 0
|
||||||
#define REMOTE_FILE_IDX 1
|
#define REMOTE_FILE_IDX 1
|
||||||
@@ -124,17 +125,13 @@ static size_t WriteCallback(void *contents, size_t size, size_t nmemb,
|
|||||||
|
|
||||||
std::string getRemoteData(std::string &url)
|
std::string getRemoteData(std::string &url)
|
||||||
{
|
{
|
||||||
CURL *curl;
|
|
||||||
CURLcode res;
|
|
||||||
std::string readBuffer;
|
std::string readBuffer;
|
||||||
|
|
||||||
curl = curl_easy_init();
|
if (switcher->curl && f_curl_setopt && f_curl_perform) {
|
||||||
if (curl) {
|
f_curl_setopt(switcher->curl, CURLOPT_URL, url.c_str());
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
f_curl_setopt(switcher->curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
f_curl_setopt(switcher->curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
f_curl_perform(switcher->curl);
|
||||||
res = curl_easy_perform(curl);
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
}
|
}
|
||||||
return readBuffer;
|
return readBuffer;
|
||||||
}
|
}
|
||||||
@@ -447,6 +444,9 @@ void SceneSwitcher::setupFileTab()
|
|||||||
"Note that the scene switcher will try to access the remote location every " +
|
"Note that the scene switcher will try to access the remote location every " +
|
||||||
QString::number(switcher->interval) + "ms");
|
QString::number(switcher->interval) + "ms");
|
||||||
|
|
||||||
|
if (switcher->curl)
|
||||||
|
ui->libcurlWarning->setVisible(false);
|
||||||
|
|
||||||
for (auto &s : switcher->fileSwitches) {
|
for (auto &s : switcher->fileSwitches) {
|
||||||
std::string sceneName = GetWeakSourceName(s.scene);
|
std::string sceneName = GetWeakSourceName(s.scene);
|
||||||
std::string transitionName = GetWeakSourceName(s.transition);
|
std::string transitionName = GetWeakSourceName(s.transition);
|
||||||
|
|||||||
172
src/general.cpp
172
src/general.cpp
@@ -159,6 +159,78 @@ void SwitcherData::autoStopStreamAndRecording()
|
|||||||
obs_weak_source_release(ws);
|
obs_weak_source_release(ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::on_autoStartType_currentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
if (loading)
|
||||||
|
return;
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
switcher->autoStartType = (AutoStartType)index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::on_autoStartScenes_currentTextChanged(const QString &text)
|
||||||
|
{
|
||||||
|
if (loading)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
UpdateAutoStartScene(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::on_autoStartSceneCheckBox_stateChanged(int state)
|
||||||
|
{
|
||||||
|
if (loading)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
if (!state) {
|
||||||
|
ui->autoStartScenes->setDisabled(true);
|
||||||
|
ui->autoStartType->setDisabled(true);
|
||||||
|
switcher->autoStartEnable = false;
|
||||||
|
} else {
|
||||||
|
ui->autoStartScenes->setDisabled(false);
|
||||||
|
ui->autoStartType->setDisabled(false);
|
||||||
|
switcher->autoStartEnable = true;
|
||||||
|
if (!switcher->autoStartScene)
|
||||||
|
UpdateAutoStartScene(
|
||||||
|
ui->autoStartScenes->currentText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::UpdateAutoStartScene(const QString &name)
|
||||||
|
{
|
||||||
|
obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData());
|
||||||
|
obs_weak_source_t *ws = obs_source_get_weak_source(scene);
|
||||||
|
|
||||||
|
switcher->autoStartScene = ws;
|
||||||
|
|
||||||
|
obs_weak_source_release(ws);
|
||||||
|
obs_source_release(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwitcherData::autoStartStreamRecording()
|
||||||
|
{
|
||||||
|
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
||||||
|
obs_weak_source_t *ws = obs_source_get_weak_source(currentSource);
|
||||||
|
|
||||||
|
if (autoStartedRecently)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ws && autoStartScene == ws) {
|
||||||
|
if ((switcher->autoStartType == STREAMING ||
|
||||||
|
switcher->autoStartType == RECORINDGSTREAMING) &&
|
||||||
|
!obs_frontend_streaming_active())
|
||||||
|
obs_frontend_streaming_start();
|
||||||
|
if ((switcher->autoStartType == RECORDING ||
|
||||||
|
switcher->autoStartType == RECORINDGSTREAMING) &&
|
||||||
|
!obs_frontend_recording_active())
|
||||||
|
obs_frontend_recording_start();
|
||||||
|
}
|
||||||
|
obs_source_release(currentSource);
|
||||||
|
obs_weak_source_release(ws);
|
||||||
|
|
||||||
|
autoStartedRecently = true;
|
||||||
|
}
|
||||||
|
|
||||||
void SceneSwitcher::on_verboseLogging_stateChanged(int state)
|
void SceneSwitcher::on_verboseLogging_stateChanged(int state)
|
||||||
{
|
{
|
||||||
if (loading)
|
if (loading)
|
||||||
@@ -193,6 +265,7 @@ void SceneSwitcher::on_exportSettings_clicked()
|
|||||||
switcher->saveFileSwitches(obj);
|
switcher->saveFileSwitches(obj);
|
||||||
switcher->saveMediaSwitches(obj);
|
switcher->saveMediaSwitches(obj);
|
||||||
switcher->saveTimeSwitches(obj);
|
switcher->saveTimeSwitches(obj);
|
||||||
|
switcher->saveAudioSwitches(obj);
|
||||||
switcher->saveGeneralSettings(obj);
|
switcher->saveGeneralSettings(obj);
|
||||||
|
|
||||||
obs_data_save_json(obj, file.fileName().toUtf8().constData());
|
obs_data_save_json(obj, file.fileName().toUtf8().constData());
|
||||||
@@ -237,6 +310,7 @@ void SceneSwitcher::on_importSettings_clicked()
|
|||||||
switcher->loadFileSwitches(obj);
|
switcher->loadFileSwitches(obj);
|
||||||
switcher->loadMediaSwitches(obj);
|
switcher->loadMediaSwitches(obj);
|
||||||
switcher->loadTimeSwitches(obj);
|
switcher->loadTimeSwitches(obj);
|
||||||
|
switcher->loadAudioSwitches(obj);
|
||||||
switcher->loadGeneralSettings(obj);
|
switcher->loadGeneralSettings(obj);
|
||||||
|
|
||||||
obs_data_release(obj);
|
obs_data_release(obj);
|
||||||
@@ -290,6 +364,9 @@ int findTabIndex(QTabBar *bar, int pos)
|
|||||||
case 11:
|
case 11:
|
||||||
tabName = "Sequence";
|
tabName = "Sequence";
|
||||||
break;
|
break;
|
||||||
|
case 12:
|
||||||
|
tabName = "Audio";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < bar->count(); ++i) {
|
for (int i = 0; i < bar->count(); ++i) {
|
||||||
@@ -345,6 +422,13 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
|||||||
obs_data_set_string(obj, "autoStopSceneName",
|
obs_data_set_string(obj, "autoStopSceneName",
|
||||||
autoStopSceneName.c_str());
|
autoStopSceneName.c_str());
|
||||||
|
|
||||||
|
std::string autoStartSceneName =
|
||||||
|
GetWeakSourceName(switcher->autoStartScene);
|
||||||
|
obs_data_set_bool(obj, "autoStartEnable", switcher->autoStartEnable);
|
||||||
|
obs_data_set_int(obj, "autoStartType", switcher->autoStartType);
|
||||||
|
obs_data_set_string(obj, "autoStartSceneName",
|
||||||
|
autoStartSceneName.c_str());
|
||||||
|
|
||||||
obs_data_set_bool(obj, "verbose", switcher->verbose);
|
obs_data_set_bool(obj, "verbose", switcher->verbose);
|
||||||
|
|
||||||
obs_data_set_int(obj, "priority0",
|
obs_data_set_int(obj, "priority0",
|
||||||
@@ -363,6 +447,8 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
|||||||
switcher->functionNamesByPriority[6]);
|
switcher->functionNamesByPriority[6]);
|
||||||
obs_data_set_int(obj, "priority7",
|
obs_data_set_int(obj, "priority7",
|
||||||
switcher->functionNamesByPriority[7]);
|
switcher->functionNamesByPriority[7]);
|
||||||
|
obs_data_set_int(obj, "priority8",
|
||||||
|
switcher->functionNamesByPriority[8]);
|
||||||
|
|
||||||
obs_data_set_int(obj, "threadPriority", switcher->threadPriority);
|
obs_data_set_int(obj, "threadPriority", switcher->threadPriority);
|
||||||
|
|
||||||
@@ -378,11 +464,12 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
|||||||
obs_data_set_int(obj, "timeTabPos", switcher->tabOrder[9]);
|
obs_data_set_int(obj, "timeTabPos", switcher->tabOrder[9]);
|
||||||
obs_data_set_int(obj, "idleTabPos", switcher->tabOrder[10]);
|
obs_data_set_int(obj, "idleTabPos", switcher->tabOrder[10]);
|
||||||
obs_data_set_int(obj, "sequenceTabPos", switcher->tabOrder[11]);
|
obs_data_set_int(obj, "sequenceTabPos", switcher->tabOrder[11]);
|
||||||
|
obs_data_set_int(obj, "audioTabPos", switcher->tabOrder[12]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
obs_data_set_default_int(obj, "interval", DEFAULT_INTERVAL);
|
obs_data_set_default_int(obj, "interval", default_interval);
|
||||||
switcher->interval = obs_data_get_int(obj, "interval");
|
switcher->interval = obs_data_get_int(obj, "interval");
|
||||||
|
|
||||||
obs_data_set_default_int(obj, "switch_if_not_matching", NO_SWITCH);
|
obs_data_set_default_int(obj, "switch_if_not_matching", NO_SWITCH);
|
||||||
@@ -406,16 +493,24 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
|||||||
switcher->autoStopEnable = obs_data_get_bool(obj, "autoStopEnable");
|
switcher->autoStopEnable = obs_data_get_bool(obj, "autoStopEnable");
|
||||||
switcher->autoStopScene = GetWeakSourceByName(autoStopScene.c_str());
|
switcher->autoStopScene = GetWeakSourceByName(autoStopScene.c_str());
|
||||||
|
|
||||||
|
std::string autoStartScene =
|
||||||
|
obs_data_get_string(obj, "autoStartSceneName");
|
||||||
|
switcher->autoStartEnable = obs_data_get_bool(obj, "autoStartEnable");
|
||||||
|
switcher->autoStartType =
|
||||||
|
(AutoStartType)obs_data_get_int(obj, "autoStartType");
|
||||||
|
switcher->autoStartScene = GetWeakSourceByName(autoStartScene.c_str());
|
||||||
|
|
||||||
switcher->verbose = obs_data_get_bool(obj, "verbose");
|
switcher->verbose = obs_data_get_bool(obj, "verbose");
|
||||||
|
|
||||||
obs_data_set_default_int(obj, "priority0", DEFAULT_PRIORITY_0);
|
obs_data_set_default_int(obj, "priority0", default_priority_0);
|
||||||
obs_data_set_default_int(obj, "priority1", DEFAULT_PRIORITY_1);
|
obs_data_set_default_int(obj, "priority1", default_priority_1);
|
||||||
obs_data_set_default_int(obj, "priority2", DEFAULT_PRIORITY_2);
|
obs_data_set_default_int(obj, "priority2", default_priority_2);
|
||||||
obs_data_set_default_int(obj, "priority3", DEFAULT_PRIORITY_3);
|
obs_data_set_default_int(obj, "priority3", default_priority_3);
|
||||||
obs_data_set_default_int(obj, "priority4", DEFAULT_PRIORITY_4);
|
obs_data_set_default_int(obj, "priority4", default_priority_4);
|
||||||
obs_data_set_default_int(obj, "priority5", DEFAULT_PRIORITY_5);
|
obs_data_set_default_int(obj, "priority5", default_priority_5);
|
||||||
obs_data_set_default_int(obj, "priority6", DEFAULT_PRIORITY_6);
|
obs_data_set_default_int(obj, "priority6", default_priority_6);
|
||||||
obs_data_set_default_int(obj, "priority7", DEFAULT_PRIORITY_7);
|
obs_data_set_default_int(obj, "priority7", default_priority_7);
|
||||||
|
obs_data_set_default_int(obj, "priority8", default_priority_8);
|
||||||
|
|
||||||
switcher->functionNamesByPriority[0] =
|
switcher->functionNamesByPriority[0] =
|
||||||
(obs_data_get_int(obj, "priority0"));
|
(obs_data_get_int(obj, "priority0"));
|
||||||
@@ -433,15 +528,18 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
|||||||
(obs_data_get_int(obj, "priority6"));
|
(obs_data_get_int(obj, "priority6"));
|
||||||
switcher->functionNamesByPriority[7] =
|
switcher->functionNamesByPriority[7] =
|
||||||
(obs_data_get_int(obj, "priority7"));
|
(obs_data_get_int(obj, "priority7"));
|
||||||
|
switcher->functionNamesByPriority[8] =
|
||||||
|
(obs_data_get_int(obj, "priority8"));
|
||||||
if (!switcher->prioFuncsValid()) {
|
if (!switcher->prioFuncsValid()) {
|
||||||
switcher->functionNamesByPriority[0] = (DEFAULT_PRIORITY_0);
|
switcher->functionNamesByPriority[0] = (default_priority_0);
|
||||||
switcher->functionNamesByPriority[1] = (DEFAULT_PRIORITY_1);
|
switcher->functionNamesByPriority[1] = (default_priority_1);
|
||||||
switcher->functionNamesByPriority[2] = (DEFAULT_PRIORITY_2);
|
switcher->functionNamesByPriority[2] = (default_priority_2);
|
||||||
switcher->functionNamesByPriority[3] = (DEFAULT_PRIORITY_3);
|
switcher->functionNamesByPriority[3] = (default_priority_3);
|
||||||
switcher->functionNamesByPriority[4] = (DEFAULT_PRIORITY_4);
|
switcher->functionNamesByPriority[4] = (default_priority_4);
|
||||||
switcher->functionNamesByPriority[5] = (DEFAULT_PRIORITY_5);
|
switcher->functionNamesByPriority[5] = (default_priority_5);
|
||||||
switcher->functionNamesByPriority[6] = (DEFAULT_PRIORITY_6);
|
switcher->functionNamesByPriority[6] = (default_priority_6);
|
||||||
switcher->functionNamesByPriority[7] = (DEFAULT_PRIORITY_7);
|
switcher->functionNamesByPriority[7] = (default_priority_7);
|
||||||
|
switcher->functionNamesByPriority[8] = (default_priority_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_data_set_default_int(obj, "threadPriority",
|
obs_data_set_default_int(obj, "threadPriority",
|
||||||
@@ -460,6 +558,7 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
|||||||
obs_data_set_default_int(obj, "timeTabPos", 9);
|
obs_data_set_default_int(obj, "timeTabPos", 9);
|
||||||
obs_data_set_default_int(obj, "idleTabPos", 10);
|
obs_data_set_default_int(obj, "idleTabPos", 10);
|
||||||
obs_data_set_default_int(obj, "sequenceTabPos", 11);
|
obs_data_set_default_int(obj, "sequenceTabPos", 11);
|
||||||
|
obs_data_set_default_int(obj, "audioTabPos", 12);
|
||||||
|
|
||||||
switcher->tabOrder.emplace_back(
|
switcher->tabOrder.emplace_back(
|
||||||
(int)(obs_data_get_int(obj, "generalTabPos")));
|
(int)(obs_data_get_int(obj, "generalTabPos")));
|
||||||
@@ -485,12 +584,15 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
|||||||
(int)(obs_data_get_int(obj, "idleTabPos")));
|
(int)(obs_data_get_int(obj, "idleTabPos")));
|
||||||
switcher->tabOrder.emplace_back(
|
switcher->tabOrder.emplace_back(
|
||||||
(int)(obs_data_get_int(obj, "sequenceTabPos")));
|
(int)(obs_data_get_int(obj, "sequenceTabPos")));
|
||||||
|
switcher->tabOrder.emplace_back(
|
||||||
|
(int)(obs_data_get_int(obj, "audioTabPos")));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneSwitcher::setupGeneralTab()
|
void SceneSwitcher::setupGeneralTab()
|
||||||
{
|
{
|
||||||
populateSceneSelection(ui->noMatchSwitchScene, false);
|
populateSceneSelection(ui->noMatchSwitchScene, false);
|
||||||
populateSceneSelection(ui->autoStopScenes, false);
|
populateSceneSelection(ui->autoStopScenes, false);
|
||||||
|
populateSceneSelection(ui->autoStartScenes, false);
|
||||||
|
|
||||||
if (switcher->switchIfNotMatching == SWITCH) {
|
if (switcher->switchIfNotMatching == SWITCH) {
|
||||||
ui->noMatchSwitch->setChecked(true);
|
ui->noMatchSwitch->setChecked(true);
|
||||||
@@ -516,35 +618,55 @@ void SceneSwitcher::setupGeneralTab()
|
|||||||
ui->autoStopScenes->setDisabled(true);
|
ui->autoStopScenes->setDisabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui->autoStartType->addItem("Recording");
|
||||||
|
ui->autoStartType->addItem("Streaming");
|
||||||
|
ui->autoStartType->addItem("Recording and Streaming");
|
||||||
|
|
||||||
|
ui->autoStartSceneCheckBox->setChecked(switcher->autoStartEnable);
|
||||||
|
ui->autoStartScenes->setCurrentText(
|
||||||
|
GetWeakSourceName(switcher->autoStartScene).c_str());
|
||||||
|
ui->autoStartType->setCurrentIndex(switcher->autoStartType);
|
||||||
|
|
||||||
|
if (ui->autoStartSceneCheckBox->checkState()) {
|
||||||
|
ui->autoStartScenes->setDisabled(false);
|
||||||
|
ui->autoStartType->setDisabled(false);
|
||||||
|
} else {
|
||||||
|
ui->autoStartScenes->setDisabled(true);
|
||||||
|
ui->autoStartType->setDisabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
ui->verboseLogging->setChecked(switcher->verbose);
|
ui->verboseLogging->setChecked(switcher->verbose);
|
||||||
|
|
||||||
for (int p : switcher->functionNamesByPriority) {
|
for (int p : switcher->functionNamesByPriority) {
|
||||||
std::string s = "";
|
std::string s = "";
|
||||||
switch (p) {
|
switch (p) {
|
||||||
case READ_FILE_FUNC:
|
case read_file_func:
|
||||||
s = "File Content";
|
s = "File Content";
|
||||||
break;
|
break;
|
||||||
case ROUND_TRIP_FUNC:
|
case round_trip_func:
|
||||||
s = "Scene Sequence";
|
s = "Scene Sequence";
|
||||||
break;
|
break;
|
||||||
case IDLE_FUNC:
|
case idle_func:
|
||||||
s = "Idle Detection";
|
s = "Idle Detection";
|
||||||
break;
|
break;
|
||||||
case EXE_FUNC:
|
case exe_func:
|
||||||
s = "Executable";
|
s = "Executable";
|
||||||
break;
|
break;
|
||||||
case SCREEN_REGION_FUNC:
|
case screen_region_func:
|
||||||
s = "Screen Region";
|
s = "Screen Region";
|
||||||
break;
|
break;
|
||||||
case WINDOW_TITLE_FUNC:
|
case window_title_func:
|
||||||
s = "Window Title";
|
s = "Window Title";
|
||||||
break;
|
break;
|
||||||
case MEDIA_FUNC:
|
case media_func:
|
||||||
s = "Media";
|
s = "Media";
|
||||||
break;
|
break;
|
||||||
case TIME_FUNC:
|
case time_func:
|
||||||
s = "Time";
|
s = "Time";
|
||||||
break;
|
break;
|
||||||
|
case audio_func:
|
||||||
|
s = "Audio";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
QString text(s.c_str());
|
QString text(s.c_str());
|
||||||
QListWidgetItem *item =
|
QListWidgetItem *item =
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "ui_advanced-scene-switcher.h"
|
#include "ui_advanced-scene-switcher.h"
|
||||||
#endif
|
#endif
|
||||||
#include "switcher-data-structs.hpp"
|
#include "switcher-data-structs.hpp"
|
||||||
|
#include "volume-control.hpp"
|
||||||
|
|
||||||
class QCloseEvent;
|
class QCloseEvent;
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ class SceneSwitcher : public QDialog {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<Ui_SceneSwitcher> ui;
|
std::unique_ptr<Ui_SceneSwitcher> ui;
|
||||||
|
VolControl *volMeter = nullptr;
|
||||||
bool loading = true;
|
bool loading = true;
|
||||||
|
|
||||||
SceneSwitcher(QWidget *parent);
|
SceneSwitcher(QWidget *parent);
|
||||||
@@ -42,12 +44,15 @@ public:
|
|||||||
int executableFindByData(const QString &exe);
|
int executableFindByData(const QString &exe);
|
||||||
int IgnoreIdleWindowsFindByData(const QString &window);
|
int IgnoreIdleWindowsFindByData(const QString &window);
|
||||||
int randomFindByData(const QString &scene);
|
int randomFindByData(const QString &scene);
|
||||||
int timeFindByData(const QString &timeStr);
|
int timeFindByData(const timeTrigger &trigger, const QTime &time);
|
||||||
|
int audioFindByData(const QString &source, const int &volume);
|
||||||
|
|
||||||
void UpdateNonMatchingScene(const QString &name);
|
void UpdateNonMatchingScene(const QString &name);
|
||||||
void UpdateAutoStopScene(const QString &name);
|
void UpdateAutoStopScene(const QString &name);
|
||||||
|
void UpdateAutoStartScene(const QString &name);
|
||||||
void UpdateIdleDataTransition(const QString &name);
|
void UpdateIdleDataTransition(const QString &name);
|
||||||
void UpdateIdleDataScene(const QString &name);
|
void UpdateIdleDataScene(const QString &name);
|
||||||
|
void SetAudioVolumeMeter(const QString &name);
|
||||||
|
|
||||||
void loadUI();
|
void loadUI();
|
||||||
void populateSceneSelection(QComboBox *sel, bool addPrevious);
|
void populateSceneSelection(QComboBox *sel, bool addPrevious);
|
||||||
@@ -65,6 +70,7 @@ public:
|
|||||||
void setupMediaTab();
|
void setupMediaTab();
|
||||||
void setupFileTab();
|
void setupFileTab();
|
||||||
void setupTimeTab();
|
void setupTimeTab();
|
||||||
|
void setupAudioTab();
|
||||||
void setTabOrder();
|
void setTabOrder();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
@@ -112,6 +118,10 @@ public slots:
|
|||||||
void on_autoStopSceneCheckBox_stateChanged(int state);
|
void on_autoStopSceneCheckBox_stateChanged(int state);
|
||||||
void on_autoStopScenes_currentTextChanged(const QString &text);
|
void on_autoStopScenes_currentTextChanged(const QString &text);
|
||||||
|
|
||||||
|
void on_autoStartSceneCheckBox_stateChanged(int state);
|
||||||
|
void on_autoStartType_currentIndexChanged(int index);
|
||||||
|
void on_autoStartScenes_currentTextChanged(const QString &text);
|
||||||
|
|
||||||
void on_verboseLogging_stateChanged(int state);
|
void on_verboseLogging_stateChanged(int state);
|
||||||
|
|
||||||
void on_exportSettings_clicked();
|
void on_exportSettings_clicked();
|
||||||
@@ -167,6 +177,15 @@ public slots:
|
|||||||
void on_timeSwitches_currentRowChanged(int idx);
|
void on_timeSwitches_currentRowChanged(int idx);
|
||||||
void on_timeAdd_clicked();
|
void on_timeAdd_clicked();
|
||||||
void on_timeRemove_clicked();
|
void on_timeRemove_clicked();
|
||||||
|
void on_timeUp_clicked();
|
||||||
|
void on_timeDown_clicked();
|
||||||
|
|
||||||
|
void on_audioAdd_clicked();
|
||||||
|
void on_audioRemove_clicked();
|
||||||
|
void on_audioUp_clicked();
|
||||||
|
void on_audioDown_clicked();
|
||||||
|
void on_audioSwitches_currentRowChanged(int idx);
|
||||||
|
void on_audioSources_currentTextChanged(const QString &text);
|
||||||
|
|
||||||
void on_priorityUp_clicked();
|
void on_priorityUp_clicked();
|
||||||
void on_priorityDown_clicked();
|
void on_priorityDown_clicked();
|
||||||
@@ -175,6 +194,8 @@ public slots:
|
|||||||
void updateScreenRegionCursorPos();
|
void updateScreenRegionCursorPos();
|
||||||
|
|
||||||
void on_close_clicked();
|
void on_close_clicked();
|
||||||
|
|
||||||
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
@@ -227,9 +248,9 @@ void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
|
|||||||
* Hotkey helper
|
* Hotkey helper
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
|
||||||
#define TOGGLE_HOTKEY_PATH "hotkey_toggle.txt"
|
constexpr auto toggle_hotkey_path = "hotkey_toggle.txt";
|
||||||
#define STOP_HOTKEY_PATH "hotkey_stop.txt"
|
constexpr auto stop_hotkey_path = "hotkey_stop.txt";
|
||||||
#define START_HOTKEY_PATH "hotkey_start.txt"
|
constexpr auto start_hotkey_path = "hotkey_start.txt";
|
||||||
|
|
||||||
void stopHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
|
void stopHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
|
||||||
bool pressed);
|
bool pressed);
|
||||||
|
|||||||
26
src/headers/curl-helper.hpp
Normal file
26
src/headers/curl-helper.hpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <QLibrary>
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
#define CURL_LIBRARY_NAME "libcurl.dll"
|
||||||
|
#elif __APPLE__
|
||||||
|
#define CURL_LIBRARY_NAME "libcurl.4.dylib"
|
||||||
|
#else
|
||||||
|
#define CURL_LIBRARY_NAME "libcurl.so.4"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef CURL *(*initFunction)(void);
|
||||||
|
typedef CURLcode (*setOptFunction)(CURL *, CURLoption, ...);
|
||||||
|
typedef CURLcode (*performFunction)(CURL *);
|
||||||
|
typedef void (*cleanupFunction)(CURL *);
|
||||||
|
|
||||||
|
extern initFunction f_curl_init;
|
||||||
|
extern setOptFunction f_curl_setopt;
|
||||||
|
extern performFunction f_curl_perform;
|
||||||
|
extern cleanupFunction f_curl_cleanup;
|
||||||
|
|
||||||
|
extern QLibrary *loaded_curl_lib;
|
||||||
|
|
||||||
|
bool resolveCurl();
|
||||||
|
bool loadCurl();
|
||||||
@@ -8,31 +8,34 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
#include <curl/curl.h>
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#define DEFAULT_INTERVAL 300
|
constexpr auto default_interval = 300;
|
||||||
|
|
||||||
#define DEFAULT_IDLE_TIME 60
|
constexpr auto default_idle_time = 60;
|
||||||
|
|
||||||
#define PREVIOUS_SCENE_NAME "Previous Scene"
|
constexpr auto previous_scene_name = "Previous Scene";
|
||||||
|
|
||||||
#define READ_FILE_FUNC 0
|
constexpr auto read_file_func = 0;
|
||||||
#define ROUND_TRIP_FUNC 1
|
constexpr auto round_trip_func = 1;
|
||||||
#define IDLE_FUNC 2
|
constexpr auto idle_func = 2;
|
||||||
#define EXE_FUNC 3
|
constexpr auto exe_func = 3;
|
||||||
#define SCREEN_REGION_FUNC 4
|
constexpr auto screen_region_func = 4;
|
||||||
#define WINDOW_TITLE_FUNC 5
|
constexpr auto window_title_func = 5;
|
||||||
#define MEDIA_FUNC 6
|
constexpr auto media_func = 6;
|
||||||
#define TIME_FUNC 7
|
constexpr auto time_func = 7;
|
||||||
|
constexpr auto audio_func = 8;
|
||||||
|
|
||||||
#define DEFAULT_PRIORITY_0 READ_FILE_FUNC
|
constexpr auto default_priority_0 = read_file_func;
|
||||||
#define DEFAULT_PRIORITY_1 ROUND_TRIP_FUNC
|
constexpr auto default_priority_1 = round_trip_func;
|
||||||
#define DEFAULT_PRIORITY_2 IDLE_FUNC
|
constexpr auto default_priority_2 = idle_func;
|
||||||
#define DEFAULT_PRIORITY_3 EXE_FUNC
|
constexpr auto default_priority_3 = exe_func;
|
||||||
#define DEFAULT_PRIORITY_4 SCREEN_REGION_FUNC
|
constexpr auto default_priority_4 = screen_region_func;
|
||||||
#define DEFAULT_PRIORITY_5 WINDOW_TITLE_FUNC
|
constexpr auto default_priority_5 = window_title_func;
|
||||||
#define DEFAULT_PRIORITY_6 MEDIA_FUNC
|
constexpr auto default_priority_6 = media_func;
|
||||||
#define DEFAULT_PRIORITY_7 TIME_FUNC
|
constexpr auto default_priority_7 = time_func;
|
||||||
|
constexpr auto default_priority_8 = audio_func;
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* Data structs for each scene switching method
|
* Data structs for each scene switching method
|
||||||
@@ -198,7 +201,7 @@ struct FileIOData {
|
|||||||
|
|
||||||
struct IdleData {
|
struct IdleData {
|
||||||
bool idleEnable = false;
|
bool idleEnable = false;
|
||||||
int time = DEFAULT_IDLE_TIME;
|
int time = default_idle_time;
|
||||||
OBSWeakSource scene;
|
OBSWeakSource scene;
|
||||||
OBSWeakSource transition;
|
OBSWeakSource transition;
|
||||||
bool usePreviousScene;
|
bool usePreviousScene;
|
||||||
@@ -235,16 +238,17 @@ struct MediaSwitch {
|
|||||||
struct TimeSwitch {
|
struct TimeSwitch {
|
||||||
OBSWeakSource scene;
|
OBSWeakSource scene;
|
||||||
OBSWeakSource transition;
|
OBSWeakSource transition;
|
||||||
|
timeTrigger trigger;
|
||||||
QTime time;
|
QTime time;
|
||||||
bool matched;
|
|
||||||
bool usePreviousScene;
|
bool usePreviousScene;
|
||||||
std::string timeSwitchStr;
|
std::string timeSwitchStr;
|
||||||
|
|
||||||
inline TimeSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
|
inline TimeSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
|
||||||
QTime time_, bool usePreviousScene_,
|
timeTrigger trigger_, QTime time_,
|
||||||
std::string timeSwitchStr_)
|
bool usePreviousScene_, std::string timeSwitchStr_)
|
||||||
: scene(scene_),
|
: scene(scene_),
|
||||||
transition(transition_),
|
transition(transition_),
|
||||||
|
trigger(trigger_),
|
||||||
time(time_),
|
time(time_),
|
||||||
usePreviousScene(usePreviousScene_),
|
usePreviousScene(usePreviousScene_),
|
||||||
timeSwitchStr(timeSwitchStr_)
|
timeSwitchStr(timeSwitchStr_)
|
||||||
@@ -252,8 +256,114 @@ struct TimeSwitch {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AudioSwitch {
|
||||||
|
OBSWeakSource scene;
|
||||||
|
OBSWeakSource audioSource;
|
||||||
|
OBSWeakSource transition;
|
||||||
|
int volumeThreshold;
|
||||||
|
float peak;
|
||||||
|
bool usePreviousScene;
|
||||||
|
obs_volmeter_t *volmeter;
|
||||||
|
std::string audioSwitchStr;
|
||||||
|
|
||||||
|
static void setVolumeLevel(void *data,
|
||||||
|
const float magnitude[MAX_AUDIO_CHANNELS],
|
||||||
|
const float peak[MAX_AUDIO_CHANNELS],
|
||||||
|
const float inputPeak[MAX_AUDIO_CHANNELS])
|
||||||
|
{
|
||||||
|
UNUSED_PARAMETER(magnitude);
|
||||||
|
UNUSED_PARAMETER(inputPeak);
|
||||||
|
AudioSwitch *s = static_cast<AudioSwitch *>(data);
|
||||||
|
|
||||||
|
s->peak = peak[0];
|
||||||
|
for (int i = 1; i < MAX_AUDIO_CHANNELS; i++)
|
||||||
|
if (peak[i] > s->peak)
|
||||||
|
s->peak = peak[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AudioSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
|
||||||
|
OBSWeakSource audioSource_, int volumeThreshold_,
|
||||||
|
bool usePreviousScene_, std::string audioSwitchStr_)
|
||||||
|
: scene(scene_),
|
||||||
|
transition(transition_),
|
||||||
|
audioSource(audioSource_),
|
||||||
|
volumeThreshold(volumeThreshold_),
|
||||||
|
usePreviousScene(usePreviousScene_),
|
||||||
|
audioSwitchStr(audioSwitchStr_)
|
||||||
|
{
|
||||||
|
volmeter = obs_volmeter_create(OBS_FADER_LOG);
|
||||||
|
obs_volmeter_add_callback(volmeter, setVolumeLevel, this);
|
||||||
|
obs_source_t *as = obs_weak_source_get_source(audioSource);
|
||||||
|
if (!obs_volmeter_attach_source(volmeter, as)) {
|
||||||
|
const char *name = obs_source_get_name(as);
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"failed to attach volmeter to source %s", name);
|
||||||
|
}
|
||||||
|
obs_source_release(as);
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioSwitch(const AudioSwitch &other)
|
||||||
|
: scene(other.scene),
|
||||||
|
transition(other.transition),
|
||||||
|
audioSource(other.audioSource),
|
||||||
|
volumeThreshold(other.volumeThreshold),
|
||||||
|
usePreviousScene(other.usePreviousScene),
|
||||||
|
audioSwitchStr(other.audioSwitchStr)
|
||||||
|
{
|
||||||
|
volmeter = obs_volmeter_create(OBS_FADER_LOG);
|
||||||
|
obs_volmeter_add_callback(volmeter, setVolumeLevel, this);
|
||||||
|
obs_source_t *as =
|
||||||
|
obs_weak_source_get_source(other.audioSource);
|
||||||
|
if (!obs_volmeter_attach_source(volmeter, as)) {
|
||||||
|
const char *name = obs_source_get_name(as);
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"failed to attach volmeter to source %s", name);
|
||||||
|
}
|
||||||
|
obs_source_release(as);
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioSwitch(AudioSwitch &&other)
|
||||||
|
: scene(other.scene),
|
||||||
|
transition(other.transition),
|
||||||
|
audioSource(other.audioSource),
|
||||||
|
volumeThreshold(other.volumeThreshold),
|
||||||
|
usePreviousScene(other.usePreviousScene),
|
||||||
|
audioSwitchStr(other.audioSwitchStr),
|
||||||
|
volmeter(other.volmeter)
|
||||||
|
{
|
||||||
|
other.volmeter = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ~AudioSwitch()
|
||||||
|
{
|
||||||
|
obs_volmeter_remove_callback(volmeter, setVolumeLevel, this);
|
||||||
|
obs_volmeter_destroy(volmeter);
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioSwitch &operator=(const AudioSwitch &other)
|
||||||
|
{
|
||||||
|
return *this = AudioSwitch(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioSwitch &operator=(AudioSwitch &&other) noexcept
|
||||||
|
{
|
||||||
|
if (this == &other) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
obs_volmeter_destroy(volmeter);
|
||||||
|
volmeter = other.volmeter;
|
||||||
|
other.volmeter = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
typedef enum { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 } NoMatch;
|
typedef enum { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 } NoMatch;
|
||||||
typedef enum { PERSIST = 0, START = 1, STOP = 2 } StartupBehavior;
|
typedef enum { PERSIST = 0, START = 1, STOP = 2 } StartupBehavior;
|
||||||
|
typedef enum {
|
||||||
|
RECORDING = 0,
|
||||||
|
STREAMING = 1,
|
||||||
|
RECORINDGSTREAMING = 2
|
||||||
|
} AutoStartType;
|
||||||
|
|
||||||
class SwitcherThread;
|
class SwitcherThread;
|
||||||
|
|
||||||
@@ -272,7 +382,7 @@ struct SwitcherData {
|
|||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
bool tansitionOverrideOverride = false;
|
bool tansitionOverrideOverride = false;
|
||||||
|
|
||||||
int interval = DEFAULT_INTERVAL;
|
int interval = default_interval;
|
||||||
|
|
||||||
obs_source_t *waitScene = NULL; //scene during which wait started
|
obs_source_t *waitScene = NULL; //scene during which wait started
|
||||||
OBSWeakSource previousScene = NULL;
|
OBSWeakSource previousScene = NULL;
|
||||||
@@ -302,23 +412,32 @@ struct SwitcherData {
|
|||||||
FileIOData fileIO;
|
FileIOData fileIO;
|
||||||
IdleData idleData;
|
IdleData idleData;
|
||||||
std::vector<FileSwitch> fileSwitches;
|
std::vector<FileSwitch> fileSwitches;
|
||||||
|
CURL *curl = nullptr;
|
||||||
|
|
||||||
std::vector<ExecutableSceneSwitch> executableSwitches;
|
std::vector<ExecutableSceneSwitch> executableSwitches;
|
||||||
|
|
||||||
bool autoStopEnable = false;
|
bool autoStopEnable = false;
|
||||||
OBSWeakSource autoStopScene;
|
OBSWeakSource autoStopScene;
|
||||||
|
|
||||||
|
bool autoStartEnable = false;
|
||||||
|
AutoStartType autoStartType = RECORDING;
|
||||||
|
OBSWeakSource autoStartScene;
|
||||||
|
bool autoStartedRecently = false;
|
||||||
|
|
||||||
std::vector<SceneTransition> sceneTransitions;
|
std::vector<SceneTransition> sceneTransitions;
|
||||||
std::vector<DefaultSceneTransition> defaultSceneTransitions;
|
std::vector<DefaultSceneTransition> defaultSceneTransitions;
|
||||||
|
|
||||||
std::vector<MediaSwitch> mediaSwitches;
|
std::vector<MediaSwitch> mediaSwitches;
|
||||||
|
|
||||||
std::vector<TimeSwitch> timeSwitches;
|
std::vector<TimeSwitch> timeSwitches;
|
||||||
|
QDateTime liveTime;
|
||||||
|
|
||||||
|
std::vector<AudioSwitch> audioSwitches;
|
||||||
|
|
||||||
std::vector<int> functionNamesByPriority = std::vector<int>{
|
std::vector<int> functionNamesByPriority = std::vector<int>{
|
||||||
DEFAULT_PRIORITY_0, DEFAULT_PRIORITY_1, DEFAULT_PRIORITY_2,
|
default_priority_0, default_priority_1, default_priority_2,
|
||||||
DEFAULT_PRIORITY_3, DEFAULT_PRIORITY_4, DEFAULT_PRIORITY_5,
|
default_priority_3, default_priority_4, default_priority_5,
|
||||||
DEFAULT_PRIORITY_6, DEFAULT_PRIORITY_7};
|
default_priority_6, default_priority_7, default_priority_8};
|
||||||
|
|
||||||
struct ThreadPrio {
|
struct ThreadPrio {
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -358,6 +477,7 @@ struct SwitcherData {
|
|||||||
void writeSceneInfoToFile();
|
void writeSceneInfoToFile();
|
||||||
void setDefaultSceneTransitions();
|
void setDefaultSceneTransitions();
|
||||||
void autoStopStreamAndRecording();
|
void autoStopStreamAndRecording();
|
||||||
|
void autoStartStreamRecording();
|
||||||
bool checkPause();
|
bool checkPause();
|
||||||
void checkSceneRoundTrip(bool &match, OBSWeakSource &scene,
|
void checkSceneRoundTrip(bool &match, OBSWeakSource &scene,
|
||||||
OBSWeakSource &transition,
|
OBSWeakSource &transition,
|
||||||
@@ -380,6 +500,8 @@ struct SwitcherData {
|
|||||||
OBSWeakSource &transition);
|
OBSWeakSource &transition);
|
||||||
void checkTimeSwitch(bool &match, OBSWeakSource &scene,
|
void checkTimeSwitch(bool &match, OBSWeakSource &scene,
|
||||||
OBSWeakSource &transition);
|
OBSWeakSource &transition);
|
||||||
|
void checkAudioSwitch(bool &match, OBSWeakSource &scene,
|
||||||
|
OBSWeakSource &transition);
|
||||||
|
|
||||||
void saveWindowTitleSwitches(obs_data_t *obj);
|
void saveWindowTitleSwitches(obs_data_t *obj);
|
||||||
void saveScreenRegionSwitches(obs_data_t *obj);
|
void saveScreenRegionSwitches(obs_data_t *obj);
|
||||||
@@ -392,6 +514,7 @@ struct SwitcherData {
|
|||||||
void saveFileSwitches(obs_data_t *obj);
|
void saveFileSwitches(obs_data_t *obj);
|
||||||
void saveMediaSwitches(obs_data_t *obj);
|
void saveMediaSwitches(obs_data_t *obj);
|
||||||
void saveTimeSwitches(obs_data_t *obj);
|
void saveTimeSwitches(obs_data_t *obj);
|
||||||
|
void saveAudioSwitches(obs_data_t *obj);
|
||||||
void saveGeneralSettings(obs_data_t *obj);
|
void saveGeneralSettings(obs_data_t *obj);
|
||||||
|
|
||||||
void loadWindowTitleSwitches(obs_data_t *obj);
|
void loadWindowTitleSwitches(obs_data_t *obj);
|
||||||
@@ -405,6 +528,7 @@ struct SwitcherData {
|
|||||||
void loadFileSwitches(obs_data_t *obj);
|
void loadFileSwitches(obs_data_t *obj);
|
||||||
void loadMediaSwitches(obs_data_t *obj);
|
void loadMediaSwitches(obs_data_t *obj);
|
||||||
void loadTimeSwitches(obs_data_t *obj);
|
void loadTimeSwitches(obs_data_t *obj);
|
||||||
|
void loadAudioSwitches(obs_data_t *obj);
|
||||||
void loadGeneralSettings(obs_data_t *obj);
|
void loadGeneralSettings(obs_data_t *obj);
|
||||||
|
|
||||||
void Prune()
|
void Prune()
|
||||||
@@ -515,6 +639,15 @@ struct SwitcherData {
|
|||||||
mediaSwitches.erase(mediaSwitches.begin() +
|
mediaSwitches.erase(mediaSwitches.begin() +
|
||||||
i--);
|
i--);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < audioSwitches.size(); i++) {
|
||||||
|
AudioSwitch &s = audioSwitches[i];
|
||||||
|
if ((!s.usePreviousScene &&
|
||||||
|
!WeakSourceValid(s.scene)) ||
|
||||||
|
!WeakSourceValid(s.transition))
|
||||||
|
audioSwitches.erase(audioSwitches.begin() +
|
||||||
|
i--);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
inline ~SwitcherData() { Stop(); }
|
inline ~SwitcherData() { Stop(); }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#include <obs.hpp>
|
#include <obs.hpp>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
#include "switcher-data-structs.hpp"
|
|
||||||
|
|
||||||
static inline bool WeakSourceValid(obs_weak_source_t *ws)
|
static inline bool WeakSourceValid(obs_weak_source_t *ws)
|
||||||
{
|
{
|
||||||
@@ -170,11 +169,70 @@ MakeMediaSwitchName(const QString &source, const QString &scene,
|
|||||||
return switchName;
|
return switchName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ANY_DAY = 0,
|
||||||
|
MONDAY = 1,
|
||||||
|
TUSEDAY = 2,
|
||||||
|
WEDNESDAY = 3,
|
||||||
|
THURSDAY = 4,
|
||||||
|
FRIDAY = 5,
|
||||||
|
SATURDAY = 6,
|
||||||
|
SUNDAY = 7,
|
||||||
|
LIVE = 8
|
||||||
|
} timeTrigger;
|
||||||
|
|
||||||
static inline QString MakeTimeSwitchName(const QString &scene,
|
static inline QString MakeTimeSwitchName(const QString &scene,
|
||||||
const QString &transition, QTime &time)
|
const QString &transition,
|
||||||
|
const timeTrigger &trigger,
|
||||||
|
const QTime &time)
|
||||||
{
|
{
|
||||||
QString switchName = QStringLiteral("At ") + time.toString() +
|
QString switchName;
|
||||||
QStringLiteral(" switch to ") + scene +
|
|
||||||
|
switch (trigger) {
|
||||||
|
case ANY_DAY:
|
||||||
|
switchName = QStringLiteral("On any weekday");
|
||||||
|
break;
|
||||||
|
case MONDAY:
|
||||||
|
switchName = QStringLiteral("Mondays");
|
||||||
|
break;
|
||||||
|
case TUSEDAY:
|
||||||
|
switchName = QStringLiteral("Tusedays");
|
||||||
|
break;
|
||||||
|
case WEDNESDAY:
|
||||||
|
switchName = QStringLiteral("Wednesdays");
|
||||||
|
break;
|
||||||
|
case THURSDAY:
|
||||||
|
switchName = QStringLiteral("Thursdays");
|
||||||
|
break;
|
||||||
|
case FRIDAY:
|
||||||
|
switchName = QStringLiteral("Fridays");
|
||||||
|
break;
|
||||||
|
case SATURDAY:
|
||||||
|
switchName = QStringLiteral("Saturdays");
|
||||||
|
break;
|
||||||
|
case SUNDAY:
|
||||||
|
switchName = QStringLiteral("Sundays");
|
||||||
|
break;
|
||||||
|
case LIVE:
|
||||||
|
switchName = QStringLiteral(
|
||||||
|
"Relative to starting streaming / recording");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switchName += QStringLiteral(" at ") + time.toString() +
|
||||||
|
QStringLiteral(" switch to ") + scene +
|
||||||
|
QStringLiteral(" using ") + transition;
|
||||||
|
return switchName;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QString MakeAudioSwitchName(const QString &scene,
|
||||||
|
const QString &transition,
|
||||||
|
const QString &audioSrouce,
|
||||||
|
const int &volume)
|
||||||
|
{
|
||||||
|
QString switchName = QStringLiteral("When volume of ") + audioSrouce +
|
||||||
|
QStringLiteral(" is above ") +
|
||||||
|
QString::number(volume) +
|
||||||
|
QStringLiteral("% switch to ") + scene +
|
||||||
QStringLiteral(" using ") + transition;
|
QStringLiteral(" using ") + transition;
|
||||||
return switchName;
|
return switchName;
|
||||||
}
|
}
|
||||||
|
|||||||
245
src/headers/volume-control.hpp
Normal file
245
src/headers/volume-control.hpp
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <obs.hpp>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QPaintEvent>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class QPushButton;
|
||||||
|
class VolumeMeterTimer;
|
||||||
|
|
||||||
|
class VolumeMeter : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QColor backgroundNominalColor READ getBackgroundNominalColor
|
||||||
|
WRITE setBackgroundNominalColor DESIGNABLE true)
|
||||||
|
Q_PROPERTY(QColor backgroundWarningColor READ getBackgroundWarningColor
|
||||||
|
WRITE setBackgroundWarningColor DESIGNABLE true)
|
||||||
|
Q_PROPERTY(QColor backgroundErrorColor READ getBackgroundErrorColor
|
||||||
|
WRITE setBackgroundErrorColor DESIGNABLE true)
|
||||||
|
Q_PROPERTY(QColor foregroundNominalColor READ getForegroundNominalColor
|
||||||
|
WRITE setForegroundNominalColor DESIGNABLE true)
|
||||||
|
Q_PROPERTY(QColor foregroundWarningColor READ getForegroundWarningColor
|
||||||
|
WRITE setForegroundWarningColor DESIGNABLE true)
|
||||||
|
Q_PROPERTY(QColor foregroundErrorColor READ getForegroundErrorColor
|
||||||
|
WRITE setForegroundErrorColor DESIGNABLE true)
|
||||||
|
Q_PROPERTY(QColor clipColor READ getClipColor WRITE setClipColor
|
||||||
|
DESIGNABLE true)
|
||||||
|
Q_PROPERTY(QColor magnitudeColor READ getMagnitudeColor WRITE
|
||||||
|
setMagnitudeColor DESIGNABLE true)
|
||||||
|
Q_PROPERTY(QColor majorTickColor READ getMajorTickColor WRITE
|
||||||
|
setMajorTickColor DESIGNABLE true)
|
||||||
|
Q_PROPERTY(QColor minorTickColor READ getMinorTickColor WRITE
|
||||||
|
setMinorTickColor DESIGNABLE true)
|
||||||
|
|
||||||
|
// Levels are denoted in dBFS.
|
||||||
|
Q_PROPERTY(qreal minimumLevel READ getMinimumLevel WRITE setMinimumLevel
|
||||||
|
DESIGNABLE true)
|
||||||
|
Q_PROPERTY(qreal warningLevel READ getWarningLevel WRITE setWarningLevel
|
||||||
|
DESIGNABLE true)
|
||||||
|
Q_PROPERTY(qreal errorLevel READ getErrorLevel WRITE setErrorLevel
|
||||||
|
DESIGNABLE true)
|
||||||
|
Q_PROPERTY(qreal clipLevel READ getClipLevel WRITE setClipLevel
|
||||||
|
DESIGNABLE true)
|
||||||
|
Q_PROPERTY(qreal minimumInputLevel READ getMinimumInputLevel WRITE
|
||||||
|
setMinimumInputLevel DESIGNABLE true)
|
||||||
|
|
||||||
|
// Rates are denoted in dB/second.
|
||||||
|
Q_PROPERTY(qreal peakDecayRate READ getPeakDecayRate WRITE
|
||||||
|
setPeakDecayRate DESIGNABLE true)
|
||||||
|
|
||||||
|
// Time in seconds for the VU meter to integrate over.
|
||||||
|
Q_PROPERTY(
|
||||||
|
qreal magnitudeIntegrationTime READ getMagnitudeIntegrationTime
|
||||||
|
WRITE setMagnitudeIntegrationTime DESIGNABLE true)
|
||||||
|
|
||||||
|
// Duration is denoted in seconds.
|
||||||
|
Q_PROPERTY(qreal peakHoldDuration READ getPeakHoldDuration WRITE
|
||||||
|
setPeakHoldDuration DESIGNABLE true)
|
||||||
|
Q_PROPERTY(qreal inputPeakHoldDuration READ getInputPeakHoldDuration
|
||||||
|
WRITE setInputPeakHoldDuration DESIGNABLE true)
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void ClipEnding();
|
||||||
|
|
||||||
|
private:
|
||||||
|
obs_volmeter_t *obs_volmeter;
|
||||||
|
static QWeakPointer<VolumeMeterTimer> updateTimer;
|
||||||
|
QSharedPointer<VolumeMeterTimer> updateTimerRef;
|
||||||
|
|
||||||
|
inline void resetLevels();
|
||||||
|
inline void handleChannelCofigurationChange();
|
||||||
|
inline bool detectIdle(uint64_t ts);
|
||||||
|
inline void calculateBallistics(uint64_t ts,
|
||||||
|
qreal timeSinceLastRedraw = 0.0);
|
||||||
|
inline void calculateBallisticsForChannel(int channelNr, uint64_t ts,
|
||||||
|
qreal timeSinceLastRedraw);
|
||||||
|
|
||||||
|
void paintInputMeter(QPainter &painter, int x, int y, int width,
|
||||||
|
int height, float peakHold);
|
||||||
|
void paintHMeter(QPainter &painter, int x, int y, int width, int height,
|
||||||
|
float magnitude, float peak, float peakHold);
|
||||||
|
void paintHTicks(QPainter &painter, int x, int y, int width,
|
||||||
|
int height);
|
||||||
|
void paintVMeter(QPainter &painter, int x, int y, int width, int height,
|
||||||
|
float magnitude, float peak, float peakHold);
|
||||||
|
void paintVTicks(QPainter &painter, int x, int y, int height);
|
||||||
|
|
||||||
|
QMutex dataMutex;
|
||||||
|
|
||||||
|
uint64_t currentLastUpdateTime = 0;
|
||||||
|
float currentMagnitude[MAX_AUDIO_CHANNELS];
|
||||||
|
float currentPeak[MAX_AUDIO_CHANNELS];
|
||||||
|
float currentInputPeak[MAX_AUDIO_CHANNELS];
|
||||||
|
|
||||||
|
QPixmap *tickPaintCache = nullptr;
|
||||||
|
int displayNrAudioChannels = 0;
|
||||||
|
float displayMagnitude[MAX_AUDIO_CHANNELS];
|
||||||
|
float displayPeak[MAX_AUDIO_CHANNELS];
|
||||||
|
float displayPeakHold[MAX_AUDIO_CHANNELS];
|
||||||
|
uint64_t displayPeakHoldLastUpdateTime[MAX_AUDIO_CHANNELS];
|
||||||
|
float displayInputPeakHold[MAX_AUDIO_CHANNELS];
|
||||||
|
uint64_t displayInputPeakHoldLastUpdateTime[MAX_AUDIO_CHANNELS];
|
||||||
|
|
||||||
|
QFont tickFont;
|
||||||
|
QColor backgroundNominalColor;
|
||||||
|
QColor backgroundWarningColor;
|
||||||
|
QColor backgroundErrorColor;
|
||||||
|
QColor foregroundNominalColor;
|
||||||
|
QColor foregroundWarningColor;
|
||||||
|
QColor foregroundErrorColor;
|
||||||
|
QColor clipColor;
|
||||||
|
QColor magnitudeColor;
|
||||||
|
QColor majorTickColor;
|
||||||
|
QColor minorTickColor;
|
||||||
|
qreal minimumLevel;
|
||||||
|
qreal warningLevel;
|
||||||
|
qreal errorLevel;
|
||||||
|
qreal clipLevel;
|
||||||
|
qreal minimumInputLevel;
|
||||||
|
qreal peakDecayRate;
|
||||||
|
qreal magnitudeIntegrationTime;
|
||||||
|
qreal peakHoldDuration;
|
||||||
|
qreal inputPeakHoldDuration;
|
||||||
|
|
||||||
|
uint64_t lastRedrawTime = 0;
|
||||||
|
int channels = 0;
|
||||||
|
bool clipping = false;
|
||||||
|
bool vertical;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit VolumeMeter(QWidget *parent = nullptr,
|
||||||
|
obs_volmeter_t *obs_volmeter = nullptr,
|
||||||
|
bool vertical = false);
|
||||||
|
~VolumeMeter();
|
||||||
|
|
||||||
|
void setLevels(const float magnitude[MAX_AUDIO_CHANNELS],
|
||||||
|
const float peak[MAX_AUDIO_CHANNELS],
|
||||||
|
const float inputPeak[MAX_AUDIO_CHANNELS]);
|
||||||
|
|
||||||
|
QColor getBackgroundNominalColor() const;
|
||||||
|
void setBackgroundNominalColor(QColor c);
|
||||||
|
QColor getBackgroundWarningColor() const;
|
||||||
|
void setBackgroundWarningColor(QColor c);
|
||||||
|
QColor getBackgroundErrorColor() const;
|
||||||
|
void setBackgroundErrorColor(QColor c);
|
||||||
|
QColor getForegroundNominalColor() const;
|
||||||
|
void setForegroundNominalColor(QColor c);
|
||||||
|
QColor getForegroundWarningColor() const;
|
||||||
|
void setForegroundWarningColor(QColor c);
|
||||||
|
QColor getForegroundErrorColor() const;
|
||||||
|
void setForegroundErrorColor(QColor c);
|
||||||
|
QColor getClipColor() const;
|
||||||
|
void setClipColor(QColor c);
|
||||||
|
QColor getMagnitudeColor() const;
|
||||||
|
void setMagnitudeColor(QColor c);
|
||||||
|
QColor getMajorTickColor() const;
|
||||||
|
void setMajorTickColor(QColor c);
|
||||||
|
QColor getMinorTickColor() const;
|
||||||
|
void setMinorTickColor(QColor c);
|
||||||
|
qreal getMinimumLevel() const;
|
||||||
|
void setMinimumLevel(qreal v);
|
||||||
|
qreal getWarningLevel() const;
|
||||||
|
void setWarningLevel(qreal v);
|
||||||
|
qreal getErrorLevel() const;
|
||||||
|
void setErrorLevel(qreal v);
|
||||||
|
qreal getClipLevel() const;
|
||||||
|
void setClipLevel(qreal v);
|
||||||
|
qreal getMinimumInputLevel() const;
|
||||||
|
void setMinimumInputLevel(qreal v);
|
||||||
|
qreal getPeakDecayRate() const;
|
||||||
|
void setPeakDecayRate(qreal v);
|
||||||
|
qreal getMagnitudeIntegrationTime() const;
|
||||||
|
void setMagnitudeIntegrationTime(qreal v);
|
||||||
|
qreal getPeakHoldDuration() const;
|
||||||
|
void setPeakHoldDuration(qreal v);
|
||||||
|
qreal getInputPeakHoldDuration() const;
|
||||||
|
void setInputPeakHoldDuration(qreal v);
|
||||||
|
void setPeakMeterType(enum obs_peak_meter_type peakMeterType);
|
||||||
|
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VolumeMeterTimer : public QTimer {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline VolumeMeterTimer() : QTimer() {}
|
||||||
|
|
||||||
|
void AddVolControl(VolumeMeter *meter);
|
||||||
|
void RemoveVolControl(VolumeMeter *meter);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void timerEvent(QTimerEvent *event) override;
|
||||||
|
QList<VolumeMeter *> volumeMeters;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
class QSlider;
|
||||||
|
class MuteCheckBox;
|
||||||
|
|
||||||
|
class VolControl : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
OBSSource source;
|
||||||
|
QLabel *nameLabel;
|
||||||
|
QLabel *volLabel;
|
||||||
|
VolumeMeter *volMeter;
|
||||||
|
QSlider *slider;
|
||||||
|
float levelTotal;
|
||||||
|
float levelCount;
|
||||||
|
obs_fader_t *obs_fader;
|
||||||
|
obs_volmeter_t *obs_volmeter;
|
||||||
|
bool vertical;
|
||||||
|
|
||||||
|
static void OBSVolumeChanged(void *param, float db);
|
||||||
|
static void OBSVolumeLevel(void *data,
|
||||||
|
const float magnitude[MAX_AUDIO_CHANNELS],
|
||||||
|
const float peak[MAX_AUDIO_CHANNELS],
|
||||||
|
const float inputPeak[MAX_AUDIO_CHANNELS]);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void SliderChanged(int vol);
|
||||||
|
void updateText();
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit VolControl(OBSSource source, bool vertical = false);
|
||||||
|
~VolControl();
|
||||||
|
|
||||||
|
inline obs_source_t *GetSource() const { return source; }
|
||||||
|
|
||||||
|
QString GetName() const;
|
||||||
|
void SetName(const QString &newName);
|
||||||
|
|
||||||
|
void SetMeterDecayRate(qreal q);
|
||||||
|
void setPeakMeterType(enum obs_peak_meter_type peakMeterType);
|
||||||
|
|
||||||
|
void EnableSlider(bool enable);
|
||||||
|
|
||||||
|
QSlider *GetSlider() const;
|
||||||
|
};
|
||||||
@@ -17,7 +17,7 @@ void startHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
|
|||||||
if (hotkeyData != NULL) {
|
if (hotkeyData != NULL) {
|
||||||
char *path = obs_module_config_path("");
|
char *path = obs_module_config_path("");
|
||||||
std::ofstream file;
|
std::ofstream file;
|
||||||
file.open(std::string(path).append(START_HOTKEY_PATH),
|
file.open(std::string(path).append(start_hotkey_path),
|
||||||
std::ofstream::trunc);
|
std::ofstream::trunc);
|
||||||
if (file.is_open()) {
|
if (file.is_open()) {
|
||||||
size_t num = obs_data_array_count(hotkeyData);
|
size_t num = obs_data_array_count(hotkeyData);
|
||||||
@@ -51,7 +51,7 @@ void stopHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
|
|||||||
if (hotkeyData != NULL) {
|
if (hotkeyData != NULL) {
|
||||||
char *path = obs_module_config_path("");
|
char *path = obs_module_config_path("");
|
||||||
std::ofstream file;
|
std::ofstream file;
|
||||||
file.open(std::string(path).append(STOP_HOTKEY_PATH),
|
file.open(std::string(path).append(stop_hotkey_path),
|
||||||
std::ofstream::trunc);
|
std::ofstream::trunc);
|
||||||
if (file.is_open()) {
|
if (file.is_open()) {
|
||||||
size_t num = obs_data_array_count(hotkeyData);
|
size_t num = obs_data_array_count(hotkeyData);
|
||||||
@@ -87,7 +87,7 @@ void startStopToggleHotkeyFunc(void *data, obs_hotkey_id id,
|
|||||||
if (hotkeyData != NULL) {
|
if (hotkeyData != NULL) {
|
||||||
char *path = obs_module_config_path("");
|
char *path = obs_module_config_path("");
|
||||||
std::ofstream file;
|
std::ofstream file;
|
||||||
file.open(std::string(path).append(TOGGLE_HOTKEY_PATH),
|
file.open(std::string(path).append(toggle_hotkey_path),
|
||||||
std::ofstream::trunc);
|
std::ofstream::trunc);
|
||||||
if (file.is_open()) {
|
if (file.is_open()) {
|
||||||
size_t num = obs_data_array_count(hotkeyData);
|
size_t num = obs_data_array_count(hotkeyData);
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ void SceneSwitcher::UpdateIdleDataTransition(const QString &name)
|
|||||||
|
|
||||||
void SceneSwitcher::UpdateIdleDataScene(const QString &name)
|
void SceneSwitcher::UpdateIdleDataScene(const QString &name)
|
||||||
{
|
{
|
||||||
switcher->idleData.usePreviousScene = (name == PREVIOUS_SCENE_NAME);
|
switcher->idleData.usePreviousScene = (name == previous_scene_name);
|
||||||
obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData());
|
obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData());
|
||||||
obs_weak_source_t *ws = obs_source_get_weak_source(scene);
|
obs_weak_source_t *ws = obs_source_get_weak_source(scene);
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ void SwitcherData::saveIdleSwitches(obs_data_t *obj)
|
|||||||
obs_data_set_bool(obj, "idleEnable", switcher->idleData.idleEnable);
|
obs_data_set_bool(obj, "idleEnable", switcher->idleData.idleEnable);
|
||||||
obs_data_set_string(obj, "idleSceneName",
|
obs_data_set_string(obj, "idleSceneName",
|
||||||
switcher->idleData.usePreviousScene
|
switcher->idleData.usePreviousScene
|
||||||
? PREVIOUS_SCENE_NAME
|
? previous_scene_name
|
||||||
: idleSceneName.c_str());
|
: idleSceneName.c_str());
|
||||||
obs_data_set_string(obj, "idleTransitionName",
|
obs_data_set_string(obj, "idleTransitionName",
|
||||||
idleTransitionName.c_str());
|
idleTransitionName.c_str());
|
||||||
@@ -256,10 +256,10 @@ void SwitcherData::loadIdleSwitches(obs_data_t *obj)
|
|||||||
GetWeakTransitionByName(idleTransitionName.c_str());
|
GetWeakTransitionByName(idleTransitionName.c_str());
|
||||||
obs_data_set_default_bool(obj, "idleEnable", false);
|
obs_data_set_default_bool(obj, "idleEnable", false);
|
||||||
switcher->idleData.idleEnable = obs_data_get_bool(obj, "idleEnable");
|
switcher->idleData.idleEnable = obs_data_get_bool(obj, "idleEnable");
|
||||||
obs_data_set_default_int(obj, "idleTime", DEFAULT_IDLE_TIME);
|
obs_data_set_default_int(obj, "idleTime", default_idle_time);
|
||||||
switcher->idleData.time = obs_data_get_int(obj, "idleTime");
|
switcher->idleData.time = obs_data_get_int(obj, "idleTime");
|
||||||
switcher->idleData.usePreviousScene =
|
switcher->idleData.usePreviousScene =
|
||||||
(idleSceneName == PREVIOUS_SCENE_NAME);
|
(idleSceneName == previous_scene_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneSwitcher::setupIdleTab()
|
void SceneSwitcher::setupIdleTab()
|
||||||
@@ -279,7 +279,7 @@ void SceneSwitcher::setupIdleTab()
|
|||||||
ui->idleCheckBox->setChecked(switcher->idleData.idleEnable);
|
ui->idleCheckBox->setChecked(switcher->idleData.idleEnable);
|
||||||
ui->idleScenes->setCurrentText(
|
ui->idleScenes->setCurrentText(
|
||||||
switcher->idleData.usePreviousScene
|
switcher->idleData.usePreviousScene
|
||||||
? PREVIOUS_SCENE_NAME
|
? previous_scene_name
|
||||||
: GetWeakSourceName(switcher->idleData.scene).c_str());
|
: GetWeakSourceName(switcher->idleData.scene).c_str());
|
||||||
ui->idleTransitions->setCurrentText(
|
ui->idleTransitions->setCurrentText(
|
||||||
GetWeakSourceName(switcher->idleData.transition).c_str());
|
GetWeakSourceName(switcher->idleData.transition).c_str());
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ void SceneSwitcher::on_mediaAdd_clicked()
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->mediaSwitches.emplace_back(
|
switcher->mediaSwitches.emplace_back(
|
||||||
scene, source, transition, state, restriction, time,
|
scene, source, transition, state, restriction, time,
|
||||||
(sceneName == QString(PREVIOUS_SCENE_NAME)),
|
(sceneName == QString(previous_scene_name)),
|
||||||
switchText.toUtf8().constData());
|
switchText.toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ void SwitcherData::saveMediaSwitches(obs_data_t *obj)
|
|||||||
obs_data_set_string(array_obj, "source", sourceName);
|
obs_data_set_string(array_obj, "source", sourceName);
|
||||||
obs_data_set_string(array_obj, "scene",
|
obs_data_set_string(array_obj, "scene",
|
||||||
s.usePreviousScene
|
s.usePreviousScene
|
||||||
? PREVIOUS_SCENE_NAME
|
? previous_scene_name
|
||||||
: sceneName);
|
: sceneName);
|
||||||
obs_data_set_string(array_obj, "transition",
|
obs_data_set_string(array_obj, "transition",
|
||||||
transitionName);
|
transitionName);
|
||||||
@@ -244,7 +244,7 @@ void SwitcherData::loadMediaSwitches(obs_data_t *obj)
|
|||||||
switcher->mediaSwitches.emplace_back(
|
switcher->mediaSwitches.emplace_back(
|
||||||
GetWeakSourceByName(scene), GetWeakSourceByName(source),
|
GetWeakSourceByName(scene), GetWeakSourceByName(source),
|
||||||
GetWeakTransitionByName(transition), state, restriction,
|
GetWeakTransitionByName(transition), state, restriction,
|
||||||
time, (strcmp(scene, PREVIOUS_SCENE_NAME) == 0),
|
time, (strcmp(scene, previous_scene_name) == 0),
|
||||||
mediaStr);
|
mediaStr);
|
||||||
|
|
||||||
obs_data_release(array_obj);
|
obs_data_release(array_obj);
|
||||||
@@ -287,7 +287,7 @@ void SceneSwitcher::setupMediaTab()
|
|||||||
for (auto &s : switcher->mediaSwitches) {
|
for (auto &s : switcher->mediaSwitches) {
|
||||||
std::string sourceName = GetWeakSourceName(s.source);
|
std::string sourceName = GetWeakSourceName(s.source);
|
||||||
std::string sceneName = (s.usePreviousScene)
|
std::string sceneName = (s.usePreviousScene)
|
||||||
? PREVIOUS_SCENE_NAME
|
? previous_scene_name
|
||||||
: GetWeakSourceName(s.scene);
|
: GetWeakSourceName(s.scene);
|
||||||
std::string transitionName = GetWeakSourceName(s.transition);
|
std::string transitionName = GetWeakSourceName(s.transition);
|
||||||
QString listText = MakeMediaSwitchName(
|
QString listText = MakeMediaSwitchName(
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ bool SwitcherData::prioFuncsValid()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int p : functionNamesByPriority) {
|
for (int p : functionNamesByPriority) {
|
||||||
if (p < 0 || p > 7)
|
if (p < 0 || p > 8)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->sceneRoundTripSwitches.emplace_back(
|
switcher->sceneRoundTripSwitches.emplace_back(
|
||||||
source1, source2, transition, delay,
|
source1, source2, transition, delay,
|
||||||
(scene2Name == QString(PREVIOUS_SCENE_NAME)),
|
(scene2Name == QString(previous_scene_name)),
|
||||||
text.toUtf8().constData());
|
text.toUtf8().constData());
|
||||||
} else {
|
} else {
|
||||||
QListWidgetItem *item = ui->sceneRoundTrips->item(idx);
|
QListWidgetItem *item = ui->sceneRoundTrips->item(idx);
|
||||||
@@ -93,7 +93,7 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
|
|||||||
s.transition = transition;
|
s.transition = transition;
|
||||||
s.usePreviousScene =
|
s.usePreviousScene =
|
||||||
(scene2Name ==
|
(scene2Name ==
|
||||||
QString(PREVIOUS_SCENE_NAME));
|
QString(previous_scene_name));
|
||||||
s.sceneRoundTripStr =
|
s.sceneRoundTripStr =
|
||||||
text.toUtf8().constData();
|
text.toUtf8().constData();
|
||||||
break;
|
break;
|
||||||
@@ -164,7 +164,7 @@ bool oldSceneRoundTripLoad(QFile *file)
|
|||||||
GetWeakTransitionByQString(lines[4]);
|
GetWeakTransitionByQString(lines[4]);
|
||||||
|
|
||||||
if (WeakSourceValid(scene1) &&
|
if (WeakSourceValid(scene1) &&
|
||||||
((lines[1] == QString(PREVIOUS_SCENE_NAME)) ||
|
((lines[1] == QString(previous_scene_name)) ||
|
||||||
(WeakSourceValid(scene2))) &&
|
(WeakSourceValid(scene2))) &&
|
||||||
WeakSourceValid(transition)) {
|
WeakSourceValid(transition)) {
|
||||||
newSceneRoundTripSwitch.emplace_back(
|
newSceneRoundTripSwitch.emplace_back(
|
||||||
@@ -175,7 +175,7 @@ bool oldSceneRoundTripLoad(QFile *file)
|
|||||||
lines[4]),
|
lines[4]),
|
||||||
lines[2].toDouble() / 1000.,
|
lines[2].toDouble() / 1000.,
|
||||||
(lines[1] ==
|
(lines[1] ==
|
||||||
QString(PREVIOUS_SCENE_NAME)),
|
QString(previous_scene_name)),
|
||||||
lines[3].toStdString()));
|
lines[3].toStdString()));
|
||||||
}
|
}
|
||||||
lines.clear();
|
lines.clear();
|
||||||
@@ -380,7 +380,7 @@ void SwitcherData::saveSceneRoundTripSwitches(obs_data_t *obj)
|
|||||||
sceneName1);
|
sceneName1);
|
||||||
obs_data_set_string(array_obj, "sceneRoundTripScene2",
|
obs_data_set_string(array_obj, "sceneRoundTripScene2",
|
||||||
s.usePreviousScene
|
s.usePreviousScene
|
||||||
? PREVIOUS_SCENE_NAME
|
? previous_scene_name
|
||||||
: sceneName2);
|
: sceneName2);
|
||||||
obs_data_set_string(array_obj, "transition",
|
obs_data_set_string(array_obj, "transition",
|
||||||
transitionName);
|
transitionName);
|
||||||
@@ -444,7 +444,7 @@ void SwitcherData::loadSceneRoundTripSwitches(obs_data_t *obj)
|
|||||||
GetWeakSourceByName(scene1),
|
GetWeakSourceByName(scene1),
|
||||||
GetWeakSourceByName(scene2),
|
GetWeakSourceByName(scene2),
|
||||||
GetWeakTransitionByName(transition), delay,
|
GetWeakTransitionByName(transition), delay,
|
||||||
(strcmp(scene2, PREVIOUS_SCENE_NAME) == 0),
|
(strcmp(scene2, previous_scene_name) == 0),
|
||||||
sceneRoundTripStr);
|
sceneRoundTripStr);
|
||||||
|
|
||||||
obs_data_release(array_obj);
|
obs_data_release(array_obj);
|
||||||
@@ -462,7 +462,7 @@ void SceneSwitcher::setupSequenceTab()
|
|||||||
for (auto &s : switcher->sceneRoundTripSwitches) {
|
for (auto &s : switcher->sceneRoundTripSwitches) {
|
||||||
std::string sceneName1 = GetWeakSourceName(s.scene1);
|
std::string sceneName1 = GetWeakSourceName(s.scene1);
|
||||||
std::string sceneName2 = (s.usePreviousScene)
|
std::string sceneName2 = (s.usePreviousScene)
|
||||||
? PREVIOUS_SCENE_NAME
|
? previous_scene_name
|
||||||
: GetWeakSourceName(s.scene2);
|
: GetWeakSourceName(s.scene2);
|
||||||
std::string transitionName = GetWeakSourceName(s.transition);
|
std::string transitionName = GetWeakSourceName(s.transition);
|
||||||
QString text = MakeSceneRoundTripSwitchName(
|
QString text = MakeSceneRoundTripSwitchName(
|
||||||
|
|||||||
@@ -1,5 +1,16 @@
|
|||||||
#include "headers/advanced-scene-switcher.hpp"
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
|
|
||||||
|
static std::vector<std::pair<std::string, timeTrigger>> triggerTable = {
|
||||||
|
{"On any day", timeTrigger::ANY_DAY},
|
||||||
|
{"Mondays", timeTrigger::MONDAY},
|
||||||
|
{"Tuesdays", timeTrigger::TUSEDAY},
|
||||||
|
{"Wednesdays", timeTrigger::WEDNESDAY},
|
||||||
|
{"Thursdays", timeTrigger::THURSDAY},
|
||||||
|
{"Fridays", timeTrigger::FRIDAY},
|
||||||
|
{"Saturdays", timeTrigger::SATURDAY},
|
||||||
|
{"Sundays", timeTrigger::SUNDAY},
|
||||||
|
{"Atfer streaming/recording start", timeTrigger::LIVE}};
|
||||||
|
|
||||||
void SceneSwitcher::on_timeSwitches_currentRowChanged(int idx)
|
void SceneSwitcher::on_timeSwitches_currentRowChanged(int idx)
|
||||||
{
|
{
|
||||||
if (loading)
|
if (loading)
|
||||||
@@ -18,6 +29,7 @@ void SceneSwitcher::on_timeSwitches_currentRowChanged(int idx)
|
|||||||
QString transitionName =
|
QString transitionName =
|
||||||
GetWeakSourceName(s.transition).c_str();
|
GetWeakSourceName(s.transition).c_str();
|
||||||
ui->timeScenes->setCurrentText(sceneName);
|
ui->timeScenes->setCurrentText(sceneName);
|
||||||
|
ui->timeTrigger->setCurrentIndex(s.trigger);
|
||||||
ui->timeEdit->setTime(s.time);
|
ui->timeEdit->setTime(s.time);
|
||||||
ui->timeTransitions->setCurrentText(transitionName);
|
ui->timeTransitions->setCurrentText(transitionName);
|
||||||
break;
|
break;
|
||||||
@@ -25,9 +37,10 @@ void SceneSwitcher::on_timeSwitches_currentRowChanged(int idx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SceneSwitcher::timeFindByData(const QString &timeStr)
|
int SceneSwitcher::timeFindByData(const timeTrigger &trigger, const QTime &time)
|
||||||
{
|
{
|
||||||
QRegExp rx("At " + timeStr + " switch to .*");
|
QRegExp rx(MakeTimeSwitchName(QStringLiteral(".*"),
|
||||||
|
QStringLiteral(".*"), trigger, time));
|
||||||
int count = ui->timeSwitches->count();
|
int count = ui->timeSwitches->count();
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
@@ -53,16 +66,26 @@ void SceneSwitcher::on_timeAdd_clicked()
|
|||||||
OBSWeakSource source = GetWeakSourceByQString(sceneName);
|
OBSWeakSource source = GetWeakSourceByQString(sceneName);
|
||||||
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
|
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
|
||||||
|
|
||||||
QString text = MakeTimeSwitchName(sceneName, transitionName, time);
|
std::string triggerStr = ui->timeTrigger->currentText().toStdString();
|
||||||
|
auto it = std::find_if(
|
||||||
|
triggerTable.begin(), triggerTable.end(),
|
||||||
|
[&triggerStr](
|
||||||
|
const std::pair<std::string, timeTrigger> &element) {
|
||||||
|
return element.first == triggerStr;
|
||||||
|
});
|
||||||
|
timeTrigger trigger = it->second;
|
||||||
|
|
||||||
|
QString text =
|
||||||
|
MakeTimeSwitchName(sceneName, transitionName, trigger, time);
|
||||||
QVariant v = QVariant::fromValue(text);
|
QVariant v = QVariant::fromValue(text);
|
||||||
|
|
||||||
int idx = timeFindByData(time.toString());
|
int idx = timeFindByData(trigger, time);
|
||||||
|
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->timeSwitches.emplace_back(
|
switcher->timeSwitches.emplace_back(
|
||||||
source, transition, time,
|
source, transition, trigger, time,
|
||||||
(sceneName == QString(PREVIOUS_SCENE_NAME)),
|
(sceneName == QString(previous_scene_name)),
|
||||||
text.toUtf8().constData());
|
text.toUtf8().constData());
|
||||||
|
|
||||||
QListWidgetItem *item =
|
QListWidgetItem *item =
|
||||||
@@ -76,20 +99,18 @@ void SceneSwitcher::on_timeAdd_clicked()
|
|||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
for (auto &s : switcher->timeSwitches) {
|
for (auto &s : switcher->timeSwitches) {
|
||||||
if (s.time == time) {
|
if (s.trigger == trigger && s.time == time) {
|
||||||
s.scene = source;
|
s.scene = source;
|
||||||
s.transition = transition;
|
s.transition = transition;
|
||||||
s.usePreviousScene =
|
s.usePreviousScene =
|
||||||
(sceneName ==
|
(sceneName ==
|
||||||
QString(PREVIOUS_SCENE_NAME));
|
QString(previous_scene_name));
|
||||||
s.timeSwitchStr =
|
s.timeSwitchStr =
|
||||||
text.toUtf8().constData();
|
text.toUtf8().constData();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->timeSwitches->sortItems();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,24 +140,82 @@ void SceneSwitcher::on_timeRemove_clicked()
|
|||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::on_timeUp_clicked()
|
||||||
|
{
|
||||||
|
int index = ui->timeSwitches->currentRow();
|
||||||
|
if (index != -1 && index != 0) {
|
||||||
|
ui->timeSwitches->insertItem(index - 1,
|
||||||
|
ui->timeSwitches->takeItem(index));
|
||||||
|
ui->timeSwitches->setCurrentRow(index - 1);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
|
||||||
|
iter_swap(switcher->timeSwitches.begin() + index,
|
||||||
|
switcher->timeSwitches.begin() + index - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneSwitcher::on_timeDown_clicked()
|
||||||
|
{
|
||||||
|
int index = ui->timeSwitches->currentRow();
|
||||||
|
if (index != -1 && index != ui->timeSwitches->count() - 1) {
|
||||||
|
ui->timeSwitches->insertItem(index + 1,
|
||||||
|
ui->timeSwitches->takeItem(index));
|
||||||
|
ui->timeSwitches->setCurrentRow(index + 1);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
|
||||||
|
iter_swap(switcher->timeSwitches.begin() + index,
|
||||||
|
switcher->timeSwitches.begin() + index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool timesAreInInterval(QTime &time1, QTime &time2, int &interval)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
QTime validSwitchTimeWindow = time1.addMSecs(interval);
|
||||||
|
|
||||||
|
ret = time1 <= time2 && time2 <= validSwitchTimeWindow;
|
||||||
|
// check for overflow
|
||||||
|
if (!ret && validSwitchTimeWindow.msecsSinceStartOfDay() < interval) {
|
||||||
|
ret = time2 >= time1 || time2 <= validSwitchTimeWindow;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkLiveTime(TimeSwitch &s, QDateTime &start, int &interval)
|
||||||
|
{
|
||||||
|
if (start.isNull())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QDateTime now = QDateTime::currentDateTime();
|
||||||
|
QTime timePassed = QTime(0, 0).addMSecs(start.msecsTo(now));
|
||||||
|
|
||||||
|
return timesAreInInterval(s.time, timePassed, interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkRegularTime(TimeSwitch &s, int &interval)
|
||||||
|
{
|
||||||
|
if (s.trigger != ANY_DAY &&
|
||||||
|
s.trigger != QDate::currentDate().dayOfWeek())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QTime now = QTime::currentTime();
|
||||||
|
|
||||||
|
return timesAreInInterval(s.time, now, interval);
|
||||||
|
}
|
||||||
|
|
||||||
void SwitcherData::checkTimeSwitch(bool &match, OBSWeakSource &scene,
|
void SwitcherData::checkTimeSwitch(bool &match, OBSWeakSource &scene,
|
||||||
OBSWeakSource &transition)
|
OBSWeakSource &transition)
|
||||||
{
|
{
|
||||||
if (timeSwitches.size() == 0)
|
if (timeSwitches.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QTime now = QTime::currentTime();
|
|
||||||
|
|
||||||
for (TimeSwitch &s : timeSwitches) {
|
for (TimeSwitch &s : timeSwitches) {
|
||||||
|
if (s.trigger == LIVE)
|
||||||
QTime validSwitchTimeWindow = s.time.addMSecs(interval);
|
match = checkLiveTime(s, liveTime, interval);
|
||||||
|
else
|
||||||
match = s.time <= now && now <= validSwitchTimeWindow;
|
match = checkRegularTime(s, interval);
|
||||||
if (!match &&
|
|
||||||
validSwitchTimeWindow.msecsSinceStartOfDay() < interval) {
|
|
||||||
// check for overflow
|
|
||||||
match = now >= s.time || now <= validSwitchTimeWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
scene = (s.usePreviousScene) ? previousScene : s.scene;
|
scene = (s.usePreviousScene) ? previousScene : s.scene;
|
||||||
@@ -168,10 +247,11 @@ void SwitcherData::saveTimeSwitches(obs_data_t *obj)
|
|||||||
obs_source_get_name(transition);
|
obs_source_get_name(transition);
|
||||||
obs_data_set_string(array_obj, "scene",
|
obs_data_set_string(array_obj, "scene",
|
||||||
s.usePreviousScene
|
s.usePreviousScene
|
||||||
? PREVIOUS_SCENE_NAME
|
? previous_scene_name
|
||||||
: sceneName);
|
: sceneName);
|
||||||
obs_data_set_string(array_obj, "transition",
|
obs_data_set_string(array_obj, "transition",
|
||||||
transitionName);
|
transitionName);
|
||||||
|
obs_data_set_int(array_obj, "trigger", s.trigger);
|
||||||
obs_data_set_string(
|
obs_data_set_string(
|
||||||
array_obj, "time",
|
array_obj, "time",
|
||||||
s.time.toString().toStdString().c_str());
|
s.time.toString().toStdString().c_str());
|
||||||
@@ -199,18 +279,20 @@ void SwitcherData::loadTimeSwitches(obs_data_t *obj)
|
|||||||
const char *scene = obs_data_get_string(array_obj, "scene");
|
const char *scene = obs_data_get_string(array_obj, "scene");
|
||||||
const char *transition =
|
const char *transition =
|
||||||
obs_data_get_string(array_obj, "transition");
|
obs_data_get_string(array_obj, "transition");
|
||||||
|
timeTrigger trigger =
|
||||||
|
(timeTrigger)obs_data_get_int(array_obj, "trigger");
|
||||||
QTime time = QTime::fromString(
|
QTime time = QTime::fromString(
|
||||||
obs_data_get_string(array_obj, "time"));
|
obs_data_get_string(array_obj, "time"));
|
||||||
|
|
||||||
std::string timeSwitchStr =
|
std::string timeSwitchStr =
|
||||||
MakeTimeSwitchName(scene, transition, time)
|
MakeTimeSwitchName(scene, transition, trigger, time)
|
||||||
.toUtf8()
|
.toUtf8()
|
||||||
.constData();
|
.constData();
|
||||||
|
|
||||||
switcher->timeSwitches.emplace_back(
|
switcher->timeSwitches.emplace_back(
|
||||||
GetWeakSourceByName(scene),
|
GetWeakSourceByName(scene),
|
||||||
GetWeakTransitionByName(transition), time,
|
GetWeakTransitionByName(transition), trigger, time,
|
||||||
(strcmp(scene, PREVIOUS_SCENE_NAME) == 0),
|
(strcmp(scene, previous_scene_name) == 0),
|
||||||
timeSwitchStr);
|
timeSwitchStr);
|
||||||
|
|
||||||
obs_data_release(array_obj);
|
obs_data_release(array_obj);
|
||||||
@@ -223,13 +305,24 @@ void SceneSwitcher::setupTimeTab()
|
|||||||
populateSceneSelection(ui->timeScenes, true);
|
populateSceneSelection(ui->timeScenes, true);
|
||||||
populateTransitionSelection(ui->timeTransitions);
|
populateTransitionSelection(ui->timeTransitions);
|
||||||
|
|
||||||
|
for (auto t : triggerTable) {
|
||||||
|
ui->timeTrigger->addItem(t.first.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// assuming the streaming / recording entry is always last
|
||||||
|
ui->timeTrigger->setItemData(
|
||||||
|
(int)triggerTable.size() - 1,
|
||||||
|
"The time relative to the start of streaming / recording will be used",
|
||||||
|
Qt::ToolTipRole);
|
||||||
|
|
||||||
for (auto &s : switcher->timeSwitches) {
|
for (auto &s : switcher->timeSwitches) {
|
||||||
std::string sceneName = (s.usePreviousScene)
|
std::string sceneName = (s.usePreviousScene)
|
||||||
? PREVIOUS_SCENE_NAME
|
? previous_scene_name
|
||||||
: GetWeakSourceName(s.scene);
|
: GetWeakSourceName(s.scene);
|
||||||
std::string transitionName = GetWeakSourceName(s.transition);
|
std::string transitionName = GetWeakSourceName(s.transition);
|
||||||
QString listText = MakeTimeSwitchName(
|
QString listText = MakeTimeSwitchName(sceneName.c_str(),
|
||||||
sceneName.c_str(), transitionName.c_str(), s.time);
|
transitionName.c_str(),
|
||||||
|
s.trigger, s.time);
|
||||||
|
|
||||||
QListWidgetItem *item =
|
QListWidgetItem *item =
|
||||||
new QListWidgetItem(listText, ui->timeSwitches);
|
new QListWidgetItem(listText, ui->timeSwitches);
|
||||||
|
|||||||
1002
src/volume-control.cpp
Normal file
1002
src/volume-control.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user