Add slide show condition

It allows you to check ...
* if the slide changed
* the current slide index
* the current slide path

Important limitation:
Its internal state is only updated whenever the "slide_changed" signal
is sent by the particular source.
This commit is contained in:
WarmUpTill
2023-07-29 23:07:16 +02:00
committed by WarmUpTill
parent f92ed3139d
commit 211eac5313
4 changed files with 408 additions and 0 deletions

View File

@@ -203,6 +203,8 @@ target_sources(
src/macro-core/macro-condition-scene-transform.hpp
src/macro-core/macro-condition-scene-visibility.cpp
src/macro-core/macro-condition-scene-visibility.hpp
src/macro-core/macro-condition-slideshow.cpp
src/macro-core/macro-condition-slideshow.hpp
src/macro-core/macro-condition-scene.cpp
src/macro-core/macro-condition-scene.hpp
src/macro-core/macro-condition-source.cpp

View File

@@ -466,6 +466,12 @@ AdvSceneSwitcher.condition.display="Display"
AdvSceneSwitcher.condition.display.type.displayName="Name of connected displays matches"
AdvSceneSwitcher.condition.display.type.displayCount="Number of connected displays is"
AdvSceneSwitcher.condition.display.entry="{{conditions}}{{displays}}{{regex}}{{displayCount}}"
AdvSceneSwitcher.condition.slideshow="Slide Show"
AdvSceneSwitcher.condition.slideshow.condition.slideChanged="Slide changed"
AdvSceneSwitcher.condition.slideshow.condition.slideIndex="Current slide number is"
AdvSceneSwitcher.condition.slideshow.condition.slidePath="Current slide path is"
AdvSceneSwitcher.condition.slideshow.updateIntervalTooltip="Information about the slide show status will only be updated based on the configured time between slides"
AdvSceneSwitcher.condition.slideshow.entry="{{sources}}{{conditions}}{{index}}{{path}}"
; Macro Actions
AdvSceneSwitcher.action.switchScene="Switch scene"

View File

@@ -0,0 +1,312 @@
#include "macro-condition-slideshow.hpp"
#include "macro.hpp"
#include "utility.hpp"
namespace advss {
const std::string MacroConditionSlideshow::id = "slideshow";
bool MacroConditionSlideshow::_registered = MacroConditionFactory::Register(
MacroConditionSlideshow::id,
{MacroConditionSlideshow::Create, MacroConditionSlideshowEdit::Create,
"AdvSceneSwitcher.condition.slideshow"});
static const std::map<MacroConditionSlideshow::Condition, std::string>
conditions = {
{MacroConditionSlideshow::Condition::SLIDE_CHANGED,
"AdvSceneSwitcher.condition.slideshow.condition.slideChanged"},
{MacroConditionSlideshow::Condition::SLIDE_INDEX,
"AdvSceneSwitcher.condition.slideshow.condition.slideIndex"},
{MacroConditionSlideshow::Condition::SLIDE_PATH,
"AdvSceneSwitcher.condition.slideshow.condition.slidePath"},
};
MacroConditionSlideshow::MacroConditionSlideshow(Macro *m)
: MacroCondition(m, true)
{
}
MacroConditionSlideshow::~MacroConditionSlideshow()
{
RemoveSignalHandler();
}
bool MacroConditionSlideshow::CheckCondition()
{
auto source = _source.GetSource();
if (_currentSignalSource != source) {
Reset();
RemoveSignalHandler();
AddSignalHandler(source);
}
if (!source) {
return false;
}
switch (_condition) {
case MacroConditionSlideshow::Condition::SLIDE_CHANGED:
if (!_slideChanged) {
SetVariableValue("false");
return false;
}
_slideChanged = false;
SetVariableValue("true");
return true;
case MacroConditionSlideshow::Condition::SLIDE_INDEX:
if (_currentIndex == -1) {
SetVariableValue("-1");
return false;
}
SetVariableValue(std::to_string(_currentIndex + 1));
return _currentIndex == _index - 1;
case MacroConditionSlideshow::Condition::SLIDE_PATH:
if (_currentPath[0] == '\0') {
SetVariableValue("");
return false;
}
SetVariableValue(_currentPath);
return std::string(_path) == std::string(_currentPath);
}
return false;
}
bool MacroConditionSlideshow::Save(obs_data_t *obj) const
{
MacroCondition::Save(obj);
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
_source.Save(obj);
_index.Save(obj, "index");
_path.Save(obj, "path");
return true;
}
bool MacroConditionSlideshow::Load(obs_data_t *obj)
{
MacroCondition::Load(obj);
_condition = static_cast<Condition>(obs_data_get_int(obj, "condition"));
_source.Load(obj);
_index.Load(obj, "index");
_path.Load(obj, "path");
auto s = _source.GetSource();
AddSignalHandler(s);
return true;
}
std::string MacroConditionSlideshow::GetShortDesc() const
{
return _source.ToString();
}
void MacroConditionSlideshow::SetSource(const SourceSelection &source)
{
Reset();
_source = source;
RemoveSignalHandler();
auto s = _source.GetSource();
AddSignalHandler(s);
}
const SourceSelection &MacroConditionSlideshow::GetSource() const
{
return _source;
}
void MacroConditionSlideshow::SlideChanged(void *c, calldata_t *data)
{
auto condition = static_cast<MacroConditionSlideshow *>(c);
const auto macro = condition->GetMacro();
if (macro && macro->Paused()) {
return;
}
long long newIndex = 0;
if (!calldata_get_int(data, "index", &newIndex)) {
condition->_currentIndex = -1;
}
// Function will be called every time the slide_time timeout is reached
// regardless of if there was actually a change in slide index.
//
// Thus we need to manually check if the slide index really changed.
if (newIndex != condition->_currentIndex) {
condition->_slideChanged = true;
}
condition->_currentIndex = newIndex;
if (!calldata_get_string(data, "path", &condition->_currentPath)) {
condition->_currentPath = "";
}
}
void MacroConditionSlideshow::RemoveSignalHandler()
{
obs_source_t *source = obs_weak_source_get_source(_currentSignalSource);
if (!source) {
return;
}
signal_handler_t *sh = obs_source_get_signal_handler(source);
signal_handler_disconnect(sh, "slide_changed", SlideChanged, this);
obs_source_release(source);
}
void MacroConditionSlideshow::AddSignalHandler(const OBSWeakSource &s)
{
_currentSignalSource = s;
if (!s) {
return;
}
obs_source_t *source = obs_weak_source_get_source(s);
signal_handler_t *sh = obs_source_get_signal_handler(source);
signal_handler_connect(sh, "slide_changed", SlideChanged, this);
obs_source_release(source);
}
void MacroConditionSlideshow::Reset()
{
_slideChanged = false;
_currentIndex = -1;
_currentPath = "";
}
static void populateConditionSelection(QComboBox *list)
{
for (const auto &[_, name] : conditions) {
list->addItem(obs_module_text(name.c_str()));
}
}
static QStringList getSlideshowNames()
{
auto sourceEnum = [](void *param, obs_source_t *source) -> bool /* -- */
{
QStringList *list = reinterpret_cast<QStringList *>(param);
std::string sourceId = obs_source_get_id(source);
if (sourceId.compare("slideshow") == 0) {
*list << obs_source_get_name(source);
}
return true;
};
QStringList list;
obs_enum_sources(sourceEnum, &list);
return list;
}
MacroConditionSlideshowEdit::MacroConditionSlideshowEdit(
QWidget *parent, std::shared_ptr<MacroConditionSlideshow> entryData)
: QWidget(parent),
_conditions(new QComboBox(this)),
_sources(new SourceSelectionWidget(this, QStringList(), true)),
_index(new VariableSpinBox(this)),
_path(new VariableLineEdit(this))
{
setToolTip(obs_module_text(
"AdvSceneSwitcher.condition.slideshow.updateIntervalTooltip"));
_index->setMinimum(1);
populateConditionSelection(_conditions);
auto sources = getSlideshowNames();
sources.sort();
_sources->SetSourceNameList(sources);
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ConditionChanged(int)));
QWidget::connect(_sources,
SIGNAL(SourceChanged(const SourceSelection &)), this,
SLOT(SourceChanged(const SourceSelection &)));
QWidget::connect(
_index,
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
this, SLOT(IndexChanged(const NumberVariable<int> &)));
QWidget::connect(_path, SIGNAL(editingFinished()), this,
SLOT(PathChanged()));
auto layout = new QHBoxLayout;
PlaceWidgets(
obs_module_text("AdvSceneSwitcher.condition.slideshow.entry"),
layout,
{{"{{conditions}}", _conditions},
{"{{sources}}", _sources},
{"{{index}}", _index},
{"{{path}}", _path}});
setLayout(layout);
_entryData = entryData;
UpdateEntryData();
_loading = false;
}
void MacroConditionSlideshowEdit::ConditionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_condition =
static_cast<MacroConditionSlideshow::Condition>(index);
SetWidgetVisibility();
}
void MacroConditionSlideshowEdit::SourceChanged(const SourceSelection &source)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->SetSource(source);
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
}
void MacroConditionSlideshowEdit::IndexChanged(const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_index = value;
}
void MacroConditionSlideshowEdit::PathChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_path = _path->text().toStdString();
}
void MacroConditionSlideshowEdit::UpdateEntryData()
{
if (!_entryData) {
return;
}
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
_sources->SetSource(_entryData->GetSource());
_index->SetValue(_entryData->_index);
_path->setText(_entryData->_path);
SetWidgetVisibility();
}
void MacroConditionSlideshowEdit::SetWidgetVisibility()
{
if (!_entryData) {
return;
}
_index->setVisible(_entryData->_condition ==
MacroConditionSlideshow::Condition::SLIDE_INDEX);
_path->setVisible(_entryData->_condition ==
MacroConditionSlideshow::Condition::SLIDE_PATH);
}
} // namespace advss

