Macro pause (#201)

* Add option to pause individual macros
* Add macro action to pause and unpause macros
This commit is contained in:
WarmUpTill 2021-05-22 23:54:59 -07:00 committed by GitHub
parent c1704f2164
commit 961ea655fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 334 additions and 25 deletions

View File

@ -84,6 +84,7 @@ set(advanced-scene-switcher_HEADERS
src/headers/macro-action-audio.hpp
src/headers/macro-action-filter.hpp
src/headers/macro-action-media.hpp
src/headers/macro-action-pause.hpp
src/headers/macro-action-recording.hpp
src/headers/macro-action-replay-buffer.hpp
src/headers/macro-action-run.hpp
@ -145,6 +146,7 @@ set(advanced-scene-switcher_SOURCES
src/macro-action-audio.cpp
src/macro-action-filter.cpp
src/macro-action-media.cpp
src/macro-action-pause.cpp
src/macro-action-recording.cpp
src/macro-action-replay-buffer.cpp
src/macro-action-run.cpp

View File

@ -179,6 +179,10 @@ AdvSceneSwitcher.action.media.type.restart="Restart"
AdvSceneSwitcher.action.media.type.next="Next"
AdvSceneSwitcher.action.media.type.previous="Previous"
AdvSceneSwitcher.action.media.entry="{{actions}} {{mediaSources}}"
AdvSceneSwitcher.action.pause="Pause"
AdvSceneSwitcher.action.pause.type.pause="Pause"
AdvSceneSwitcher.action.pause.type.unpause="Unpause"
AdvSceneSwitcher.action.pause.entry="{{actions}} {{macros}}"
; Transition Tab
@ -435,6 +439,7 @@ AdvSceneSwitcher.selectVideoSource="--select video source--"
AdvSceneSwitcher.selectMediaSource="--select media source--"
AdvSceneSwitcher.selectProcess="--select process--"
AdvSceneSwitcher.selectFilter="--select filter--"
AdvSceneSwitcher.selectMacro="--select macro--"
AdvSceneSwitcher.selectItem="--select item--"
AdvSceneSwitcher.enterPath="--enter path--"
AdvSceneSwitcher.enterText="--enter text--"

View File

@ -107,6 +107,9 @@ public:
bool listMoveDown(QListWidget *list);
signals:
void MacroAdded(const QString &name);
void MacroRemoved(const QString &name);
void MacroRenamed(const QString &oldName, const QString newName);
void SceneGroupAdded(const QString &name);
void SceneGroupRemoved(const QString &name);
void SceneGroupRenamed(const QString &oldName, const QString newName);
@ -137,6 +140,7 @@ public slots:
void on_macroDown_clicked();
void on_macroName_editingFinished();
void on_macros_currentRowChanged(int idx);
void on_macros_itemChanged(QListWidgetItem *);
void on_conditionAdd_clicked();
void on_conditionRemove_clicked();
void on_actionAdd_clicked();

View File

@ -0,0 +1,61 @@
#pragma once
#include <QDoubleSpinBox>
#include "macro-action-edit.hpp"
enum class PauseAction {
PAUSE,
UNPAUSE,
};
class MacroActionPause : public MacroAction {
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<MacroActionPause>();
}
PauseAction _action = PauseAction::PAUSE;
Macro *_macro = nullptr;
private:
static bool _registered;
static const std::string id;
};
class MacroActionPauseEdit : public QWidget {
Q_OBJECT
public:
MacroActionPauseEdit(
QWidget *parent,
std::shared_ptr<MacroActionPause> entryData = nullptr);
void UpdateEntryData();
static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroAction> action)
{
return new MacroActionPauseEdit(
parent,
std::dynamic_pointer_cast<MacroActionPause>(action));
}
private slots:
void MacroChanged(const QString &text);
void ActionChanged(int value);
void MacroAdd(const QString &name);
void MacroRemove(const QString &name);
void MacroRename(const QString &oldName, const QString &newName);
protected:
QComboBox *_macros;
QComboBox *_actions;
std::shared_ptr<MacroActionPause> _entryData;
private:
QHBoxLayout *_mainLayout;
bool _loading = true;
};

View File

@ -5,6 +5,7 @@
#include <map>
#include <obs.hpp>
#include <obs-module.h>
#include <QString>
constexpr auto macro_func = 10;
constexpr auto default_priority_10 = macro_func;
@ -68,6 +69,8 @@ public:
bool Matched() { return _matched; }
std::string Name() { return _name; }
void SetName(std::string name) { _name = name; }
void SetPaused(bool pause = true) { _paused = pause; }
bool Paused() { return _paused; }
std::deque<std::shared_ptr<MacroCondition>> &Conditions()
{
return _conditions;
@ -85,4 +88,8 @@ private:
std::deque<std::shared_ptr<MacroCondition>> _conditions;
std::deque<std::shared_ptr<MacroAction>> _actions;
bool _matched = false;
bool _paused = false;
};
Macro *GetMacroByName(const char *name);
Macro *GetMacroByQString(const QString &name);

189
src/macro-action-pause.cpp Normal file
View File

@ -0,0 +1,189 @@
#include "headers/macro-action-pause.hpp"
#include "headers/advanced-scene-switcher.hpp"
#include "headers/utility.hpp"
const std::string MacroActionPause::id = "pause";
bool MacroActionPause::_registered = MacroActionFactory::Register(
MacroActionPause::id,
{MacroActionPause::Create, MacroActionPauseEdit::Create,
"AdvSceneSwitcher.action.pause"});
const static std::map<PauseAction, std::string> actionTypes = {
{PauseAction::PAUSE, "AdvSceneSwitcher.action.pause.type.pause"},
{PauseAction::UNPAUSE, "AdvSceneSwitcher.action.pause.type.unpause"},
};
bool MacroActionPause::PerformAction()
{
if (!_macro) {
return true;
}
switch (_action) {
case PauseAction::PAUSE:
_macro->SetPaused();
break;
case PauseAction::UNPAUSE:
_macro->SetPaused(false);
break;
default:
break;
}
return true;
}
void MacroActionPause::LogAction()
{
if (!_macro) {
return;
}
switch (_action) {
case PauseAction::PAUSE:
vblog(LOG_INFO, "paused \"%s\"", _macro->Name().c_str());
break;
case PauseAction::UNPAUSE:
vblog(LOG_INFO, "unpaused \"%s\"", _macro->Name().c_str());
break;
default:
break;
}
}
bool MacroActionPause::Save(obs_data_t *obj)
{
MacroAction::Save(obj);
if (_macro) {
obs_data_set_string(obj, "macro", _macro->Name().c_str());
}
obs_data_set_int(obj, "action", static_cast<int>(_action));
return true;
}
bool MacroActionPause::Load(obs_data_t *obj)
{
MacroAction::Load(obj);
_macro = GetMacroByName(obs_data_get_string(obj, "macro"));
_action = static_cast<PauseAction>(obs_data_get_int(obj, "action"));
return true;
}
static inline void populateActionSelection(QComboBox *list)
{
for (auto entry : actionTypes) {
list->addItem(obs_module_text(entry.second.c_str()));
}
}
static inline void populateMacroSelection(QComboBox *list)
{
list->addItem(obs_module_text("AdvSceneSwitcher.selectMacro"));
for (auto &m : switcher->macros) {
list->addItem(QString::fromStdString(m.Name()));
}
}
MacroActionPauseEdit::MacroActionPauseEdit(
QWidget *parent, std::shared_ptr<MacroActionPause> entryData)
: QWidget(parent)
{
_macros = new QComboBox();
_actions = new QComboBox();
populateActionSelection(_actions);
populateMacroSelection(_macros);
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
this, SLOT(MacroChanged(const QString &)));
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ActionChanged(int)));
QWidget::connect(parent, SIGNAL(MacroAdded(const QString &)), this,
SLOT(MacroAdd(const QString &)));
QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this,
SLOT(MacroRemove(const QString &)));
QWidget::connect(parent,
SIGNAL(MacroRenamed(const QString &, const QString &)),
this,
SLOT(MacroRename(const QString &, const QString &)));
QHBoxLayout *mainLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{actions}}", _actions},
{"{{macros}}", _macros},
};
placeWidgets(obs_module_text("AdvSceneSwitcher.action.pause.entry"),
mainLayout, widgetPlaceholders);
setLayout(mainLayout);
_entryData = entryData;
UpdateEntryData();
_loading = false;
}
void MacroActionPauseEdit::UpdateEntryData()
{
if (!_entryData) {
return;
}
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
if (_entryData->_macro) {
_macros->setCurrentText(
QString::fromStdString(_entryData->_macro->Name()));
} else {
_macros->setCurrentIndex(0);
}
}
void MacroActionPauseEdit::MacroChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_macro = GetMacroByQString(text);
}
void MacroActionPauseEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_action = static_cast<PauseAction>(value);
}
void MacroActionPauseEdit::MacroAdd(const QString &name)
{
_macros->addItem(name);
}
void MacroActionPauseEdit::MacroRemove(const QString &name)
{
int idx = _macros->findText(name);
if (idx == -1) {
return;
}
_macros->removeItem(idx);
if (_entryData && _entryData->_macro == GetMacroByQString(name)) {
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_macro = nullptr;
}
_macros->setCurrentIndex(0);
}
void MacroActionPauseEdit::MacroRename(const QString &oldName,
const QString &newName)
{
bool renameSelected = _macros->currentText() == oldName;
int idx = _macros->findText(oldName);
if (idx == -1) {
return;
}
_macros->removeItem(idx);
_macros->insertItem(idx, newName);
if (renameSelected) {
_macros->setCurrentIndex(_macros->findText(newName));
}
}

