mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-29 04:36:21 -05:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
255d10e603 | ||
|
|
ab3e93ab84 | ||
|
|
3b5f88c14f | ||
|
|
2f33b6bdc3 | ||
|
|
3c1e240722 | ||
|
|
91831a1075 | ||
|
|
ccc824abc1 | ||
|
|
6f39d4648b | ||
|
|
74cb400426 | ||
|
|
910b1dde99 | ||
|
|
e462d7f420 | ||
|
|
0cdd8bf1d0 | ||
|
|
f8ad8c31be | ||
|
|
93c889c215 | ||
|
|
f8b505fa4e | ||
|
|
1516263d2a | ||
|
|
79f5ec340d | ||
|
|
cd54cc17c0 | ||
|
|
098159dc0f | ||
|
|
a4418996f4 | ||
|
|
340cb559ee | ||
|
|
eeefd8279f | ||
|
|
e62dc91cd7 | ||
|
|
536041abd2 | ||
|
|
d3ab9e01c5 | ||
|
|
2113025877 | ||
|
|
6aaffeb5a4 | ||
|
|
2a92df4f3c | ||
|
|
560044bbbf | ||
|
|
4bd8cdf5a0 | ||
|
|
c17cbb66d9 | ||
|
|
8d23dd46b0 | ||
|
|
bf70bd7c60 |
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@@ -35,6 +35,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
cd UI/frontend-plugins/${{ env.PLUGIN_NAME }}/CI/macos
|
||||
brew update
|
||||
brew bundle
|
||||
cd -
|
||||
- name: 'Install prerequisite: Pre-built dependencies'
|
||||
|
||||
@@ -13,6 +13,7 @@ if(BUILD_OUT_OF_TREE)
|
||||
find_package(LibObs REQUIRED)
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Libcurl REQUIRED)
|
||||
find_path(LIBOBS_FRONTEND_INCLUDE_DIR HINTS ${LIBOBS_INCLUDE_DIRS})
|
||||
find_file(LIBOBS_FRONTEND_API_LIB NAMES libobs-frontend-api.* HINTS ${LIBOBS_LIB} )
|
||||
|
||||
@@ -96,14 +97,16 @@ if(BUILD_OUT_OF_TREE)
|
||||
"${LIBOBS_INCLUDE_DIRS}"
|
||||
"${LIBOBS_FRONTEND_INCLUDE_DIR}"
|
||||
${Qt5Core_INCLUDES}
|
||||
${Qt5Widgets_INCLUDES})
|
||||
${Qt5Widgets_INCLUDES}
|
||||
${LIBCURL_INCLUDE_DIRS})
|
||||
|
||||
target_link_libraries(advanced-scene-switcher
|
||||
${advanced-scene-switcher_PLATFORM_LIBS}
|
||||
${LIBOBS_LIB}
|
||||
${LIBOBS_FRONTEND_API_LIB}
|
||||
Qt5::Core
|
||||
Qt5::Widgets)
|
||||
Qt5::Widgets
|
||||
${LIBCURL_LIBRARIES})
|
||||
|
||||
# Additional commands to install the module in the correct place.
|
||||
# Find all the translation files so we can copy them to the correct
|
||||
@@ -224,7 +227,8 @@ else ()
|
||||
${advanced-scene-switcher_PLATFORM_LIBS}
|
||||
obs-frontend-api
|
||||
Qt5::Widgets
|
||||
libobs)
|
||||
libobs
|
||||
${LIBCURL_LIBRARIES})
|
||||
|
||||
install_obs_plugin(advanced-scene-switcher data)
|
||||
endif()
|
||||
|
||||
@@ -37,15 +37,18 @@
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="movable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="generalTab">
|
||||
<attribute name="title">
|
||||
<string notr="true">General</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_41">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_55">
|
||||
<widget class="QLabel" name="label_63">
|
||||
<property name="text">
|
||||
<string>WARNING! Condition checking interval must be greater than the duration of transitions to avoid scene locking</string>
|
||||
</property>
|
||||
@@ -62,6 +65,42 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="2">
|
||||
<widget class="Line" name="line_13">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="10">
|
||||
<spacer name="horizontalSpacer_47">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<spacer name="horizontalSpacer_52">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="2" column="1">
|
||||
@@ -116,22 +155,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="2">
|
||||
@@ -217,13 +240,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="Line" name="line_13">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<spacer name="horizontalSpacer_46">
|
||||
<property name="orientation">
|
||||
@@ -240,19 +256,55 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<spacer name="horizontalSpacer_47">
|
||||
<item row="0" column="9">
|
||||
<widget class="QComboBox" name="startupBehavior"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
<width>10</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="7">
|
||||
<spacer name="horizontalSpacer_53">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="Line" name="line_18">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="8">
|
||||
<widget class="QLabel" name="label_64">
|
||||
<property name="text">
|
||||
<string>On startup:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@@ -394,7 +446,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_44">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_49">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_56">
|
||||
<property name="text">
|
||||
@@ -447,6 +499,44 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_47">
|
||||
<item>
|
||||
<widget class="QPushButton" name="exportSettings">
|
||||
<property name="text">
|
||||
<string>Export settings to file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="importSettings">
|
||||
<property name="text">
|
||||
<string>Import settings from file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_48">
|
||||
<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="Line" name="line_15">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
@@ -454,6 +544,37 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_14">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_48">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="verboseLogging">
|
||||
<property name="text">
|
||||
<string>Enable verbose logging (Only needed for debugging)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_49">
|
||||
<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="QPushButton" name="close">
|
||||
<property name="text">
|
||||
@@ -470,6 +591,20 @@
|
||||
<layout class="QVBoxLayout" name="verticalLayout_15">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="transitionOverridecheckBox">
|
||||
<property name="text">
|
||||
<string>Scene transitions defined in the scene switcher take priority over Transition Overrides defined per scene</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_17">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_36">
|
||||
<property name="text">
|
||||
@@ -1610,7 +1745,7 @@
|
||||
<attribute name="title">
|
||||
<string notr="true">Region</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_27">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
@@ -1810,7 +1945,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -1848,6 +1983,91 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_50">
|
||||
<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_16">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_51">
|
||||
<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="screenRegionUp">
|
||||
<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="screenRegionDown">
|
||||
<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_3">
|
||||
<property name="orientation">
|
||||
@@ -1867,9 +2087,9 @@
|
||||
</widget>
|
||||
<widget class="QWidget" name="mediaTab">
|
||||
<attribute name="title">
|
||||
<string notr="true"> Media </string>
|
||||
<string notr="true">Media</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_28">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_39">
|
||||
<item>
|
||||
@@ -1970,15 +2190,12 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_40">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="mediaAdd">
|
||||
<property name="maximumSize">
|
||||
@@ -2011,6 +2228,91 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_106">
|
||||
<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_34">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_107">
|
||||
<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="mediaUp">
|
||||
<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="mediaDown">
|
||||
<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_35">
|
||||
<property name="orientation">
|
||||
@@ -2129,10 +2431,20 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_36">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_62">
|
||||
<property name="text">
|
||||
<string>If the</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="fileType"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_44">
|
||||
<property name="text">
|
||||
<string>If the file</string>
|
||||
<string>file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -2155,6 +2467,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="remoteFileWarningLabel">
|
||||
<property name="text">
|
||||
<string>Please note that if you choose the remote option the scene switcher will try to access the remote location every x ms as specified on the General tab!</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="fileTextEdit"/>
|
||||
</item>
|
||||
@@ -2286,6 +2605,91 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_108">
|
||||
<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_35">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_109">
|
||||
<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="fileUp">
|
||||
<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="fileDown">
|
||||
<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_38">
|
||||
<property name="orientation">
|
||||
@@ -2527,10 +2931,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_41">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_99">
|
||||
<item>
|
||||
<widget class="QPushButton" name="timeAdd">
|
||||
<property name="maximumSize">
|
||||
@@ -2788,7 +3189,7 @@
|
||||
<attribute name="title">
|
||||
<string notr="true">Sequence</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<item>
|
||||
@@ -2847,13 +3248,16 @@
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="sceneRoundTripSpinBox">
|
||||
<property name="suffix">
|
||||
<string>s</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000.000000000000000</double>
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="sceneRoundTripDelayUnits"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
@@ -2895,15 +3299,12 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="sceneRoundTripAdd">
|
||||
<property name="maximumSize">
|
||||
@@ -2936,6 +3337,91 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_112">
|
||||
<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_37">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_113">
|
||||
<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="sceneRoundTripUp">
|
||||
<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="sceneRoundTripDown">
|
||||
<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_8">
|
||||
<property name="orientation">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -189,7 +189,92 @@ void SwitcherData::checkExeSwitch(bool &match, OBSWeakSource &scene,
|
||||
scene = s.mScene;
|
||||
transition = s.mTransition;
|
||||
|
||||
if (verbose)
|
||||
blog(LOG_INFO,
|
||||
"Advanced Scene Switcher exec match");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::saveExecutableSwitches(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *executableArray = obs_data_array_create();
|
||||
for (ExecutableSceneSwitch &s : switcher->executableSwitches) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(s.mScene);
|
||||
obs_source_t *transition =
|
||||
obs_weak_source_get_source(s.mTransition);
|
||||
|
||||
if (source && transition) {
|
||||
const char *sceneName = obs_source_get_name(source);
|
||||
const char *transitionName =
|
||||
obs_source_get_name(transition);
|
||||
obs_data_set_string(array_obj, "scene", sceneName);
|
||||
obs_data_set_string(array_obj, "transition",
|
||||
transitionName);
|
||||
obs_data_set_string(array_obj, "exefile",
|
||||
s.mExe.toUtf8());
|
||||
obs_data_set_bool(array_obj, "infocus", s.mInFocus);
|
||||
obs_data_array_push_back(executableArray, array_obj);
|
||||
obs_source_release(source);
|
||||
obs_source_release(transition);
|
||||
}
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "executableSwitches", executableArray);
|
||||
obs_data_array_release(executableArray);
|
||||
}
|
||||
|
||||
void SwitcherData::loadExecutableSwitches(obs_data_t *obj)
|
||||
{
|
||||
switcher->executableSwitches.clear();
|
||||
|
||||
obs_data_array_t *executableArray =
|
||||
obs_data_get_array(obj, "executableSwitches");
|
||||
size_t count = obs_data_array_count(executableArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj = obs_data_array_item(executableArray, i);
|
||||
|
||||
const char *scene = obs_data_get_string(array_obj, "scene");
|
||||
const char *transition =
|
||||
obs_data_get_string(array_obj, "transition");
|
||||
const char *exe = obs_data_get_string(array_obj, "exefile");
|
||||
bool infocus = obs_data_get_bool(array_obj, "infocus");
|
||||
|
||||
switcher->executableSwitches.emplace_back(
|
||||
GetWeakSourceByName(scene),
|
||||
GetWeakTransitionByName(transition), exe, infocus);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(executableArray);
|
||||
}
|
||||
|
||||
void SceneSwitcher::setupExecutableTab()
|
||||
{
|
||||
populateSceneSelection(ui->executableScenes, false);
|
||||
populateTransitionSelection(ui->executableTransitions);
|
||||
|
||||
QStringList processes;
|
||||
GetProcessList(processes);
|
||||
for (QString &process : processes)
|
||||
ui->executable->addItem(process);
|
||||
|
||||
for (auto &s : switcher->executableSwitches) {
|
||||
std::string sceneName = GetWeakSourceName(s.mScene);
|
||||
std::string transitionName = GetWeakSourceName(s.mTransition);
|
||||
QString text = MakeSwitchNameExecutable(sceneName.c_str(),
|
||||
s.mExe,
|
||||
transitionName.c_str(),
|
||||
s.mInFocus);
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->executables);
|
||||
item->setData(Qt::UserRole, s.mExe);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
#include <QTextStream>
|
||||
#include <QDateTime>
|
||||
#include <obs.hpp>
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
#define LOCAL_FILE_IDX 0
|
||||
#define REMOTE_FILE_IDX 1
|
||||
|
||||
void SceneSwitcher::on_browseButton_clicked()
|
||||
{
|
||||
QString path = QFileDialog::getOpenFileName(
|
||||
@@ -110,54 +115,114 @@ void SwitcherData::checkSwitchInfoFromFile(bool &match, OBSWeakSource &scene,
|
||||
}
|
||||
}
|
||||
|
||||
static size_t WriteCallback(void *contents, size_t size, size_t nmemb,
|
||||
void *userp)
|
||||
{
|
||||
((std::string *)userp)->append((char *)contents, size * nmemb);
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
std::string getRemoteData(std::string &url)
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
std::string readBuffer;
|
||||
|
||||
curl = curl_easy_init();
|
||||
if (curl) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||
res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
return readBuffer;
|
||||
}
|
||||
|
||||
bool compareIgnoringLineEnding(QString &s1, QString &s2)
|
||||
{
|
||||
/*
|
||||
Im using QTextStream here so the conversion between different lineendings is done by QT.
|
||||
QT itself uses only the linefeed internally so the input by the user is always using that,
|
||||
but the files selected by the user might use different line endings.
|
||||
If you are reading this and know of a cleaner way to do this, please let me know :)
|
||||
*/
|
||||
QTextStream s1stream(&s1);
|
||||
QTextStream s2stream(&s2);
|
||||
|
||||
while (!s1stream.atEnd() && !s2stream.atEnd()) {
|
||||
QString s1s = s1stream.readLine();
|
||||
QString s2s = s2stream.readLine();
|
||||
if (QString::compare(s1s, s2s, Qt::CaseSensitive) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkRemoteFileContent(FileSwitch &s)
|
||||
{
|
||||
std::string data = getRemoteData(s.file);
|
||||
bool ret = false;
|
||||
if (s.useRegex) {
|
||||
ret = QString::fromStdString(data).contains(
|
||||
QRegularExpression(QString::fromStdString(s.text)));
|
||||
return ret;
|
||||
}
|
||||
QString t = QString::fromStdString(s.text);
|
||||
QString d = QString::fromStdString(data);
|
||||
|
||||
return compareIgnoringLineEnding(t, d);
|
||||
}
|
||||
|
||||
bool checkLocalFileContent(FileSwitch &s)
|
||||
{
|
||||
bool equal = false;
|
||||
QString t = QString::fromStdString(s.text);
|
||||
QFile file(QString::fromStdString(s.file));
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
|
||||
if (s.useTime) {
|
||||
QDateTime newLastMod = QFileInfo(file).lastModified();
|
||||
if (s.lastMod == newLastMod)
|
||||
return false;
|
||||
s.lastMod = newLastMod;
|
||||
}
|
||||
|
||||
if (s.useRegex) {
|
||||
QTextStream in(&file);
|
||||
QRegExp rx(t);
|
||||
equal = rx.exactMatch(in.readAll());
|
||||
} else {
|
||||
QTextStream in(&file);
|
||||
QString filedata = in.readAll();
|
||||
equal = compareIgnoringLineEnding(filedata, t);
|
||||
}
|
||||
file.close();
|
||||
return equal;
|
||||
}
|
||||
|
||||
void SwitcherData::checkFileContent(bool &match, OBSWeakSource &scene,
|
||||
OBSWeakSource &transition)
|
||||
{
|
||||
for (FileSwitch &s : fileSwitches) {
|
||||
bool equal = false;
|
||||
QString t = QString::fromStdString(s.text);
|
||||
QFile file(QString::fromStdString(s.file));
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
continue;
|
||||
|
||||
if (s.useTime) {
|
||||
QDateTime newLastMod = QFileInfo(file).lastModified();
|
||||
if (s.lastMod == newLastMod)
|
||||
continue;
|
||||
s.lastMod = newLastMod;
|
||||
}
|
||||
|
||||
if (s.useRegex) {
|
||||
QTextStream in(&file);
|
||||
QRegExp rx(t);
|
||||
equal = rx.exactMatch(in.readAll());
|
||||
if (s.remote) {
|
||||
equal = checkRemoteFileContent(s);
|
||||
} else {
|
||||
/*Im using QTextStream here so the conversion between different lineendings is done by QT.
|
||||
*QT itself uses only the linefeed internally so the input by the user is always using that,
|
||||
*but the files selected by the user might use different line endings.
|
||||
*If you are reading this and know of a cleaner way to do this, please let me know :)
|
||||
*/
|
||||
QTextStream in(&file);
|
||||
QTextStream text(&t);
|
||||
while (!in.atEnd() && !text.atEnd()) {
|
||||
QString fileLine = in.readLine();
|
||||
QString textLine = text.readLine();
|
||||
if (QString::compare(fileLine, textLine,
|
||||
Qt::CaseSensitive) != 0) {
|
||||
equal = false;
|
||||
break;
|
||||
} else {
|
||||
equal = true;
|
||||
}
|
||||
}
|
||||
equal = checkLocalFileContent(s);
|
||||
}
|
||||
file.close();
|
||||
|
||||
if (equal) {
|
||||
scene = s.scene;
|
||||
transition = s.transition;
|
||||
match = true;
|
||||
|
||||
if (verbose)
|
||||
blog(LOG_INFO,
|
||||
"Advanced Scene Switcher file match");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -172,12 +237,29 @@ void SceneSwitcher::on_browseButton_3_clicked()
|
||||
ui->filePathLineEdit->setText(path);
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_fileType_currentIndexChanged(int idx)
|
||||
{
|
||||
if (idx == -1)
|
||||
return;
|
||||
if (idx == LOCAL_FILE_IDX) {
|
||||
ui->browseButton_3->setDisabled(false);
|
||||
ui->fileContentTimeCheckBox->setDisabled(false);
|
||||
ui->remoteFileWarningLabel->hide();
|
||||
}
|
||||
if (idx == REMOTE_FILE_IDX) {
|
||||
ui->browseButton_3->setDisabled(true);
|
||||
ui->fileContentTimeCheckBox->setDisabled(true);
|
||||
ui->remoteFileWarningLabel->show();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_fileAdd_clicked()
|
||||
{
|
||||
QString sceneName = ui->fileScenes->currentText();
|
||||
QString transitionName = ui->fileTransitions->currentText();
|
||||
QString fileName = ui->filePathLineEdit->text();
|
||||
QString text = ui->fileTextEdit->toPlainText();
|
||||
bool remote = (ui->fileType->currentIndex() == REMOTE_FILE_IDX);
|
||||
bool useRegex = ui->fileContentRegExCheckBox->isChecked();
|
||||
bool useTime = ui->fileContentTimeCheckBox->isChecked();
|
||||
|
||||
@@ -199,8 +281,8 @@ void SceneSwitcher::on_fileAdd_clicked()
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->fileSwitches.emplace_back(source, transition,
|
||||
fileName.toUtf8().constData(),
|
||||
text.toUtf8().constData(), useRegex,
|
||||
useTime);
|
||||
text.toUtf8().constData(), remote,
|
||||
useRegex, useTime);
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_fileRemove_clicked()
|
||||
@@ -242,6 +324,152 @@ void SceneSwitcher::on_fileScenesList_currentRowChanged(int idx)
|
||||
ui->fileTransitions->setCurrentText(transitionName.c_str());
|
||||
ui->fileTextEdit->setPlainText(s.text.c_str());
|
||||
ui->filePathLineEdit->setText(s.file.c_str());
|
||||
if (s.remote)
|
||||
ui->fileType->setCurrentIndex(REMOTE_FILE_IDX);
|
||||
else
|
||||
ui->fileType->setCurrentIndex(LOCAL_FILE_IDX);
|
||||
ui->fileContentRegExCheckBox->setChecked(s.useRegex);
|
||||
ui->fileContentTimeCheckBox->setChecked(s.useTime);
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_fileUp_clicked()
|
||||
{
|
||||
int index = ui->fileScenesList->currentRow();
|
||||
if (index != -1 && index != 0) {
|
||||
ui->fileScenesList->insertItem(
|
||||
index - 1, ui->fileScenesList->takeItem(index));
|
||||
ui->fileScenesList->setCurrentRow(index - 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
iter_swap(switcher->fileSwitches.begin() + index,
|
||||
switcher->fileSwitches.begin() + index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_fileDown_clicked()
|
||||
{
|
||||
int index = ui->fileScenesList->currentRow();
|
||||
if (index != -1 && index != ui->fileScenesList->count() - 1) {
|
||||
ui->fileScenesList->insertItem(
|
||||
index + 1, ui->fileScenesList->takeItem(index));
|
||||
ui->fileScenesList->setCurrentRow(index + 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
iter_swap(switcher->fileSwitches.begin() + index,
|
||||
switcher->fileSwitches.begin() + index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::saveFileSwitches(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *fileArray = obs_data_array_create();
|
||||
for (FileSwitch &s : switcher->fileSwitches) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(s.scene);
|
||||
obs_source_t *transition =
|
||||
obs_weak_source_get_source(s.transition);
|
||||
|
||||
if (source && transition) {
|
||||
const char *sceneName = obs_source_get_name(source);
|
||||
const char *transitionName =
|
||||
obs_source_get_name(transition);
|
||||
obs_data_set_string(array_obj, "scene", sceneName);
|
||||
obs_data_set_string(array_obj, "transition",
|
||||
transitionName);
|
||||
obs_data_set_string(array_obj, "file", s.file.c_str());
|
||||
obs_data_set_string(array_obj, "text", s.text.c_str());
|
||||
obs_data_set_bool(array_obj, "remote", s.remote);
|
||||
obs_data_set_bool(array_obj, "useRegex", s.useRegex);
|
||||
obs_data_set_bool(array_obj, "useTime", s.useTime);
|
||||
obs_data_array_push_back(fileArray, array_obj);
|
||||
obs_source_release(source);
|
||||
obs_source_release(transition);
|
||||
}
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "fileSwitches", fileArray);
|
||||
obs_data_array_release(fileArray);
|
||||
|
||||
obs_data_set_bool(obj, "readEnabled", switcher->fileIO.readEnabled);
|
||||
obs_data_set_string(obj, "readPath", switcher->fileIO.readPath.c_str());
|
||||
obs_data_set_bool(obj, "writeEnabled", switcher->fileIO.writeEnabled);
|
||||
obs_data_set_string(obj, "writePath",
|
||||
switcher->fileIO.writePath.c_str());
|
||||
}
|
||||
|
||||
void SwitcherData::loadFileSwitches(obs_data_t *obj)
|
||||
{
|
||||
switcher->fileSwitches.clear();
|
||||
obs_data_array_t *fileArray = obs_data_get_array(obj, "fileSwitches");
|
||||
size_t count = obs_data_array_count(fileArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj = obs_data_array_item(fileArray, i);
|
||||
|
||||
const char *scene = obs_data_get_string(array_obj, "scene");
|
||||
const char *transition =
|
||||
obs_data_get_string(array_obj, "transition");
|
||||
const char *file = obs_data_get_string(array_obj, "file");
|
||||
const char *text = obs_data_get_string(array_obj, "text");
|
||||
bool remote = obs_data_get_bool(array_obj, "remote");
|
||||
bool useRegex = obs_data_get_bool(array_obj, "useRegex");
|
||||
bool useTime = obs_data_get_bool(array_obj, "useTime");
|
||||
|
||||
switcher->fileSwitches.emplace_back(
|
||||
GetWeakSourceByName(scene),
|
||||
GetWeakTransitionByName(transition), file, text, remote,
|
||||
useRegex, useTime);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(fileArray);
|
||||
|
||||
obs_data_set_default_bool(obj, "readEnabled", false);
|
||||
switcher->fileIO.readEnabled = obs_data_get_bool(obj, "readEnabled");
|
||||
switcher->fileIO.readPath = obs_data_get_string(obj, "readPath");
|
||||
obs_data_set_default_bool(obj, "writeEnabled", false);
|
||||
switcher->fileIO.writeEnabled = obs_data_get_bool(obj, "writeEnabled");
|
||||
switcher->fileIO.writePath = obs_data_get_string(obj, "writePath");
|
||||
}
|
||||
|
||||
void SceneSwitcher::setupFileTab()
|
||||
{
|
||||
populateSceneSelection(ui->fileScenes, false);
|
||||
populateTransitionSelection(ui->fileTransitions);
|
||||
|
||||
ui->fileType->addItem("local");
|
||||
ui->fileType->addItem("remote");
|
||||
ui->remoteFileWarningLabel->setText(
|
||||
"Note that the scene switcher will try to access the remote location every " +
|
||||
QString::number(switcher->interval) + "ms");
|
||||
|
||||
for (auto &s : switcher->fileSwitches) {
|
||||
std::string sceneName = GetWeakSourceName(s.scene);
|
||||
std::string transitionName = GetWeakSourceName(s.transition);
|
||||
QString listText = MakeFileSwitchName(
|
||||
sceneName.c_str(), transitionName.c_str(),
|
||||
s.file.c_str(), s.text.c_str(), s.useRegex, s.useTime);
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(listText, ui->fileScenesList);
|
||||
item->setData(Qt::UserRole, listText);
|
||||
}
|
||||
|
||||
ui->readPathLineEdit->setText(
|
||||
QString::fromStdString(switcher->fileIO.readPath.c_str()));
|
||||
ui->readFileCheckBox->setChecked(switcher->fileIO.readEnabled);
|
||||
ui->writePathLineEdit->setText(
|
||||
QString::fromStdString(switcher->fileIO.writePath.c_str()));
|
||||
|
||||
if (ui->readFileCheckBox->checkState()) {
|
||||
ui->browseButton_2->setDisabled(false);
|
||||
ui->readPathLineEdit->setDisabled(false);
|
||||
} else {
|
||||
ui->browseButton_2->setDisabled(true);
|
||||
ui->readPathLineEdit->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
495
src/general.cpp
495
src/general.cpp
@@ -1,20 +1,15 @@
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include <obs-module.h>
|
||||
#include <QFileDialog>
|
||||
#include <QTextStream>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
void SceneSwitcher::on_close_clicked()
|
||||
{
|
||||
done(0);
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_startAtLaunch_toggled(bool value)
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->startAtLaunch = value;
|
||||
}
|
||||
|
||||
void SceneSwitcher::UpdateNonMatchingScene(const QString &name)
|
||||
{
|
||||
obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData());
|
||||
@@ -57,6 +52,15 @@ void SceneSwitcher::on_noMatchRandomSwitch_clicked()
|
||||
ui->noMatchSwitchScene->setEnabled(false);
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_startupBehavior_currentIndexChanged(int index)
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->startupBehavior = (StartupBehavior)index;
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_noMatchSwitchScene_currentTextChanged(const QString &text)
|
||||
{
|
||||
if (loading)
|
||||
@@ -102,3 +106,474 @@ void SceneSwitcher::closeEvent(QCloseEvent *)
|
||||
{
|
||||
obs_frontend_save();
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_autoStopScenes_currentTextChanged(const QString &text)
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
UpdateAutoStopScene(text);
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_autoStopSceneCheckBox_stateChanged(int state)
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
if (!state) {
|
||||
ui->autoStopScenes->setDisabled(true);
|
||||
switcher->autoStopEnable = false;
|
||||
} else {
|
||||
ui->autoStopScenes->setDisabled(false);
|
||||
switcher->autoStopEnable = true;
|
||||
if (!switcher->autoStopScene)
|
||||
UpdateAutoStopScene(ui->autoStopScenes->currentText());
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::UpdateAutoStopScene(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->autoStopScene = ws;
|
||||
|
||||
obs_weak_source_release(ws);
|
||||
obs_source_release(scene);
|
||||
}
|
||||
|
||||
void SwitcherData::autoStopStreamAndRecording()
|
||||
{
|
||||
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
||||
obs_weak_source_t *ws = obs_source_get_weak_source(currentSource);
|
||||
|
||||
if (ws && autoStopScene == ws) {
|
||||
if (obs_frontend_streaming_active())
|
||||
obs_frontend_streaming_stop();
|
||||
if (obs_frontend_recording_active())
|
||||
obs_frontend_recording_stop();
|
||||
}
|
||||
obs_source_release(currentSource);
|
||||
obs_weak_source_release(ws);
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_verboseLogging_stateChanged(int state)
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->verbose = state;
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_exportSettings_clicked()
|
||||
{
|
||||
QString directory = QFileDialog::getSaveFileName(
|
||||
this, tr("Export Advanced Scene Switcher settings to file ..."),
|
||||
QDir::currentPath(), tr("Text files (*.txt)"));
|
||||
if (directory.isEmpty())
|
||||
return;
|
||||
|
||||
QFile file(directory);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
return;
|
||||
|
||||
obs_data_t *obj = obs_data_create();
|
||||
|
||||
switcher->saveWindowTitleSwitches(obj);
|
||||
switcher->saveScreenRegionSwitches(obj);
|
||||
switcher->savePauseSwitches(obj);
|
||||
switcher->saveSceneRoundTripSwitches(obj);
|
||||
switcher->saveSceneTransitions(obj);
|
||||
switcher->saveIdleSwitches(obj);
|
||||
switcher->saveExecutableSwitches(obj);
|
||||
switcher->saveRandomSwitches(obj);
|
||||
switcher->saveFileSwitches(obj);
|
||||
switcher->saveMediaSwitches(obj);
|
||||
switcher->saveTimeSwitches(obj);
|
||||
switcher->saveGeneralSettings(obj);
|
||||
|
||||
obs_data_save_json(obj, file.fileName().toUtf8().constData());
|
||||
|
||||
obs_data_release(obj);
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_importSettings_clicked()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
QString directory = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
tr("Import Advanced Scene Switcher settings from file ..."),
|
||||
QDir::currentPath(), tr("Text files (*.txt)"));
|
||||
if (directory.isEmpty())
|
||||
return;
|
||||
|
||||
QFile file(directory);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
return;
|
||||
|
||||
obs_data_t *obj = obs_data_create_from_json_file(
|
||||
file.fileName().toUtf8().constData());
|
||||
|
||||
if (!obj) {
|
||||
QMessageBox Msgbox;
|
||||
Msgbox.setText(
|
||||
"Advanced Scene Switcher failed to import settings");
|
||||
Msgbox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
switcher->loadWindowTitleSwitches(obj);
|
||||
switcher->loadScreenRegionSwitches(obj);
|
||||
switcher->loadPauseSwitches(obj);
|
||||
switcher->loadSceneRoundTripSwitches(obj);
|
||||
switcher->loadSceneTransitions(obj);
|
||||
switcher->loadIdleSwitches(obj);
|
||||
switcher->loadExecutableSwitches(obj);
|
||||
switcher->loadRandomSwitches(obj);
|
||||
switcher->loadFileSwitches(obj);
|
||||
switcher->loadMediaSwitches(obj);
|
||||
switcher->loadTimeSwitches(obj);
|
||||
switcher->loadGeneralSettings(obj);
|
||||
|
||||
obs_data_release(obj);
|
||||
|
||||
QMessageBox Msgbox;
|
||||
Msgbox.setText(
|
||||
"Advanced Scene Switcher settings imported successfully");
|
||||
Msgbox.exec();
|
||||
close();
|
||||
}
|
||||
|
||||
int findTabIndex(QTabBar *bar, int pos)
|
||||
{
|
||||
int at = -1;
|
||||
|
||||
QString tabName = "";
|
||||
switch (pos) {
|
||||
case 0:
|
||||
tabName = "General";
|
||||
break;
|
||||
case 1:
|
||||
tabName = "Transition";
|
||||
break;
|
||||
case 2:
|
||||
tabName = "Pause";
|
||||
break;
|
||||
case 3:
|
||||
tabName = "Title";
|
||||
break;
|
||||
case 4:
|
||||
tabName = "Executable";
|
||||
break;
|
||||
case 5:
|
||||
tabName = "Region";
|
||||
break;
|
||||
case 6:
|
||||
tabName = "Media";
|
||||
break;
|
||||
case 7:
|
||||
tabName = "File";
|
||||
break;
|
||||
case 8:
|
||||
tabName = "Random";
|
||||
break;
|
||||
case 9:
|
||||
tabName = "Time";
|
||||
break;
|
||||
case 10:
|
||||
tabName = "Idle";
|
||||
break;
|
||||
case 11:
|
||||
tabName = "Sequence";
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < bar->count(); ++i) {
|
||||
if (bar->tabText(i).compare(tabName) == 0) {
|
||||
at = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (at == -1)
|
||||
blog(LOG_INFO, "Advanced Scene Switcher failed to find tab %s",
|
||||
tabName.toUtf8().constData());
|
||||
|
||||
return at;
|
||||
}
|
||||
|
||||
void SceneSwitcher::setTabOrder()
|
||||
{
|
||||
QTabBar *bar = ui->tabWidget->tabBar();
|
||||
for (int i = 0; i < bar->count(); ++i) {
|
||||
int curPos = findTabIndex(bar, switcher->tabOrder[i]);
|
||||
|
||||
if (i != curPos && curPos != -1)
|
||||
bar->moveTab(curPos, i);
|
||||
}
|
||||
|
||||
connect(bar, &QTabBar::tabMoved, this, &SceneSwitcher::on_tabMoved);
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_tabMoved(int from, int to)
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
std::swap(switcher->tabOrder[from], switcher->tabOrder[to]);
|
||||
}
|
||||
|
||||
void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
||||
{
|
||||
obs_data_set_int(obj, "interval", switcher->interval);
|
||||
|
||||
std::string nonMatchingSceneName =
|
||||
GetWeakSourceName(switcher->nonMatchingScene);
|
||||
obs_data_set_string(obj, "non_matching_scene",
|
||||
nonMatchingSceneName.c_str());
|
||||
obs_data_set_int(obj, "switch_if_not_matching",
|
||||
switcher->switchIfNotMatching);
|
||||
|
||||
obs_data_set_bool(obj, "active", !switcher->stop);
|
||||
obs_data_set_int(obj, "startup_behavior", switcher->startupBehavior);
|
||||
|
||||
std::string autoStopSceneName =
|
||||
GetWeakSourceName(switcher->autoStopScene);
|
||||
obs_data_set_bool(obj, "autoStopEnable", switcher->autoStopEnable);
|
||||
obs_data_set_string(obj, "autoStopSceneName",
|
||||
autoStopSceneName.c_str());
|
||||
|
||||
obs_data_set_bool(obj, "verbose", switcher->verbose);
|
||||
|
||||
obs_data_set_int(obj, "priority0",
|
||||
switcher->functionNamesByPriority[0]);
|
||||
obs_data_set_int(obj, "priority1",
|
||||
switcher->functionNamesByPriority[1]);
|
||||
obs_data_set_int(obj, "priority2",
|
||||
switcher->functionNamesByPriority[2]);
|
||||
obs_data_set_int(obj, "priority3",
|
||||
switcher->functionNamesByPriority[3]);
|
||||
obs_data_set_int(obj, "priority4",
|
||||
switcher->functionNamesByPriority[4]);
|
||||
obs_data_set_int(obj, "priority5",
|
||||
switcher->functionNamesByPriority[5]);
|
||||
obs_data_set_int(obj, "priority6",
|
||||
switcher->functionNamesByPriority[6]);
|
||||
obs_data_set_int(obj, "priority7",
|
||||
switcher->functionNamesByPriority[7]);
|
||||
|
||||
obs_data_set_int(obj, "threadPriority", switcher->threadPriority);
|
||||
|
||||
obs_data_set_int(obj, "generalTabPos", switcher->tabOrder[0]);
|
||||
obs_data_set_int(obj, "transitionTabPos", switcher->tabOrder[1]);
|
||||
obs_data_set_int(obj, "pauseTabPos", switcher->tabOrder[2]);
|
||||
obs_data_set_int(obj, "titleTabPos", switcher->tabOrder[3]);
|
||||
obs_data_set_int(obj, "exeTabPos", switcher->tabOrder[4]);
|
||||
obs_data_set_int(obj, "regionTabPos", switcher->tabOrder[5]);
|
||||
obs_data_set_int(obj, "mediaTabPos", switcher->tabOrder[6]);
|
||||
obs_data_set_int(obj, "fileTabPos", switcher->tabOrder[7]);
|
||||
obs_data_set_int(obj, "randomTabPos", switcher->tabOrder[8]);
|
||||
obs_data_set_int(obj, "timeTabPos", switcher->tabOrder[9]);
|
||||
obs_data_set_int(obj, "idleTabPos", switcher->tabOrder[10]);
|
||||
obs_data_set_int(obj, "sequenceTabPos", switcher->tabOrder[11]);
|
||||
}
|
||||
|
||||
void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
||||
{
|
||||
obs_data_set_default_int(obj, "interval", DEFAULT_INTERVAL);
|
||||
switcher->interval = obs_data_get_int(obj, "interval");
|
||||
|
||||
obs_data_set_default_int(obj, "switch_if_not_matching", NO_SWITCH);
|
||||
switcher->switchIfNotMatching =
|
||||
(NoMatch)obs_data_get_int(obj, "switch_if_not_matching");
|
||||
std::string nonMatchingScene =
|
||||
obs_data_get_string(obj, "non_matching_scene");
|
||||
switcher->nonMatchingScene =
|
||||
GetWeakSourceByName(nonMatchingScene.c_str());
|
||||
|
||||
switcher->stop = !obs_data_get_bool(obj, "active");
|
||||
switcher->startupBehavior =
|
||||
(StartupBehavior)obs_data_get_int(obj, "startup_behavior");
|
||||
if (switcher->startupBehavior == START)
|
||||
switcher->stop = false;
|
||||
if (switcher->startupBehavior == STOP)
|
||||
switcher->stop = true;
|
||||
|
||||
std::string autoStopScene =
|
||||
obs_data_get_string(obj, "autoStopSceneName");
|
||||
switcher->autoStopEnable = obs_data_get_bool(obj, "autoStopEnable");
|
||||
switcher->autoStopScene = GetWeakSourceByName(autoStopScene.c_str());
|
||||
|
||||
switcher->verbose = obs_data_get_bool(obj, "verbose");
|
||||
|
||||
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, "priority2", DEFAULT_PRIORITY_2);
|
||||
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, "priority5", DEFAULT_PRIORITY_5);
|
||||
obs_data_set_default_int(obj, "priority6", DEFAULT_PRIORITY_6);
|
||||
obs_data_set_default_int(obj, "priority7", DEFAULT_PRIORITY_7);
|
||||
|
||||
switcher->functionNamesByPriority[0] =
|
||||
(obs_data_get_int(obj, "priority0"));
|
||||
switcher->functionNamesByPriority[1] =
|
||||
(obs_data_get_int(obj, "priority1"));
|
||||
switcher->functionNamesByPriority[2] =
|
||||
(obs_data_get_int(obj, "priority2"));
|
||||
switcher->functionNamesByPriority[3] =
|
||||
(obs_data_get_int(obj, "priority3"));
|
||||
switcher->functionNamesByPriority[4] =
|
||||
(obs_data_get_int(obj, "priority4"));
|
||||
switcher->functionNamesByPriority[5] =
|
||||
(obs_data_get_int(obj, "priority5"));
|
||||
switcher->functionNamesByPriority[6] =
|
||||
(obs_data_get_int(obj, "priority6"));
|
||||
switcher->functionNamesByPriority[7] =
|
||||
(obs_data_get_int(obj, "priority7"));
|
||||
if (!switcher->prioFuncsValid()) {
|
||||
switcher->functionNamesByPriority[0] = (DEFAULT_PRIORITY_0);
|
||||
switcher->functionNamesByPriority[1] = (DEFAULT_PRIORITY_1);
|
||||
switcher->functionNamesByPriority[2] = (DEFAULT_PRIORITY_2);
|
||||
switcher->functionNamesByPriority[3] = (DEFAULT_PRIORITY_3);
|
||||
switcher->functionNamesByPriority[4] = (DEFAULT_PRIORITY_4);
|
||||
switcher->functionNamesByPriority[5] = (DEFAULT_PRIORITY_5);
|
||||
switcher->functionNamesByPriority[6] = (DEFAULT_PRIORITY_6);
|
||||
switcher->functionNamesByPriority[7] = (DEFAULT_PRIORITY_7);
|
||||
}
|
||||
|
||||
obs_data_set_default_int(obj, "threadPriority",
|
||||
QThread::NormalPriority);
|
||||
switcher->threadPriority = obs_data_get_int(obj, "threadPriority");
|
||||
|
||||
obs_data_set_default_int(obj, "generalTabPos", 0);
|
||||
obs_data_set_default_int(obj, "transitionTabPos", 1);
|
||||
obs_data_set_default_int(obj, "pauseTabPos", 2);
|
||||
obs_data_set_default_int(obj, "titleTabPos", 3);
|
||||
obs_data_set_default_int(obj, "exeTabPos", 4);
|
||||
obs_data_set_default_int(obj, "regionTabPos", 5);
|
||||
obs_data_set_default_int(obj, "mediaTabPos", 6);
|
||||
obs_data_set_default_int(obj, "fileTabPos", 7);
|
||||
obs_data_set_default_int(obj, "randomTabPos", 8);
|
||||
obs_data_set_default_int(obj, "timeTabPos", 9);
|
||||
obs_data_set_default_int(obj, "idleTabPos", 10);
|
||||
obs_data_set_default_int(obj, "sequenceTabPos", 11);
|
||||
|
||||
switcher->tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(obj, "generalTabPos")));
|
||||
switcher->tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(obj, "transitionTabPos")));
|
||||
switcher->tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(obj, "pauseTabPos")));
|
||||
switcher->tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(obj, "titleTabPos")));
|
||||
switcher->tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(obj, "exeTabPos")));
|
||||
switcher->tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(obj, "regionTabPos")));
|
||||
switcher->tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(obj, "mediaTabPos")));
|
||||
switcher->tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(obj, "fileTabPos")));
|
||||
switcher->tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(obj, "randomTabPos")));
|
||||
switcher->tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(obj, "timeTabPos")));
|
||||
switcher->tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(obj, "idleTabPos")));
|
||||
switcher->tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(obj, "sequenceTabPos")));
|
||||
}
|
||||
|
||||
void SceneSwitcher::setupGeneralTab()
|
||||
{
|
||||
populateSceneSelection(ui->noMatchSwitchScene, false);
|
||||
populateSceneSelection(ui->autoStopScenes, false);
|
||||
|
||||
if (switcher->switchIfNotMatching == SWITCH) {
|
||||
ui->noMatchSwitch->setChecked(true);
|
||||
ui->noMatchSwitchScene->setEnabled(true);
|
||||
} else if (switcher->switchIfNotMatching == NO_SWITCH) {
|
||||
ui->noMatchDontSwitch->setChecked(true);
|
||||
ui->noMatchSwitchScene->setEnabled(false);
|
||||
} else {
|
||||
ui->noMatchRandomSwitch->setChecked(true);
|
||||
ui->noMatchSwitchScene->setEnabled(false);
|
||||
}
|
||||
ui->noMatchSwitchScene->setCurrentText(
|
||||
GetWeakSourceName(switcher->nonMatchingScene).c_str());
|
||||
ui->checkInterval->setValue(switcher->interval);
|
||||
|
||||
ui->autoStopSceneCheckBox->setChecked(switcher->autoStopEnable);
|
||||
ui->autoStopScenes->setCurrentText(
|
||||
GetWeakSourceName(switcher->autoStopScene).c_str());
|
||||
|
||||
if (ui->autoStopSceneCheckBox->checkState()) {
|
||||
ui->autoStopScenes->setDisabled(false);
|
||||
} else {
|
||||
ui->autoStopScenes->setDisabled(true);
|
||||
}
|
||||
|
||||
ui->verboseLogging->setChecked(switcher->verbose);
|
||||
|
||||
for (int p : switcher->functionNamesByPriority) {
|
||||
std::string s = "";
|
||||
switch (p) {
|
||||
case READ_FILE_FUNC:
|
||||
s = "File Content";
|
||||
break;
|
||||
case ROUND_TRIP_FUNC:
|
||||
s = "Scene Sequence";
|
||||
break;
|
||||
case IDLE_FUNC:
|
||||
s = "Idle Detection";
|
||||
break;
|
||||
case EXE_FUNC:
|
||||
s = "Executable";
|
||||
break;
|
||||
case SCREEN_REGION_FUNC:
|
||||
s = "Screen Region";
|
||||
break;
|
||||
case WINDOW_TITLE_FUNC:
|
||||
s = "Window Title";
|
||||
break;
|
||||
case MEDIA_FUNC:
|
||||
s = "Media";
|
||||
break;
|
||||
case TIME_FUNC:
|
||||
s = "Time";
|
||||
break;
|
||||
}
|
||||
QString text(s.c_str());
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->priorityList);
|
||||
item->setData(Qt::UserRole, text);
|
||||
}
|
||||
|
||||
for (int i = 0; i < switcher->threadPriorities.size(); ++i) {
|
||||
ui->threadPriority->addItem(
|
||||
switcher->threadPriorities[i].name.c_str());
|
||||
ui->threadPriority->setItemData(
|
||||
i, switcher->threadPriorities[i].description.c_str(),
|
||||
Qt::ToolTipRole);
|
||||
if (switcher->threadPriority ==
|
||||
switcher->threadPriorities[i].value) {
|
||||
ui->threadPriority->setCurrentText(
|
||||
switcher->threadPriorities[i].name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
ui->startupBehavior->addItem(
|
||||
"Start the scene switcher if it was running");
|
||||
ui->startupBehavior->addItem("Always start the scene switcher");
|
||||
ui->startupBehavior->addItem("Do not start the scene switcher");
|
||||
|
||||
ui->startupBehavior->setCurrentIndex(switcher->startupBehavior);
|
||||
|
||||
if (switcher->th && switcher->th->isRunning())
|
||||
SetStarted();
|
||||
else
|
||||
SetStopped();
|
||||
}
|
||||
|
||||
@@ -49,6 +49,24 @@ public:
|
||||
void UpdateIdleDataTransition(const QString &name);
|
||||
void UpdateIdleDataScene(const QString &name);
|
||||
|
||||
void loadUI();
|
||||
void populateSceneSelection(QComboBox *sel, bool addPrevious);
|
||||
void populateTransitionSelection(QComboBox *sel);
|
||||
void populateWindowSelection(QComboBox *sel);
|
||||
void setupGeneralTab();
|
||||
void setupTitleTab();
|
||||
void setupExecutableTab();
|
||||
void setupRegionTab();
|
||||
void setupPauseTab();
|
||||
void setupSequenceTab();
|
||||
void setupTransitionsTab();
|
||||
void setupIdleTab();
|
||||
void setupRandomTab();
|
||||
void setupMediaTab();
|
||||
void setupFileTab();
|
||||
void setupTimeTab();
|
||||
void setTabOrder();
|
||||
|
||||
public slots:
|
||||
void on_switches_currentRowChanged(int idx);
|
||||
void on_up_clicked();
|
||||
@@ -58,14 +76,17 @@ public slots:
|
||||
void on_noMatchDontSwitch_clicked();
|
||||
void on_noMatchSwitch_clicked();
|
||||
void on_noMatchRandomSwitch_clicked();
|
||||
void on_startAtLaunch_toggled(bool value);
|
||||
void on_startupBehavior_currentIndexChanged(int index);
|
||||
void on_noMatchSwitchScene_currentTextChanged(const QString &text);
|
||||
void on_checkInterval_valueChanged(int value);
|
||||
void on_toggleStartButton_clicked();
|
||||
void on_tabMoved(int from, int to);
|
||||
|
||||
void on_screenRegions_currentRowChanged(int idx);
|
||||
void on_screenRegionAdd_clicked();
|
||||
void on_screenRegionRemove_clicked();
|
||||
void on_screenRegionUp_clicked();
|
||||
void on_screenRegionDown_clicked();
|
||||
|
||||
void on_pauseScenes_currentRowChanged(int idx);
|
||||
void on_pauseScenesAdd_clicked();
|
||||
@@ -84,19 +105,29 @@ public slots:
|
||||
void on_sceneRoundTripRemove_clicked();
|
||||
void on_sceneRoundTripSave_clicked();
|
||||
void on_sceneRoundTripLoad_clicked();
|
||||
void on_sceneRoundTripUp_clicked();
|
||||
void on_sceneRoundTripDown_clicked();
|
||||
void on_sceneRoundTripDelayUnits_currentIndexChanged(int index);
|
||||
|
||||
void on_autoStopSceneCheckBox_stateChanged(int state);
|
||||
void on_autoStopScenes_currentTextChanged(const QString &text);
|
||||
|
||||
void on_verboseLogging_stateChanged(int state);
|
||||
|
||||
void on_exportSettings_clicked();
|
||||
void on_importSettings_clicked();
|
||||
|
||||
void on_sceneTransitions_currentRowChanged(int idx);
|
||||
void on_transitionsAdd_clicked();
|
||||
void on_transitionsRemove_clicked();
|
||||
void on_defaultTransitions_currentRowChanged(int idx);
|
||||
void on_defaultTransitionsAdd_clicked();
|
||||
void on_defaultTransitionsRemove_clicked();
|
||||
void on_transitionOverridecheckBox_stateChanged(int state);
|
||||
|
||||
void on_browseButton_clicked();
|
||||
void on_readFileCheckBox_stateChanged(int state);
|
||||
void on_fileType_currentIndexChanged(int idx);
|
||||
void on_readPathLineEdit_textChanged(const QString &text);
|
||||
void on_writePathLineEdit_textChanged(const QString &text);
|
||||
void on_browseButton_2_clicked();
|
||||
@@ -123,10 +154,15 @@ public slots:
|
||||
void on_fileRemove_clicked();
|
||||
void on_fileScenesList_currentRowChanged(int idx);
|
||||
void on_browseButton_3_clicked();
|
||||
void on_fileUp_clicked();
|
||||
void on_fileDown_clicked();
|
||||
|
||||
void on_mediaSwitches_currentRowChanged(int idx);
|
||||
void on_mediaAdd_clicked();
|
||||
void on_mediaRemove_clicked();
|
||||
void on_mediaUp_clicked();
|
||||
void on_mediaDown_clicked();
|
||||
void on_mediaTimeRestrictions_currentIndexChanged(int idx);
|
||||
|
||||
void on_timeSwitches_currentRowChanged(int idx);
|
||||
void on_timeAdd_clicked();
|
||||
@@ -171,9 +207,20 @@ bool isInFocus(const QString &executable);
|
||||
struct obs_weak_source;
|
||||
typedef struct obs_weak_source obs_weak_source_t;
|
||||
|
||||
obs_weak_source_t *getNextTransition(obs_weak_source_t *scene1,
|
||||
obs_weak_source_t *scene2);
|
||||
typedef struct transitionData {
|
||||
std::string name = "";
|
||||
int duration = 0;
|
||||
} transitionData;
|
||||
|
||||
void setNextTransition(OBSWeakSource &targetScene, obs_source_t *currentSource,
|
||||
OBSWeakSource &transition,
|
||||
bool &transitionOverrideOverride, transitionData &td);
|
||||
void overwriteTransitionOverride(obs_weak_source_t *sceneWs,
|
||||
obs_source_t *transition, transitionData &td);
|
||||
void restoreTransitionOverride(obs_source_t *scene, transitionData td);
|
||||
|
||||
void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
|
||||
bool &transitionOverrideOverride,
|
||||
std::unique_lock<std::mutex> &lock);
|
||||
|
||||
/********************************************************************************
|
||||
|
||||
@@ -98,13 +98,13 @@ struct SceneRoundTripSwitch {
|
||||
OBSWeakSource scene1;
|
||||
OBSWeakSource scene2;
|
||||
OBSWeakSource transition;
|
||||
int delay;
|
||||
double delay;
|
||||
bool usePreviousScene;
|
||||
std::string sceneRoundTripStr;
|
||||
|
||||
inline SceneRoundTripSwitch(OBSWeakSource scene1_,
|
||||
OBSWeakSource scene2_,
|
||||
OBSWeakSource transition_, int delay_,
|
||||
OBSWeakSource transition_, double delay_,
|
||||
bool usePreviousScene_, std::string str)
|
||||
: scene1(scene1_),
|
||||
scene2(scene2_),
|
||||
@@ -169,17 +169,19 @@ struct FileSwitch {
|
||||
OBSWeakSource transition;
|
||||
std::string file;
|
||||
std::string text;
|
||||
bool remote = false;
|
||||
bool useRegex = false;
|
||||
bool useTime = false;
|
||||
QDateTime lastMod;
|
||||
|
||||
inline FileSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
|
||||
const char *file_, const char *text_, bool useRegex_,
|
||||
bool useTime_)
|
||||
const char *file_, const char *text_, bool remote_,
|
||||
bool useRegex_, bool useTime_)
|
||||
: scene(scene_),
|
||||
transition(transition_),
|
||||
file(file_),
|
||||
text(text_),
|
||||
remote(remote_),
|
||||
useRegex(useRegex_),
|
||||
useTime(useTime_),
|
||||
lastMod()
|
||||
@@ -208,7 +210,7 @@ struct MediaSwitch {
|
||||
OBSWeakSource source;
|
||||
OBSWeakSource transition;
|
||||
obs_media_state state;
|
||||
uint64_t time;
|
||||
int64_t time;
|
||||
time_restriction restriction;
|
||||
bool matched;
|
||||
bool usePreviousScene;
|
||||
@@ -251,6 +253,7 @@ struct TimeSwitch {
|
||||
};
|
||||
|
||||
typedef enum { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 } NoMatch;
|
||||
typedef enum { PERSIST = 0, START = 1, STOP = 2 } StartupBehavior;
|
||||
|
||||
class SwitcherThread;
|
||||
|
||||
@@ -265,8 +268,9 @@ struct SwitcherData {
|
||||
bool transitionActive = false;
|
||||
bool waitForTransition = false;
|
||||
std::condition_variable transitionCv;
|
||||
bool startAtLaunch = false;
|
||||
bool stop = false;
|
||||
bool verbose = false;
|
||||
bool tansitionOverrideOverride = false;
|
||||
|
||||
int interval = DEFAULT_INTERVAL;
|
||||
|
||||
@@ -276,6 +280,7 @@ struct SwitcherData {
|
||||
OBSWeakSource lastRandomScene;
|
||||
OBSWeakSource nonMatchingScene;
|
||||
NoMatch switchIfNotMatching = NO_SWITCH;
|
||||
StartupBehavior startupBehavior = PERSIST;
|
||||
|
||||
std::vector<WindowSceneSwitch> windowSwitches;
|
||||
std::vector<std::string> ignoreIdleWindows;
|
||||
@@ -290,6 +295,7 @@ struct SwitcherData {
|
||||
std::vector<std::string> ignoreWindowsSwitches;
|
||||
|
||||
std::vector<SceneRoundTripSwitch> sceneRoundTripSwitches;
|
||||
int sceneRoundTripUnitMultiplier = 1;
|
||||
|
||||
std::vector<RandomSwitch> randomSwitches;
|
||||
|
||||
@@ -341,6 +347,8 @@ struct SwitcherData {
|
||||
|
||||
uint32_t threadPriority = QThread::NormalPriority;
|
||||
|
||||
std::vector<int> tabOrder;
|
||||
|
||||
void Thread();
|
||||
void Start();
|
||||
void Stop();
|
||||
@@ -373,6 +381,32 @@ struct SwitcherData {
|
||||
void checkTimeSwitch(bool &match, OBSWeakSource &scene,
|
||||
OBSWeakSource &transition);
|
||||
|
||||
void saveWindowTitleSwitches(obs_data_t *obj);
|
||||
void saveScreenRegionSwitches(obs_data_t *obj);
|
||||
void savePauseSwitches(obs_data_t *obj);
|
||||
void saveSceneRoundTripSwitches(obs_data_t *obj);
|
||||
void saveSceneTransitions(obs_data_t *obj);
|
||||
void saveIdleSwitches(obs_data_t *obj);
|
||||
void saveExecutableSwitches(obs_data_t *obj);
|
||||
void saveRandomSwitches(obs_data_t *obj);
|
||||
void saveFileSwitches(obs_data_t *obj);
|
||||
void saveMediaSwitches(obs_data_t *obj);
|
||||
void saveTimeSwitches(obs_data_t *obj);
|
||||
void saveGeneralSettings(obs_data_t *obj);
|
||||
|
||||
void loadWindowTitleSwitches(obs_data_t *obj);
|
||||
void loadScreenRegionSwitches(obs_data_t *obj);
|
||||
void loadPauseSwitches(obs_data_t *obj);
|
||||
void loadSceneRoundTripSwitches(obs_data_t *obj);
|
||||
void loadSceneTransitions(obs_data_t *obj);
|
||||
void loadIdleSwitches(obs_data_t *obj);
|
||||
void loadExecutableSwitches(obs_data_t *obj);
|
||||
void loadRandomSwitches(obs_data_t *obj);
|
||||
void loadFileSwitches(obs_data_t *obj);
|
||||
void loadMediaSwitches(obs_data_t *obj);
|
||||
void loadTimeSwitches(obs_data_t *obj);
|
||||
void loadGeneralSettings(obs_data_t *obj);
|
||||
|
||||
void Prune()
|
||||
{
|
||||
for (size_t i = 0; i < windowSwitches.size(); i++) {
|
||||
|
||||
@@ -41,6 +41,9 @@ void SwitcherData::checkIdleSwitch(bool &match, OBSWeakSource &scene,
|
||||
transition = idleData.transition;
|
||||
match = true;
|
||||
idleData.alreadySwitched = true;
|
||||
|
||||
if (verbose)
|
||||
blog(LOG_INFO, "Advanced Scene Switcher idle match");
|
||||
} else
|
||||
idleData.alreadySwitched = false;
|
||||
}
|
||||
@@ -199,3 +202,96 @@ int SceneSwitcher::IgnoreIdleWindowsFindByData(const QString &window)
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void SwitcherData::saveIdleSwitches(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *ignoreIdleWindowsArray = obs_data_array_create();
|
||||
for (std::string &window : switcher->ignoreIdleWindows) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
obs_data_set_string(array_obj, "window", window.c_str());
|
||||
obs_data_array_push_back(ignoreIdleWindowsArray, array_obj);
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "ignoreIdleWindows", ignoreIdleWindowsArray);
|
||||
obs_data_array_release(ignoreIdleWindowsArray);
|
||||
|
||||
std::string idleSceneName = GetWeakSourceName(switcher->idleData.scene);
|
||||
std::string idleTransitionName =
|
||||
GetWeakSourceName(switcher->idleData.transition);
|
||||
obs_data_set_bool(obj, "idleEnable", switcher->idleData.idleEnable);
|
||||
obs_data_set_string(obj, "idleSceneName",
|
||||
switcher->idleData.usePreviousScene
|
||||
? PREVIOUS_SCENE_NAME
|
||||
: idleSceneName.c_str());
|
||||
obs_data_set_string(obj, "idleTransitionName",
|
||||
idleTransitionName.c_str());
|
||||
obs_data_set_int(obj, "idleTime", switcher->idleData.time);
|
||||
}
|
||||
|
||||
void SwitcherData::loadIdleSwitches(obs_data_t *obj)
|
||||
{
|
||||
switcher->ignoreIdleWindows.clear();
|
||||
|
||||
obs_data_array_t *ignoreIdleWindowsArray =
|
||||
obs_data_get_array(obj, "ignoreIdleWindows");
|
||||
size_t count = obs_data_array_count(ignoreIdleWindowsArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj =
|
||||
obs_data_array_item(ignoreIdleWindowsArray, i);
|
||||
|
||||
const char *window = obs_data_get_string(array_obj, "window");
|
||||
|
||||
switcher->ignoreIdleWindows.emplace_back(window);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(ignoreIdleWindowsArray);
|
||||
|
||||
std::string idleSceneName = obs_data_get_string(obj, "idleSceneName");
|
||||
std::string idleTransitionName =
|
||||
obs_data_get_string(obj, "idleTransitionName");
|
||||
switcher->idleData.scene = GetWeakSourceByName(idleSceneName.c_str());
|
||||
switcher->idleData.transition =
|
||||
GetWeakTransitionByName(idleTransitionName.c_str());
|
||||
obs_data_set_default_bool(obj, "idleEnable", false);
|
||||
switcher->idleData.idleEnable = obs_data_get_bool(obj, "idleEnable");
|
||||
obs_data_set_default_int(obj, "idleTime", DEFAULT_IDLE_TIME);
|
||||
switcher->idleData.time = obs_data_get_int(obj, "idleTime");
|
||||
switcher->idleData.usePreviousScene =
|
||||
(idleSceneName == PREVIOUS_SCENE_NAME);
|
||||
}
|
||||
|
||||
void SceneSwitcher::setupIdleTab()
|
||||
{
|
||||
populateSceneSelection(ui->idleScenes, true);
|
||||
populateTransitionSelection(ui->idleTransitions);
|
||||
populateWindowSelection(ui->ignoreIdleWindowsWindows);
|
||||
|
||||
for (auto &window : switcher->ignoreIdleWindows) {
|
||||
QString text = QString::fromStdString(window);
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->ignoreIdleWindows);
|
||||
item->setData(Qt::UserRole, text);
|
||||
}
|
||||
|
||||
ui->idleCheckBox->setChecked(switcher->idleData.idleEnable);
|
||||
ui->idleScenes->setCurrentText(
|
||||
switcher->idleData.usePreviousScene
|
||||
? PREVIOUS_SCENE_NAME
|
||||
: GetWeakSourceName(switcher->idleData.scene).c_str());
|
||||
ui->idleTransitions->setCurrentText(
|
||||
GetWeakSourceName(switcher->idleData.transition).c_str());
|
||||
ui->idleSpinBox->setValue(switcher->idleData.time);
|
||||
|
||||
if (ui->idleCheckBox->checkState()) {
|
||||
ui->idleScenes->setDisabled(false);
|
||||
ui->idleSpinBox->setDisabled(false);
|
||||
ui->idleTransitions->setDisabled(false);
|
||||
} else {
|
||||
ui->idleScenes->setDisabled(true);
|
||||
ui->idleSpinBox->setDisabled(true);
|
||||
ui->idleTransitions->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,49 @@ void SceneSwitcher::on_mediaRemove_clicked()
|
||||
delete item;
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_mediaUp_clicked()
|
||||
{
|
||||
int index = ui->mediaSwitches->currentRow();
|
||||
if (index != -1 && index != 0) {
|
||||
ui->mediaSwitches->insertItem(
|
||||
index - 1, ui->mediaSwitches->takeItem(index));
|
||||
ui->mediaSwitches->setCurrentRow(index - 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
iter_swap(switcher->mediaSwitches.begin() + index,
|
||||
switcher->mediaSwitches.begin() + index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_mediaDown_clicked()
|
||||
{
|
||||
int index = ui->mediaSwitches->currentRow();
|
||||
if (index != -1 && index != ui->mediaSwitches->count() - 1) {
|
||||
ui->mediaSwitches->insertItem(
|
||||
index + 1, ui->mediaSwitches->takeItem(index));
|
||||
ui->mediaSwitches->setCurrentRow(index + 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
iter_swap(switcher->mediaSwitches.begin() + index,
|
||||
switcher->mediaSwitches.begin() + index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_mediaTimeRestrictions_currentIndexChanged(int idx)
|
||||
{
|
||||
if (idx == -1)
|
||||
return;
|
||||
|
||||
if ((time_restriction)ui->mediaTimeRestrictions->currentIndex() ==
|
||||
TIME_RESTRICTION_NONE) {
|
||||
ui->mediaTime->setDisabled(true);
|
||||
} else {
|
||||
ui->mediaTime->setDisabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
|
||||
OBSWeakSource &transition)
|
||||
{
|
||||
@@ -122,8 +165,137 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
|
||||
? previousScene
|
||||
: mediaSwitch.scene;
|
||||
transition = mediaSwitch.transition;
|
||||
|
||||
if (verbose)
|
||||
blog(LOG_INFO,
|
||||
"Advanced Scene Switcher meida match");
|
||||
}
|
||||
mediaSwitch.matched = matched;
|
||||
obs_source_release(source);
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::saveMediaSwitches(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *mediaArray = obs_data_array_create();
|
||||
for (MediaSwitch &s : switcher->mediaSwitches) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(s.source);
|
||||
obs_source_t *sceneSource = obs_weak_source_get_source(s.scene);
|
||||
obs_source_t *transition =
|
||||
obs_weak_source_get_source(s.transition);
|
||||
if ((s.usePreviousScene || sceneSource) && source &&
|
||||
transition) {
|
||||
const char *sourceName = obs_source_get_name(source);
|
||||
const char *sceneName =
|
||||
obs_source_get_name(sceneSource);
|
||||
const char *transitionName =
|
||||
obs_source_get_name(transition);
|
||||
obs_data_set_string(array_obj, "source", sourceName);
|
||||
obs_data_set_string(array_obj, "scene",
|
||||
s.usePreviousScene
|
||||
? PREVIOUS_SCENE_NAME
|
||||
: sceneName);
|
||||
obs_data_set_string(array_obj, "transition",
|
||||
transitionName);
|
||||
obs_data_set_int(array_obj, "state", s.state);
|
||||
obs_data_set_int(array_obj, "restriction",
|
||||
s.restriction);
|
||||
obs_data_set_int(array_obj, "time", s.time);
|
||||
obs_data_array_push_back(mediaArray, array_obj);
|
||||
}
|
||||
obs_source_release(source);
|
||||
obs_source_release(sceneSource);
|
||||
obs_source_release(transition);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "mediaSwitches", mediaArray);
|
||||
obs_data_array_release(mediaArray);
|
||||
}
|
||||
|
||||
void SwitcherData::loadMediaSwitches(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *mediaArray = obs_data_get_array(obj, "mediaSwitches");
|
||||
switcher->mediaSwitches.clear();
|
||||
size_t count = obs_data_array_count(mediaArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj = obs_data_array_item(mediaArray, i);
|
||||
|
||||
const char *source = obs_data_get_string(array_obj, "source");
|
||||
const char *scene = obs_data_get_string(array_obj, "scene");
|
||||
const char *transition =
|
||||
obs_data_get_string(array_obj, "transition");
|
||||
obs_media_state state =
|
||||
(obs_media_state)obs_data_get_int(array_obj, "state");
|
||||
time_restriction restriction =
|
||||
(time_restriction)obs_data_get_int(array_obj,
|
||||
"restriction");
|
||||
uint64_t time = obs_data_get_int(array_obj, "time");
|
||||
|
||||
std::string mediaStr = MakeMediaSwitchName(source, scene,
|
||||
transition, state,
|
||||
restriction, time)
|
||||
.toUtf8()
|
||||
.constData();
|
||||
|
||||
switcher->mediaSwitches.emplace_back(
|
||||
GetWeakSourceByName(scene), GetWeakSourceByName(source),
|
||||
GetWeakTransitionByName(transition), state, restriction,
|
||||
time, (strcmp(scene, PREVIOUS_SCENE_NAME) == 0),
|
||||
mediaStr);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(mediaArray);
|
||||
}
|
||||
|
||||
void SceneSwitcher::setupMediaTab()
|
||||
{
|
||||
populateSceneSelection(ui->mediaScenes, true);
|
||||
populateTransitionSelection(ui->mediaTransitions);
|
||||
|
||||
auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */
|
||||
{
|
||||
QComboBox *combo = reinterpret_cast<QComboBox *>(data);
|
||||
if (strcmp(obs_source_get_id(source), "ffmpeg_source") == 0) {
|
||||
const char *name = obs_source_get_name(source);
|
||||
combo->addItem(name);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
obs_enum_sources(sourceEnum, ui->mediaSources);
|
||||
|
||||
ui->mediaStates->addItem("None");
|
||||
ui->mediaStates->addItem("Playing");
|
||||
ui->mediaStates->addItem("Opening");
|
||||
ui->mediaStates->addItem("Buffering");
|
||||
ui->mediaStates->addItem("Paused");
|
||||
ui->mediaStates->addItem("Stopped");
|
||||
ui->mediaStates->addItem("Ended");
|
||||
ui->mediaStates->addItem("Error");
|
||||
|
||||
ui->mediaTimeRestrictions->addItem("None");
|
||||
ui->mediaTimeRestrictions->addItem("Time shorter");
|
||||
ui->mediaTimeRestrictions->addItem("Time longer");
|
||||
ui->mediaTimeRestrictions->addItem("Time remaining shorter");
|
||||
ui->mediaTimeRestrictions->addItem("Time remaining longer");
|
||||
|
||||
for (auto &s : switcher->mediaSwitches) {
|
||||
std::string sourceName = GetWeakSourceName(s.source);
|
||||
std::string sceneName = (s.usePreviousScene)
|
||||
? PREVIOUS_SCENE_NAME
|
||||
: GetWeakSourceName(s.scene);
|
||||
std::string transitionName = GetWeakSourceName(s.transition);
|
||||
QString listText = MakeMediaSwitchName(
|
||||
sourceName.c_str(), sceneName.c_str(),
|
||||
transitionName.c_str(), s.state, s.restriction, s.time);
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(listText, ui->mediaSwitches);
|
||||
item->setData(Qt::UserRole, listText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,5 +219,104 @@ bool SwitcherData::checkPause()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose && pause)
|
||||
blog(LOG_INFO, "Advanced Scene Switcher pause match");
|
||||
|
||||
return pause;
|
||||
}
|
||||
|
||||
void SwitcherData::savePauseSwitches(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *pauseScenesArray = obs_data_array_create();
|
||||
for (OBSWeakSource &scene : switcher->pauseScenesSwitches) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(scene);
|
||||
if (source) {
|
||||
const char *n = obs_source_get_name(source);
|
||||
obs_data_set_string(array_obj, "pauseScene", n);
|
||||
obs_data_array_push_back(pauseScenesArray, array_obj);
|
||||
obs_source_release(source);
|
||||
}
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "pauseScenes", pauseScenesArray);
|
||||
obs_data_array_release(pauseScenesArray);
|
||||
|
||||
obs_data_array_t *pauseWindowsArray = obs_data_array_create();
|
||||
for (std::string &window : switcher->pauseWindowsSwitches) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
obs_data_set_string(array_obj, "pauseWindow", window.c_str());
|
||||
obs_data_array_push_back(pauseWindowsArray, array_obj);
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "pauseWindows", pauseWindowsArray);
|
||||
obs_data_array_release(pauseWindowsArray);
|
||||
}
|
||||
|
||||
void SwitcherData::loadPauseSwitches(obs_data_t *obj)
|
||||
{
|
||||
switcher->pauseScenesSwitches.clear();
|
||||
|
||||
obs_data_array_t *pauseScenesArray =
|
||||
obs_data_get_array(obj, "pauseScenes");
|
||||
size_t count = obs_data_array_count(pauseScenesArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj =
|
||||
obs_data_array_item(pauseScenesArray, i);
|
||||
|
||||
const char *scene =
|
||||
obs_data_get_string(array_obj, "pauseScene");
|
||||
|
||||
switcher->pauseScenesSwitches.emplace_back(
|
||||
GetWeakSourceByName(scene));
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(pauseScenesArray);
|
||||
|
||||
switcher->pauseWindowsSwitches.clear();
|
||||
|
||||
obs_data_array_t *pauseWindowsArray =
|
||||
obs_data_get_array(obj, "pauseWindows");
|
||||
count = obs_data_array_count(pauseWindowsArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj =
|
||||
obs_data_array_item(pauseWindowsArray, i);
|
||||
|
||||
const char *window =
|
||||
obs_data_get_string(array_obj, "pauseWindow");
|
||||
|
||||
switcher->pauseWindowsSwitches.emplace_back(window);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(pauseWindowsArray);
|
||||
}
|
||||
|
||||
void SceneSwitcher::setupPauseTab()
|
||||
{
|
||||
populateSceneSelection(ui->pauseScenesScenes, false);
|
||||
populateWindowSelection(ui->pauseWindowsWindows);
|
||||
|
||||
for (auto &scene : switcher->pauseScenesSwitches) {
|
||||
std::string sceneName = GetWeakSourceName(scene);
|
||||
QString text = QString::fromStdString(sceneName);
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->pauseScenes);
|
||||
item->setData(Qt::UserRole, text);
|
||||
}
|
||||
|
||||
for (auto &window : switcher->pauseWindowsSwitches) {
|
||||
QString text = QString::fromStdString(window);
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->pauseWindows);
|
||||
item->setData(Qt::UserRole, text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +132,84 @@ void SwitcherData::checkRandom(bool &match, OBSWeakSource &scene,
|
||||
delay = (int)r.delay * 1000;
|
||||
match = true;
|
||||
lastRandomScene = r.scene;
|
||||
|
||||
if (verbose)
|
||||
blog(LOG_INFO, "Advanced Scene Switcher random match");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::saveRandomSwitches(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *randomArray = obs_data_array_create();
|
||||
for (RandomSwitch &s : switcher->randomSwitches) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(s.scene);
|
||||
obs_source_t *transition =
|
||||
obs_weak_source_get_source(s.transition);
|
||||
|
||||
if (source && transition) {
|
||||
const char *sceneName = obs_source_get_name(source);
|
||||
const char *transitionName =
|
||||
obs_source_get_name(transition);
|
||||
obs_data_set_string(array_obj, "scene", sceneName);
|
||||
obs_data_set_string(array_obj, "transition",
|
||||
transitionName);
|
||||
obs_data_set_double(array_obj, "delay", s.delay);
|
||||
obs_data_set_string(array_obj, "str",
|
||||
s.randomSwitchStr.c_str());
|
||||
obs_data_array_push_back(randomArray, array_obj);
|
||||
obs_source_release(source);
|
||||
obs_source_release(transition);
|
||||
}
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "randomSwitches", randomArray);
|
||||
obs_data_array_release(randomArray);
|
||||
}
|
||||
|
||||
void SwitcherData::loadRandomSwitches(obs_data_t *obj)
|
||||
{
|
||||
switcher->randomSwitches.clear();
|
||||
|
||||
obs_data_array_t *randomArray =
|
||||
obs_data_get_array(obj, "randomSwitches");
|
||||
size_t count = obs_data_array_count(randomArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj = obs_data_array_item(randomArray, i);
|
||||
|
||||
const char *scene = obs_data_get_string(array_obj, "scene");
|
||||
const char *transition =
|
||||
obs_data_get_string(array_obj, "transition");
|
||||
double delay = obs_data_get_double(array_obj, "delay");
|
||||
const char *str = obs_data_get_string(array_obj, "str");
|
||||
|
||||
switcher->randomSwitches.emplace_back(
|
||||
GetWeakSourceByName(scene),
|
||||
GetWeakTransitionByName(transition), delay, str);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(randomArray);
|
||||
}
|
||||
|
||||
void SceneSwitcher::setupRandomTab()
|
||||
{
|
||||
populateSceneSelection(ui->randomScenes, false);
|
||||
populateTransitionSelection(ui->randomTransitions);
|
||||
|
||||
for (auto &s : switcher->randomSwitches) {
|
||||
std::string sceneName = GetWeakSourceName(s.scene);
|
||||
std::string transitionName = GetWeakSourceName(s.transition);
|
||||
QString text = MakeRandomSwitchName(
|
||||
sceneName.c_str(), transitionName.c_str(), s.delay);
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->randomScenesList);
|
||||
item->setData(Qt::UserRole, text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,50 @@
|
||||
#include <QFileDialog>
|
||||
#include <QTextStream>
|
||||
#include <QMessageBox>
|
||||
#include <obs.hpp>
|
||||
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
#define SECONDS_INDEX 0
|
||||
#define MINUTES_INDEX 1
|
||||
#define HOURS_INDEX 2
|
||||
|
||||
void SceneSwitcher::on_sceneRoundTripDelayUnits_currentIndexChanged(int index)
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
double val = ui->sceneRoundTripSpinBox->value();
|
||||
|
||||
switch (switcher->sceneRoundTripUnitMultiplier) {
|
||||
case 1:
|
||||
val /= pow(60, index);
|
||||
break;
|
||||
case 60:
|
||||
val /= pow(60, index - 1);
|
||||
break;
|
||||
case 3600:
|
||||
val /= pow(60, index - 2);
|
||||
break;
|
||||
}
|
||||
|
||||
ui->sceneRoundTripSpinBox->setValue(val);
|
||||
|
||||
switch (index) {
|
||||
case SECONDS_INDEX:
|
||||
switcher->sceneRoundTripUnitMultiplier = 1;
|
||||
break;
|
||||
case MINUTES_INDEX:
|
||||
switcher->sceneRoundTripUnitMultiplier = 60;
|
||||
break;
|
||||
case HOURS_INDEX:
|
||||
switcher->sceneRoundTripUnitMultiplier = 3600;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_sceneRoundTripAdd_clicked()
|
||||
{
|
||||
QString scene1Name = ui->sceneRoundTripScenes1->currentText();
|
||||
@@ -13,7 +54,8 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
|
||||
if (scene1Name.isEmpty() || scene2Name.isEmpty())
|
||||
return;
|
||||
|
||||
double delay = ui->sceneRoundTripSpinBox->value();
|
||||
double delay = ui->sceneRoundTripSpinBox->value() *
|
||||
switcher->sceneRoundTripUnitMultiplier;
|
||||
|
||||
if (scene1Name == scene2Name)
|
||||
return;
|
||||
@@ -35,7 +77,7 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->sceneRoundTripSwitches.emplace_back(
|
||||
source1, source2, transition, int(delay * 1000),
|
||||
source1, source2, transition, delay,
|
||||
(scene2Name == QString(PREVIOUS_SCENE_NAME)),
|
||||
text.toUtf8().constData());
|
||||
} else {
|
||||
@@ -47,7 +89,7 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
|
||||
for (auto &s : switcher->sceneRoundTripSwitches) {
|
||||
if (s.scene1 == source1) {
|
||||
s.scene2 = source2;
|
||||
s.delay = int(delay * 1000);
|
||||
s.delay = delay;
|
||||
s.transition = transition;
|
||||
s.usePreviousScene =
|
||||
(scene2Name ==
|
||||
@@ -58,8 +100,6 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui->sceneRoundTrips->sortItems();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,70 +129,65 @@ void SceneSwitcher::on_sceneRoundTripRemove_clicked()
|
||||
delete item;
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_autoStopSceneCheckBox_stateChanged(int state)
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
if (!state) {
|
||||
ui->autoStopScenes->setDisabled(true);
|
||||
switcher->autoStopEnable = false;
|
||||
} else {
|
||||
ui->autoStopScenes->setDisabled(false);
|
||||
switcher->autoStopEnable = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::UpdateAutoStopScene(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->autoStopScene = ws;
|
||||
|
||||
obs_weak_source_release(ws);
|
||||
obs_source_release(scene);
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_autoStopScenes_currentTextChanged(const QString &text)
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
UpdateAutoStopScene(text);
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_sceneRoundTripSave_clicked()
|
||||
{
|
||||
QString directory = QFileDialog::getSaveFileName(
|
||||
this, tr("Save Scene Round Trip to file ..."),
|
||||
QDir::currentPath(), tr("Text files (*.txt)"));
|
||||
if (!directory.isEmpty()) {
|
||||
QFile file(directory);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
return;
|
||||
QTextStream out(&file);
|
||||
for (SceneRoundTripSwitch s :
|
||||
switcher->sceneRoundTripSwitches) {
|
||||
out << QString::fromStdString(
|
||||
GetWeakSourceName(s.scene1))
|
||||
<< "\n";
|
||||
if (s.usePreviousScene)
|
||||
out << (PREVIOUS_SCENE_NAME) << "\n";
|
||||
else
|
||||
out << QString::fromStdString(
|
||||
GetWeakSourceName(s.scene2))
|
||||
<< "\n";
|
||||
out << s.delay << "\n";
|
||||
out << QString::fromStdString(s.sceneRoundTripStr)
|
||||
<< "\n";
|
||||
out << QString::fromStdString(
|
||||
GetWeakSourceName(s.transition))
|
||||
<< "\n";
|
||||
if (directory.isEmpty())
|
||||
return;
|
||||
QFile file(directory);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
return;
|
||||
|
||||
obs_data_t *obj = obs_data_create();
|
||||
switcher->saveSceneRoundTripSwitches(obj);
|
||||
obs_data_save_json(obj, file.fileName().toUtf8().constData());
|
||||
obs_data_release(obj);
|
||||
}
|
||||
|
||||
// to be removed once support for old file format is dropped
|
||||
bool oldSceneRoundTripLoad(QFile *file)
|
||||
{
|
||||
QTextStream in(file);
|
||||
std::vector<QString> lines;
|
||||
|
||||
std::vector<SceneRoundTripSwitch> newSceneRoundTripSwitch;
|
||||
|
||||
while (!in.atEnd()) {
|
||||
QString line = in.readLine();
|
||||
lines.push_back(line);
|
||||
if (lines.size() == 5) {
|
||||
OBSWeakSource scene1 = GetWeakSourceByQString(lines[0]);
|
||||
OBSWeakSource scene2 = GetWeakSourceByQString(lines[1]);
|
||||
OBSWeakSource transition =
|
||||
GetWeakTransitionByQString(lines[4]);
|
||||
|
||||
if (WeakSourceValid(scene1) &&
|
||||
((lines[1] == QString(PREVIOUS_SCENE_NAME)) ||
|
||||
(WeakSourceValid(scene2))) &&
|
||||
WeakSourceValid(transition)) {
|
||||
newSceneRoundTripSwitch.emplace_back(
|
||||
SceneRoundTripSwitch(
|
||||
GetWeakSourceByQString(lines[0]),
|
||||
GetWeakSourceByQString(lines[1]),
|
||||
GetWeakTransitionByQString(
|
||||
lines[4]),
|
||||
lines[2].toDouble() / 1000.,
|
||||
(lines[1] ==
|
||||
QString(PREVIOUS_SCENE_NAME)),
|
||||
lines[3].toStdString()));
|
||||
}
|
||||
lines.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (lines.size() != 0 || newSceneRoundTripSwitch.size() == 0)
|
||||
return false;
|
||||
|
||||
switcher->sceneRoundTripSwitches.clear();
|
||||
switcher->sceneRoundTripSwitches = newSceneRoundTripSwitch;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_sceneRoundTripLoad_clicked()
|
||||
@@ -162,65 +197,45 @@ void SceneSwitcher::on_sceneRoundTripLoad_clicked()
|
||||
QString directory = QFileDialog::getOpenFileName(
|
||||
this, tr("Select a file to read Scene Round Trip from ..."),
|
||||
QDir::currentPath(), tr("Text files (*.txt)"));
|
||||
if (!directory.isEmpty()) {
|
||||
QFile file(directory);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
return;
|
||||
if (directory.isEmpty())
|
||||
return;
|
||||
|
||||
QTextStream in(&file);
|
||||
std::vector<QString> lines;
|
||||
QFile file(directory);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
return;
|
||||
|
||||
std::vector<SceneRoundTripSwitch> newSceneRoundTripSwitch;
|
||||
obs_data_t *obj = obs_data_create_from_json_file(
|
||||
file.fileName().toUtf8().constData());
|
||||
|
||||
while (!in.atEnd()) {
|
||||
QString line = in.readLine();
|
||||
lines.push_back(line);
|
||||
if (lines.size() == 5) {
|
||||
OBSWeakSource scene1 =
|
||||
GetWeakSourceByQString(lines[0]);
|
||||
OBSWeakSource scene2 =
|
||||
GetWeakSourceByQString(lines[1]);
|
||||
OBSWeakSource transition =
|
||||
GetWeakTransitionByQString(lines[4]);
|
||||
|
||||
if (WeakSourceValid(scene1) &&
|
||||
((lines[1] ==
|
||||
QString(PREVIOUS_SCENE_NAME)) ||
|
||||
(WeakSourceValid(scene2))) &&
|
||||
WeakSourceValid(transition)) {
|
||||
newSceneRoundTripSwitch.emplace_back(
|
||||
SceneRoundTripSwitch(
|
||||
GetWeakSourceByQString(
|
||||
lines[0]),
|
||||
GetWeakSourceByQString(
|
||||
lines[1]),
|
||||
GetWeakTransitionByQString(
|
||||
lines[4]),
|
||||
lines[2].toInt(),
|
||||
(lines[1] ==
|
||||
QString(PREVIOUS_SCENE_NAME)),
|
||||
lines[3].toStdString()));
|
||||
}
|
||||
lines.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (lines.size() != 0 || newSceneRoundTripSwitch.size() == 0)
|
||||
return;
|
||||
|
||||
switcher->sceneRoundTripSwitches.clear();
|
||||
ui->sceneRoundTrips->clear();
|
||||
switcher->sceneRoundTripSwitches = newSceneRoundTripSwitch;
|
||||
for (SceneRoundTripSwitch s :
|
||||
switcher->sceneRoundTripSwitches) {
|
||||
QListWidgetItem *item = new QListWidgetItem(
|
||||
QString::fromStdString(s.sceneRoundTripStr),
|
||||
ui->sceneRoundTrips);
|
||||
item->setData(
|
||||
Qt::UserRole,
|
||||
QString::fromStdString(s.sceneRoundTripStr));
|
||||
if (!obj) {
|
||||
QMessageBox Msgbox;
|
||||
QString txt =
|
||||
"Advanced Scene Switcher failed to import settings!\n";
|
||||
txt += "Falling back to old format.";
|
||||
Msgbox.setText(txt);
|
||||
Msgbox.exec();
|
||||
if (oldSceneRoundTripLoad(&file)) {
|
||||
QString txt =
|
||||
"Advanced Scene Switcher settings imported successfully!\n";
|
||||
txt += "Please resave settings as support for old format will be dropped in next version.";
|
||||
Msgbox.setText(txt);
|
||||
Msgbox.exec();
|
||||
close();
|
||||
} else {
|
||||
Msgbox.setText(
|
||||
"Advanced Scene Switcher failed to import settings!");
|
||||
Msgbox.exec();
|
||||
}
|
||||
return;
|
||||
}
|
||||
switcher->loadSceneRoundTripSwitches(obj);
|
||||
obs_data_release(obj);
|
||||
|
||||
QMessageBox Msgbox;
|
||||
Msgbox.setText(
|
||||
"Advanced Scene Switcher settings imported successfully!");
|
||||
Msgbox.exec();
|
||||
close();
|
||||
}
|
||||
|
||||
void SwitcherData::checkSceneRoundTrip(bool &match, OBSWeakSource &scene,
|
||||
@@ -234,11 +249,18 @@ void SwitcherData::checkSceneRoundTrip(bool &match, OBSWeakSource &scene,
|
||||
for (SceneRoundTripSwitch &s : sceneRoundTripSwitches) {
|
||||
if (s.scene1 == ws) {
|
||||
sceneRoundTripActive = true;
|
||||
int dur = s.delay - interval;
|
||||
int dur = s.delay * 1000 - interval;
|
||||
if (dur > 0) {
|
||||
waitScene = currentSource;
|
||||
|
||||
if (verbose)
|
||||
blog(LOG_INFO,
|
||||
"Advanced Scene Switcher sequence sleep %d",
|
||||
dur);
|
||||
|
||||
cv.wait_for(lock,
|
||||
std::chrono::milliseconds(dur));
|
||||
waitScene = nullptr;
|
||||
}
|
||||
obs_source_t *currentSource2 =
|
||||
obs_frontend_get_current_scene();
|
||||
@@ -276,15 +298,15 @@ void SceneSwitcher::on_sceneRoundTrips_currentRowChanged(int idx)
|
||||
std::string scene2 = GetWeakSourceName(s.scene2);
|
||||
std::string transitionName =
|
||||
GetWeakSourceName(s.transition);
|
||||
int delay = s.delay;
|
||||
double delay = s.delay /
|
||||
switcher->sceneRoundTripUnitMultiplier;
|
||||
ui->sceneRoundTripScenes1->setCurrentText(
|
||||
scene1.c_str());
|
||||
ui->sceneRoundTripScenes2->setCurrentText(
|
||||
scene2.c_str());
|
||||
ui->sceneRoundTripTransitions->setCurrentText(
|
||||
transitionName.c_str());
|
||||
ui->sceneRoundTripSpinBox->setValue((double)delay /
|
||||
1000);
|
||||
ui->sceneRoundTripSpinBox->setValue(delay);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -309,17 +331,170 @@ int SceneSwitcher::SceneRoundTripFindByData(const QString &scene1)
|
||||
return idx;
|
||||
}
|
||||
|
||||
void SwitcherData::autoStopStreamAndRecording()
|
||||
void SceneSwitcher::on_sceneRoundTripUp_clicked()
|
||||
{
|
||||
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
||||
obs_weak_source_t *ws = obs_source_get_weak_source(currentSource);
|
||||
int index = ui->sceneRoundTrips->currentRow();
|
||||
if (index != -1 && index != 0) {
|
||||
ui->sceneRoundTrips->insertItem(
|
||||
index - 1, ui->sceneRoundTrips->takeItem(index));
|
||||
ui->sceneRoundTrips->setCurrentRow(index - 1);
|
||||
|
||||
if (ws && autoStopScene == ws) {
|
||||
if (obs_frontend_streaming_active())
|
||||
obs_frontend_streaming_stop();
|
||||
if (obs_frontend_recording_active())
|
||||
obs_frontend_recording_stop();
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
iter_swap(switcher->sceneRoundTripSwitches.begin() + index,
|
||||
switcher->sceneRoundTripSwitches.begin() + index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_sceneRoundTripDown_clicked()
|
||||
{
|
||||
int index = ui->sceneRoundTrips->currentRow();
|
||||
if (index != -1 && index != ui->sceneRoundTrips->count() - 1) {
|
||||
ui->sceneRoundTrips->insertItem(
|
||||
index + 1, ui->sceneRoundTrips->takeItem(index));
|
||||
ui->sceneRoundTrips->setCurrentRow(index + 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
iter_swap(switcher->sceneRoundTripSwitches.begin() + index,
|
||||
switcher->sceneRoundTripSwitches.begin() + index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::saveSceneRoundTripSwitches(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *sceneRoundTripArray = obs_data_array_create();
|
||||
for (SceneRoundTripSwitch &s : switcher->sceneRoundTripSwitches) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
obs_source_t *source1 = obs_weak_source_get_source(s.scene1);
|
||||
obs_source_t *source2 = obs_weak_source_get_source(s.scene2);
|
||||
obs_source_t *transition =
|
||||
obs_weak_source_get_source(s.transition);
|
||||
if (source1 && (s.usePreviousScene || source2) && transition) {
|
||||
const char *sceneName1 = obs_source_get_name(source1);
|
||||
const char *sceneName2 = obs_source_get_name(source2);
|
||||
const char *transitionName =
|
||||
obs_source_get_name(transition);
|
||||
obs_data_set_string(array_obj, "sceneRoundTripScene1",
|
||||
sceneName1);
|
||||
obs_data_set_string(array_obj, "sceneRoundTripScene2",
|
||||
s.usePreviousScene
|
||||
? PREVIOUS_SCENE_NAME
|
||||
: sceneName2);
|
||||
obs_data_set_string(array_obj, "transition",
|
||||
transitionName);
|
||||
obs_data_set_double(array_obj, "delay", s.delay);
|
||||
obs_data_set_string(array_obj, "sceneRoundTripStr",
|
||||
s.sceneRoundTripStr.c_str());
|
||||
obs_data_array_push_back(sceneRoundTripArray,
|
||||
array_obj);
|
||||
obs_source_release(source1);
|
||||
obs_source_release(source2);
|
||||
obs_source_release(transition);
|
||||
}
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "sceneRoundTrip", sceneRoundTripArray);
|
||||
obs_data_array_release(sceneRoundTripArray);
|
||||
}
|
||||
|
||||
void SwitcherData::loadSceneRoundTripSwitches(obs_data_t *obj)
|
||||
{
|
||||
switcher->sceneRoundTripSwitches.clear();
|
||||
|
||||
obs_data_array_t *sceneRoundTripArray =
|
||||
obs_data_get_array(obj, "sceneRoundTrip");
|
||||
size_t count = obs_data_array_count(sceneRoundTripArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj =
|
||||
obs_data_array_item(sceneRoundTripArray, i);
|
||||
|
||||
const char *scene1 =
|
||||
obs_data_get_string(array_obj, "sceneRoundTripScene1");
|
||||
const char *scene2 =
|
||||
obs_data_get_string(array_obj, "sceneRoundTripScene2");
|
||||
const char *transition =
|
||||
obs_data_get_string(array_obj, "transition");
|
||||
|
||||
double delay = 0;
|
||||
|
||||
// To be removed in future version
|
||||
// to be compatible with older versions
|
||||
if (!obs_data_has_user_value(array_obj, "delay")) {
|
||||
delay = double(obs_data_get_int(array_obj,
|
||||
"sceneRoundTripDelay"));
|
||||
delay = delay * 1000. +
|
||||
double(obs_data_get_int(
|
||||
array_obj, "sceneRoundTripDelayMs"));
|
||||
delay /= 1000.;
|
||||
} else {
|
||||
delay = obs_data_get_double(array_obj, "delay");
|
||||
}
|
||||
|
||||
std::string str = MakeSceneRoundTripSwitchName(
|
||||
scene1, scene2, transition, delay)
|
||||
.toUtf8()
|
||||
.constData();
|
||||
const char *sceneRoundTripStr = str.c_str();
|
||||
|
||||
switcher->sceneRoundTripSwitches.emplace_back(
|
||||
GetWeakSourceByName(scene1),
|
||||
GetWeakSourceByName(scene2),
|
||||
GetWeakTransitionByName(transition), delay,
|
||||
(strcmp(scene2, PREVIOUS_SCENE_NAME) == 0),
|
||||
sceneRoundTripStr);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(sceneRoundTripArray);
|
||||
}
|
||||
|
||||
void SceneSwitcher::setupSequenceTab()
|
||||
{
|
||||
populateSceneSelection(ui->sceneRoundTripScenes1, false);
|
||||
populateSceneSelection(ui->sceneRoundTripScenes2, true);
|
||||
populateTransitionSelection(ui->sceneRoundTripTransitions);
|
||||
|
||||
double smallestDelay = double(switcher->interval) / 1000;
|
||||
for (auto &s : switcher->sceneRoundTripSwitches) {
|
||||
std::string sceneName1 = GetWeakSourceName(s.scene1);
|
||||
std::string sceneName2 = (s.usePreviousScene)
|
||||
? PREVIOUS_SCENE_NAME
|
||||
: GetWeakSourceName(s.scene2);
|
||||
std::string transitionName = GetWeakSourceName(s.transition);
|
||||
QString text = MakeSceneRoundTripSwitchName(
|
||||
sceneName1.c_str(), sceneName2.c_str(),
|
||||
transitionName.c_str(), s.delay);
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->sceneRoundTrips);
|
||||
item->setData(Qt::UserRole, text);
|
||||
|
||||
if (s.delay < smallestDelay)
|
||||
smallestDelay = s.delay;
|
||||
}
|
||||
(smallestDelay * 1000 < switcher->interval)
|
||||
? ui->intervalWarning->setVisible(true)
|
||||
: ui->intervalWarning->setVisible(false);
|
||||
|
||||
ui->sceneRoundTripDelayUnits->addItem("seconds");
|
||||
ui->sceneRoundTripDelayUnits->addItem("minutes");
|
||||
ui->sceneRoundTripDelayUnits->addItem("hours");
|
||||
|
||||
switch (switcher->sceneRoundTripUnitMultiplier) {
|
||||
case 1:
|
||||
ui->sceneRoundTripDelayUnits->setCurrentIndex(0);
|
||||
break;
|
||||
case 60:
|
||||
ui->sceneRoundTripDelayUnits->setCurrentIndex(1);
|
||||
break;
|
||||
case 3600:
|
||||
ui->sceneRoundTripDelayUnits->setCurrentIndex(2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
obs_source_release(currentSource);
|
||||
obs_weak_source_release(ws);
|
||||
}
|
||||
|
||||
@@ -162,6 +162,11 @@ void SwitcherData::setDefaultSceneTransitions()
|
||||
//This might cancel the current transition
|
||||
//There is no way to be sure when the previous transition finished
|
||||
obs_frontend_set_current_transition(transition);
|
||||
|
||||
if (verbose)
|
||||
blog(LOG_INFO,
|
||||
"Advanced Scene Switcher default transition set");
|
||||
|
||||
obs_source_release(transition);
|
||||
break;
|
||||
}
|
||||
@@ -264,6 +269,19 @@ void SceneSwitcher::on_defaultTransitions_currentRowChanged(int idx)
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_transitionOverridecheckBox_stateChanged(int state)
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
if (!state) {
|
||||
switcher->tansitionOverrideOverride = false;
|
||||
} else {
|
||||
switcher->tansitionOverrideOverride = true;
|
||||
}
|
||||
}
|
||||
|
||||
obs_weak_source_t *getNextTransition(obs_weak_source_t *scene1,
|
||||
obs_weak_source_t *scene2)
|
||||
{
|
||||
@@ -277,3 +295,221 @@ obs_weak_source_t *getNextTransition(obs_weak_source_t *scene1,
|
||||
}
|
||||
return ws;
|
||||
}
|
||||
|
||||
void overwriteTransitionOverride(obs_weak_source_t *sceneWs,
|
||||
obs_source_t *transition, transitionData &td)
|
||||
{
|
||||
obs_source_t *scene = obs_weak_source_get_source(sceneWs);
|
||||
obs_data_t *data = obs_source_get_private_settings(scene);
|
||||
|
||||
td.name = obs_data_get_string(data, "transition");
|
||||
td.duration = obs_data_get_int(data, "duration");
|
||||
|
||||
const char *name = obs_source_get_name(transition);
|
||||
int duration = obs_frontend_get_transition_duration();
|
||||
|
||||
obs_data_set_string(data, "transition", name);
|
||||
obs_data_set_int(data, "transition_duration", duration);
|
||||
|
||||
obs_data_release(data);
|
||||
obs_source_release(scene);
|
||||
}
|
||||
|
||||
void restoreTransitionOverride(obs_source_t *scene, transitionData td)
|
||||
{
|
||||
obs_data_t *data = obs_source_get_private_settings(scene);
|
||||
|
||||
obs_data_set_string(data, "transition", td.name.c_str());
|
||||
obs_data_set_int(data, "transition_duration", td.duration);
|
||||
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void setNextTransition(OBSWeakSource &targetScene, obs_source_t *currentSource,
|
||||
OBSWeakSource &transition,
|
||||
bool &transitionOverrideOverride, transitionData &td)
|
||||
{
|
||||
obs_weak_source_t *currentScene =
|
||||
obs_source_get_weak_source(currentSource);
|
||||
obs_weak_source_t *nextTransitionWs =
|
||||
getNextTransition(currentScene, targetScene);
|
||||
obs_weak_source_release(currentScene);
|
||||
|
||||
obs_source_t *nextTransition = nullptr;
|
||||
if (nextTransitionWs) {
|
||||
nextTransition = obs_weak_source_get_source(nextTransitionWs);
|
||||
} else if (transition) {
|
||||
nextTransition = obs_weak_source_get_source(transition);
|
||||
}
|
||||
|
||||
if (nextTransition) {
|
||||
obs_frontend_set_current_transition(nextTransition);
|
||||
}
|
||||
|
||||
if (transitionOverrideOverride)
|
||||
overwriteTransitionOverride(targetScene, nextTransition, td);
|
||||
|
||||
obs_weak_source_release(nextTransitionWs);
|
||||
obs_source_release(nextTransition);
|
||||
}
|
||||
|
||||
void SwitcherData::saveSceneTransitions(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *sceneTransitionsArray = obs_data_array_create();
|
||||
for (SceneTransition &s : switcher->sceneTransitions) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
obs_source_t *source1 = obs_weak_source_get_source(s.scene1);
|
||||
obs_source_t *source2 = obs_weak_source_get_source(s.scene2);
|
||||
obs_source_t *transition =
|
||||
obs_weak_source_get_source(s.transition);
|
||||
if (source1 && source2 && transition) {
|
||||
const char *sceneName1 = obs_source_get_name(source1);
|
||||
const char *sceneName2 = obs_source_get_name(source2);
|
||||
const char *transitionName =
|
||||
obs_source_get_name(transition);
|
||||
obs_data_set_string(array_obj, "Scene1", sceneName1);
|
||||
obs_data_set_string(array_obj, "Scene2", sceneName2);
|
||||
obs_data_set_string(array_obj, "transition",
|
||||
transitionName);
|
||||
obs_data_set_string(array_obj, "Str",
|
||||
s.sceneTransitionStr.c_str());
|
||||
obs_data_array_push_back(sceneTransitionsArray,
|
||||
array_obj);
|
||||
obs_source_release(source1);
|
||||
obs_source_release(source2);
|
||||
obs_source_release(transition);
|
||||
}
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "sceneTransitions", sceneTransitionsArray);
|
||||
obs_data_array_release(sceneTransitionsArray);
|
||||
|
||||
obs_data_array_t *defaultTransitionsArray = obs_data_array_create();
|
||||
for (DefaultSceneTransition &s : switcher->defaultSceneTransitions) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(s.scene);
|
||||
obs_source_t *transition =
|
||||
obs_weak_source_get_source(s.transition);
|
||||
if (source && transition) {
|
||||
const char *sceneName = obs_source_get_name(source);
|
||||
const char *transitionName =
|
||||
obs_source_get_name(transition);
|
||||
obs_data_set_string(array_obj, "Scene", sceneName);
|
||||
obs_data_set_string(array_obj, "transition",
|
||||
transitionName);
|
||||
obs_data_set_string(array_obj, "Str",
|
||||
s.sceneTransitionStr.c_str());
|
||||
obs_data_array_push_back(defaultTransitionsArray,
|
||||
array_obj);
|
||||
obs_source_release(source);
|
||||
obs_source_release(transition);
|
||||
}
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "defaultTransitions", defaultTransitionsArray);
|
||||
obs_data_array_release(defaultTransitionsArray);
|
||||
|
||||
obs_data_set_bool(obj, "tansitionOverrideOverride",
|
||||
switcher->tansitionOverrideOverride);
|
||||
}
|
||||
|
||||
void SwitcherData::loadSceneTransitions(obs_data_t *obj)
|
||||
{
|
||||
switcher->sceneTransitions.clear();
|
||||
|
||||
obs_data_array_t *sceneTransitionsArray =
|
||||
obs_data_get_array(obj, "sceneTransitions");
|
||||
size_t count = obs_data_array_count(sceneTransitionsArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj =
|
||||
obs_data_array_item(sceneTransitionsArray, i);
|
||||
|
||||
const char *scene1 = obs_data_get_string(array_obj, "Scene1");
|
||||
const char *scene2 = obs_data_get_string(array_obj, "Scene2");
|
||||
const char *transition =
|
||||
obs_data_get_string(array_obj, "transition");
|
||||
const char *sceneTransitionsStr =
|
||||
obs_data_get_string(array_obj, "Str");
|
||||
|
||||
switcher->sceneTransitions.emplace_back(
|
||||
GetWeakSourceByName(scene1),
|
||||
GetWeakSourceByName(scene2),
|
||||
GetWeakTransitionByName(transition),
|
||||
sceneTransitionsStr);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(sceneTransitionsArray);
|
||||
|
||||
switcher->defaultSceneTransitions.clear();
|
||||
|
||||
obs_data_array_t *defaultTransitionsArray =
|
||||
obs_data_get_array(obj, "defaultTransitions");
|
||||
count = obs_data_array_count(defaultTransitionsArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj =
|
||||
obs_data_array_item(defaultTransitionsArray, i);
|
||||
|
||||
const char *scene = obs_data_get_string(array_obj, "Scene");
|
||||
const char *transition =
|
||||
obs_data_get_string(array_obj, "transition");
|
||||
const char *sceneTransitionsStr =
|
||||
obs_data_get_string(array_obj, "Str");
|
||||
|
||||
switcher->defaultSceneTransitions.emplace_back(
|
||||
GetWeakSourceByName(scene),
|
||||
GetWeakTransitionByName(transition),
|
||||
sceneTransitionsStr);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(defaultTransitionsArray);
|
||||
|
||||
switcher->tansitionOverrideOverride =
|
||||
obs_data_get_bool(obj, "tansitionOverrideOverride");
|
||||
}
|
||||
|
||||
void SceneSwitcher::setupTransitionsTab()
|
||||
{
|
||||
populateSceneSelection(ui->transitionsScene1, false);
|
||||
populateSceneSelection(ui->transitionsScene2, false);
|
||||
populateSceneSelection(ui->defaultTransitionsScene, false);
|
||||
populateTransitionSelection(ui->transitionsTransitions);
|
||||
populateTransitionSelection(ui->defaultTransitionsTransitions);
|
||||
|
||||
for (auto &s : switcher->sceneTransitions) {
|
||||
std::string sceneName1 = GetWeakSourceName(s.scene1);
|
||||
std::string sceneName2 = GetWeakSourceName(s.scene2);
|
||||
std::string transitionName = GetWeakSourceName(s.transition);
|
||||
QString text = MakeSceneTransitionName(sceneName1.c_str(),
|
||||
sceneName2.c_str(),
|
||||
transitionName.c_str());
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->sceneTransitions);
|
||||
item->setData(Qt::UserRole, text);
|
||||
}
|
||||
//(transitionDurationLongerThanInterval(switcher->interval))
|
||||
// ? ui->transitionWarning->setVisible(true)
|
||||
// : ui->transitionWarning->setVisible(false);
|
||||
|
||||
for (auto &s : switcher->defaultSceneTransitions) {
|
||||
std::string sceneName = GetWeakSourceName(s.scene);
|
||||
std::string transitionName = GetWeakSourceName(s.transition);
|
||||
QString text = MakeDefaultSceneTransitionName(
|
||||
sceneName.c_str(), transitionName.c_str());
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->defaultTransitions);
|
||||
item->setData(Qt::UserRole, text);
|
||||
}
|
||||
|
||||
ui->transitionOverridecheckBox->setChecked(
|
||||
switcher->tansitionOverrideOverride);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include <QTimer>
|
||||
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
void SwitcherData::checkScreenRegionSwitch(bool &match, OBSWeakSource &scene,
|
||||
@@ -15,6 +17,12 @@ void SwitcherData::checkScreenRegionSwitch(bool &match, OBSWeakSource &scene,
|
||||
scene = s.scene;
|
||||
transition = s.transition;
|
||||
minRegionSize = regionSize;
|
||||
|
||||
if (verbose)
|
||||
blog(LOG_INFO,
|
||||
"Advanced Scene Switcher region match");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,8 +86,6 @@ void SceneSwitcher::on_screenRegionAdd_clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui->screenRegions->sortItems();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,3 +161,124 @@ int SceneSwitcher::ScreenRegionFindByData(const QString ®ion)
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_screenRegionUp_clicked()
|
||||
{
|
||||
int index = ui->screenRegions->currentRow();
|
||||
if (index != -1 && index != 0) {
|
||||
ui->screenRegions->insertItem(
|
||||
index - 1, ui->screenRegions->takeItem(index));
|
||||
ui->screenRegions->setCurrentRow(index - 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
iter_swap(switcher->screenRegionSwitches.begin() + index,
|
||||
switcher->screenRegionSwitches.begin() + index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_screenRegionDown_clicked()
|
||||
{
|
||||
int index = ui->screenRegions->currentRow();
|
||||
if (index != -1 && index != ui->screenRegions->count() - 1) {
|
||||
ui->screenRegions->insertItem(
|
||||
index + 1, ui->screenRegions->takeItem(index));
|
||||
ui->screenRegions->setCurrentRow(index + 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
iter_swap(switcher->screenRegionSwitches.begin() + index,
|
||||
switcher->screenRegionSwitches.begin() + index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::saveScreenRegionSwitches(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *screenRegionArray = obs_data_array_create();
|
||||
for (ScreenRegionSwitch &s : switcher->screenRegionSwitches) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(s.scene);
|
||||
obs_source_t *transition =
|
||||
obs_weak_source_get_source(s.transition);
|
||||
if (source && transition) {
|
||||
const char *sceneName = obs_source_get_name(source);
|
||||
const char *transitionName =
|
||||
obs_source_get_name(transition);
|
||||
obs_data_set_string(array_obj, "screenRegionScene",
|
||||
sceneName);
|
||||
obs_data_set_string(array_obj, "transition",
|
||||
transitionName);
|
||||
obs_data_set_int(array_obj, "minX", s.minX);
|
||||
obs_data_set_int(array_obj, "minY", s.minY);
|
||||
obs_data_set_int(array_obj, "maxX", s.maxX);
|
||||
obs_data_set_int(array_obj, "maxY", s.maxY);
|
||||
obs_data_set_string(array_obj, "screenRegionStr",
|
||||
s.regionStr.c_str());
|
||||
obs_data_array_push_back(screenRegionArray, array_obj);
|
||||
obs_source_release(source);
|
||||
obs_source_release(transition);
|
||||
}
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "screenRegion", screenRegionArray);
|
||||
obs_data_array_release(screenRegionArray);
|
||||
}
|
||||
|
||||
void SwitcherData::loadScreenRegionSwitches(obs_data_t *obj)
|
||||
{
|
||||
switcher->screenRegionSwitches.clear();
|
||||
|
||||
obs_data_array_t *screenRegionArray =
|
||||
obs_data_get_array(obj, "screenRegion");
|
||||
size_t count = obs_data_array_count(screenRegionArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj =
|
||||
obs_data_array_item(screenRegionArray, i);
|
||||
|
||||
const char *scene =
|
||||
obs_data_get_string(array_obj, "screenRegionScene");
|
||||
const char *transition =
|
||||
obs_data_get_string(array_obj, "transition");
|
||||
int minX = obs_data_get_int(array_obj, "minX");
|
||||
int minY = obs_data_get_int(array_obj, "minY");
|
||||
int maxX = obs_data_get_int(array_obj, "maxX");
|
||||
int maxY = obs_data_get_int(array_obj, "maxY");
|
||||
std::string regionStr =
|
||||
obs_data_get_string(array_obj, "screenRegionStr");
|
||||
|
||||
switcher->screenRegionSwitches.emplace_back(
|
||||
GetWeakSourceByName(scene),
|
||||
GetWeakTransitionByName(transition), minX, minY, maxX,
|
||||
maxY, regionStr);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(screenRegionArray);
|
||||
}
|
||||
|
||||
void SceneSwitcher::setupRegionTab()
|
||||
{
|
||||
populateSceneSelection(ui->screenRegionScenes, false);
|
||||
populateTransitionSelection(ui->screenRegionsTransitions);
|
||||
|
||||
for (auto &s : switcher->screenRegionSwitches) {
|
||||
std::string sceneName = GetWeakSourceName(s.scene);
|
||||
std::string transitionName = GetWeakSourceName(s.transition);
|
||||
QString text = MakeScreenRegionSwitchName(
|
||||
sceneName.c_str(), transitionName.c_str(), s.minX,
|
||||
s.minY, s.maxX, s.maxY);
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->screenRegions);
|
||||
item->setData(Qt::UserRole, s.regionStr.c_str());
|
||||
}
|
||||
|
||||
// screen region cursor position
|
||||
QTimer *screenRegionTimer = new QTimer(this);
|
||||
connect(screenRegionTimer, SIGNAL(timeout()), this,
|
||||
SLOT(updateScreenRegionCursorPos()));
|
||||
screenRegionTimer->start(1000);
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ void SceneSwitcher::on_timeAdd_clicked()
|
||||
} else {
|
||||
QListWidgetItem *item = ui->timeSwitches->item(idx);
|
||||
item->setText(text);
|
||||
item->setData(Qt::UserRole, v);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
@@ -83,7 +84,6 @@ void SceneSwitcher::on_timeAdd_clicked()
|
||||
QString(PREVIOUS_SCENE_NAME));
|
||||
s.timeSwitchStr =
|
||||
text.toUtf8().constData();
|
||||
;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -142,7 +142,97 @@ void SwitcherData::checkTimeSwitch(bool &match, OBSWeakSource &scene,
|
||||
scene = (s.usePreviousScene) ? previousScene : s.scene;
|
||||
transition = s.transition;
|
||||
match = true;
|
||||
|
||||
if (verbose)
|
||||
blog(LOG_INFO,
|
||||
"Advanced Scene Switcher time match");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::saveTimeSwitches(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *timeArray = obs_data_array_create();
|
||||
for (TimeSwitch &s : switcher->timeSwitches) {
|
||||
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);
|
||||
if ((s.usePreviousScene || sceneSource) && transition) {
|
||||
const char *sceneName =
|
||||
obs_source_get_name(sceneSource);
|
||||
const char *transitionName =
|
||||
obs_source_get_name(transition);
|
||||
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, "time",
|
||||
s.time.toString().toStdString().c_str());
|
||||
obs_data_array_push_back(timeArray, array_obj);
|
||||
}
|
||||
obs_source_release(sceneSource);
|
||||
obs_source_release(transition);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "timeSwitches", timeArray);
|
||||
obs_data_array_release(timeArray);
|
||||
}
|
||||
|
||||
void SwitcherData::loadTimeSwitches(obs_data_t *obj)
|
||||
{
|
||||
switcher->timeSwitches.clear();
|
||||
|
||||
obs_data_array_t *timeArray = obs_data_get_array(obj, "timeSwitches");
|
||||
size_t count = obs_data_array_count(timeArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj = obs_data_array_item(timeArray, i);
|
||||
|
||||
const char *scene = obs_data_get_string(array_obj, "scene");
|
||||
const char *transition =
|
||||
obs_data_get_string(array_obj, "transition");
|
||||
QTime time = QTime::fromString(
|
||||
obs_data_get_string(array_obj, "time"));
|
||||
|
||||
std::string timeSwitchStr =
|
||||
MakeTimeSwitchName(scene, transition, time)
|
||||
.toUtf8()
|
||||
.constData();
|
||||
|
||||
switcher->timeSwitches.emplace_back(
|
||||
GetWeakSourceByName(scene),
|
||||
GetWeakTransitionByName(transition), time,
|
||||
(strcmp(scene, PREVIOUS_SCENE_NAME) == 0),
|
||||
timeSwitchStr);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(timeArray);
|
||||
}
|
||||
|
||||
void SceneSwitcher::setupTimeTab()
|
||||
{
|
||||
populateSceneSelection(ui->timeScenes, true);
|
||||
populateTransitionSelection(ui->timeTransitions);
|
||||
|
||||
for (auto &s : switcher->timeSwitches) {
|
||||
std::string sceneName = (s.usePreviousScene)
|
||||
? PREVIOUS_SCENE_NAME
|
||||
: GetWeakSourceName(s.scene);
|
||||
std::string transitionName = GetWeakSourceName(s.transition);
|
||||
QString listText = MakeTimeSwitchName(
|
||||
sceneName.c_str(), transitionName.c_str(), s.time);
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(listText, ui->timeSwitches);
|
||||
item->setData(Qt::UserRole, listText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,3 +312,121 @@ void SwitcherData::checkWindowTitleSwitch(bool &match, OBSWeakSource &scene,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::saveWindowTitleSwitches(obs_data_t *obj)
|
||||
{
|
||||
obs_data_array_t *windowTitleArray = obs_data_array_create();
|
||||
for (WindowSceneSwitch &s : switcher->windowSwitches) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(s.scene);
|
||||
obs_source_t *transition =
|
||||
obs_weak_source_get_source(s.transition);
|
||||
if (source && transition) {
|
||||
const char *sceneName = obs_source_get_name(source);
|
||||
const char *transitionName =
|
||||
obs_source_get_name(transition);
|
||||
obs_data_set_string(array_obj, "scene", sceneName);
|
||||
obs_data_set_string(array_obj, "transition",
|
||||
transitionName);
|
||||
obs_data_set_string(array_obj, "window_title",
|
||||
s.window.c_str());
|
||||
obs_data_set_bool(array_obj, "fullscreen",
|
||||
s.fullscreen);
|
||||
obs_data_set_bool(array_obj, "focus", s.focus);
|
||||
obs_data_array_push_back(windowTitleArray, array_obj);
|
||||
obs_source_release(source);
|
||||
obs_source_release(transition);
|
||||
}
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "switches", windowTitleArray);
|
||||
obs_data_array_release(windowTitleArray);
|
||||
|
||||
obs_data_array_t *ignoreWindowsArray = obs_data_array_create();
|
||||
for (std::string &window : switcher->ignoreWindowsSwitches) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
obs_data_set_string(array_obj, "ignoreWindow", window.c_str());
|
||||
obs_data_array_push_back(ignoreWindowsArray, array_obj);
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "ignoreWindows", ignoreWindowsArray);
|
||||
obs_data_array_release(ignoreWindowsArray);
|
||||
}
|
||||
|
||||
void SwitcherData::loadWindowTitleSwitches(obs_data_t *obj)
|
||||
{
|
||||
switcher->windowSwitches.clear();
|
||||
|
||||
obs_data_array_t *windowTitleArray =
|
||||
obs_data_get_array(obj, "switches");
|
||||
size_t count = obs_data_array_count(windowTitleArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj =
|
||||
obs_data_array_item(windowTitleArray, i);
|
||||
|
||||
const char *scene = obs_data_get_string(array_obj, "scene");
|
||||
const char *transition =
|
||||
obs_data_get_string(array_obj, "transition");
|
||||
const char *window =
|
||||
obs_data_get_string(array_obj, "window_title");
|
||||
bool fullscreen = obs_data_get_bool(array_obj, "fullscreen");
|
||||
bool focus = obs_data_get_bool(array_obj, "focus") ||
|
||||
!obs_data_has_user_value(array_obj, "focus");
|
||||
|
||||
switcher->windowSwitches.emplace_back(
|
||||
GetWeakSourceByName(scene), window,
|
||||
GetWeakTransitionByName(transition), fullscreen, focus);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(windowTitleArray);
|
||||
|
||||
switcher->ignoreWindowsSwitches.clear();
|
||||
|
||||
obs_data_array_t *ignoreWindowsArray =
|
||||
obs_data_get_array(obj, "ignoreWindows");
|
||||
count = obs_data_array_count(ignoreWindowsArray);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj =
|
||||
obs_data_array_item(ignoreWindowsArray, i);
|
||||
|
||||
const char *window =
|
||||
obs_data_get_string(array_obj, "ignoreWindow");
|
||||
|
||||
switcher->ignoreWindowsSwitches.emplace_back(window);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(ignoreWindowsArray);
|
||||
}
|
||||
|
||||
void SceneSwitcher::setupTitleTab()
|
||||
{
|
||||
populateSceneSelection(ui->scenes, false);
|
||||
populateTransitionSelection(ui->transitions);
|
||||
populateWindowSelection(ui->windows);
|
||||
populateWindowSelection(ui->ignoreWindowsWindows);
|
||||
|
||||
for (auto &s : switcher->windowSwitches) {
|
||||
std::string sceneName = GetWeakSourceName(s.scene);
|
||||
std::string transitionName = GetWeakSourceName(s.transition);
|
||||
QString text = MakeSwitchName(sceneName.c_str(),
|
||||
s.window.c_str(),
|
||||
transitionName.c_str(),
|
||||
s.fullscreen, s.focus);
|
||||
|
||||
QListWidgetItem *item = new QListWidgetItem(text, ui->switches);
|
||||
item->setData(Qt::UserRole, s.window.c_str());
|
||||
}
|
||||
|
||||
for (auto &window : switcher->ignoreWindowsSwitches) {
|
||||
QString text = QString::fromStdString(window);
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->ignoreWindows);
|
||||
item->setData(Qt::UserRole, text);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user