View File

@@ -0,0 +1,88 @@
#pragma once
#include "macro-condition-edit.hpp"
#include "source-selection.hpp"
#include "variable-spinbox.hpp"
#include "variable-line-edit.hpp"
namespace advss {
class MacroConditionSlideshow : public MacroCondition {
public:
MacroConditionSlideshow(Macro *m);
~MacroConditionSlideshow();
bool CheckCondition();
bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj);
std::string GetShortDesc() const;
std::string GetId() const { return id; };
static std::shared_ptr<MacroCondition> Create(Macro *m)
{
return std::make_shared<MacroConditionSlideshow>(m);
}
void SetSource(const SourceSelection &source);
const SourceSelection &GetSource() const;
enum class Condition {
SLIDE_CHANGED,
SLIDE_INDEX,
SLIDE_PATH,
};
Condition _condition = Condition::SLIDE_CHANGED;
IntVariable _index;
StringVariable _path;
private:
static void SlideChanged(void *condition, calldata_t *);
void RemoveSignalHandler();
void AddSignalHandler(const OBSWeakSource &);
void Reset();
SourceSelection _source;
OBSWeakSource _currentSignalSource;
bool _slideChanged = false;
long long _currentIndex = -1;
const char *_currentPath = "";
static bool _registered;
static const std::string id;
};
class MacroConditionSlideshowEdit : public QWidget {
Q_OBJECT
public:
MacroConditionSlideshowEdit(
QWidget *parent,
std::shared_ptr<MacroConditionSlideshow> cond = nullptr);
void UpdateEntryData();
static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroCondition> cond)
{
return new MacroConditionSlideshowEdit(
parent,
std::dynamic_pointer_cast<MacroConditionSlideshow>(
cond));
}
private slots:
void ConditionChanged(int index);
void SourceChanged(const SourceSelection &);
void IndexChanged(const NumberVariable<int> &);
void PathChanged();
signals:
void HeaderInfoChanged(const QString &);
private:
void SetWidgetVisibility();
QComboBox *_conditions;
VariableSpinBox *_index;
VariableLineEdit *_path;
SourceSelectionWidget *_sources;
std::shared_ptr<MacroConditionSlideshow> _entryData;
bool _loading = true;
};
} // namespace advss