mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-09-07 00:56:00 -05:00
Add option to select OSB' main video output
This commit is contained in:
@@ -729,6 +729,7 @@ AdvSceneSwitcher.selectWindow="--select window--"
|
||||
AdvSceneSwitcher.selectSource="--select source--"
|
||||
AdvSceneSwitcher.selectAudioSource="--select audio source--"
|
||||
AdvSceneSwitcher.selectVideoSource="--select video source--"
|
||||
AdvSceneSwitcher.OBSVideoOutput="OBS video output"
|
||||
AdvSceneSwitcher.selectMediaSource="--select media source--"
|
||||
AdvSceneSwitcher.selectProcess="--select process--"
|
||||
AdvSceneSwitcher.selectFilter="--select filter--"
|
||||
|
||||
@@ -21,12 +21,14 @@ set(module_SOURCES
|
||||
area-selection.hpp
|
||||
macro-condition-video.cpp
|
||||
macro-condition-video.hpp
|
||||
opencv-helpers.cpp
|
||||
opencv-helpers.hpp
|
||||
preview-dialog.cpp
|
||||
preview-dialog.hpp
|
||||
threshold-slider.cpp
|
||||
threshold-slider.hpp
|
||||
opencv-helpers.cpp
|
||||
opencv-helpers.hpp)
|
||||
video-selection.cpp
|
||||
video-selection.hpp)
|
||||
add_library(advanced-scene-switcher-opencv MODULE ${module_SOURCES})
|
||||
|
||||
if(BUILD_OUT_OF_TREE)
|
||||
|
||||
@@ -72,8 +72,11 @@ bool MacroConditionVideo::CheckShouldBeSkipped()
|
||||
|
||||
bool MacroConditionVideo::CheckCondition()
|
||||
{
|
||||
bool match = false;
|
||||
if (!_video.ValidSelection()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool match = false;
|
||||
if (CheckShouldBeSkipped()) {
|
||||
return _lastMatchResult;
|
||||
}
|
||||
@@ -99,8 +102,7 @@ bool MacroConditionVideo::CheckCondition()
|
||||
bool MacroConditionVideo::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_string(obj, "videoSource",
|
||||
GetWeakSourceName(_videoSource).c_str());
|
||||
_video.Save(obj);
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
obs_data_set_string(obj, "filePath", _file.c_str());
|
||||
obs_data_set_bool(obj, "usePatternForChangedCheck",
|
||||
@@ -133,8 +135,10 @@ bool isMinNeighborsValid(int minNeighbors)
|
||||
bool MacroConditionVideo::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
const char *videoSourceName = obs_data_get_string(obj, "videoSource");
|
||||
_videoSource = GetWeakSourceByName(videoSourceName);
|
||||
_video.Load(obj);
|
||||
if (obs_data_has_user_value(obj, "videoSource")) {
|
||||
_video.Load(obj, "videoSource");
|
||||
}
|
||||
_condition =
|
||||
static_cast<VideoCondition>(obs_data_get_int(obj, "condition"));
|
||||
_file = obs_data_get_string(obj, "filePath");
|
||||
@@ -178,15 +182,12 @@ bool MacroConditionVideo::Load(obs_data_t *obj)
|
||||
|
||||
std::string MacroConditionVideo::GetShortDesc()
|
||||
{
|
||||
if (_videoSource) {
|
||||
return GetWeakSourceName(_videoSource);
|
||||
}
|
||||
return "";
|
||||
return _video.ToString();
|
||||
}
|
||||
|
||||
void MacroConditionVideo::GetScreenshot()
|
||||
{
|
||||
auto source = obs_weak_source_get_source(_videoSource);
|
||||
auto source = obs_weak_source_get_source(_video.GetVideo());
|
||||
_screenshotData.~ScreenshotHelper();
|
||||
new (&_screenshotData) ScreenshotHelper(source);
|
||||
obs_source_release(source);
|
||||
@@ -281,7 +282,7 @@ static inline void populateConditionSelection(QComboBox *list)
|
||||
MacroConditionVideoEdit::MacroConditionVideoEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionVideo> entryData)
|
||||
: QWidget(parent),
|
||||
_videoSelection(new QComboBox()),
|
||||
_videoSelection(new VideoSelectionWidget(this)),
|
||||
_condition(new QComboBox()),
|
||||
_usePatternForChangedCheck(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.video.usePatternForChangedCheck"))),
|
||||
@@ -331,8 +332,9 @@ MacroConditionVideoEdit::MacroConditionVideoEdit(
|
||||
_throttleCount->setSingleStep(GetSwitcher()->interval);
|
||||
|
||||
QWidget::connect(_videoSelection,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
SLOT(SourceChanged(const QString &)));
|
||||
SIGNAL(VideoSelectionChange(const VideoSelection &)),
|
||||
this,
|
||||
SLOT(VideoSelectionChanged(const VideoSelection &)));
|
||||
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_imagePath, SIGNAL(PathChanged(const QString &)), this,
|
||||
@@ -371,7 +373,6 @@ MacroConditionVideoEdit::MacroConditionVideoEdit(
|
||||
QWidget::connect(_selectArea, SIGNAL(clicked()), this,
|
||||
SLOT(SelectAreaClicked()));
|
||||
|
||||
populateVideoSelection(_videoSelection);
|
||||
populateConditionSelection(_condition);
|
||||
|
||||
QHBoxLayout *entryLine1Layout = new QHBoxLayout;
|
||||
@@ -471,14 +472,14 @@ void MacroConditionVideoEdit::UpdatePreviewTooltip()
|
||||
this->setToolTip(html);
|
||||
}
|
||||
|
||||
void MacroConditionVideoEdit::SourceChanged(const QString &text)
|
||||
void MacroConditionVideoEdit::VideoSelectionChanged(const VideoSelection &v)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(GetSwitcher()->m);
|
||||
_entryData->_videoSource = GetWeakSourceByQString(text);
|
||||
_entryData->_video = v;
|
||||
_entryData->ResetLastMatch();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
@@ -533,7 +534,7 @@ void MacroConditionVideoEdit::ImageBrowseButtonClicked()
|
||||
QString path;
|
||||
bool useExistingFile = false;
|
||||
// Ask whether to create screenshot or to select existing file
|
||||
if (_entryData->_videoSource) {
|
||||
if (_entryData->_video.ValidSelection()) {
|
||||
QMessageBox msgBox(
|
||||
QMessageBox::Question,
|
||||
obs_module_text("AdvSceneSwitcher.windowTitle"),
|
||||
@@ -560,8 +561,8 @@ void MacroConditionVideoEdit::ImageBrowseButtonClicked()
|
||||
}
|
||||
|
||||
} else {
|
||||
auto source =
|
||||
obs_weak_source_get_source(_entryData->_videoSource);
|
||||
auto source = obs_weak_source_get_source(
|
||||
_entryData->_video.GetVideo());
|
||||
ScreenshotHelper screenshot(source);
|
||||
obs_source_release(source);
|
||||
|
||||
@@ -818,8 +819,7 @@ void MacroConditionVideoEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
|
||||
_videoSelection->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_videoSource).c_str());
|
||||
_videoSelection->SetVideoSelection(_entryData->_video);
|
||||
_condition->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
_imagePath->SetPath(QString::fromStdString(_entryData->_file));
|
||||
_usePatternForChangedCheck->setChecked(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "threshold-slider.hpp"
|
||||
#include "preview-dialog.hpp"
|
||||
#include "area-selection.hpp"
|
||||
#include "video-selection.hpp"
|
||||
|
||||
#include <macro.hpp>
|
||||
#include <file-selection.hpp>
|
||||
@@ -45,7 +46,7 @@ public:
|
||||
std::string GetModelDataPath() { return _modelDataPath; }
|
||||
void ResetLastMatch() { _lastMatchResult = false; }
|
||||
|
||||
OBSWeakSource _videoSource;
|
||||
VideoSelection _video;
|
||||
VideoCondition _condition = VideoCondition::MATCH;
|
||||
std::string _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
bool _useAlphaAsMask = false;
|
||||
@@ -104,7 +105,7 @@ public:
|
||||
void UpdatePreviewTooltip();
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void VideoSelectionChanged(const VideoSelection &);
|
||||
void ConditionChanged(int cond);
|
||||
void ImagePathChanged(const QString &text);
|
||||
void ImageBrowseButtonClicked();
|
||||
@@ -130,7 +131,7 @@ signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_videoSelection;
|
||||
VideoSelectionWidget *_videoSelection;
|
||||
QComboBox *_condition;
|
||||
|
||||
QCheckBox *_usePatternForChangedCheck;
|
||||
|
||||
@@ -126,7 +126,7 @@ void PreviewDialog::CheckForMatchLoop()
|
||||
while (!_stop) {
|
||||
std::unique_lock<std::mutex> lock(*_mtx);
|
||||
auto source = obs_weak_source_get_source(
|
||||
_conditionData->_videoSource);
|
||||
_conditionData->_video.GetVideo());
|
||||
ScreenshotHelper screenshot(source);
|
||||
obs_source_release(source);
|
||||
cv.wait_for(lock, std::chrono::seconds(1));
|
||||
@@ -136,7 +136,8 @@ void PreviewDialog::CheckForMatchLoop()
|
||||
if (isHidden()) {
|
||||
continue;
|
||||
}
|
||||
if (!screenshot.done) {
|
||||
if (!screenshot.done ||
|
||||
!_conditionData->_video.ValidSelection()) {
|
||||
_statusLabel->setText(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.video.screenshotFail"));
|
||||
_imageLabel->setPixmap(QPixmap());
|
||||
|
||||
122
src/external-macro-modules/opencv/video-selection.cpp
Normal file
122
src/external-macro-modules/opencv/video-selection.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "video-selection.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
void VideoSelection::Save(obs_data_t *obj, const char *name,
|
||||
const char *typeName)
|
||||
{
|
||||
obs_data_set_int(obj, typeName, static_cast<int>(_type));
|
||||
|
||||
switch (_type) {
|
||||
case VideoSelectionType::SOURCE:
|
||||
obs_data_set_string(obj, name,
|
||||
GetWeakSourceName(_source).c_str());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VideoSelection::Load(obs_data_t *obj, const char *name,
|
||||
const char *typeName)
|
||||
{
|
||||
_type = static_cast<VideoSelectionType>(
|
||||
obs_data_get_int(obj, typeName));
|
||||
auto target = obs_data_get_string(obj, name);
|
||||
switch (_type) {
|
||||
case VideoSelectionType::SOURCE:
|
||||
_source = GetWeakSourceByName(target);
|
||||
break;
|
||||
case VideoSelectionType::OBS_MAIN:
|
||||
_source = nullptr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
OBSWeakSource VideoSelection::GetVideo()
|
||||
{
|
||||
if (_type == VideoSelectionType::SOURCE) {
|
||||
return _source;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string VideoSelection::ToString()
|
||||
{
|
||||
switch (_type) {
|
||||
case VideoSelectionType::SOURCE:
|
||||
return GetWeakSourceName(_source);
|
||||
case VideoSelectionType::OBS_MAIN:
|
||||
return obs_module_text("AdvSceneSwitcher.OBSVideoOutput");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool VideoSelection::ValidSelection()
|
||||
{
|
||||
return _type == VideoSelectionType::OBS_MAIN || !!_source;
|
||||
}
|
||||
|
||||
VideoSelectionWidget::VideoSelectionWidget(QWidget *parent, bool addOBSVideoOut)
|
||||
: QComboBox(parent)
|
||||
{
|
||||
setDuplicatesEnabled(true);
|
||||
populateVideoSelection(this, addOBSVideoOut);
|
||||
QWidget::connect(this, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SelectionChanged(const QString &)));
|
||||
}
|
||||
|
||||
void VideoSelectionWidget::SetVideoSelection(VideoSelection &t)
|
||||
{
|
||||
int idx;
|
||||
switch (t.GetType()) {
|
||||
case VideoSelectionType::SOURCE:
|
||||
setCurrentText(QString::fromStdString(t.ToString()));
|
||||
break;
|
||||
case VideoSelectionType::OBS_MAIN:
|
||||
idx = findText(QString::fromStdString(obs_module_text(
|
||||
obs_module_text("AdvSceneSwitcher.OBSVideoOutput"))));
|
||||
if (idx != -1) {
|
||||
setCurrentIndex(idx);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
setCurrentIndex(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isFirstEntry(QComboBox *l, QString name, int idx)
|
||||
{
|
||||
for (int i = 0; i < l->count(); i++) {
|
||||
if (l->itemText(i) == name) {
|
||||
return idx == i;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VideoSelectionWidget::IsOBSVideoOutSelected(const QString &name)
|
||||
{
|
||||
if (name == QString::fromStdString(obs_module_text(
|
||||
"AdvSceneSwitcher.OBSVideoOutput"))) {
|
||||
return isFirstEntry(this, name, currentIndex());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void VideoSelectionWidget::SelectionChanged(const QString &name)
|
||||
{
|
||||
VideoSelection t;
|
||||
if (IsOBSVideoOutSelected(name)) {
|
||||
t._type = VideoSelectionType::OBS_MAIN;
|
||||
} else {
|
||||
auto source = GetWeakSourceByQString(name);
|
||||
t._type = VideoSelectionType::SOURCE;
|
||||
t._source = source;
|
||||
}
|
||||
emit VideoSelectionChange(t);
|
||||
}
|
||||
43
src/external-macro-modules/opencv/video-selection.hpp
Normal file
43
src/external-macro-modules/opencv/video-selection.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
#include <QComboBox>
|
||||
#include <obs-module.h>
|
||||
#include <obs.hpp>
|
||||
|
||||
enum class VideoSelectionType {
|
||||
SOURCE,
|
||||
OBS_MAIN,
|
||||
};
|
||||
|
||||
class VideoSelection {
|
||||
public:
|
||||
void Save(obs_data_t *obj, const char *name = "video",
|
||||
const char *typeName = "videoType");
|
||||
void Load(obs_data_t *obj, const char *name = "video",
|
||||
const char *typeName = "videoType");
|
||||
|
||||
VideoSelectionType GetType() { return _type; }
|
||||
OBSWeakSource GetVideo();
|
||||
std::string ToString();
|
||||
bool ValidSelection();
|
||||
|
||||
private:
|
||||
OBSWeakSource _source;
|
||||
VideoSelectionType _type = VideoSelectionType::SOURCE;
|
||||
friend class VideoSelectionWidget;
|
||||
};
|
||||
|
||||
class VideoSelectionWidget : public QComboBox {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VideoSelectionWidget(QWidget *parent, bool addOBSVideoOut = true);
|
||||
void SetVideoSelection(VideoSelection &);
|
||||
signals:
|
||||
void VideoSelectionChange(const VideoSelection &);
|
||||
|
||||
private slots:
|
||||
void SelectionChanged(const QString &name);
|
||||
|
||||
private:
|
||||
bool IsOBSVideoOutSelected(const QString &name);
|
||||
};
|
||||
@@ -63,8 +63,8 @@ void populateTransitionSelection(QComboBox *sel, bool addCurrent = true,
|
||||
bool addAny = false);
|
||||
void populateWindowSelection(QComboBox *sel, bool addSelect = true);
|
||||
void populateAudioSelection(QComboBox *sel, bool addSelect = true);
|
||||
void populateVideoSelection(QComboBox *sel, bool addScenes = false,
|
||||
bool addSelect = true);
|
||||
void populateVideoSelection(QComboBox *sel, bool addMainOutput = false,
|
||||
bool addScenes = false, bool addSelect = true);
|
||||
void populateMediaSelection(QComboBox *sel, bool addSelect = true);
|
||||
void populateProcessSelection(QComboBox *sel, bool addSelect = true);
|
||||
void populateSourceSelection(QComboBox *list, bool addSelect = true);
|
||||
|
||||
@@ -600,7 +600,8 @@ void populateAudioSelection(QComboBox *sel, bool addSelect)
|
||||
sel->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
void populateVideoSelection(QComboBox *sel, bool addScenes, bool addSelect)
|
||||
void populateVideoSelection(QComboBox *sel, bool addMainOutput, bool addScenes,
|
||||
bool addSelect)
|
||||
{
|
||||
|
||||
auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */
|
||||
@@ -628,6 +629,10 @@ void populateVideoSelection(QComboBox *sel, bool addScenes, bool addSelect)
|
||||
}
|
||||
|
||||
sel->model()->sort(0);
|
||||
if (addMainOutput) {
|
||||
sel->insertItem(
|
||||
0, obs_module_text("AdvSceneSwitcher.OBSVideoOutput"));
|
||||
}
|
||||
if (addSelect) {
|
||||
addSelectionEntry(
|
||||
sel,
|
||||
|
||||
Reference in New Issue
Block a user