mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-09-07 09:05:57 -05:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dfed8ac2a | ||
|
|
d7102d395e | ||
|
|
82a41694a1 | ||
|
|
a1cae263c1 | ||
|
|
cce6e240c2 | ||
|
|
9d04b4d1a0 | ||
|
|
fd7e48eff9 | ||
|
|
0350a46004 | ||
|
|
00fec4b573 | ||
|
|
c40a3af8ca | ||
|
|
e452d8cc8c | ||
|
|
fbc9818764 | ||
|
|
5ef09f661f | ||
|
|
2155a942f3 | ||
|
|
5af206da60 | ||
|
|
924f68df64 | ||
|
|
2f3c4a6dae | ||
|
|
f955c07bda | ||
|
|
6f1cd3cbcc |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -5,7 +5,7 @@ on: [push, pull_request, workflow_dispatch]
|
|||||||
env:
|
env:
|
||||||
PLUGIN_NAME: SceneSwitcher
|
PLUGIN_NAME: SceneSwitcher
|
||||||
LIB_NAME: advanced-scene-switcher
|
LIB_NAME: advanced-scene-switcher
|
||||||
OBS_TAG: 27.1.1
|
OBS_TAG: 27.1.3
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
macos64:
|
macos64:
|
||||||
|
|||||||
@@ -147,7 +147,6 @@ if(UNIX AND NOT APPLE)
|
|||||||
if(NOT PROCPS_LIBRARY)
|
if(NOT PROCPS_LIBRARY)
|
||||||
message(FATAL_ERROR "procps lib not found - please set PROCPS_LIBRARY")
|
message(FATAL_ERROR "procps lib not found - please set PROCPS_LIBRARY")
|
||||||
endif()
|
endif()
|
||||||
message (STATUS "WHAT THE FUCK IS GOING ON ${PROCPS_LIBRARY}")
|
|
||||||
link_libraries(${X11_LIBRARIES} ${procps_LIBRARIES})
|
link_libraries(${X11_LIBRARIES} ${procps_LIBRARIES})
|
||||||
include_directories("${X11_INCLUDE_DIR}" "${X11_Xtst_INCLUDE_PATH}"
|
include_directories("${X11_INCLUDE_DIR}" "${X11_Xtst_INCLUDE_PATH}"
|
||||||
"${X11_Xss_INCLUDE_PATH}" "${PROCPS_INCLUDE_DIR}")
|
"${X11_Xss_INCLUDE_PATH}" "${PROCPS_INCLUDE_DIR}")
|
||||||
@@ -176,10 +175,6 @@ if(WIN32)
|
|||||||
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# opencv
|
|
||||||
find_package(OpenCV REQUIRED)
|
|
||||||
include_directories("${OpenCV_INCLUDE_DIRS}")
|
|
||||||
|
|
||||||
# Setup QT tools
|
# Setup QT tools
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
@@ -220,6 +215,7 @@ set(advanced-scene-switcher_HEADERS
|
|||||||
src/headers/macro-action-media.hpp
|
src/headers/macro-action-media.hpp
|
||||||
src/headers/macro-action-plugin-state.hpp
|
src/headers/macro-action-plugin-state.hpp
|
||||||
src/headers/macro-action-preview-scene.hpp
|
src/headers/macro-action-preview-scene.hpp
|
||||||
|
src/headers/macro-action-random.hpp
|
||||||
src/headers/macro-action-recording.hpp
|
src/headers/macro-action-recording.hpp
|
||||||
src/headers/macro-action-replay-buffer.hpp
|
src/headers/macro-action-replay-buffer.hpp
|
||||||
src/headers/macro-action-run.hpp
|
src/headers/macro-action-run.hpp
|
||||||
@@ -250,6 +246,7 @@ set(advanced-scene-switcher_HEADERS
|
|||||||
src/headers/macro-condition-replay-buffer.hpp
|
src/headers/macro-condition-replay-buffer.hpp
|
||||||
src/headers/macro-condition-scene-order.hpp
|
src/headers/macro-condition-scene-order.hpp
|
||||||
src/headers/macro-condition-scene-transform.hpp
|
src/headers/macro-condition-scene-transform.hpp
|
||||||
|
src/headers/macro-condition-scene-visibility.hpp
|
||||||
src/headers/macro-condition-scene.hpp
|
src/headers/macro-condition-scene.hpp
|
||||||
src/headers/macro-condition-source.hpp
|
src/headers/macro-condition-source.hpp
|
||||||
src/headers/macro-condition-streaming.hpp
|
src/headers/macro-condition-streaming.hpp
|
||||||
@@ -311,6 +308,7 @@ set(advanced-scene-switcher_SOURCES
|
|||||||
src/macro-action-media.cpp
|
src/macro-action-media.cpp
|
||||||
src/macro-action-plugin-state.cpp
|
src/macro-action-plugin-state.cpp
|
||||||
src/macro-action-preview-scene.cpp
|
src/macro-action-preview-scene.cpp
|
||||||
|
src/macro-action-random.cpp
|
||||||
src/macro-action-recording.cpp
|
src/macro-action-recording.cpp
|
||||||
src/macro-action-replay-buffer.cpp
|
src/macro-action-replay-buffer.cpp
|
||||||
src/macro-action-run.cpp
|
src/macro-action-run.cpp
|
||||||
@@ -341,6 +339,7 @@ set(advanced-scene-switcher_SOURCES
|
|||||||
src/macro-condition-replay-buffer.cpp
|
src/macro-condition-replay-buffer.cpp
|
||||||
src/macro-condition-scene-order.cpp
|
src/macro-condition-scene-order.cpp
|
||||||
src/macro-condition-scene-transform.cpp
|
src/macro-condition-scene-transform.cpp
|
||||||
|
src/macro-condition-scene-visibility.cpp
|
||||||
src/macro-condition-scene.cpp
|
src/macro-condition-scene.cpp
|
||||||
src/macro-condition-source.cpp
|
src/macro-condition-source.cpp
|
||||||
src/macro-condition-streaming.cpp
|
src/macro-condition-streaming.cpp
|
||||||
@@ -365,6 +364,22 @@ set(advanced-scene-switcher_SOURCES
|
|||||||
src/volume-control.cpp
|
src/volume-control.cpp
|
||||||
src/version.cpp)
|
src/version.cpp)
|
||||||
|
|
||||||
|
# opencv
|
||||||
|
find_package(OpenCV)
|
||||||
|
if(OpenCV_FOUND)
|
||||||
|
include_directories("${OpenCV_INCLUDE_DIRS}")
|
||||||
|
else()
|
||||||
|
set(OpenCV_LIBRARIES "")
|
||||||
|
message(
|
||||||
|
WARNING
|
||||||
|
"OpenCV not found! Functionality relying on OpenCV will be disabled!\nOpenCV sources are available under: ${CMAKE_CURRENT_SOURCE_DIR}/deps/opencv"
|
||||||
|
)
|
||||||
|
list(REMOVE_ITEM advanced-scene-switcher_SOURCES
|
||||||
|
src/macro-condition-video.cpp)
|
||||||
|
list(REMOVE_ITEM advanced-scene-switcher_HEADERS
|
||||||
|
src/headers/macro-condition-video.hpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_library(
|
add_library(
|
||||||
advanced-scene-switcher MODULE
|
advanced-scene-switcher MODULE
|
||||||
${advanced-scene-switcher_HEADERS}
|
${advanced-scene-switcher_HEADERS}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ AdvSceneSwitcher.generalTab.priority.fileContent="Datei Inhalt"
|
|||||||
AdvSceneSwitcher.generalTab.priority.sceneSequence="Szenenfolge"
|
AdvSceneSwitcher.generalTab.priority.sceneSequence="Szenenfolge"
|
||||||
AdvSceneSwitcher.generalTab.priority.idleDetection="Inaktivitätserkennung"
|
AdvSceneSwitcher.generalTab.priority.idleDetection="Inaktivitätserkennung"
|
||||||
AdvSceneSwitcher.generalTab.priority.executable="Prozess"
|
AdvSceneSwitcher.generalTab.priority.executable="Prozess"
|
||||||
AdvSceneSwitcher.generalTab.priority.screenRegion="Bildschrimbereich"
|
AdvSceneSwitcher.generalTab.priority.screenRegion="Bildschirmbereich"
|
||||||
AdvSceneSwitcher.generalTab.priority.windowTitle="Fenstername"
|
AdvSceneSwitcher.generalTab.priority.windowTitle="Fenstername"
|
||||||
AdvSceneSwitcher.generalTab.priority.media="Medien"
|
AdvSceneSwitcher.generalTab.priority.media="Medien"
|
||||||
AdvSceneSwitcher.generalTab.priority.time="Zeit"
|
AdvSceneSwitcher.generalTab.priority.time="Zeit"
|
||||||
@@ -98,7 +98,7 @@ AdvSceneSwitcher.executableTab.entry="Wenn {{processes}} läuft wechsle zu {{sce
|
|||||||
AdvSceneSwitcher.executableTab.help="Dieser Tab erlaubt es Szenen zu wechseln, wenn bestimmte Prozesse laufen.\nDas kann nützlich sein, wenn sich der Name eines Fensters ändern kann oder dieser nicht bekannt ist.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
AdvSceneSwitcher.executableTab.help="Dieser Tab erlaubt es Szenen zu wechseln, wenn bestimmte Prozesse laufen.\nDas kann nützlich sein, wenn sich der Name eines Fensters ändern kann oder dieser nicht bekannt ist.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
||||||
|
|
||||||
; Screen Region Tab
|
; Screen Region Tab
|
||||||
AdvSceneSwitcher.screenRegionTab.title="Bildschrimbereich"
|
AdvSceneSwitcher.screenRegionTab.title="Bildschirmbereich"
|
||||||
AdvSceneSwitcher.screenRegionTab.currentPosition="Mauszeiger ist bei:"
|
AdvSceneSwitcher.screenRegionTab.currentPosition="Mauszeiger ist bei:"
|
||||||
AdvSceneSwitcher.screenRegionTab.showGuideFrames="Hilfsrahmen einblenden"
|
AdvSceneSwitcher.screenRegionTab.showGuideFrames="Hilfsrahmen einblenden"
|
||||||
AdvSceneSwitcher.screenRegionTab.hideGuideFrames="Hilfsrahmen ausblenden"
|
AdvSceneSwitcher.screenRegionTab.hideGuideFrames="Hilfsrahmen ausblenden"
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ AdvSceneSwitcher.condition.cursor.entry.line2="Cursor is currently at {{xPos}} x
|
|||||||
AdvSceneSwitcher.condition.scene="Scene"
|
AdvSceneSwitcher.condition.scene="Scene"
|
||||||
AdvSceneSwitcher.condition.scene.type.current="Current scene is"
|
AdvSceneSwitcher.condition.scene.type.current="Current scene is"
|
||||||
AdvSceneSwitcher.condition.scene.type.previous="Previous scene is"
|
AdvSceneSwitcher.condition.scene.type.previous="Previous scene is"
|
||||||
AdvSceneSwitcher.condition.scene.type.changed="Scene chagned"
|
AdvSceneSwitcher.condition.scene.type.changed="Scene changed"
|
||||||
AdvSceneSwitcher.condition.scene.type.notChanged="Scene has not changed"
|
AdvSceneSwitcher.condition.scene.type.notChanged="Scene has not changed"
|
||||||
AdvSceneSwitcher.condition.scene.waitForTransition="Wait for transition to complete"
|
AdvSceneSwitcher.condition.scene.waitForTransition="Wait for transition to complete"
|
||||||
AdvSceneSwitcher.condition.scene.entry="{{sceneType}} {{scenes}} {{waitForTransition}}"
|
AdvSceneSwitcher.condition.scene.entry="{{sceneType}} {{scenes}} {{waitForTransition}}"
|
||||||
@@ -172,6 +172,7 @@ AdvSceneSwitcher.condition.macro.count.type.below="Less than"
|
|||||||
AdvSceneSwitcher.condition.macro.count.type.above="More than"
|
AdvSceneSwitcher.condition.macro.count.type.above="More than"
|
||||||
AdvSceneSwitcher.condition.macro.count.type.equal="Exactly"
|
AdvSceneSwitcher.condition.macro.count.type.equal="Exactly"
|
||||||
AdvSceneSwitcher.condition.macro.count.reset="Reset"
|
AdvSceneSwitcher.condition.macro.count.reset="Reset"
|
||||||
|
AdvSceneSwitcher.condition.macro.pausedWarning="Selected macro is currently paused!"
|
||||||
AdvSceneSwitcher.condition.macro.state.entry="Conditions of {{macros}} are true"
|
AdvSceneSwitcher.condition.macro.state.entry="Conditions of {{macros}} are true"
|
||||||
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} was executed {{conditions}} {{count}} times"
|
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} was executed {{conditions}} {{count}} times"
|
||||||
AdvSceneSwitcher.condition.macro.count.entry.line2="Current count: {{currentCount}} {{resetCount}}"
|
AdvSceneSwitcher.condition.macro.count.entry.line2="Current count: {{currentCount}} {{resetCount}}"
|
||||||
@@ -232,6 +233,10 @@ AdvSceneSwitcher.condition.transition.type.started="Transition active"
|
|||||||
AdvSceneSwitcher.condition.transition.type.ended="Transition ended"
|
AdvSceneSwitcher.condition.transition.type.ended="Transition ended"
|
||||||
AdvSceneSwitcher.condition.transition.durationSuffix="seconds"
|
AdvSceneSwitcher.condition.transition.durationSuffix="seconds"
|
||||||
AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{duration}}{{durationSuffix}}"
|
AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{duration}}{{durationSuffix}}"
|
||||||
|
AdvSceneSwitcher.condition.sceneVisibility="Scene item visibility"
|
||||||
|
AdvSceneSwitcher.condition.sceneVisibility.type.shown="Shown"
|
||||||
|
AdvSceneSwitcher.condition.sceneVisibility.type.hidden="Hidden"
|
||||||
|
AdvSceneSwitcher.condition.sceneVisibility.entry="On {{scenes}} {{sources}} is {{conditions}} "
|
||||||
|
|
||||||
; Macro Actions
|
; Macro Actions
|
||||||
AdvSceneSwitcher.action.switchScene="Switch scene"
|
AdvSceneSwitcher.action.switchScene="Switch scene"
|
||||||
@@ -246,6 +251,7 @@ AdvSceneSwitcher.action.audio.type.mute="Mute"
|
|||||||
AdvSceneSwitcher.action.audio.type.unmute="Unmute"
|
AdvSceneSwitcher.action.audio.type.unmute="Unmute"
|
||||||
AdvSceneSwitcher.action.audio.type.sourceVolume="Set source volume"
|
AdvSceneSwitcher.action.audio.type.sourceVolume="Set source volume"
|
||||||
AdvSceneSwitcher.action.audio.type.masterVolume="Set master volume"
|
AdvSceneSwitcher.action.audio.type.masterVolume="Set master volume"
|
||||||
|
AdvSceneSwitcher.action.audio.fade="{{fade}}Fade over {{duration}} seconds"
|
||||||
AdvSceneSwitcher.action.audio.entry="{{actions}} {{audioSources}} {{volume}}"
|
AdvSceneSwitcher.action.audio.entry="{{actions}} {{audioSources}} {{volume}}"
|
||||||
AdvSceneSwitcher.action.recording="Recording"
|
AdvSceneSwitcher.action.recording="Recording"
|
||||||
AdvSceneSwitcher.action.recording.type.stop="Stop recording"
|
AdvSceneSwitcher.action.recording.type.stop="Stop recording"
|
||||||
@@ -271,7 +277,9 @@ AdvSceneSwitcher.action.run.entry="Run {{filePath}}"
|
|||||||
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
|
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
|
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
|
AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.entry="On {{scenes}} {{actions}} {{sources}}"
|
AdvSceneSwitcher.action.sceneVisibility.type.source="Source"
|
||||||
|
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Any"
|
||||||
|
AdvSceneSwitcher.action.sceneVisibility.entry="On {{scenes}} {{actions}} {{sourceTypes}} {{sources}}"
|
||||||
AdvSceneSwitcher.action.filter="Filter"
|
AdvSceneSwitcher.action.filter="Filter"
|
||||||
AdvSceneSwitcher.action.filter.type.enable="Enable"
|
AdvSceneSwitcher.action.filter.type.enable="Enable"
|
||||||
AdvSceneSwitcher.action.filter.type.disable="Disable"
|
AdvSceneSwitcher.action.filter.type.disable="Disable"
|
||||||
@@ -345,6 +353,10 @@ AdvSceneSwitcher.action.timer.type.continue="Continue"
|
|||||||
AdvSceneSwitcher.action.timer.type.reset="Reset"
|
AdvSceneSwitcher.action.timer.type.reset="Reset"
|
||||||
AdvSceneSwitcher.action.timer.type.setTimeRemaining="Set time remaining of"
|
AdvSceneSwitcher.action.timer.type.setTimeRemaining="Set time remaining of"
|
||||||
AdvSceneSwitcher.action.timer.entry="{{timerAction}} timers on {{macros}} {{duration}}"
|
AdvSceneSwitcher.action.timer.entry="{{timerAction}} timers on {{macros}} {{duration}}"
|
||||||
|
AdvSceneSwitcher.action.random="Random"
|
||||||
|
AdvSceneSwitcher.action.random.arguments="Macros:"
|
||||||
|
AdvSceneSwitcher.action.random.addArgument="Add Macro"
|
||||||
|
AdvSceneSwitcher.action.random.entry="Run {{macroSelection}}"
|
||||||
|
|
||||||
; Transition Tab
|
; Transition Tab
|
||||||
AdvSceneSwitcher.transitionTab.title="Transition"
|
AdvSceneSwitcher.transitionTab.title="Transition"
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ SwitcherData *switcher = nullptr;
|
|||||||
AdvSceneSwitcher::AdvSceneSwitcher(QWidget *parent)
|
AdvSceneSwitcher::AdvSceneSwitcher(QWidget *parent)
|
||||||
: QDialog(parent), ui(new Ui_AdvSceneSwitcher)
|
: QDialog(parent), ui(new Ui_AdvSceneSwitcher)
|
||||||
{
|
{
|
||||||
|
switcher->settingsWindowOpened = true;
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
@@ -28,6 +29,13 @@ AdvSceneSwitcher::AdvSceneSwitcher(QWidget *parent)
|
|||||||
loadUI();
|
loadUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AdvSceneSwitcher::~AdvSceneSwitcher()
|
||||||
|
{
|
||||||
|
if (switcher) {
|
||||||
|
switcher->settingsWindowOpened = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool translationAvailable()
|
bool translationAvailable()
|
||||||
{
|
{
|
||||||
return !!strcmp(obs_module_text("AdvSceneSwitcher.pluginName"),
|
return !!strcmp(obs_module_text("AdvSceneSwitcher.pluginName"),
|
||||||
@@ -422,7 +430,7 @@ void SwitcherData::Start()
|
|||||||
void ResetMacroCounters()
|
void ResetMacroCounters()
|
||||||
{
|
{
|
||||||
for (auto &m : switcher->macros) {
|
for (auto &m : switcher->macros) {
|
||||||
m.ResetCount();
|
m->ResetCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,6 +452,13 @@ void SwitcherData::Stop()
|
|||||||
server.stop();
|
server.stop();
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
|
|
||||||
|
for (auto &t : audioHelperThreads) {
|
||||||
|
if (t.joinable()) {
|
||||||
|
t.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
audioHelperThreads.clear();
|
||||||
|
|
||||||
if (showSystemTrayNotifications) {
|
if (showSystemTrayNotifications) {
|
||||||
DisplayTrayMessage(
|
DisplayTrayMessage(
|
||||||
obs_module_text("AdvSceneSwitcher.pluginName"),
|
obs_module_text("AdvSceneSwitcher.pluginName"),
|
||||||
@@ -628,6 +643,8 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AdvSceneSwitcher *ssWindow;
|
||||||
|
|
||||||
extern "C" void InitSceneSwitcher()
|
extern "C" void InitSceneSwitcher()
|
||||||
{
|
{
|
||||||
blog(LOG_INFO, "version: %s", g_GIT_TAG);
|
blog(LOG_INFO, "version: %s", g_GIT_TAG);
|
||||||
@@ -645,11 +662,16 @@ extern "C" void InitSceneSwitcher()
|
|||||||
PlatformInit();
|
PlatformInit();
|
||||||
|
|
||||||
auto cb = []() {
|
auto cb = []() {
|
||||||
QMainWindow *window =
|
if (switcher->settingsWindowOpened) {
|
||||||
(QMainWindow *)obs_frontend_get_main_window();
|
ssWindow->show();
|
||||||
|
ssWindow->raise();
|
||||||
AdvSceneSwitcher ss(window);
|
ssWindow->activateWindow();
|
||||||
ss.exec();
|
} else {
|
||||||
|
ssWindow = new AdvSceneSwitcher(
|
||||||
|
(QMainWindow *)obs_frontend_get_main_window());
|
||||||
|
ssWindow->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
ssWindow->show();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
obs_frontend_add_save_callback(SaveSceneSwitcher, nullptr);
|
obs_frontend_add_save_callback(SaveSceneSwitcher, nullptr);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
|
||||||
FileSelection::FileSelection(FileSelection::Type type, QWidget *parent)
|
FileSelection::FileSelection(FileSelection::Type type, QWidget *parent)
|
||||||
: _type(type), QWidget(parent)
|
: QWidget(parent), _type(type)
|
||||||
{
|
{
|
||||||
_filePath = new QLineEdit();
|
_filePath = new QLineEdit();
|
||||||
_browseButton =
|
_browseButton =
|
||||||
|
|||||||
@@ -186,6 +186,9 @@ void AdvSceneSwitcher::on_toggleStartButton_clicked()
|
|||||||
|
|
||||||
void AdvSceneSwitcher::closeEvent(QCloseEvent *)
|
void AdvSceneSwitcher::closeEvent(QCloseEvent *)
|
||||||
{
|
{
|
||||||
|
if (!switcher) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switcher->windowPos = this->pos();
|
switcher->windowPos = this->pos();
|
||||||
switcher->windowSize = this->size();
|
switcher->windowSize = this->size();
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ public:
|
|||||||
bool currentStatusActive = false;
|
bool currentStatusActive = false;
|
||||||
|
|
||||||
AdvSceneSwitcher(QWidget *parent);
|
AdvSceneSwitcher(QWidget *parent);
|
||||||
|
~AdvSceneSwitcher();
|
||||||
|
|
||||||
void reject() override;
|
void reject() override;
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
@@ -52,8 +53,8 @@ public:
|
|||||||
void SetEditMacro(Macro &m);
|
void SetEditMacro(Macro &m);
|
||||||
void HighlightAction(int idx);
|
void HighlightAction(int idx);
|
||||||
void HighlightCondition(int idx);
|
void HighlightCondition(int idx);
|
||||||
void PopulateMacroActions(Macro &m, int afterIdx = 0);
|
void PopulateMacroActions(Macro &m, uint32_t afterIdx = 0);
|
||||||
void PopulateMacroConditions(Macro &m, int afterIdx = 0);
|
void PopulateMacroConditions(Macro &m, uint32_t afterIdx = 0);
|
||||||
void ConnectControlSignals(MacroActionEdit *);
|
void ConnectControlSignals(MacroActionEdit *);
|
||||||
void ConnectControlSignals(MacroConditionEdit *);
|
void ConnectControlSignals(MacroConditionEdit *);
|
||||||
void SwapActions(Macro *m, int pos1, int pos2);
|
void SwapActions(Macro *m, int pos1, int pos2);
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QSpinBox>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "duration-control.hpp"
|
||||||
|
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
enum class AudioAction {
|
enum class AudioAction {
|
||||||
MUTE,
|
MUTE,
|
||||||
@@ -26,6 +29,8 @@ public:
|
|||||||
OBSWeakSource _audioSource;
|
OBSWeakSource _audioSource;
|
||||||
AudioAction _action = AudioAction::MUTE;
|
AudioAction _action = AudioAction::MUTE;
|
||||||
int _volume = 0;
|
int _volume = 0;
|
||||||
|
bool _fade = false;
|
||||||
|
Duration _duration;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
@@ -53,6 +58,8 @@ private slots:
|
|||||||
void SourceChanged(const QString &text);
|
void SourceChanged(const QString &text);
|
||||||
void ActionChanged(int value);
|
void ActionChanged(int value);
|
||||||
void VolumeChanged(int value);
|
void VolumeChanged(int value);
|
||||||
|
void FadeChanged(int value);
|
||||||
|
void DurationChanged(double seconds);
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
@@ -60,9 +67,11 @@ protected:
|
|||||||
QComboBox *_audioSources;
|
QComboBox *_audioSources;
|
||||||
QComboBox *_actions;
|
QComboBox *_actions;
|
||||||
QSpinBox *_volumePercent;
|
QSpinBox *_volumePercent;
|
||||||
|
QCheckBox *_fade;
|
||||||
|
DurationSelection *_duration;
|
||||||
|
QHBoxLayout *_fadeLayout;
|
||||||
std::shared_ptr<MacroActionAudio> _entryData;
|
std::shared_ptr<MacroActionAudio> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QHBoxLayout *_mainLayout;
|
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|||||||
63
src/headers/macro-action-random.hpp
Normal file
63
src/headers/macro-action-random.hpp
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "macro-selection.hpp"
|
||||||
|
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QListWidget>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class MacroActionRandom : public MultiMacroRefAction {
|
||||||
|
public:
|
||||||
|
bool PerformAction();
|
||||||
|
void LogAction();
|
||||||
|
bool Save(obs_data_t *obj);
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetId() { return id; };
|
||||||
|
static std::shared_ptr<MacroAction> Create()
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroActionRandom>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add weights to each macro ...
|
||||||
|
// std::unordered_map<MacroRef, int> _weights;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MacroRef lastRandomMacro;
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroActionRandomEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroActionRandomEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroActionRandom> entryData = nullptr);
|
||||||
|
void UpdateEntryData();
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroAction> action)
|
||||||
|
{
|
||||||
|
return new MacroActionRandomEdit(
|
||||||
|
parent,
|
||||||
|
std::dynamic_pointer_cast<MacroActionRandom>(action));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void MacroRemove(const QString &name);
|
||||||
|
void MacroRename(const QString &oldName, const QString &newName);
|
||||||
|
void AddMacro();
|
||||||
|
void RemoveMacro();
|
||||||
|
int FindEntry(const std::string ¯o);
|
||||||
|
void MacroSelectionChanged(int idx);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<MacroActionRandom> _entryData;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MacroSelection *_macroSelection;
|
||||||
|
QListWidget *_macroList;
|
||||||
|
QPushButton *_add;
|
||||||
|
QPushButton *_remove;
|
||||||
|
bool _loading = true;
|
||||||
|
};
|
||||||
@@ -8,6 +8,11 @@ enum class SceneVisibilityAction {
|
|||||||
HIDE,
|
HIDE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class SceneItemSourceType {
|
||||||
|
SOURCE,
|
||||||
|
SOURCE_GROUP,
|
||||||
|
};
|
||||||
|
|
||||||
class MacroActionSceneVisibility : public MacroAction {
|
class MacroActionSceneVisibility : public MacroAction {
|
||||||
public:
|
public:
|
||||||
bool PerformAction();
|
bool PerformAction();
|
||||||
@@ -22,7 +27,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
SceneSelection _scene;
|
SceneSelection _scene;
|
||||||
|
SceneItemSourceType _sourceType = SceneItemSourceType::SOURCE;
|
||||||
OBSWeakSource _source;
|
OBSWeakSource _source;
|
||||||
|
std::string _sourceGroup = "";
|
||||||
SceneVisibilityAction _action = SceneVisibilityAction::SHOW;
|
SceneVisibilityAction _action = SceneVisibilityAction::SHOW;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -49,6 +56,7 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void SceneChanged(const SceneSelection &);
|
void SceneChanged(const SceneSelection &);
|
||||||
|
void SourceTypeChanged(int value);
|
||||||
void SourceChanged(const QString &text);
|
void SourceChanged(const QString &text);
|
||||||
void ActionChanged(int value);
|
void ActionChanged(int value);
|
||||||
signals:
|
signals:
|
||||||
@@ -56,6 +64,7 @@ signals:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
SceneSelectionWidget *_scenes;
|
SceneSelectionWidget *_scenes;
|
||||||
|
QComboBox *_sourceTypes;
|
||||||
QComboBox *_sources;
|
QComboBox *_sources;
|
||||||
QComboBox *_actions;
|
QComboBox *_actions;
|
||||||
std::shared_ptr<MacroActionSceneVisibility> _entryData;
|
std::shared_ptr<MacroActionSceneVisibility> _entryData;
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ private slots:
|
|||||||
void ConditionChanged(int cond);
|
void ConditionChanged(int cond);
|
||||||
void ResetClicked();
|
void ResetClicked();
|
||||||
void UpdateCount();
|
void UpdateCount();
|
||||||
|
void UpdatePaused();
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
@@ -76,16 +77,17 @@ protected:
|
|||||||
QComboBox *_counterConditions;
|
QComboBox *_counterConditions;
|
||||||
QSpinBox *_count;
|
QSpinBox *_count;
|
||||||
QLabel *_currentCount;
|
QLabel *_currentCount;
|
||||||
|
QLabel *_pausedWarning;
|
||||||
QPushButton *_resetCount;
|
QPushButton *_resetCount;
|
||||||
QHBoxLayout *_settingsLine1;
|
QHBoxLayout *_settingsLine1;
|
||||||
QHBoxLayout *_settingsLine2;
|
QHBoxLayout *_settingsLine2;
|
||||||
std::unique_ptr<QTimer> _timer;
|
QTimer _countTimer;
|
||||||
|
QTimer _pausedTimer;
|
||||||
std::shared_ptr<MacroConditionMacro> _entryData;
|
std::shared_ptr<MacroConditionMacro> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ClearLayouts();
|
void ClearLayouts();
|
||||||
void SetupStateWidgets();
|
void SetupStateWidgets();
|
||||||
void SetupCountWidgets();
|
void SetupCountWidgets();
|
||||||
void ResetTimer();
|
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|||||||
66
src/headers/macro-condition-scene-visibility.hpp
Normal file
66
src/headers/macro-condition-scene-visibility.hpp
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro.hpp"
|
||||||
|
#include "scene-selection.hpp"
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
|
enum class SceneVisibilityCondition {
|
||||||
|
SHOWN,
|
||||||
|
HIDDEN,
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroConditionSceneVisibility : public MacroCondition {
|
||||||
|
public:
|
||||||
|
bool CheckCondition();
|
||||||
|
bool Save(obs_data_t *obj);
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetShortDesc();
|
||||||
|
std::string GetId() { return id; };
|
||||||
|
static std::shared_ptr<MacroCondition> Create()
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroConditionSceneVisibility>();
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneSelection _scene;
|
||||||
|
OBSWeakSource _source;
|
||||||
|
SceneVisibilityCondition _condition = SceneVisibilityCondition::SHOWN;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroConditionSceneVisibilityEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroConditionSceneVisibilityEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroConditionSceneVisibility> cond = nullptr);
|
||||||
|
void UpdateEntryData();
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroCondition> cond)
|
||||||
|
{
|
||||||
|
return new MacroConditionSceneVisibilityEdit(
|
||||||
|
parent,
|
||||||
|
std::dynamic_pointer_cast<MacroConditionSceneVisibility>(
|
||||||
|
cond));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void SceneChanged(const SceneSelection &);
|
||||||
|
void SourceChanged(const QString &text);
|
||||||
|
void ConditionChanged(int cond);
|
||||||
|
signals:
|
||||||
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SceneSelectionWidget *_scenes;
|
||||||
|
QComboBox *_sources;
|
||||||
|
QComboBox *_conditions;
|
||||||
|
|
||||||
|
std::shared_ptr<MacroConditionSceneVisibility> _entryData;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _loading = true;
|
||||||
|
};
|
||||||
@@ -77,7 +77,7 @@ public:
|
|||||||
bool Matched() { return _matched; }
|
bool Matched() { return _matched; }
|
||||||
std::string Name() { return _name; }
|
std::string Name() { return _name; }
|
||||||
void SetName(const std::string &name);
|
void SetName(const std::string &name);
|
||||||
void SetPaused(bool pause = true) { _paused = pause; }
|
void SetPaused(bool pause = true);
|
||||||
bool Paused() { return _paused; }
|
bool Paused() { return _paused; }
|
||||||
int GetCount() { return _count; };
|
int GetCount() { return _count; };
|
||||||
void ResetCount() { _count = 0; };
|
void ResetCount() { _count = 0; };
|
||||||
@@ -102,6 +102,7 @@ private:
|
|||||||
void SetupHotkeys();
|
void SetupHotkeys();
|
||||||
void ClearHotkeys();
|
void ClearHotkeys();
|
||||||
void SetHotkeysDesc();
|
void SetHotkeysDesc();
|
||||||
|
void ResetTimers();
|
||||||
|
|
||||||
std::string _name = "";
|
std::string _name = "";
|
||||||
std::deque<std::shared_ptr<MacroCondition>> _conditions;
|
std::deque<std::shared_ptr<MacroCondition>> _conditions;
|
||||||
@@ -144,3 +145,9 @@ public:
|
|||||||
void ResolveMacroRef();
|
void ResolveMacroRef();
|
||||||
MacroRef _macro;
|
MacroRef _macro;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MultiMacroRefAction : public MacroAction {
|
||||||
|
public:
|
||||||
|
void ResolveMacroRef();
|
||||||
|
std::vector<MacroRef> _macros;
|
||||||
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "scene-group.hpp"
|
#include "scene-group.hpp"
|
||||||
#include "scene-trigger.hpp"
|
#include "scene-trigger.hpp"
|
||||||
@@ -63,6 +64,8 @@ class SwitcherThread;
|
|||||||
struct SwitcherData {
|
struct SwitcherData {
|
||||||
SwitcherThread *th = nullptr;
|
SwitcherThread *th = nullptr;
|
||||||
|
|
||||||
|
bool settingsWindowOpened = false;
|
||||||
|
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
std::mutex m;
|
std::mutex m;
|
||||||
bool transitionActive = false;
|
bool transitionActive = false;
|
||||||
@@ -92,10 +95,14 @@ struct SwitcherData {
|
|||||||
StartupBehavior startupBehavior = PERSIST;
|
StartupBehavior startupBehavior = PERSIST;
|
||||||
AutoStartEvent autoStartEvent = AutoStartEvent::NEVER;
|
AutoStartEvent autoStartEvent = AutoStartEvent::NEVER;
|
||||||
|
|
||||||
|
std::vector<std::thread> audioHelperThreads;
|
||||||
|
std::atomic_bool masterAudioFadeActive = {false};
|
||||||
|
std::unordered_map<std::string, std::atomic_bool> activeAudioFades;
|
||||||
|
|
||||||
Duration cooldown;
|
Duration cooldown;
|
||||||
std::chrono::high_resolution_clock::time_point lastMatchTime;
|
std::chrono::high_resolution_clock::time_point lastMatchTime;
|
||||||
|
|
||||||
std::deque<Macro> macros;
|
std::deque<std::shared_ptr<Macro>> macros;
|
||||||
std::condition_variable macroWaitCv;
|
std::condition_variable macroWaitCv;
|
||||||
std::atomic_bool abortMacroWait = {false};
|
std::atomic_bool abortMacroWait = {false};
|
||||||
bool macroSceneSwitched = false;
|
bool macroSceneSwitched = false;
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ void placeWidgets(std::string text, QBoxLayout *layout,
|
|||||||
bool addStretch = true);
|
bool addStretch = true);
|
||||||
void deleteLayoutItem(QLayoutItem *item);
|
void deleteLayoutItem(QLayoutItem *item);
|
||||||
void clearLayout(QLayout *layout, int afterIdx = 0);
|
void clearLayout(QLayout *layout, int afterIdx = 0);
|
||||||
|
void setLayoutVisible(QLayout *layout, bool visible);
|
||||||
QMetaObject::Connection PulseWidget(QWidget *widget, QColor startColor,
|
QMetaObject::Connection PulseWidget(QWidget *widget, QColor startColor,
|
||||||
QColor = QColor(0, 0, 0, 0),
|
QColor = QColor(0, 0, 0, 0),
|
||||||
QString specifier = "QLabel ",
|
QString specifier = "QLabel ",
|
||||||
@@ -78,3 +79,4 @@ void populateFilterSelection(QComboBox *list,
|
|||||||
void populateSceneItemSelection(QComboBox *list,
|
void populateSceneItemSelection(QComboBox *list,
|
||||||
OBSWeakSource sceneWeakSource = nullptr);
|
OBSWeakSource sceneWeakSource = nullptr);
|
||||||
void populateSceneItemSelection(QComboBox *list, SceneSelection &s);
|
void populateSceneItemSelection(QComboBox *list, SceneSelection &s);
|
||||||
|
void populateSourceTypeSelection(QComboBox *list);
|
||||||
|
|||||||
@@ -18,6 +18,94 @@ const static std::map<AudioAction, std::string> actionTypes = {
|
|||||||
"AdvSceneSwitcher.action.audio.type.masterVolume"},
|
"AdvSceneSwitcher.action.audio.type.masterVolume"},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr auto fadeInterval = std::chrono::milliseconds(100);
|
||||||
|
constexpr float minFade = 0.000001f;
|
||||||
|
|
||||||
|
void fadeSourceVolume(Duration duration, float vol, OBSWeakSource audioSource)
|
||||||
|
{
|
||||||
|
auto s = obs_weak_source_get_source(audioSource);
|
||||||
|
if (!s) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float curVol = obs_source_get_volume(s);
|
||||||
|
obs_source_release(s);
|
||||||
|
bool volIncrease = curVol <= vol;
|
||||||
|
int nrSteps = duration.seconds * 1000 / fadeInterval.count();
|
||||||
|
float volDiff = (volIncrease) ? vol - curVol : curVol - vol;
|
||||||
|
float volStep = volDiff / nrSteps;
|
||||||
|
|
||||||
|
if (volStep < minFade) {
|
||||||
|
switcher->activeAudioFades[GetWeakSourceName(audioSource)] =
|
||||||
|
false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int step = 0; step < nrSteps && !switcher->stop; ++step) {
|
||||||
|
auto s = obs_weak_source_get_source(audioSource);
|
||||||
|
if (!s) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
curVol = (volIncrease) ? curVol + volStep : curVol - volStep;
|
||||||
|
obs_source_set_volume(s, curVol);
|
||||||
|
std::this_thread::sleep_for(fadeInterval);
|
||||||
|
obs_source_release(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
switcher->activeAudioFades[GetWeakSourceName(audioSource)] = false;
|
||||||
|
}
|
||||||
|
void fadeMasterVolume(Duration duration, float vol)
|
||||||
|
{
|
||||||
|
float curVol = obs_get_master_volume();
|
||||||
|
bool volIncrease = curVol <= vol;
|
||||||
|
int nrSteps = duration.seconds * 1000 / fadeInterval.count();
|
||||||
|
float volDiff = (volIncrease) ? vol - curVol : curVol - vol;
|
||||||
|
float volStep = volDiff / nrSteps;
|
||||||
|
|
||||||
|
if (volStep < minFade) {
|
||||||
|
switcher->masterAudioFadeActive = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int step = 0; step < nrSteps && !switcher->stop; ++step) {
|
||||||
|
curVol = (volIncrease) ? curVol + volStep : curVol - volStep;
|
||||||
|
obs_set_master_volume(curVol);
|
||||||
|
std::this_thread::sleep_for(fadeInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
switcher->masterAudioFadeActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void startSourceFade(Duration &duration, float vol, OBSWeakSource audioSource)
|
||||||
|
{
|
||||||
|
if (!audioSource) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto it =
|
||||||
|
switcher->activeAudioFades.find(GetWeakSourceName(audioSource));
|
||||||
|
if (it != switcher->activeAudioFades.end() && it->second == true) {
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"Audio fade for volume of %s already active! New fade request will be ignored!",
|
||||||
|
GetWeakSourceName(audioSource).c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switcher->activeAudioFades[GetWeakSourceName(audioSource)] = true;
|
||||||
|
switcher->audioHelperThreads.emplace_back(fadeSourceVolume, duration,
|
||||||
|
vol, audioSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
void startMasterFade(Duration &duration, float vol)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (switcher->masterAudioFadeActive) {
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"Audio fade for master volume already active! New fade request will be ignored!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switcher->masterAudioFadeActive = true;
|
||||||
|
switcher->audioHelperThreads.emplace_back(fadeMasterVolume, duration,
|
||||||
|
vol);
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroActionAudio::PerformAction()
|
bool MacroActionAudio::PerformAction()
|
||||||
{
|
{
|
||||||
auto s = obs_weak_source_get_source(_audioSource);
|
auto s = obs_weak_source_get_source(_audioSource);
|
||||||
@@ -29,10 +117,19 @@ bool MacroActionAudio::PerformAction()
|
|||||||
obs_source_set_muted(s, false);
|
obs_source_set_muted(s, false);
|
||||||
break;
|
break;
|
||||||
case AudioAction::SOURCE_VOLUME:
|
case AudioAction::SOURCE_VOLUME:
|
||||||
obs_source_set_volume(s, (float)_volume / 100.0f);
|
if (_fade) {
|
||||||
|
startSourceFade(_duration, (float)_volume / 100.0f,
|
||||||
|
_audioSource);
|
||||||
|
} else {
|
||||||
|
obs_source_set_volume(s, (float)_volume / 100.0f);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case AudioAction::MASTER_VOLUME:
|
case AudioAction::MASTER_VOLUME:
|
||||||
obs_set_master_volume((float)_volume / 100.0f);
|
if (_fade) {
|
||||||
|
startMasterFade(_duration, (float)_volume / 100.0f);
|
||||||
|
} else {
|
||||||
|
obs_set_master_volume((float)_volume / 100.0f);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -46,9 +143,10 @@ void MacroActionAudio::LogAction()
|
|||||||
auto it = actionTypes.find(_action);
|
auto it = actionTypes.find(_action);
|
||||||
if (it != actionTypes.end()) {
|
if (it != actionTypes.end()) {
|
||||||
vblog(LOG_INFO,
|
vblog(LOG_INFO,
|
||||||
"performed action \"%s\" for source \"%s\" with volume %d",
|
"performed action \"%s\" for source \"%s\" with volume %d with fade %d %f",
|
||||||
it->second.c_str(),
|
it->second.c_str(),
|
||||||
GetWeakSourceName(_audioSource).c_str(), _volume);
|
GetWeakSourceName(_audioSource).c_str(), _volume, _fade,
|
||||||
|
_duration.seconds);
|
||||||
} else {
|
} else {
|
||||||
blog(LOG_WARNING, "ignored unknown audio action %d",
|
blog(LOG_WARNING, "ignored unknown audio action %d",
|
||||||
static_cast<int>(_action));
|
static_cast<int>(_action));
|
||||||
@@ -58,20 +156,24 @@ void MacroActionAudio::LogAction()
|
|||||||
bool MacroActionAudio::Save(obs_data_t *obj)
|
bool MacroActionAudio::Save(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
|
_duration.Save(obj);
|
||||||
obs_data_set_string(obj, "audioSource",
|
obs_data_set_string(obj, "audioSource",
|
||||||
GetWeakSourceName(_audioSource).c_str());
|
GetWeakSourceName(_audioSource).c_str());
|
||||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||||
obs_data_set_int(obj, "volume", _volume);
|
obs_data_set_int(obj, "volume", _volume);
|
||||||
|
obs_data_set_bool(obj, "fade", _fade);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroActionAudio::Load(obs_data_t *obj)
|
bool MacroActionAudio::Load(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
|
_duration.Load(obj);
|
||||||
const char *audioSourceName = obs_data_get_string(obj, "audioSource");
|
const char *audioSourceName = obs_data_get_string(obj, "audioSource");
|
||||||
_audioSource = GetWeakSourceByName(audioSourceName);
|
_audioSource = GetWeakSourceByName(audioSourceName);
|
||||||
_action = static_cast<AudioAction>(obs_data_get_int(obj, "action"));
|
_action = static_cast<AudioAction>(obs_data_get_int(obj, "action"));
|
||||||
_volume = obs_data_get_int(obj, "volume");
|
_volume = obs_data_get_int(obj, "volume");
|
||||||
|
_fade = obs_data_get_bool(obj, "fade");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +202,8 @@ MacroActionAudioEdit::MacroActionAudioEdit(
|
|||||||
_volumePercent->setMinimum(0);
|
_volumePercent->setMinimum(0);
|
||||||
_volumePercent->setMaximum(2000);
|
_volumePercent->setMaximum(2000);
|
||||||
_volumePercent->setSuffix("%");
|
_volumePercent->setSuffix("%");
|
||||||
|
_fade = new QCheckBox();
|
||||||
|
_duration = new DurationSelection(parent, false);
|
||||||
|
|
||||||
populateActionSelection(_actions);
|
populateActionSelection(_actions);
|
||||||
populateAudioSelection(_audioSources);
|
populateAudioSelection(_audioSources);
|
||||||
@@ -111,15 +215,25 @@ MacroActionAudioEdit::MacroActionAudioEdit(
|
|||||||
SLOT(SourceChanged(const QString &)));
|
SLOT(SourceChanged(const QString &)));
|
||||||
QWidget::connect(_volumePercent, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(_volumePercent, SIGNAL(valueChanged(int)), this,
|
||||||
SLOT(VolumeChanged(int)));
|
SLOT(VolumeChanged(int)));
|
||||||
|
QWidget::connect(_fade, SIGNAL(stateChanged(int)), this,
|
||||||
|
SLOT(FadeChanged(int)));
|
||||||
|
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
||||||
|
SLOT(DurationChanged(double)));
|
||||||
|
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{audioSources}}", _audioSources},
|
{"{{audioSources}}", _audioSources}, {"{{actions}}", _actions},
|
||||||
{"{{actions}}", _actions},
|
{"{{volume}}", _volumePercent}, {"{{fade}}", _fade},
|
||||||
{"{{volume}}", _volumePercent},
|
{"{{duration}}", _duration},
|
||||||
};
|
};
|
||||||
|
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.audio.entry"),
|
placeWidgets(obs_module_text("AdvSceneSwitcher.action.audio.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
entryLayout, widgetPlaceholders);
|
||||||
|
_fadeLayout = new QHBoxLayout;
|
||||||
|
placeWidgets(obs_module_text("AdvSceneSwitcher.action.audio.fade"),
|
||||||
|
_fadeLayout, widgetPlaceholders);
|
||||||
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
|
mainLayout->addLayout(entryLayout);
|
||||||
|
mainLayout->addLayout(_fadeLayout);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
@@ -140,19 +254,11 @@ bool hasSourceControl(AudioAction action)
|
|||||||
|
|
||||||
void MacroActionAudioEdit::SetWidgetVisibility()
|
void MacroActionAudioEdit::SetWidgetVisibility()
|
||||||
{
|
{
|
||||||
if (hasVolumeControl(_entryData->_action)) {
|
_volumePercent->setVisible(hasVolumeControl(_entryData->_action));
|
||||||
_volumePercent->show();
|
_audioSources->setVisible(hasSourceControl(_entryData->_action));
|
||||||
} else {
|
setLayoutVisible(_fadeLayout, hasVolumeControl(_entryData->_action));
|
||||||
_volumePercent->hide();
|
adjustSize();
|
||||||
}
|
|
||||||
|
|
||||||
if (hasSourceControl(_entryData->_action)) {
|
|
||||||
_audioSources->show();
|
|
||||||
} else {
|
|
||||||
_audioSources->hide();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionAudioEdit::UpdateEntryData()
|
void MacroActionAudioEdit::UpdateEntryData()
|
||||||
{
|
{
|
||||||
if (!_entryData) {
|
if (!_entryData) {
|
||||||
@@ -163,7 +269,8 @@ void MacroActionAudioEdit::UpdateEntryData()
|
|||||||
GetWeakSourceName(_entryData->_audioSource).c_str());
|
GetWeakSourceName(_entryData->_audioSource).c_str());
|
||||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||||
_volumePercent->setValue(_entryData->_volume);
|
_volumePercent->setValue(_entryData->_volume);
|
||||||
|
_fade->setChecked(_entryData->_fade);
|
||||||
|
_duration->SetDuration(_entryData->_duration);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,3 +306,23 @@ void MacroActionAudioEdit::VolumeChanged(int value)
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_volume = value;
|
_entryData->_volume = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionAudioEdit::FadeChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_fade = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionAudioEdit::DurationChanged(double seconds)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_duration.seconds = seconds;
|
||||||
|
}
|
||||||
|
|||||||
@@ -92,12 +92,14 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto idx = _entryData->get()->GetIndex();
|
||||||
std::string id = MacroActionFactory::GetIdByName(text);
|
std::string id = MacroActionFactory::GetIdByName(text);
|
||||||
HeaderInfoChanged("");
|
HeaderInfoChanged("");
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->reset();
|
_entryData->reset();
|
||||||
*_entryData = MacroActionFactory::Create(id);
|
*_entryData = MacroActionFactory::Create(id);
|
||||||
|
(*_entryData)->SetIndex(idx);
|
||||||
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
||||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
|||||||
{
|
{
|
||||||
_sources = new QComboBox();
|
_sources = new QComboBox();
|
||||||
_filters = new QComboBox();
|
_filters = new QComboBox();
|
||||||
|
_filters->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||||
_actions = new QComboBox();
|
_actions = new QComboBox();
|
||||||
_getSettings = new QPushButton(
|
_getSettings = new QPushButton(
|
||||||
obs_module_text("AdvSceneSwitcher.action.filter.getSettings"));
|
obs_module_text("AdvSceneSwitcher.action.filter.getSettings"));
|
||||||
@@ -165,6 +166,7 @@ void MacroActionFilterEdit::SourceChanged(const QString &text)
|
|||||||
}
|
}
|
||||||
_filters->clear();
|
_filters->clear();
|
||||||
populateFilterSelection(_filters, _entryData->_source);
|
populateFilterSelection(_filters, _entryData->_source);
|
||||||
|
_filters->adjustSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionFilterEdit::FilterChanged(const QString &text)
|
void MacroActionFilterEdit::FilterChanged(const QString &text)
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ obs_key_combination keysToOBSKeycombo(const std::vector<HotkeyType> &keys)
|
|||||||
return combo;
|
return combo;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < keys.size() - 1; i++) {
|
for (uint32_t i = 0; i < keys.size() - 1; i++) {
|
||||||
switch (keys[i]) {
|
switch (keys[i]) {
|
||||||
case HotkeyType::Key_Shift_L:
|
case HotkeyType::Key_Shift_L:
|
||||||
combo.modifiers |= INTERACT_SHIFT_KEY;
|
combo.modifiers |= INTERACT_SHIFT_KEY;
|
||||||
|
|||||||
263
src/macro-action-random.cpp
Normal file
263
src/macro-action-random.cpp
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
#include "headers/macro-action-random.hpp"
|
||||||
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
|
#include "headers/name-dialog.hpp"
|
||||||
|
#include "headers/utility.hpp"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
const std::string MacroActionRandom::id = "random";
|
||||||
|
|
||||||
|
bool MacroActionRandom::_registered = MacroActionFactory::Register(
|
||||||
|
MacroActionRandom::id,
|
||||||
|
{MacroActionRandom::Create, MacroActionRandomEdit::Create,
|
||||||
|
"AdvSceneSwitcher.action.random"});
|
||||||
|
|
||||||
|
std::vector<MacroRef> getPossibleMacros(std::vector<MacroRef> ¯os,
|
||||||
|
MacroRef &lastRandomMacro)
|
||||||
|
{
|
||||||
|
std::vector<MacroRef> res;
|
||||||
|
if (macros.size() == 1) {
|
||||||
|
if (macros[0]->Paused()) {
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
return macros;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &m : macros) {
|
||||||
|
if (m.get() && !m->Paused() &&
|
||||||
|
!(lastRandomMacro.get() == m.get())) {
|
||||||
|
res.push_back(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionRandom::PerformAction()
|
||||||
|
{
|
||||||
|
if (_macros.size() == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto macros = getPossibleMacros(_macros, lastRandomMacro);
|
||||||
|
if (macros.size() == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (macros.size() == 1) {
|
||||||
|
lastRandomMacro = macros[0];
|
||||||
|
return macros[0]->PerformAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t idx = std::rand() % (macros.size());
|
||||||
|
lastRandomMacro = macros[idx];
|
||||||
|
return macros[idx]->PerformAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionRandom::LogAction()
|
||||||
|
{
|
||||||
|
vblog(LOG_INFO, "running random macro");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionRandom::Save(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroAction::Save(obj);
|
||||||
|
obs_data_array_t *args = obs_data_array_create();
|
||||||
|
for (auto &m : _macros) {
|
||||||
|
obs_data_t *array_obj = obs_data_create();
|
||||||
|
m.Save(array_obj);
|
||||||
|
obs_data_array_push_back(args, array_obj);
|
||||||
|
obs_data_release(array_obj);
|
||||||
|
}
|
||||||
|
obs_data_set_array(obj, "macros", args);
|
||||||
|
obs_data_array_release(args);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionRandom::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroAction::Load(obj);
|
||||||
|
obs_data_array_t *args = obs_data_get_array(obj, "macros");
|
||||||
|
size_t count = obs_data_array_count(args);
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
obs_data_t *array_obj = obs_data_array_item(args, i);
|
||||||
|
MacroRef ref;
|
||||||
|
ref.Load(array_obj);
|
||||||
|
_macros.push_back(ref);
|
||||||
|
obs_data_release(array_obj);
|
||||||
|
}
|
||||||
|
obs_data_array_release(args);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroActionRandomEdit::MacroActionRandomEdit(
|
||||||
|
QWidget *parent, std::shared_ptr<MacroActionRandom> entryData)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
_macroSelection = new MacroSelection(window());
|
||||||
|
_macroList = new QListWidget();
|
||||||
|
_macroList->setSortingEnabled(true);
|
||||||
|
_add = new QPushButton();
|
||||||
|
_add->setMaximumSize(QSize(22, 22));
|
||||||
|
_add->setProperty("themeID",
|
||||||
|
QVariant(QString::fromUtf8("addIconSmall")));
|
||||||
|
_add->setFlat(true);
|
||||||
|
_remove = new QPushButton();
|
||||||
|
_remove->setMaximumSize(QSize(22, 22));
|
||||||
|
_remove->setProperty("themeID",
|
||||||
|
QVariant(QString::fromUtf8("removeIconSmall")));
|
||||||
|
_remove->setFlat(true);
|
||||||
|
|
||||||
|
QWidget::connect(_add, SIGNAL(clicked()), this, SLOT(AddMacro()));
|
||||||
|
QWidget::connect(_remove, SIGNAL(clicked()), this, SLOT(RemoveMacro()));
|
||||||
|
QWidget::connect(_macroList, SIGNAL(currentRowChanged(int)), this,
|
||||||
|
SLOT(MacroSelectionChanged(int)));
|
||||||
|
QWidget::connect(window(),
|
||||||
|
SIGNAL(MacroRenamed(const QString &, const QString &)),
|
||||||
|
this,
|
||||||
|
SLOT(MacroRename(const QString &, const QString &)));
|
||||||
|
|
||||||
|
auto *entryLayout = new QHBoxLayout;
|
||||||
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
|
{"{{macroSelection}}", _macroSelection},
|
||||||
|
};
|
||||||
|
placeWidgets(obs_module_text("AdvSceneSwitcher.action.random.entry"),
|
||||||
|
entryLayout, widgetPlaceholders);
|
||||||
|
|
||||||
|
auto *argButtonLayout = new QHBoxLayout;
|
||||||
|
argButtonLayout->addWidget(_add);
|
||||||
|
argButtonLayout->addWidget(_remove);
|
||||||
|
argButtonLayout->addStretch();
|
||||||
|
|
||||||
|
auto *mainLayout = new QVBoxLayout;
|
||||||
|
mainLayout->addLayout(entryLayout);
|
||||||
|
mainLayout->addWidget(new QLabel(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.random.arguments")));
|
||||||
|
mainLayout->addWidget(_macroList);
|
||||||
|
mainLayout->addLayout(argButtonLayout);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
|
UpdateEntryData();
|
||||||
|
_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionRandomEdit::UpdateEntryData()
|
||||||
|
{
|
||||||
|
if (!_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &m : _entryData->_macros) {
|
||||||
|
if (!m.get()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto name = QString::fromStdString(m->Name());
|
||||||
|
QListWidgetItem *item = new QListWidgetItem(name, _macroList);
|
||||||
|
item->setData(Qt::UserRole, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionRandomEdit::MacroRemove(const QString &name)
|
||||||
|
{
|
||||||
|
if (_entryData) {
|
||||||
|
auto it = _entryData->_macros.begin();
|
||||||
|
while (it != _entryData->_macros.end()) {
|
||||||
|
if (it->get()->Name() == name.toStdString()) {
|
||||||
|
it = _entryData->_macros.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionRandomEdit::MacroRename(const QString &oldName,
|
||||||
|
const QString &newName)
|
||||||
|
{
|
||||||
|
auto count = _macroList->count();
|
||||||
|
for (int idx = 0; idx < count; ++idx) {
|
||||||
|
QListWidgetItem *item = _macroList->item(idx);
|
||||||
|
QString itemString = item->data(Qt::UserRole).toString();
|
||||||
|
if (oldName == itemString) {
|
||||||
|
item->setData(Qt::UserRole, newName);
|
||||||
|
item->setText(newName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionRandomEdit::AddMacro()
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto macroName = _macroSelection->currentText();
|
||||||
|
MacroRef macro(macroName.toStdString());
|
||||||
|
|
||||||
|
if (!macro.get()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FindEntry(macro->Name()) != -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant v = QVariant::fromValue(macroName);
|
||||||
|
QListWidgetItem *item = new QListWidgetItem(macroName, _macroList);
|
||||||
|
item->setData(Qt::UserRole, macroName);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_macros.push_back(macro);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionRandomEdit::RemoveMacro()
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
auto item = _macroList->currentItem();
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string name = item->data(Qt::UserRole).toString().toStdString();
|
||||||
|
for (auto it = _entryData->_macros.begin();
|
||||||
|
it != _entryData->_macros.end(); ++it) {
|
||||||
|
auto m = *it;
|
||||||
|
if (m.get() && m->Name() == name) {
|
||||||
|
_entryData->_macros.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MacroActionRandomEdit::FindEntry(const std::string ¯o)
|
||||||
|
{
|
||||||
|
int count = _macroList->count();
|
||||||
|
int idx = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
QListWidgetItem *item = _macroList->item(i);
|
||||||
|
QString itemString = item->data(Qt::UserRole).toString();
|
||||||
|
if (QString::fromStdString(macro) == itemString) {
|
||||||
|
idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionRandomEdit::MacroSelectionChanged(int idx)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData || idx == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QListWidgetItem *item = _macroList->item(idx);
|
||||||
|
QString name = item->text();
|
||||||
|
_macroSelection->SetCurrentMacro(GetMacroByName(name.toUtf8().data()));
|
||||||
|
}
|
||||||
@@ -17,14 +17,22 @@ const static std::map<SceneVisibilityAction, std::string> actionTypes = {
|
|||||||
"AdvSceneSwitcher.action.sceneVisibility.type.hide"},
|
"AdvSceneSwitcher.action.sceneVisibility.type.hide"},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VisInfo {
|
const static std::map<SceneItemSourceType, std::string> sourceItemSourceTypes = {
|
||||||
|
{SceneItemSourceType::SOURCE,
|
||||||
|
"AdvSceneSwitcher.action.sceneVisibility.type.source"},
|
||||||
|
{SceneItemSourceType::SOURCE_GROUP,
|
||||||
|
"AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup"},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VisibilityData {
|
||||||
std::string name;
|
std::string name;
|
||||||
bool visible;
|
bool visible;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool visibilityEnum(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
static bool visibilitySourceEnum(obs_scene_t *, obs_sceneitem_t *item,
|
||||||
|
void *ptr)
|
||||||
{
|
{
|
||||||
VisInfo *vInfo = reinterpret_cast<VisInfo *>(ptr);
|
VisibilityData *vInfo = reinterpret_cast<VisibilityData *>(ptr);
|
||||||
auto sourceName = obs_source_get_name(obs_sceneitem_get_source(item));
|
auto sourceName = obs_source_get_name(obs_sceneitem_get_source(item));
|
||||||
if (vInfo->name == sourceName) {
|
if (vInfo->name == sourceName) {
|
||||||
obs_sceneitem_set_visible(item, vInfo->visible);
|
obs_sceneitem_set_visible(item, vInfo->visible);
|
||||||
@@ -32,7 +40,26 @@ static bool visibilityEnum(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
|||||||
|
|
||||||
if (obs_sceneitem_is_group(item)) {
|
if (obs_sceneitem_is_group(item)) {
|
||||||
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||||
obs_scene_enum_items(scene, visibilityEnum, ptr);
|
obs_scene_enum_items(scene, visibilitySourceEnum, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool visibilitySourceTypeEnum(obs_scene_t *, obs_sceneitem_t *item,
|
||||||
|
void *ptr)
|
||||||
|
{
|
||||||
|
VisibilityData *vInfo = reinterpret_cast<VisibilityData *>(ptr);
|
||||||
|
|
||||||
|
auto sourceTypeName = obs_source_get_display_name(
|
||||||
|
obs_source_get_id(obs_sceneitem_get_source(item)));
|
||||||
|
if (vInfo->name == sourceTypeName) {
|
||||||
|
obs_sceneitem_set_visible(item, vInfo->visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obs_sceneitem_is_group(item)) {
|
||||||
|
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||||
|
obs_scene_enum_items(scene, visibilitySourceTypeEnum, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -43,18 +70,21 @@ bool MacroActionSceneVisibility::PerformAction()
|
|||||||
auto s = obs_weak_source_get_source(_scene.GetScene());
|
auto s = obs_weak_source_get_source(_scene.GetScene());
|
||||||
auto scene = obs_scene_from_source(s);
|
auto scene = obs_scene_from_source(s);
|
||||||
auto sourceName = GetWeakSourceName(_source);
|
auto sourceName = GetWeakSourceName(_source);
|
||||||
VisInfo vInfo = {sourceName, _action == SceneVisibilityAction::SHOW};
|
VisibilityData vInfo = {"", _action == SceneVisibilityAction::SHOW};
|
||||||
|
|
||||||
switch (_action) {
|
switch (_sourceType) {
|
||||||
case SceneVisibilityAction::SHOW:
|
case SceneItemSourceType::SOURCE:
|
||||||
obs_scene_enum_items(scene, visibilityEnum, &vInfo);
|
vInfo.name = sourceName;
|
||||||
|
obs_scene_enum_items(scene, visibilitySourceEnum, &vInfo);
|
||||||
break;
|
break;
|
||||||
case SceneVisibilityAction::HIDE:
|
case SceneItemSourceType::SOURCE_GROUP:
|
||||||
obs_scene_enum_items(scene, visibilityEnum, &vInfo);
|
vInfo.name = _sourceGroup;
|
||||||
|
obs_scene_enum_items(scene, visibilitySourceTypeEnum, &vInfo);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_source_release(s);
|
obs_source_release(s);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -63,10 +93,18 @@ void MacroActionSceneVisibility::LogAction()
|
|||||||
{
|
{
|
||||||
auto it = actionTypes.find(_action);
|
auto it = actionTypes.find(_action);
|
||||||
if (it != actionTypes.end()) {
|
if (it != actionTypes.end()) {
|
||||||
vblog(LOG_INFO,
|
if (_sourceType == SceneItemSourceType::SOURCE) {
|
||||||
"performed visibility action \"%s\" for source \"%s\" on scene \"%s\"",
|
vblog(LOG_INFO,
|
||||||
it->second.c_str(), GetWeakSourceName(_source).c_str(),
|
"performed visibility action \"%s\" for source \"%s\" on scene \"%s\"",
|
||||||
_scene.ToString().c_str());
|
it->second.c_str(),
|
||||||
|
GetWeakSourceName(_source).c_str(),
|
||||||
|
_scene.ToString().c_str());
|
||||||
|
} else {
|
||||||
|
vblog(LOG_INFO,
|
||||||
|
"performed visibility action \"%s\" for any source type \"%s\" on scene \"%s\"",
|
||||||
|
it->second.c_str(), _sourceGroup.c_str(),
|
||||||
|
_scene.ToString().c_str());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
blog(LOG_WARNING, "ignored unknown SceneVisibility action %d",
|
blog(LOG_WARNING, "ignored unknown SceneVisibility action %d",
|
||||||
static_cast<int>(_action));
|
static_cast<int>(_action));
|
||||||
@@ -77,8 +115,14 @@ bool MacroActionSceneVisibility::Save(obs_data_t *obj)
|
|||||||
{
|
{
|
||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
_scene.Save(obj);
|
_scene.Save(obj);
|
||||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
if (_sourceType == SceneItemSourceType::SOURCE) {
|
||||||
|
obs_data_set_string(obj, "source",
|
||||||
|
GetWeakSourceName(_source).c_str());
|
||||||
|
} else {
|
||||||
|
obs_data_set_string(obj, "source", _sourceGroup.c_str());
|
||||||
|
}
|
||||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||||
|
obs_data_set_int(obj, "sourceType", static_cast<int>(_sourceType));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,8 +130,11 @@ bool MacroActionSceneVisibility::Load(obs_data_t *obj)
|
|||||||
{
|
{
|
||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
_scene.Load(obj);
|
_scene.Load(obj);
|
||||||
|
_sourceType = static_cast<SceneItemSourceType>(
|
||||||
|
obs_data_get_int(obj, "sourceType"));
|
||||||
const char *sourceName = obs_data_get_string(obj, "source");
|
const char *sourceName = obs_data_get_string(obj, "source");
|
||||||
_source = GetWeakSourceByName(sourceName);
|
_source = GetWeakSourceByName(sourceName);
|
||||||
|
_sourceGroup = sourceName;
|
||||||
_action = static_cast<SceneVisibilityAction>(
|
_action = static_cast<SceneVisibilityAction>(
|
||||||
obs_data_get_int(obj, "action"));
|
obs_data_get_int(obj, "action"));
|
||||||
return true;
|
return true;
|
||||||
@@ -95,9 +142,16 @@ bool MacroActionSceneVisibility::Load(obs_data_t *obj)
|
|||||||
|
|
||||||
std::string MacroActionSceneVisibility::GetShortDesc()
|
std::string MacroActionSceneVisibility::GetShortDesc()
|
||||||
{
|
{
|
||||||
if (_source) {
|
if (_sourceType == SceneItemSourceType::SOURCE && _source) {
|
||||||
return _scene.ToString() + " - " + GetWeakSourceName(_source);
|
return _scene.ToString() + " - " + GetWeakSourceName(_source);
|
||||||
}
|
}
|
||||||
|
if (_sourceType == SceneItemSourceType::SOURCE_GROUP &&
|
||||||
|
!_sourceGroup.empty()) {
|
||||||
|
return _scene.ToString() + " - " +
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup") +
|
||||||
|
" " + _sourceGroup;
|
||||||
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,31 +162,44 @@ static inline void populateActionSelection(QComboBox *list)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void populateSourceItemTypeSelection(QComboBox *list)
|
||||||
|
{
|
||||||
|
for (auto entry : sourceItemSourceTypes) {
|
||||||
|
list->addItem(obs_module_text(entry.second.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MacroActionSceneVisibilityEdit::MacroActionSceneVisibilityEdit(
|
MacroActionSceneVisibilityEdit::MacroActionSceneVisibilityEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroActionSceneVisibility> entryData)
|
QWidget *parent, std::shared_ptr<MacroActionSceneVisibility> entryData)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
_scenes = new SceneSelectionWidget(window(), false, false, true);
|
_scenes = new SceneSelectionWidget(window(), false, true, true);
|
||||||
|
_sourceTypes = new QComboBox();
|
||||||
_sources = new QComboBox();
|
_sources = new QComboBox();
|
||||||
|
_sources->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||||
_actions = new QComboBox();
|
_actions = new QComboBox();
|
||||||
|
|
||||||
|
populateSourceItemTypeSelection(_sourceTypes);
|
||||||
populateActionSelection(_actions);
|
populateActionSelection(_actions);
|
||||||
|
|
||||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ActionChanged(int)));
|
SLOT(ActionChanged(int)));
|
||||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||||
|
QWidget::connect(_sourceTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(SourceTypeChanged(int)));
|
||||||
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
|
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
|
||||||
this, SLOT(SourceChanged(const QString &)));
|
this, SLOT(SourceChanged(const QString &)));
|
||||||
|
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{scenes}}", _scenes},
|
{"{{scenes}}", _scenes},
|
||||||
|
{"{{sourceTypes}}", _sourceTypes},
|
||||||
{"{{sources}}", _sources},
|
{"{{sources}}", _sources},
|
||||||
{"{{actions}}", _actions},
|
{"{{actions}}", _actions},
|
||||||
};
|
};
|
||||||
placeWidgets(obs_module_text(
|
placeWidgets(obs_module_text(
|
||||||
"AdvSceneSwitcher.action.SceneVisibility.entry"),
|
"AdvSceneSwitcher.action.sceneVisibility.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
mainLayout, widgetPlaceholders);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -148,10 +215,17 @@ void MacroActionSceneVisibilityEdit::UpdateEntryData()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||||
|
_sourceTypes->setCurrentIndex(
|
||||||
|
static_cast<int>(_entryData->_sourceType));
|
||||||
_scenes->SetScene(_entryData->_scene);
|
_scenes->SetScene(_entryData->_scene);
|
||||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
if (_entryData->_sourceType == SceneItemSourceType::SOURCE) {
|
||||||
_sources->setCurrentText(
|
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||||
GetWeakSourceName(_entryData->_source).c_str());
|
_sources->setCurrentText(
|
||||||
|
GetWeakSourceName(_entryData->_source).c_str());
|
||||||
|
} else {
|
||||||
|
populateSourceTypeSelection(_sources);
|
||||||
|
_sources->setCurrentText(_entryData->_sourceGroup.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
|
void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
|
||||||
@@ -165,6 +239,26 @@ void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
|
|||||||
}
|
}
|
||||||
_sources->clear();
|
_sources->clear();
|
||||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||||
|
_sources->adjustSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionSceneVisibilityEdit::SourceTypeChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_sourceType =
|
||||||
|
static_cast<SceneItemSourceType>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
_sources->clear();
|
||||||
|
if (_entryData->_sourceType == SceneItemSourceType::SOURCE) {
|
||||||
|
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||||
|
} else {
|
||||||
|
populateSourceTypeSelection(_sources);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSceneVisibilityEdit::SourceChanged(const QString &text)
|
void MacroActionSceneVisibilityEdit::SourceChanged(const QString &text)
|
||||||
@@ -174,7 +268,15 @@ void MacroActionSceneVisibilityEdit::SourceChanged(const QString &text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_source = GetWeakSourceByQString(text);
|
if (_entryData->_sourceType == SceneItemSourceType::SOURCE) {
|
||||||
|
_entryData->_source = GetWeakSourceByQString(text);
|
||||||
|
} else {
|
||||||
|
if (text == obs_module_text("AdvSceneSwitcher.selectItem")) {
|
||||||
|
_entryData->_sourceGroup = "";
|
||||||
|
} else {
|
||||||
|
_entryData->_sourceGroup = text.toStdString();
|
||||||
|
}
|
||||||
|
}
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto idx = _entryData->get()->GetIndex();
|
||||||
std::string id = MacroConditionFactory::GetIdByName(text);
|
std::string id = MacroConditionFactory::GetIdByName(text);
|
||||||
|
|
||||||
auto temp = DurationConstraint();
|
auto temp = DurationConstraint();
|
||||||
@@ -198,6 +199,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
|||||||
auto logic = (*_entryData)->GetLogicType();
|
auto logic = (*_entryData)->GetLogicType();
|
||||||
_entryData->reset();
|
_entryData->reset();
|
||||||
*_entryData = MacroConditionFactory::Create(id);
|
*_entryData = MacroConditionFactory::Create(id);
|
||||||
|
(*_entryData)->SetIndex(idx);
|
||||||
(*_entryData)->SetLogicType(logic);
|
(*_entryData)->SetLogicType(logic);
|
||||||
auto widget =
|
auto widget =
|
||||||
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ MacroConditionFilterEdit::MacroConditionFilterEdit(
|
|||||||
{
|
{
|
||||||
_sources = new QComboBox();
|
_sources = new QComboBox();
|
||||||
_filters = new QComboBox();
|
_filters = new QComboBox();
|
||||||
|
_filters->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||||
_conditions = new QComboBox();
|
_conditions = new QComboBox();
|
||||||
_getSettings = new QPushButton(obs_module_text(
|
_getSettings = new QPushButton(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.filter.getSettings"));
|
"AdvSceneSwitcher.condition.filter.getSettings"));
|
||||||
@@ -159,6 +160,7 @@ void MacroConditionFilterEdit::SourceChanged(const QString &text)
|
|||||||
}
|
}
|
||||||
_filters->clear();
|
_filters->clear();
|
||||||
populateFilterSelection(_filters, _entryData->_source);
|
populateFilterSelection(_filters, _entryData->_source);
|
||||||
|
_filters->adjustSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionFilterEdit::FilterChanged(const QString &text)
|
void MacroConditionFilterEdit::FilterChanged(const QString &text)
|
||||||
|
|||||||
@@ -125,6 +125,8 @@ MacroConditionMacroEdit::MacroConditionMacroEdit(
|
|||||||
_currentCount = new QLabel(parent);
|
_currentCount = new QLabel(parent);
|
||||||
_resetCount = new QPushButton(obs_module_text(
|
_resetCount = new QPushButton(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.macro.count.reset"));
|
"AdvSceneSwitcher.condition.macro.count.reset"));
|
||||||
|
_pausedWarning = new QLabel(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.condition.macro.pausedWarning"));
|
||||||
|
|
||||||
_count->setMaximum(10000000);
|
_count->setMaximum(10000000);
|
||||||
populateTypeSelection(_types);
|
populateTypeSelection(_types);
|
||||||
@@ -156,9 +158,18 @@ MacroConditionMacroEdit::MacroConditionMacroEdit(
|
|||||||
mainLayout->addLayout(typesLayout);
|
mainLayout->addLayout(typesLayout);
|
||||||
mainLayout->addLayout(_settingsLine1);
|
mainLayout->addLayout(_settingsLine1);
|
||||||
mainLayout->addLayout(_settingsLine2);
|
mainLayout->addLayout(_settingsLine2);
|
||||||
|
mainLayout->addWidget(_pausedWarning);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
|
|
||||||
|
connect(&_countTimer, SIGNAL(timeout()), this, SLOT(UpdateCount()));
|
||||||
|
_countTimer.start(1000);
|
||||||
|
|
||||||
|
_pausedWarning->setVisible(false);
|
||||||
|
connect(&_pausedTimer, SIGNAL(timeout()), this, SLOT(UpdatePaused()));
|
||||||
|
_pausedTimer.start(1000);
|
||||||
|
|
||||||
UpdateEntryData();
|
UpdateEntryData();
|
||||||
_loading = false;
|
_loading = false;
|
||||||
}
|
}
|
||||||
@@ -237,7 +248,6 @@ void MacroConditionMacroEdit::UpdateEntryData()
|
|||||||
_counterConditions->setCurrentIndex(
|
_counterConditions->setCurrentIndex(
|
||||||
static_cast<int>(_entryData->_counterCondition));
|
static_cast<int>(_entryData->_counterCondition));
|
||||||
_count->setValue(_entryData->_count);
|
_count->setValue(_entryData->_count);
|
||||||
ResetTimer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMacroEdit::MacroChanged(const QString &text)
|
void MacroConditionMacroEdit::MacroChanged(const QString &text)
|
||||||
@@ -248,7 +258,6 @@ void MacroConditionMacroEdit::MacroChanged(const QString &text)
|
|||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_macro.UpdateRef(text);
|
_entryData->_macro.UpdateRef(text);
|
||||||
ResetTimer();
|
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
@@ -303,7 +312,6 @@ void MacroConditionMacroEdit::ResetClicked()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_entryData->_macro->ResetCount();
|
_entryData->_macro->ResetCount();
|
||||||
ResetTimer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMacroEdit::UpdateCount()
|
void MacroConditionMacroEdit::UpdateCount()
|
||||||
@@ -316,9 +324,9 @@ void MacroConditionMacroEdit::UpdateCount()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMacroEdit::ResetTimer()
|
void MacroConditionMacroEdit::UpdatePaused()
|
||||||
{
|
{
|
||||||
_timer.reset(new QTimer(this));
|
_pausedWarning->setVisible(_entryData && _entryData->_macro.get() &&
|
||||||
connect(_timer.get(), SIGNAL(timeout()), this, SLOT(UpdateCount()));
|
_entryData->_macro->Paused());
|
||||||
_timer->start(1000);
|
adjustSize();
|
||||||
}
|
}
|
||||||
|
|||||||
184
src/macro-condition-scene-visibility.cpp
Normal file
184
src/macro-condition-scene-visibility.cpp
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
#include "headers/macro-condition-edit.hpp"
|
||||||
|
#include "headers/macro-condition-scene-visibility.hpp"
|
||||||
|
#include "headers/utility.hpp"
|
||||||
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
const std::string MacroConditionSceneVisibility::id = "scene_visibility";
|
||||||
|
|
||||||
|
bool MacroConditionSceneVisibility::_registered =
|
||||||
|
MacroConditionFactory::Register(
|
||||||
|
MacroConditionSceneVisibility::id,
|
||||||
|
{MacroConditionSceneVisibility::Create,
|
||||||
|
MacroConditionSceneVisibilityEdit::Create,
|
||||||
|
"AdvSceneSwitcher.condition.sceneVisibility"});
|
||||||
|
|
||||||
|
static std::map<SceneVisibilityCondition, std::string>
|
||||||
|
SceneVisibilityConditionTypes = {
|
||||||
|
{SceneVisibilityCondition::SHOWN,
|
||||||
|
"AdvSceneSwitcher.condition.sceneVisibility.type.shown"},
|
||||||
|
{SceneVisibilityCondition::HIDDEN,
|
||||||
|
"AdvSceneSwitcher.condition.sceneVisibility.type.hidden"},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VisibilityData {
|
||||||
|
std::string name;
|
||||||
|
bool visible;
|
||||||
|
bool result;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool visibilityEnum(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
||||||
|
{
|
||||||
|
VisibilityData *vInfo = reinterpret_cast<VisibilityData *>(ptr);
|
||||||
|
auto sourceName = obs_source_get_name(obs_sceneitem_get_source(item));
|
||||||
|
if (vInfo->name == sourceName &&
|
||||||
|
obs_sceneitem_visible(item) == vInfo->visible) {
|
||||||
|
vInfo->result = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obs_sceneitem_is_group(item)) {
|
||||||
|
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||||
|
obs_scene_enum_items(scene, visibilityEnum, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionSceneVisibility::CheckCondition()
|
||||||
|
{
|
||||||
|
if (!_source) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto s = obs_weak_source_get_source(_scene.GetScene());
|
||||||
|
auto scene = obs_scene_from_source(s);
|
||||||
|
auto sourceName = GetWeakSourceName(_source);
|
||||||
|
VisibilityData data = {sourceName,
|
||||||
|
_condition == SceneVisibilityCondition::SHOWN,
|
||||||
|
false};
|
||||||
|
obs_scene_enum_items(scene, visibilityEnum, &data);
|
||||||
|
obs_source_release(s);
|
||||||
|
return data.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionSceneVisibility::Save(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroCondition::Save(obj);
|
||||||
|
_scene.Save(obj);
|
||||||
|
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||||
|
|
||||||
|
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionSceneVisibility::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroCondition::Load(obj);
|
||||||
|
_scene.Load(obj);
|
||||||
|
const char *sourceName = obs_data_get_string(obj, "source");
|
||||||
|
_source = GetWeakSourceByName(sourceName);
|
||||||
|
_condition = static_cast<SceneVisibilityCondition>(
|
||||||
|
obs_data_get_int(obj, "condition"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MacroConditionSceneVisibility::GetShortDesc()
|
||||||
|
{
|
||||||
|
if (_source) {
|
||||||
|
return _scene.ToString() + " - " + GetWeakSourceName(_source);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void populateConditionSelection(QComboBox *list)
|
||||||
|
{
|
||||||
|
for (auto entry : SceneVisibilityConditionTypes) {
|
||||||
|
list->addItem(obs_module_text(entry.second.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroConditionSceneVisibilityEdit::MacroConditionSceneVisibilityEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroConditionSceneVisibility> entryData)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
_scenes = new SceneSelectionWidget(window(), false, true, true);
|
||||||
|
_sources = new QComboBox();
|
||||||
|
_sources->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||||
|
_conditions = new QComboBox();
|
||||||
|
|
||||||
|
populateConditionSelection(_conditions);
|
||||||
|
|
||||||
|
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||||
|
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||||
|
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
|
||||||
|
this, SLOT(SourceChanged(const QString &)));
|
||||||
|
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(ConditionChanged(int)));
|
||||||
|
|
||||||
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
|
{"{{sources}}", _sources},
|
||||||
|
{"{{scenes}}", _scenes},
|
||||||
|
{"{{conditions}}", _conditions},
|
||||||
|
};
|
||||||
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
|
placeWidgets(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.condition.sceneVisibility.entry"),
|
||||||
|
mainLayout, widgetPlaceholders);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
|
UpdateEntryData();
|
||||||
|
_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionSceneVisibilityEdit::SourceChanged(const QString &text)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_source = GetWeakSourceByQString(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_scene = s;
|
||||||
|
}
|
||||||
|
_sources->clear();
|
||||||
|
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||||
|
_sources->adjustSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionSceneVisibilityEdit::ConditionChanged(int index)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_condition = static_cast<SceneVisibilityCondition>(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionSceneVisibilityEdit::UpdateEntryData()
|
||||||
|
{
|
||||||
|
if (!_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||||
|
_scenes->SetScene(_entryData->_scene);
|
||||||
|
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||||
|
_sources->setCurrentText(
|
||||||
|
GetWeakSourceName(_entryData->_source).c_str());
|
||||||
|
}
|
||||||
@@ -947,16 +947,6 @@ bool patternControlIsOptional(VideoCondition cond)
|
|||||||
cond == VideoCondition::HAS_NOT_CHANGED;
|
cond == VideoCondition::HAS_NOT_CHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLayoutVisible(QLayout *layout, bool visible)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < layout->count(); ++i) {
|
|
||||||
QWidget *widget = layout->itemAt(i)->widget();
|
|
||||||
if (widget != NULL) {
|
|
||||||
widget->setVisible(visible);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroConditionVideoEdit::SetWidgetVisibility()
|
void MacroConditionVideoEdit::SetWidgetVisibility()
|
||||||
{
|
{
|
||||||
_imagePath->setVisible(requiresFileInput(_entryData->_condition));
|
_imagePath->setVisible(requiresFileInput(_entryData->_condition));
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ MacroSelection::MacroSelection(QWidget *parent) : QComboBox(parent)
|
|||||||
firstItem->setEnabled(false);
|
firstItem->setEnabled(false);
|
||||||
|
|
||||||
for (auto &m : switcher->macros) {
|
for (auto &m : switcher->macros) {
|
||||||
addItem(QString::fromStdString(m.Name()));
|
addItem(QString::fromStdString(m->Name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget::connect(parent, SIGNAL(MacroAdded(const QString &)), this,
|
QWidget::connect(parent, SIGNAL(MacroAdded(const QString &)), this,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ bool AdvSceneSwitcher::addNewMacro(std::string &name)
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->macros.emplace_back(name);
|
switcher->macros.emplace_back(std::make_shared<Macro>(name));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -84,8 +84,11 @@ void AdvSceneSwitcher::on_macroRemove_clicked()
|
|||||||
switcher->abortMacroWait = true;
|
switcher->abortMacroWait = true;
|
||||||
switcher->macroWaitCv.notify_one();
|
switcher->macroWaitCv.notify_one();
|
||||||
int idx = ui->macros->currentRow();
|
int idx = ui->macros->currentRow();
|
||||||
QString::fromStdString(switcher->macros[idx].Name());
|
QString::fromStdString(switcher->macros[idx]->Name());
|
||||||
switcher->macros.erase(switcher->macros.begin() + idx);
|
switcher->macros.erase(switcher->macros.begin() + idx);
|
||||||
|
for (auto &m : switcher->macros) {
|
||||||
|
m->ResolveMacroRef();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete item;
|
delete item;
|
||||||
@@ -108,7 +111,7 @@ void AdvSceneSwitcher::on_macroUp_clicked()
|
|||||||
switcher->macros.begin() + index - 1);
|
switcher->macros.begin() + index - 1);
|
||||||
|
|
||||||
for (auto &m : switcher->macros) {
|
for (auto &m : switcher->macros) {
|
||||||
m.ResolveMacroRef();
|
m->ResolveMacroRef();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,7 +128,7 @@ void AdvSceneSwitcher::on_macroDown_clicked()
|
|||||||
switcher->macros.begin() + index + 1);
|
switcher->macros.begin() + index + 1);
|
||||||
|
|
||||||
for (auto &m : switcher->macros) {
|
for (auto &m : switcher->macros) {
|
||||||
m.ResolveMacroRef();
|
m->ResolveMacroRef();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,9 +173,8 @@ void AdvSceneSwitcher::on_macroName_editingFinished()
|
|||||||
emit MacroRenamed(oldName, newName);
|
emit MacroRenamed(oldName, newName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::PopulateMacroActions(Macro &m, int afterIdx)
|
void AdvSceneSwitcher::PopulateMacroActions(Macro &m, uint32_t afterIdx)
|
||||||
{
|
{
|
||||||
bool root = afterIdx == 0;
|
|
||||||
auto &actions = m.Actions();
|
auto &actions = m.Actions();
|
||||||
for (; afterIdx < actions.size(); afterIdx++) {
|
for (; afterIdx < actions.size(); afterIdx++) {
|
||||||
auto newEntry = new MacroActionEdit(this, &actions[afterIdx],
|
auto newEntry = new MacroActionEdit(this, &actions[afterIdx],
|
||||||
@@ -180,12 +182,11 @@ void AdvSceneSwitcher::PopulateMacroActions(Macro &m, int afterIdx)
|
|||||||
ConnectControlSignals(newEntry);
|
ConnectControlSignals(newEntry);
|
||||||
ui->macroEditActionLayout->addWidget(newEntry);
|
ui->macroEditActionLayout->addWidget(newEntry);
|
||||||
ui->macroEditActionHelp->setVisible(false);
|
ui->macroEditActionHelp->setVisible(false);
|
||||||
root = false;
|
|
||||||
}
|
}
|
||||||
ui->macroEditActionHelp->setVisible(actions.size() == 0);
|
ui->macroEditActionHelp->setVisible(actions.size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::PopulateMacroConditions(Macro &m, int afterIdx)
|
void AdvSceneSwitcher::PopulateMacroConditions(Macro &m, uint32_t afterIdx)
|
||||||
{
|
{
|
||||||
bool root = afterIdx == 0;
|
bool root = afterIdx == 0;
|
||||||
auto &conditions = m.Conditions();
|
auto &conditions = m.Conditions();
|
||||||
@@ -314,12 +315,12 @@ void AdvSceneSwitcher::on_macros_itemChanged(QListWidgetItem *item)
|
|||||||
void AdvSceneSwitcher::setupMacroTab()
|
void AdvSceneSwitcher::setupMacroTab()
|
||||||
{
|
{
|
||||||
for (auto &m : switcher->macros) {
|
for (auto &m : switcher->macros) {
|
||||||
QString text = QString::fromStdString(m.Name());
|
QString text = QString::fromStdString(m->Name());
|
||||||
|
|
||||||
QListWidgetItem *item = new QListWidgetItem(text, ui->macros);
|
QListWidgetItem *item = new QListWidgetItem(text, ui->macros);
|
||||||
item->setData(Qt::UserRole, text);
|
item->setData(Qt::UserRole, text);
|
||||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||||
if (m.Paused()) {
|
if (m->Paused()) {
|
||||||
item->setCheckState(Qt::Unchecked);
|
item->setCheckState(Qt::Unchecked);
|
||||||
} else {
|
} else {
|
||||||
item->setCheckState(Qt::Checked);
|
item->setCheckState(Qt::Checked);
|
||||||
@@ -392,8 +393,8 @@ void AdvSceneSwitcher::CopyMacro()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switcher->macros.back().Load(data);
|
switcher->macros.back()->Load(data);
|
||||||
switcher->macros.back().SetName(name);
|
switcher->macros.back()->SetName(name);
|
||||||
obs_data_release(data);
|
obs_data_release(data);
|
||||||
|
|
||||||
QString text = QString::fromStdString(name);
|
QString text = QString::fromStdString(name);
|
||||||
|
|||||||
@@ -36,6 +36,11 @@ bool Macro::CeckMatch()
|
|||||||
{
|
{
|
||||||
_matched = false;
|
_matched = false;
|
||||||
for (auto &c : _conditions) {
|
for (auto &c : _conditions) {
|
||||||
|
if (_paused) {
|
||||||
|
vblog(LOG_INFO, "Macro %s is paused", _name.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto startTime = std::chrono::high_resolution_clock::now();
|
auto startTime = std::chrono::high_resolution_clock::now();
|
||||||
bool cond = c->CheckCondition();
|
bool cond = c->CheckCondition();
|
||||||
auto endTime = std::chrono::high_resolution_clock::now();
|
auto endTime = std::chrono::high_resolution_clock::now();
|
||||||
@@ -89,15 +94,11 @@ bool Macro::CeckMatch()
|
|||||||
|
|
||||||
vblog(LOG_INFO, "Macro %s returned %d", _name.c_str(), _matched);
|
vblog(LOG_INFO, "Macro %s returned %d", _name.c_str(), _matched);
|
||||||
|
|
||||||
// Condition checks shall still be run even if macro is paused.
|
// TODO: Move back to PerformAction() once new scene collection frontend
|
||||||
// Otherwise conditions might behave in unexpected ways when resuming.
|
// events are available - see:
|
||||||
//
|
// https://github.com/obsproject/obs-studio/commit/feda1aaa283e8a99f6ba1159cfe6b9c1f2934a61
|
||||||
// For example, audio could immediately match after unpause, when it
|
if (_matched && _count != std::numeric_limits<int>::max()) {
|
||||||
// matched before it was paused due to timers not being updated.
|
_count++;
|
||||||
if (_paused) {
|
|
||||||
vblog(LOG_INFO, "Macro %s is paused", _name.c_str());
|
|
||||||
_matched = false;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _matched;
|
return _matched;
|
||||||
@@ -113,9 +114,6 @@ bool Macro::PerformAction()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_count != std::numeric_limits<int>::max()) {
|
|
||||||
_count++;
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +123,21 @@ void Macro::SetName(const std::string &name)
|
|||||||
SetHotkeysDesc();
|
SetHotkeysDesc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Macro::ResetTimers()
|
||||||
|
{
|
||||||
|
for (auto &c : _conditions) {
|
||||||
|
c->ResetDuration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Macro::SetPaused(bool pause)
|
||||||
|
{
|
||||||
|
if (_paused && !pause) {
|
||||||
|
ResetTimers();
|
||||||
|
}
|
||||||
|
_paused = pause;
|
||||||
|
}
|
||||||
|
|
||||||
void Macro::UpdateActionIndices()
|
void Macro::UpdateActionIndices()
|
||||||
{
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
@@ -290,13 +303,18 @@ void Macro::ResolveMacroRef()
|
|||||||
MacroRefCondition *ref =
|
MacroRefCondition *ref =
|
||||||
dynamic_cast<MacroRefCondition *>(c.get());
|
dynamic_cast<MacroRefCondition *>(c.get());
|
||||||
if (ref) {
|
if (ref) {
|
||||||
ref->_macro.UpdateRef();
|
ref->ResolveMacroRef();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto &a : _actions) {
|
for (auto &a : _actions) {
|
||||||
MacroRefAction *ref = dynamic_cast<MacroRefAction *>(a.get());
|
MacroRefAction *ref = dynamic_cast<MacroRefAction *>(a.get());
|
||||||
if (ref) {
|
if (ref) {
|
||||||
ref->_macro.UpdateRef();
|
ref->ResolveMacroRef();
|
||||||
|
}
|
||||||
|
MultiMacroRefAction *ref2 =
|
||||||
|
dynamic_cast<MultiMacroRefAction *>(a.get());
|
||||||
|
if (ref2) {
|
||||||
|
ref2->ResolveMacroRef();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,7 +463,7 @@ void SwitcherData::saveMacros(obs_data_t *obj)
|
|||||||
for (auto &m : macros) {
|
for (auto &m : macros) {
|
||||||
obs_data_t *array_obj = obs_data_create();
|
obs_data_t *array_obj = obs_data_create();
|
||||||
|
|
||||||
m.Save(array_obj);
|
m->Save(array_obj);
|
||||||
obs_data_array_push_back(macroArray, array_obj);
|
obs_data_array_push_back(macroArray, array_obj);
|
||||||
|
|
||||||
obs_data_release(array_obj);
|
obs_data_release(array_obj);
|
||||||
@@ -463,14 +481,14 @@ void SwitcherData::loadMacros(obs_data_t *obj)
|
|||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
obs_data_t *array_obj = obs_data_array_item(macroArray, i);
|
obs_data_t *array_obj = obs_data_array_item(macroArray, i);
|
||||||
macros.emplace_back();
|
macros.emplace_back(std::make_shared<Macro>());
|
||||||
macros.back().Load(array_obj);
|
macros.back()->Load(array_obj);
|
||||||
obs_data_release(array_obj);
|
obs_data_release(array_obj);
|
||||||
}
|
}
|
||||||
obs_data_array_release(macroArray);
|
obs_data_array_release(macroArray);
|
||||||
|
|
||||||
for (auto &m : macros) {
|
for (auto &m : macros) {
|
||||||
m.ResolveMacroRef();
|
m->ResolveMacroRef();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,11 +496,11 @@ bool SwitcherData::checkMacros()
|
|||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
for (auto &m : macros) {
|
for (auto &m : macros) {
|
||||||
if (m.CeckMatch()) {
|
if (m->CeckMatch()) {
|
||||||
ret = true;
|
ret = true;
|
||||||
// This has to be performed here for now as actions are
|
// This has to be performed here for now as actions are
|
||||||
// not performed immediately after checking conditions.
|
// not performed immediately after checking conditions.
|
||||||
if (m.SwitchesScene()) {
|
if (m->SwitchesScene()) {
|
||||||
switcher->macroSceneSwitched = true;
|
switcher->macroSceneSwitched = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -492,12 +510,15 @@ bool SwitcherData::checkMacros()
|
|||||||
|
|
||||||
bool SwitcherData::runMacros()
|
bool SwitcherData::runMacros()
|
||||||
{
|
{
|
||||||
|
// TODO: Don't rely on creating a copy of each macro once new frontend
|
||||||
|
// events are available - see:
|
||||||
|
// https://github.com/obsproject/obs-studio/commit/feda1aaa283e8a99f6ba1159cfe6b9c1f2934a61
|
||||||
for (auto m : macros) {
|
for (auto m : macros) {
|
||||||
if (m.Matched()) {
|
if (m->Matched()) {
|
||||||
vblog(LOG_INFO, "running macro: %s", m.Name().c_str());
|
vblog(LOG_INFO, "running macro: %s", m->Name().c_str());
|
||||||
if (!m.PerformAction()) {
|
if (!m->PerformAction()) {
|
||||||
blog(LOG_WARNING, "abort macro: %s",
|
blog(LOG_WARNING, "abort macro: %s",
|
||||||
m.Name().c_str());
|
m->Name().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -508,8 +529,8 @@ bool SwitcherData::runMacros()
|
|||||||
Macro *GetMacroByName(const char *name)
|
Macro *GetMacroByName(const char *name)
|
||||||
{
|
{
|
||||||
for (auto &m : switcher->macros) {
|
for (auto &m : switcher->macros) {
|
||||||
if (m.Name() == name) {
|
if (m->Name() == name) {
|
||||||
return &m;
|
return m.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,3 +591,10 @@ void MacroRefAction::ResolveMacroRef()
|
|||||||
{
|
{
|
||||||
_macro.UpdateRef();
|
_macro.UpdateRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MultiMacroRefAction::ResolveMacroRef()
|
||||||
|
{
|
||||||
|
for (auto &m : _macros) {
|
||||||
|
m.UpdateRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -229,6 +229,16 @@ void clearLayout(QLayout *layout, int afterIdx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setLayoutVisible(QLayout *layout, bool visible)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < layout->count(); ++i) {
|
||||||
|
QWidget *widget = layout->itemAt(i)->widget();
|
||||||
|
if (widget != NULL) {
|
||||||
|
widget->setVisible(visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool compareIgnoringLineEnding(QString &s1, QString &s2)
|
bool compareIgnoringLineEnding(QString &s1, QString &s2)
|
||||||
{
|
{
|
||||||
// Let QT deal with different types of lineendings
|
// Let QT deal with different types of lineendings
|
||||||
@@ -800,7 +810,8 @@ void populateSceneItemSelection(QComboBox *list, SceneSelection &s)
|
|||||||
{
|
{
|
||||||
std::set<QString> names;
|
std::set<QString> names;
|
||||||
|
|
||||||
if (s.GetType() == SceneSelectionType::CURRENT) {
|
if (s.GetType() == SceneSelectionType::CURRENT ||
|
||||||
|
s.GetType() == SceneSelectionType::PREVIOUS) {
|
||||||
auto enumScenes = [](void *param, obs_source_t *source) {
|
auto enumScenes = [](void *param, obs_source_t *source) {
|
||||||
if (!source) {
|
if (!source) {
|
||||||
return true;
|
return true;
|
||||||
@@ -828,6 +839,36 @@ void populateSceneItemSelection(QComboBox *list, SceneSelection &s)
|
|||||||
list->setCurrentIndex(0);
|
list->setCurrentIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void populateSourceTypeSelection(QComboBox *list)
|
||||||
|
{
|
||||||
|
std::set<QString> sourceTypeNames;
|
||||||
|
auto enumSourcesTypes = [](void *param, obs_source_t *source) {
|
||||||
|
if (!source) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
std::set<QString> *names =
|
||||||
|
reinterpret_cast<std::set<QString> *>(param);
|
||||||
|
if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
names->insert(
|
||||||
|
obs_source_get_display_name(obs_source_get_id(source)));
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
obs_enum_sources(enumSourcesTypes, &sourceTypeNames);
|
||||||
|
|
||||||
|
for (auto &name : sourceTypeNames) {
|
||||||
|
if (!name.isEmpty()) {
|
||||||
|
list->addItem(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list->model()->sort(0);
|
||||||
|
addSelectionEntry(list, obs_module_text("AdvSceneSwitcher.selectItem"));
|
||||||
|
list->setCurrentIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
QMetaObject::Connection PulseWidget(QWidget *widget, QColor startColor,
|
QMetaObject::Connection PulseWidget(QWidget *widget, QColor startColor,
|
||||||
QColor endColor, QString specifier,
|
QColor endColor, QString specifier,
|
||||||
bool once)
|
bool once)
|
||||||
|
|||||||
Reference in New Issue
Block a user