Add option to select OSB' main video output

This commit is contained in:
WarmUpTill
2022-03-28 21:52:38 +02:00
committed by WarmUpTill
parent 102b93d3b5
commit 123d308a0d
9 changed files with 206 additions and 31 deletions

View File

@@ -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--"

View File

@@ -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)

View File

@@ -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(

View File

@@ -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;

View File

@@ -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());

View 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);
}

View 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);
};

View File

@@ -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);

View File

@@ -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,