View File

@ -13,13 +13,7 @@ const auto actionsCollapseThreshold = 2;
bool macroNameExists(std::string name)
{
for (auto &m : switcher->macros) {
if (m.Name() == name) {
return true;
}
}
return false;
return !!GetMacroByName(name.c_str());
}
bool AdvSceneSwitcher::addNewMacro(std::string &name)
@ -69,10 +63,14 @@ void AdvSceneSwitcher::on_macroAdd_clicked()
QListWidgetItem *item = new QListWidgetItem(text, ui->macros);
item->setData(Qt::UserRole, text);
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Checked);
ui->macros->setCurrentItem(item);
ui->macroAdd->disconnect(addPulse);
ui->macroHelp->setVisible(false);
emit MacroAdded(QString::fromStdString(name));
}
void AdvSceneSwitcher::on_macroRemove_clicked()
@ -81,9 +79,11 @@ void AdvSceneSwitcher::on_macroRemove_clicked()
if (!item) {
return;
}
QString name;
{
std::lock_guard<std::mutex> lock(switcher->m);
int idx = ui->macros->currentRow();
QString::fromStdString(switcher->macros[idx].Name());
switcher->macros.erase(switcher->macros.begin() + idx);
}
@ -92,6 +92,7 @@ void AdvSceneSwitcher::on_macroRemove_clicked()
if (ui->macros->count() == 0) {
ui->macroHelp->setVisible(true);
}
emit MacroRemoved(name);
}
void AdvSceneSwitcher::on_macroUp_clicked()
@ -147,12 +148,17 @@ void AdvSceneSwitcher::on_macroName_editingFinished()
if (nameValid) {
macro->SetName(newName.toUtf8().constData());
QListWidgetItem *item = ui->macros->currentItem();
item->setData(Qt::UserRole, newName);
// Don't trigger itemChanged()
// pause state remains as is
ui->macros->blockSignals(true);
item->setText(newName);
ui->macros->blockSignals(false);
} else {
ui->macroName->setText(oldName);
}
}
emit MacroRenamed(oldName, newName);
}
void AdvSceneSwitcher::SetEditMacro(Macro &m)
@ -196,22 +202,14 @@ void AdvSceneSwitcher::SetEditMacro(Macro &m)
Macro *AdvSceneSwitcher::getSelectedMacro()
{
Macro *macro = nullptr;
QListWidgetItem *item = ui->macros->currentItem();
if (!item) {
return macro;
return nullptr;
}
QString name = item->data(Qt::UserRole).toString();
for (auto &m : switcher->macros) {
if (name.compare(m.Name().c_str()) == 0) {
macro = &m;
break;
}
}
return macro;
QString name = item->text();
return GetMacroByQString(name);
}
void AdvSceneSwitcher::on_macros_currentRowChanged(int idx)
@ -226,13 +224,26 @@ void AdvSceneSwitcher::on_macros_currentRowChanged(int idx)
}
QListWidgetItem *item = ui->macros->item(idx);
QString macroName = item->data(Qt::UserRole).toString();
QString macroName = item->text();
for (auto &m : switcher->macros) {
if (macroName.compare(m.Name().c_str()) == 0) {
SetEditMacro(m);
break;
}
auto macro = GetMacroByQString(macroName);
if (macro) {
SetEditMacro(*macro);
}
}
void AdvSceneSwitcher::on_macros_itemChanged(QListWidgetItem *item)
{
if (loading) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
QString name = item->text();
auto m = GetMacroByQString(name);
if (m) {
m->SetPaused(item->checkState() != Qt::Checked);
}
}
@ -243,6 +254,12 @@ void AdvSceneSwitcher::setupMacroTab()
QListWidgetItem *item = new QListWidgetItem(text, ui->macros);
item->setData(Qt::UserRole, text);
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
if (m.Paused()) {
item->setCheckState(Qt::Unchecked);
} else {
item->setCheckState(Qt::Checked);
}
}
if (switcher->macros.size() == 0) {
@ -286,5 +303,7 @@ void AdvSceneSwitcher::copyMacro()
QString text = QString::fromStdString(name);
QListWidgetItem *item = new QListWidgetItem(text, ui->macros);
item->setData(Qt::UserRole, text);
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Checked);
ui->macros->setCurrentItem(item);
}

View File

@ -20,6 +20,10 @@ Macro::~Macro() {}
bool Macro::CeckMatch()
{
if (_paused) {
vblog(LOG_INFO, "Macro %s is paused", _name.c_str());
return false;
}
_matched = false;
for (auto &c : _conditions) {
bool cond = c->CheckCondition();
@ -80,6 +84,7 @@ bool Macro::PerformAction()
bool Macro::Save(obs_data_t *obj)
{
obs_data_set_string(obj, "name", _name.c_str());
obs_data_set_bool(obj, "pause", _paused);
obs_data_array_t *conditions = obs_data_array_create();
for (auto &c : _conditions) {
@ -145,6 +150,7 @@ void setValidLogic(MacroCondition *c, bool root, std::string name)
bool Macro::Load(obs_data_t *obj)
{
_name = obs_data_get_string(obj, "name");
_paused = obs_data_get_bool(obj, "pause");
bool root = true;
obs_data_array_t *conditions = obs_data_get_array(obj, "conditions");
@ -363,3 +369,19 @@ bool SwitcherData::runMacros()
}
return true;
}
Macro *GetMacroByName(const char *name)
{
for (auto &m : switcher->macros) {
if (m.Name() == name) {
return &m;
}
}
return nullptr;
}
Macro *GetMacroByQString(const QString &name)
{
return GetMacroByName(name.toUtf8().constData());
}