mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-29 04:36:21 -05:00
Compare commits
12 Commits
lind-clean
...
1.32.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03fe7016e4 | ||
|
|
2ea89912a3 | ||
|
|
78d2efa083 | ||
|
|
149fce1c2b | ||
|
|
2dd9120265 | ||
|
|
3a9f315b67 | ||
|
|
6ba01dca39 | ||
|
|
ad1f1effeb | ||
|
|
0a53a8649f | ||
|
|
7ea721f9f1 | ||
|
|
718a899a98 | ||
|
|
4c493451f4 |
@@ -429,7 +429,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="Verstecken"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Umschalten"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Quelle"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Beliebig"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="Auf{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.layout="Auf{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.filter="Filter"
|
||||
AdvSceneSwitcher.action.filter.type.enable="Aktivieren"
|
||||
AdvSceneSwitcher.action.filter.type.disable="Deaktivieren"
|
||||
|
||||
@@ -157,11 +157,15 @@ AdvSceneSwitcher.mqttConnectionTab.removeMultipleConnectionsPopup.text="Are you
|
||||
|
||||
# Macro Tab
|
||||
AdvSceneSwitcher.macroTab.title="Macro"
|
||||
AdvSceneSwitcher.macroTab.macros="Macros"
|
||||
AdvSceneSwitcher.macroTab.priorityWarning="Note: It is recommended to configure macros to be the highest priority functionality.\nThis setting can be changed on the General tab."
|
||||
AdvSceneSwitcher.macroTab.help="Macros allow you to execute a string of actions depending on multiple conditions.\n\nClick on the highlighted plus symbol to add a new Macro."
|
||||
AdvSceneSwitcher.macroTab.macroLastExecutedTooltip="Was last executed %1 seconds ago."
|
||||
AdvSceneSwitcher.macroTab.macroNotYetExecutedTooltip="Was not yet executed."
|
||||
AdvSceneSwitcher.macroTab.editConditionHelp="This section allows you to define macro conditions.\n\nSelect an existing or add a new macro on the left.\nThen click the plus button below to add a new condition."
|
||||
AdvSceneSwitcher.macroTab.editActionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are met.\n\nSelect an existing or add a new macro on the left.\nThen click the plus button below to add a new action."
|
||||
AdvSceneSwitcher.macroTab.editElseActionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are *not* met.\n\nSelect an existing or add a new macro on the left.\nThen click the plus button below to add a new action."
|
||||
AdvSceneSwitcher.macroTab.edit="Edit macro"
|
||||
AdvSceneSwitcher.macroTab.edit.logic="Logic type:"
|
||||
AdvSceneSwitcher.macroTab.edit.condition="Condition type:"
|
||||
AdvSceneSwitcher.macroTab.edit.action="Action type:"
|
||||
@@ -914,7 +918,9 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Toggle"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Source"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Any"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="On{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.layout="On{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.layout.transition="{{updateTransition}}Set transition to{{transitions}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.layout.duration="{{updateDuration}}Set transition duration to{{duration}}seconds"
|
||||
AdvSceneSwitcher.action.filter="Filter"
|
||||
AdvSceneSwitcher.action.filter.type.enable="Enable"
|
||||
AdvSceneSwitcher.action.filter.type.disable="Disable"
|
||||
@@ -1190,6 +1196,8 @@ AdvSceneSwitcher.action.variable.type.swapValues="Swap variable values"
|
||||
AdvSceneSwitcher.action.variable.type.trim="Trim whitespace"
|
||||
AdvSceneSwitcher.action.variable.type.changeCase="Change case"
|
||||
AdvSceneSwitcher.action.variable.type.randomNumber="Generate random number"
|
||||
AdvSceneSwitcher.action.variable.type.randomListValue="Select random value"
|
||||
AdvSceneSwitcher.action.variable.type.allowRepeat="Allow repeat values"
|
||||
AdvSceneSwitcher.action.variable.case.type.lowerCase="lowercase"
|
||||
AdvSceneSwitcher.action.variable.case.type.upperCase="UPPERCASE"
|
||||
AdvSceneSwitcher.action.variable.case.type.capitalized="Capitalized"
|
||||
|
||||
@@ -350,7 +350,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.show="Mostrar"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Ocultar"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Fuente"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Cualquiera"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="En{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.layout="En{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.filter="Filtro"
|
||||
AdvSceneSwitcher.action.filter.type.enable="Habilitar"
|
||||
AdvSceneSwitcher.action.filter.type.disable="Deshabilitar"
|
||||
|
||||
@@ -510,7 +510,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="Masquer"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Basculer"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Source"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="N'importe"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="Sur{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.layout="Sur{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.filter="Filtre"
|
||||
AdvSceneSwitcher.action.filter.type.enable="Activer"
|
||||
AdvSceneSwitcher.action.filter.type.disable="Désactiver"
|
||||
|
||||
@@ -870,7 +870,6 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="非表示"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="切り替え"
|
||||
; AdvSceneSwitcher.action.sceneVisibility.type.source="Source"
|
||||
; AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Any"
|
||||
; AdvSceneSwitcher.action.sceneVisibility.entry="On{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.filter="フィルタ"
|
||||
AdvSceneSwitcher.action.filter.type.enable="有効にする"
|
||||
AdvSceneSwitcher.action.filter.type.disable="無効化"
|
||||
|
||||
@@ -781,7 +781,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="Ocultar"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Alternar"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Fonte"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Qualquer"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="Em{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.layout="Em{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.filter="Filtro"
|
||||
AdvSceneSwitcher.action.filter.type.enable="Habilitar"
|
||||
AdvSceneSwitcher.action.filter.type.disable="Desabilitar"
|
||||
|
||||
@@ -281,7 +281,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.show="Göster"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Gizle"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Kayıt"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Herhangi"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="Açık{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.layout="Açık{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.filter="Filtrele"
|
||||
AdvSceneSwitcher.action.filter.type.enable="Etkin"
|
||||
AdvSceneSwitcher.action.filter.type.disable="Etkisiz"
|
||||
|
||||
@@ -840,7 +840,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="隐藏"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="切换可见性"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="源"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="任何"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.layout="{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.filter="滤镜"
|
||||
AdvSceneSwitcher.action.filter.type.enable="开启"
|
||||
AdvSceneSwitcher.action.filter.type.disable="关闭"
|
||||
|
||||
@@ -68,22 +68,10 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>962</width>
|
||||
<height>1142</height>
|
||||
<height>1160</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="statusBox">
|
||||
<property name="title">
|
||||
@@ -602,8 +590,11 @@
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="wrapper">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>AdvSceneSwitcher.macroTab.macros</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_36">
|
||||
<item>
|
||||
<widget class="QLabel" name="macroPriorityWarning">
|
||||
<property name="text">
|
||||
@@ -686,34 +677,66 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolBar" name="macrosToolbar">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="floatable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<addaction name="macroAdd"/>
|
||||
<addaction name="macroRemove"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="macroUp"/>
|
||||
<addaction name="macroDown"/>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="macroControlLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="macroAdd">
|
||||
<property name="toolTip">
|
||||
<string>AdvSceneSwitcher.macroTab.tooltip.macroAddButton</string>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">addIconSmall</string>
|
||||
</property>
|
||||
<property name="class" stdset="0">
|
||||
<string notr="true">icon-plus</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="macroRemove">
|
||||
<property name="toolTip">
|
||||
<string>AdvSceneSwitcher.macroTab.tooltip.macroRemoveButton</string>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">removeIconSmall</string>
|
||||
</property>
|
||||
<property name="class" stdset="0">
|
||||
<string notr="true">icon-trash</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="macroUp">
|
||||
<property name="toolTip">
|
||||
<string>AdvSceneSwitcher.macroTab.tooltip.macroUpButton</string>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">upArrowIconSmall</string>
|
||||
</property>
|
||||
<property name="class" stdset="0">
|
||||
<string notr="true">icon-up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="macroDown">
|
||||
<property name="toolTip">
|
||||
<string>AdvSceneSwitcher.macroTab.tooltip.macroDownButton</string>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">downArrowIconSmall</string>
|
||||
</property>
|
||||
<property name="class" stdset="0">
|
||||
<string notr="true">icon-down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="macroEditGroup">
|
||||
<property name="title">
|
||||
<string>AdvSceneSwitcher.macroTab.title</string>
|
||||
<string>AdvSceneSwitcher.macroTab.edit</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_38">
|
||||
<item>
|
||||
@@ -4022,78 +4045,6 @@
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="macroAdd">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/res/images/plus.svg</normaloff>:/res/images/plus.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>AdvSceneSwitcher.macroTab.tooltip.macroAddButton</string>
|
||||
</property>
|
||||
<property name="class" stdset="0">
|
||||
<string notr="true">icon-plus</string>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">addIconSmall</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="macroRemove">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/res/images/minus.svg</normaloff>:/res/images/minus.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>AdvSceneSwitcher.macroTab.tooltip.macroRemoveButton</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Del</string>
|
||||
</property>
|
||||
<property name="shortcutContext">
|
||||
<enum>Qt::WidgetWithChildrenShortcut</enum>
|
||||
</property>
|
||||
<property name="iconVisibleInMenu">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="class" stdset="0">
|
||||
<string notr="true">icon-trash</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="macroUp">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/res/images/up.svg</normaloff>:/res/images/up.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MoveUp</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>AdvSceneSwitcher.macroTab.tooltip.macroUpButton</string>
|
||||
</property>
|
||||
<property name="class" stdset="0">
|
||||
<string notr="true">icon-up</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="macroDown">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/res/images/down.svg</normaloff>:/res/images/down.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MoveDown</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>AdvSceneSwitcher.macroTab.tooltip.macroDownButton</string>
|
||||
</property>
|
||||
<property name="class" stdset="0">
|
||||
<string notr="true">icon-down</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
@@ -4159,6 +4110,11 @@
|
||||
<tabstop>priorityUp</tabstop>
|
||||
<tabstop>priorityDown</tabstop>
|
||||
<tabstop>threadPriority</tabstop>
|
||||
<tabstop>macros</tabstop>
|
||||
<tabstop>macroAdd</tabstop>
|
||||
<tabstop>macroRemove</tabstop>
|
||||
<tabstop>macroUp</tabstop>
|
||||
<tabstop>macroDown</tabstop>
|
||||
<tabstop>macroName</tabstop>
|
||||
<tabstop>runMacro</tabstop>
|
||||
<tabstop>runMacroInParallel</tabstop>
|
||||
|
||||
@@ -101,10 +101,10 @@ public:
|
||||
void HighlightMacroSettingsButton(bool enable = true);
|
||||
|
||||
public slots:
|
||||
void on_macroAdd_triggered();
|
||||
void on_macroRemove_triggered();
|
||||
void on_macroUp_triggered() const;
|
||||
void on_macroDown_triggered() const;
|
||||
void on_macroAdd_clicked();
|
||||
void on_macroRemove_clicked();
|
||||
void on_macroUp_clicked() const;
|
||||
void on_macroDown_clicked() const;
|
||||
void on_macroName_editingFinished();
|
||||
void on_runMacroInParallel_stateChanged(int value) const;
|
||||
void on_runMacroOnChange_stateChanged(int value) const;
|
||||
|
||||
@@ -219,6 +219,43 @@ void MacroActionVariable::GenerateRandomNumber(Variable *var)
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionVariable::PickRandomValue(Variable *var)
|
||||
{
|
||||
static std::random_device rd;
|
||||
static std::mt19937 gen(rd());
|
||||
static const uint8_t maxIter = 255;
|
||||
|
||||
if (_randomValues.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_randomValues.size() == 1) {
|
||||
const auto &value = _randomValues.at(0);
|
||||
var->SetValue(value);
|
||||
_lastRandomValue = value;
|
||||
}
|
||||
|
||||
std::uniform_int_distribution<int> dis(0, _randomValues.size() - 1);
|
||||
StringVariable value = _randomValues.at(dis(gen));
|
||||
|
||||
uint8_t iter = 0;
|
||||
for (; !_allowRepeatValues && iter < maxIter &&
|
||||
_lastRandomValue.has_value() &&
|
||||
std::string(value) == _lastRandomValue.value();
|
||||
iter++) {
|
||||
value = _randomValues.at(dis(gen));
|
||||
}
|
||||
|
||||
if (iter == maxIter) {
|
||||
blog(LOG_INFO,
|
||||
"giving up picking non-repeat random value after %d tries",
|
||||
maxIter);
|
||||
}
|
||||
|
||||
var->SetValue(value);
|
||||
_lastRandomValue = value;
|
||||
}
|
||||
|
||||
struct AskForInputParams {
|
||||
AskForInputParams(const QString &prompt_, const QString &placeholder_)
|
||||
: prompt(prompt_),
|
||||
@@ -458,6 +495,9 @@ bool MacroActionVariable::PerformAction()
|
||||
case Action::RANDOM_NUMBER:
|
||||
GenerateRandomNumber(var.get());
|
||||
return true;
|
||||
case Action::RANDOM_LIST_VALUE:
|
||||
PickRandomValue(var.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -498,6 +538,8 @@ bool MacroActionVariable::Save(obs_data_t *obj) const
|
||||
_randomNumberStart.Save(obj, "randomNumberStart");
|
||||
_randomNumberEnd.Save(obj, "randomNumberEnd");
|
||||
obs_data_set_bool(obj, "generateInteger", _generateInteger);
|
||||
_randomValues.Save(obj, "randomValues", "value");
|
||||
obs_data_set_bool(obj, "allowRepeatValues", _allowRepeatValues);
|
||||
_jsonQuery.Save(obj, "jsonQuery");
|
||||
_jsonIndex.Save(obj, "jsonIndex");
|
||||
|
||||
@@ -556,6 +598,8 @@ bool MacroActionVariable::Load(obs_data_t *obj)
|
||||
_randomNumberStart.Load(obj, "randomNumberStart");
|
||||
_randomNumberEnd.Load(obj, "randomNumberEnd");
|
||||
_generateInteger = obs_data_get_bool(obj, "generateInteger");
|
||||
_randomValues.Load(obj, "randomValues", "value");
|
||||
_allowRepeatValues = obs_data_get_bool(obj, "allowRepeatValues");
|
||||
_jsonQuery.Load(obj, "jsonQuery");
|
||||
_jsonIndex.Load(obj, "jsonIndex");
|
||||
|
||||
@@ -724,6 +768,8 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
"AdvSceneSwitcher.action.variable.type.roundToInt"},
|
||||
{MacroActionVariable::Action::RANDOM_NUMBER,
|
||||
"AdvSceneSwitcher.action.variable.type.randomNumber"},
|
||||
{MacroActionVariable::Action::RANDOM_LIST_VALUE,
|
||||
"AdvSceneSwitcher.action.variable.type.randomListValue"},
|
||||
{true, ""}, // Separator
|
||||
|
||||
{MacroActionVariable::Action::USER_INPUT,
|
||||
@@ -836,7 +882,13 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.generateInteger"),
|
||||
this)),
|
||||
_randomLayout(new QVBoxLayout()),
|
||||
_randomNumberLayout(new QVBoxLayout()),
|
||||
_randomValues(new StringListEdit(this)),
|
||||
_allowRepeatValues(new QCheckBox(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.type.allowRepeat"),
|
||||
this)),
|
||||
_randomValueLayout(new QVBoxLayout()),
|
||||
_jsonQuery(new VariableLineEdit(this)),
|
||||
_jsonQueryHelp(new HelpIcon(
|
||||
obs_module_text(
|
||||
@@ -872,6 +924,7 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
_randomNumberStart->setMaximum(9999999999);
|
||||
_randomNumberEnd->setMinimum(-9999999999);
|
||||
_randomNumberEnd->setMaximum(9999999999);
|
||||
_randomValues->SetMaxStringSize(99999999);
|
||||
_jsonIndex->setMaximum(999);
|
||||
|
||||
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
||||
@@ -960,6 +1013,11 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
SLOT(RandomNumberEndChanged(const NumberVariable<double> &)));
|
||||
QWidget::connect(_generateInteger, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(GenerateIntegerChanged(int)));
|
||||
QWidget::connect(_randomValues,
|
||||
SIGNAL(StringListChanged(const StringList &)), this,
|
||||
SLOT(RandomValueListChanged(const StringList &)));
|
||||
QWidget::connect(_allowRepeatValues, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(AllowRepeatValuesChanged(int)));
|
||||
QWidget::connect(_jsonQuery, SIGNAL(editingFinished()), this,
|
||||
SLOT(JsonQueryChanged()));
|
||||
QWidget::connect(
|
||||
@@ -1026,8 +1084,11 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.layout.randomNumber"),
|
||||
randomLayout, widgetPlaceholders);
|
||||
_randomLayout->addLayout(randomLayout);
|
||||
_randomLayout->addWidget(_generateInteger);
|
||||
_randomNumberLayout->addLayout(randomLayout);
|
||||
_randomNumberLayout->addWidget(_generateInteger);
|
||||
|
||||
_randomValueLayout->addWidget(_randomValues);
|
||||
_randomValueLayout->addWidget(_allowRepeatValues);
|
||||
|
||||
auto regexConfigLayout = new QHBoxLayout;
|
||||
regexConfigLayout->addWidget(_subStringRegex);
|
||||
@@ -1046,7 +1107,8 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
layout->addWidget(_mathExpressionResult);
|
||||
layout->addLayout(_promptLayout);
|
||||
layout->addLayout(_placeholderLayout);
|
||||
layout->addLayout(_randomLayout);
|
||||
layout->addLayout(_randomNumberLayout);
|
||||
layout->addLayout(_randomValueLayout);
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -1105,6 +1167,8 @@ void MacroActionVariableEdit::UpdateEntryData()
|
||||
_randomNumberStart->SetValue(_entryData->_randomNumberStart);
|
||||
_randomNumberEnd->SetValue(_entryData->_randomNumberEnd);
|
||||
_generateInteger->setChecked(_entryData->_generateInteger);
|
||||
_allowRepeatValues->setChecked(_entryData->_allowRepeatValues);
|
||||
_randomValues->SetStringList(_entryData->_randomValues);
|
||||
_jsonQuery->setText(_entryData->_jsonQuery);
|
||||
_jsonIndex->SetValue(_entryData->_jsonIndex);
|
||||
|
||||
@@ -1447,6 +1511,18 @@ void MacroActionVariableEdit::GenerateIntegerChanged(int value)
|
||||
_entryData->_generateInteger = value;
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::RandomValueListChanged(const StringList &values)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_randomValues = values;
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::AllowRepeatValuesChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_allowRepeatValues = value;
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::JsonQueryChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
@@ -1641,9 +1717,13 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
||||
MacroActionVariable::Action::PAD);
|
||||
_caseType->setVisible(_entryData->_action ==
|
||||
MacroActionVariable::Action::CHANGE_CASE);
|
||||
SetLayoutVisible(_randomLayout,
|
||||
SetLayoutVisible(_randomNumberLayout,
|
||||
_entryData->_action ==
|
||||
MacroActionVariable::Action::RANDOM_NUMBER);
|
||||
SetLayoutVisible(
|
||||
_randomValueLayout,
|
||||
_entryData->_action ==
|
||||
MacroActionVariable::Action::RANDOM_LIST_VALUE);
|
||||
_jsonQuery->setVisible(_entryData->_action ==
|
||||
MacroActionVariable::Action::QUERY_JSON);
|
||||
_jsonQueryHelp->setVisible(_entryData->_action ==
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "resizing-text-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
#include "single-char-selection.hpp"
|
||||
#include "string-list.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
#include "variable-text-edit.hpp"
|
||||
#include "variable-spinbox.hpp"
|
||||
@@ -56,6 +57,7 @@ public:
|
||||
QUERY_JSON,
|
||||
ARRAY_JSON,
|
||||
COPY_VAR,
|
||||
RANDOM_LIST_VALUE,
|
||||
};
|
||||
|
||||
Action _action = Action::SET_VALUE;
|
||||
@@ -107,6 +109,10 @@ public:
|
||||
DoubleVariable _randomNumberEnd = 100;
|
||||
bool _generateInteger = true;
|
||||
|
||||
StringList _randomValues = {"value1", "value2", "value3"};
|
||||
bool _allowRepeatValues = true;
|
||||
std::optional<std::string> _lastRandomValue;
|
||||
|
||||
StringVariable _jsonQuery = "$.some.nested.value";
|
||||
IntVariable _jsonIndex = 0;
|
||||
|
||||
@@ -119,6 +125,7 @@ private:
|
||||
void HandleCaseChange(Variable *);
|
||||
void SetToSceneItemName(Variable *);
|
||||
void GenerateRandomNumber(Variable *);
|
||||
void PickRandomValue(Variable *);
|
||||
|
||||
std::weak_ptr<MacroSegment> _macroSegment;
|
||||
int _segmentIdxLoadValue = -1;
|
||||
@@ -175,6 +182,8 @@ private slots:
|
||||
void RandomNumberStartChanged(const NumberVariable<double> &);
|
||||
void RandomNumberEndChanged(const NumberVariable<double> &);
|
||||
void GenerateIntegerChanged(int);
|
||||
void RandomValueListChanged(const StringList &);
|
||||
void AllowRepeatValuesChanged(int);
|
||||
void JsonQueryChanged();
|
||||
void JsonIndexChanged(const NumberVariable<int> &);
|
||||
|
||||
@@ -224,7 +233,10 @@ private:
|
||||
VariableDoubleSpinBox *_randomNumberStart;
|
||||
VariableDoubleSpinBox *_randomNumberEnd;
|
||||
QCheckBox *_generateInteger;
|
||||
QVBoxLayout *_randomLayout;
|
||||
QVBoxLayout *_randomNumberLayout;
|
||||
StringListEdit *_randomValues;
|
||||
QCheckBox *_allowRepeatValues;
|
||||
QVBoxLayout *_randomValueLayout;
|
||||
VariableLineEdit *_jsonQuery;
|
||||
QLabel *_jsonQueryHelp;
|
||||
VariableSpinBox *_jsonIndex;
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace advss {
|
||||
|
||||
static QObject *addPulse = nullptr;
|
||||
static QTimer onChangeHighlightTimer;
|
||||
static std::chrono::high_resolution_clock::time_point
|
||||
lastOnChangeHighlightCheckTime{};
|
||||
|
||||
static void disableAddButtonHighlight()
|
||||
{
|
||||
@@ -97,7 +99,7 @@ bool AdvSceneSwitcher::AddNewMacro(std::shared_ptr<Macro> &res,
|
||||
return true;
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_macroAdd_triggered()
|
||||
void AdvSceneSwitcher::on_macroAdd_clicked()
|
||||
{
|
||||
// Hotkey to add new macro will also use this function.
|
||||
// Since we don't want the hotkey to have an effect if the macro tab is
|
||||
@@ -247,12 +249,12 @@ void AdvSceneSwitcher::RenameMacro(std::shared_ptr<Macro> ¯o,
|
||||
MacroSignalManager::Instance()->Rename(oldName, name);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_macroRemove_triggered()
|
||||
void AdvSceneSwitcher::on_macroRemove_clicked()
|
||||
{
|
||||
RemoveSelectedMacros();
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_macroUp_triggered() const
|
||||
void AdvSceneSwitcher::on_macroUp_clicked() const
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
@@ -261,7 +263,7 @@ void AdvSceneSwitcher::on_macroUp_triggered() const
|
||||
ui->macros->Up(macro);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_macroDown_triggered() const
|
||||
void AdvSceneSwitcher::on_macroDown_clicked() const
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
@@ -550,10 +552,14 @@ void AdvSceneSwitcher::HighlightOnChange() const
|
||||
return;
|
||||
}
|
||||
|
||||
if (macro->OnChangePreventedActionsRecently()) {
|
||||
if (macro->OnChangePreventedActionsSince(
|
||||
lastOnChangeHighlightCheckTime)) {
|
||||
HighlightWidget(ui->runMacroOnChange, Qt::yellow,
|
||||
Qt::transparent, true);
|
||||
}
|
||||
|
||||
lastOnChangeHighlightCheckTime =
|
||||
std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_macroSettings_clicked()
|
||||
@@ -632,11 +638,13 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||
auto ¯os = GetTopLevelMacros();
|
||||
|
||||
if (macros.size() == 0 && !switcher->disableHints) {
|
||||
addPulse = HighlightWidget(
|
||||
ui->macrosToolbar->widgetForAction(ui->macroAdd),
|
||||
QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->macroAdd, QColor(Qt::green));
|
||||
}
|
||||
|
||||
auto macroControls = setupToolBar({{ui->macroAdd, ui->macroRemove},
|
||||
{ui->macroUp, ui->macroDown}});
|
||||
ui->macroControlLayout->addWidget(macroControls);
|
||||
|
||||
ui->macros->Reset(macros, GetGlobalMacroSettings()._highlightExecuted);
|
||||
connect(ui->macros, SIGNAL(MacroSelectionChanged()), this,
|
||||
SLOT(MacroSelectionChanged()));
|
||||
@@ -650,6 +658,8 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||
ui->macroPriorityWarning->setVisible(
|
||||
switcher->functionNamesByPriority[0] != macro_func);
|
||||
|
||||
lastOnChangeHighlightCheckTime =
|
||||
std::chrono::high_resolution_clock::now();
|
||||
onChangeHighlightTimer.setInterval(1500);
|
||||
connect(&onChangeHighlightTimer, SIGNAL(timeout()), this,
|
||||
SLOT(HighlightOnChange()));
|
||||
@@ -681,7 +691,7 @@ void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
|
||||
|
||||
menu.addAction(
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.contextMenuAdd"),
|
||||
this, &AdvSceneSwitcher::on_macroAdd_triggered);
|
||||
this, &AdvSceneSwitcher::on_macroAdd_clicked);
|
||||
|
||||
auto copy = menu.addAction(
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.copy"), this,
|
||||
@@ -697,7 +707,7 @@ void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
|
||||
|
||||
auto remove = menu.addAction(
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.remove"), this,
|
||||
&AdvSceneSwitcher::on_macroRemove_triggered);
|
||||
&AdvSceneSwitcher::on_macroRemove_clicked);
|
||||
remove->setDisabled(ui->macros->SelectionEmpty());
|
||||
menu.addSeparator();
|
||||
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
#include "path-helpers.hpp"
|
||||
#include "sync-helpers.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <obs.h>
|
||||
#include <string>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QSpacerItem>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMouseEvent>
|
||||
#include <QStylePainter>
|
||||
#include <QToolTip>
|
||||
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<advss::Macro>);
|
||||
|
||||
@@ -90,6 +89,35 @@ MacroTreeItem::MacroTreeItem(MacroTree *tree, std::shared_ptr<Macro> macroItem,
|
||||
_timer.start(1500);
|
||||
}
|
||||
|
||||
bool MacroTreeItem::event(QEvent *event)
|
||||
{
|
||||
if (event->type() != QEvent::ToolTip) {
|
||||
return QFrame::event(event);
|
||||
}
|
||||
|
||||
if (_macro->IsGroup()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QString text;
|
||||
if (!_macro->WasExecutedSince({})) {
|
||||
text = obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.macroNotYetExecutedTooltip");
|
||||
} else {
|
||||
const QString formatStr = obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.macroLastExecutedTooltip");
|
||||
const auto secondsSinceLastRun =
|
||||
std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::high_resolution_clock::now() -
|
||||
_macro->GetLastExecutionTime());
|
||||
text = formatStr.arg(secondsSinceLastRun.count());
|
||||
}
|
||||
|
||||
auto helpEvent = static_cast<QHelpEvent *>(event);
|
||||
QToolTip::showText(helpEvent->globalPos(), text, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroTreeItem::EnableHighlight(bool enable)
|
||||
{
|
||||
_highlight = enable;
|
||||
@@ -187,10 +215,19 @@ void MacroTreeItem::HighlightIfExecuted()
|
||||
return;
|
||||
}
|
||||
|
||||
bool wasHighlighted = false;
|
||||
if (_lastHighlightCheckTime.time_since_epoch().count() != 0 &&
|
||||
_macro->WasExecutedSince(_lastHighlightCheckTime)) {
|
||||
HighlightWidget(this, Qt::green, QColor(0, 0, 0, 0), true);
|
||||
wasHighlighted = true;
|
||||
}
|
||||
|
||||
if (!wasHighlighted &&
|
||||
_lastHighlightCheckTime.time_since_epoch().count() != 0 &&
|
||||
_macro->OnChangePreventedActionsSince(_lastHighlightCheckTime)) {
|
||||
HighlightWidget(this, Qt::yellow, QColor(0, 0, 0, 0), true);
|
||||
}
|
||||
|
||||
_lastHighlightCheckTime = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
@@ -267,7 +304,7 @@ void MacroTreeItem::Update(bool force)
|
||||
_expand->blockSignals(true);
|
||||
_expand->setChecked(_macro->IsCollapsed());
|
||||
_expand->blockSignals(false);
|
||||
connect(_expand, &QPushButton::toggled, this,
|
||||
connect(_expand, &QCheckBox::toggled, this,
|
||||
&MacroTreeItem::ExpandClicked);
|
||||
} else {
|
||||
_spacer = new QSpacerItem(3, 1);
|
||||
|
||||
@@ -34,6 +34,9 @@ public:
|
||||
explicit MacroTreeItem(MacroTree *tree, std::shared_ptr<Macro> macro,
|
||||
bool highlight);
|
||||
|
||||
protected:
|
||||
bool event(QEvent *) override;
|
||||
|
||||
private slots:
|
||||
void ExpandClicked(bool checked);
|
||||
void EnableHighlight(bool enable);
|
||||
|
||||
@@ -242,8 +242,12 @@ bool Macro::CheckConditions(bool ignorePause)
|
||||
vblog(LOG_INFO, "Macro %s returned %d", _name.c_str(), _matched);
|
||||
|
||||
_conditionSateChanged = _lastMatched != _matched;
|
||||
if (!_conditionSateChanged && _performActionsOnChange) {
|
||||
_onPreventedActionExecution = true;
|
||||
const bool hasActionsToExecute = _matched ? (_actions.size() > 0)
|
||||
: (_elseActions.size() > 0);
|
||||
if (!_conditionSateChanged && _performActionsOnChange &&
|
||||
hasActionsToExecute) {
|
||||
_lastOnChangeActionsPreventedTime =
|
||||
std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
_lastMatched = _matched;
|
||||
@@ -302,6 +306,16 @@ bool Macro::WasExecutedSince(const TimePoint &time) const
|
||||
return _lastExecutionTime > time;
|
||||
}
|
||||
|
||||
bool Macro::OnChangePreventedActionsSince(const TimePoint &time) const
|
||||
{
|
||||
return _lastOnChangeActionsPreventedTime > time;
|
||||
}
|
||||
|
||||
Macro::TimePoint Macro::GetLastExecutionTime() const
|
||||
{
|
||||
return _lastExecutionTime;
|
||||
}
|
||||
|
||||
bool Macro::ConditionsShouldBeChecked() const
|
||||
{
|
||||
if (!_useCustomConditionCheckInterval) {
|
||||
@@ -986,18 +1000,8 @@ bool Macro::HasValidSplitterPositions() const
|
||||
!_elseActionSplitterPosition.empty();
|
||||
}
|
||||
|
||||
bool Macro::OnChangePreventedActionsRecently()
|
||||
{
|
||||
if (_onPreventedActionExecution) {
|
||||
_onPreventedActionExecution = false;
|
||||
return _matched ? _actions.size() > 0 : _elseActions.size() > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Macro::ResetUIHelpers()
|
||||
{
|
||||
_onPreventedActionExecution = false;
|
||||
for (auto c : _conditions) {
|
||||
c->GetHighlightAndReset();
|
||||
}
|
||||
|
||||
@@ -137,7 +137,8 @@ public:
|
||||
const QList<int> &GetElseActionSplitterPosition() const;
|
||||
bool HasValidSplitterPositions() const;
|
||||
bool WasExecutedSince(const TimePoint &) const;
|
||||
bool OnChangePreventedActionsRecently();
|
||||
bool OnChangePreventedActionsSince(const TimePoint &) const;
|
||||
TimePoint GetLastExecutionTime() const;
|
||||
void ResetUIHelpers();
|
||||
|
||||
// Hotkeys
|
||||
@@ -168,6 +169,7 @@ private:
|
||||
TimePoint _lastCheckTime{};
|
||||
TimePoint _lastUnpauseTime{};
|
||||
TimePoint _lastExecutionTime{};
|
||||
TimePoint _lastOnChangeActionsPreventedTime{};
|
||||
std::vector<std::thread> _helperThreads;
|
||||
|
||||
std::deque<std::shared_ptr<MacroCondition>> _conditions;
|
||||
@@ -204,9 +206,6 @@ private:
|
||||
|
||||
MacroInputVariables _inputVariables;
|
||||
|
||||
// UI helpers
|
||||
bool _onPreventedActionExecution = false;
|
||||
|
||||
QList<int> _actionConditionSplitterPosition;
|
||||
QList<int> _elseActionSplitterPosition;
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "auto-update-tooltip-label.hpp"
|
||||
|
||||
#include <QToolTip>
|
||||
|
||||
namespace advss {
|
||||
|
||||
AutoUpdateHelpIcon::AutoUpdateHelpIcon(
|
||||
@@ -16,6 +18,7 @@ AutoUpdateHelpIcon::AutoUpdateHelpIcon(
|
||||
|
||||
void AutoUpdateHelpIcon::enterEvent(QEnterEvent *event)
|
||||
{
|
||||
UpdateTooltip();
|
||||
_timer->start(_updateIntervalMs);
|
||||
QLabel::enterEvent(event);
|
||||
}
|
||||
@@ -28,7 +31,12 @@ void AutoUpdateHelpIcon::leaveEvent(QEvent *event)
|
||||
|
||||
void AutoUpdateHelpIcon::UpdateTooltip()
|
||||
{
|
||||
setToolTip(_callback());
|
||||
if (!underMouse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QString text = _callback();
|
||||
QToolTip::showText(QCursor::pos(), text, this);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -57,7 +57,6 @@ ResourceTable::ResourceTable(QWidget *parent, const QString &help,
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->addLayout(helpAndTableLayout);
|
||||
layout->addLayout(controlLayout);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(layout);
|
||||
|
||||
QWidget::connect(_add, SIGNAL(clicked()), this, SLOT(Add()));
|
||||
|
||||
@@ -58,6 +58,9 @@ StringListEdit::StringListEdit(
|
||||
_filterCallback(filter),
|
||||
_preprocessCallback(preprocess)
|
||||
{
|
||||
if (_addString.isEmpty()) {
|
||||
_addString = obs_module_text("AdvSceneSwitcher.windowTitle");
|
||||
}
|
||||
}
|
||||
|
||||
void StringListEdit::SetStringList(const StringList &list)
|
||||
|
||||
@@ -10,6 +10,8 @@ namespace advss {
|
||||
|
||||
class StringList : public QList<StringVariable> {
|
||||
public:
|
||||
using QList<StringVariable>::QList;
|
||||
|
||||
EXPORT bool Save(obs_data_t *obj, const char *name,
|
||||
const char *elementName = "string") const;
|
||||
EXPORT bool Load(obs_data_t *obj, const char *name,
|
||||
|
||||
@@ -166,6 +166,8 @@ target_sources(
|
||||
utils/scene-item-selection.hpp
|
||||
utils/scene-item-transform-helpers.cpp
|
||||
utils/scene-item-transform-helpers.hpp
|
||||
utils/transition-helpers.cpp
|
||||
utils/transition-helpers.hpp
|
||||
utils/source-properties-button.cpp
|
||||
utils/source-properties-button.hpp
|
||||
utils/source-settings-helpers.cpp
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "plugin-state-helpers.hpp"
|
||||
#include "scene-switch-helpers.hpp"
|
||||
#include "source-helpers.hpp"
|
||||
#include "transition-helpers.hpp"
|
||||
|
||||
#include <obs-frontend-api.h>
|
||||
|
||||
@@ -68,14 +69,6 @@ static int getTransitionOverrideDuration(OBSWeakSource &scene)
|
||||
return duration;
|
||||
}
|
||||
|
||||
static bool isUsingFixedLengthTransition(const OBSWeakSource &transition)
|
||||
{
|
||||
obs_source_t *source = obs_weak_source_get_source(transition);
|
||||
bool ret = obs_transition_fixed(source);
|
||||
obs_source_release(source);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static OBSWeakSource getOverrideTransition(OBSWeakSource &scene)
|
||||
{
|
||||
OBSWeakSource transition;
|
||||
@@ -101,13 +94,13 @@ static int getExpectedTransitionDuration(OBSWeakSource &scene,
|
||||
auto overrideTransition = getOverrideTransition(scene);
|
||||
if (overrideTransition) {
|
||||
transition = overrideTransition;
|
||||
if (!isUsingFixedLengthTransition(transition)) {
|
||||
if (!IsFixedLengthTransition(transition)) {
|
||||
return getTransitionOverrideDuration(scene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isUsingFixedLengthTransition(transition)) {
|
||||
if (IsFixedLengthTransition(transition)) {
|
||||
return -1; // no API is available to access the fixed duration
|
||||
}
|
||||
if (duration != 0) {
|
||||
@@ -503,7 +496,7 @@ shouldShowDurationInTransitionLayout(MacroActionSwitchScene::SceneType type,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isUsingFixedLengthTransition(transition.GetTransition())) {
|
||||
if (IsFixedLengthTransition(transition.GetTransition())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "macro-action-scene-visibility.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "transition-helpers.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
@@ -21,9 +22,74 @@ const static std::map<MacroActionSceneVisibility::Action, std::string>
|
||||
"AdvSceneSwitcher.action.sceneVisibility.type.toggle"},
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
struct TransitionRestoreContext {
|
||||
obs_sceneitem_t *item;
|
||||
bool wasVisible;
|
||||
|
||||
bool restoreTransition;
|
||||
OBSSource originalTransition;
|
||||
bool restoreDuration;
|
||||
uint32_t originalDuration;
|
||||
|
||||
signal_handler_t *sh = nullptr;
|
||||
|
||||
~TransitionRestoreContext()
|
||||
{
|
||||
if (!sh) {
|
||||
return;
|
||||
}
|
||||
|
||||
signal_handler_disconnect(
|
||||
sh, "transition_stop",
|
||||
&TransitionRestoreContext::ResetSceneItemTransition,
|
||||
this);
|
||||
}
|
||||
|
||||
static void ResetSceneItemTransition(void *param, calldata_t *)
|
||||
{
|
||||
auto *ctx = static_cast<TransitionRestoreContext *>(param);
|
||||
SetSceneItemTransition(ctx->item, ctx->originalTransition,
|
||||
!ctx->wasVisible);
|
||||
|
||||
obs_sceneitem_set_transition_duration(
|
||||
ctx->item, !ctx->wasVisible, ctx->originalDuration);
|
||||
delete ctx;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
static void setSceneItemVisibility(obs_sceneitem_t *item,
|
||||
const bool setTransition,
|
||||
const OBSWeakSource &transitionWeak,
|
||||
const bool setDuration,
|
||||
const Duration &duration,
|
||||
MacroActionSceneVisibility::Action action)
|
||||
{
|
||||
const OBSSourceAutoRelease transition = OBSGetStrongRef(transitionWeak);
|
||||
const bool itemIsVisible = obs_sceneitem_visible(item);
|
||||
|
||||
const OBSSource currentTransition =
|
||||
obs_sceneitem_get_transition(item, !itemIsVisible);
|
||||
const uint32_t currentTransitionDuration =
|
||||
obs_sceneitem_get_transition_duration(item, !itemIsVisible);
|
||||
|
||||
obs_source_t *privateTransitionSource = nullptr;
|
||||
if (setTransition) {
|
||||
privateTransitionSource = SetSceneItemTransition(
|
||||
item, transition, !itemIsVisible);
|
||||
} else {
|
||||
privateTransitionSource =
|
||||
obs_sceneitem_get_transition(item, !itemIsVisible);
|
||||
}
|
||||
|
||||
if (setDuration) {
|
||||
obs_sceneitem_set_transition_duration(item, !itemIsVisible,
|
||||
duration.Milliseconds());
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case MacroActionSceneVisibility::Action::SHOW:
|
||||
obs_sceneitem_set_visible(item, true);
|
||||
@@ -32,16 +98,48 @@ static void setSceneItemVisibility(obs_sceneitem_t *item,
|
||||
obs_sceneitem_set_visible(item, false);
|
||||
break;
|
||||
case MacroActionSceneVisibility::Action::TOGGLE:
|
||||
obs_sceneitem_set_visible(item, !obs_sceneitem_visible(item));
|
||||
obs_sceneitem_set_visible(item, !itemIsVisible);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!privateTransitionSource) {
|
||||
if (setTransition) {
|
||||
SetSceneItemTransition(item, currentTransition,
|
||||
!itemIsVisible);
|
||||
}
|
||||
if (setDuration) {
|
||||
obs_sceneitem_set_transition_duration(
|
||||
item, !itemIsVisible,
|
||||
currentTransitionDuration);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto sh = obs_source_get_signal_handler(privateTransitionSource);
|
||||
if (!sh) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto ctx = new TransitionRestoreContext{item,
|
||||
itemIsVisible,
|
||||
setTransition,
|
||||
currentTransition,
|
||||
setDuration,
|
||||
currentTransitionDuration,
|
||||
sh};
|
||||
|
||||
signal_handler_connect(
|
||||
sh, "transition_stop",
|
||||
&TransitionRestoreContext::ResetSceneItemTransition, ctx);
|
||||
}
|
||||
|
||||
bool MacroActionSceneVisibility::PerformAction()
|
||||
{
|
||||
auto items = _source.GetSceneItems(_scene);
|
||||
for (const auto &item : items) {
|
||||
setSceneItemVisibility(item, _action);
|
||||
setSceneItemVisibility(item, _updateTransition,
|
||||
_transition.GetTransition(),
|
||||
_updateDuration, _duration, _action);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -66,6 +164,10 @@ bool MacroActionSceneVisibility::Save(obs_data_t *obj) const
|
||||
MacroAction::Save(obj);
|
||||
_scene.Save(obj);
|
||||
_source.Save(obj);
|
||||
obs_data_set_bool(obj, "updateTransition", _updateTransition);
|
||||
_transition.Save(obj);
|
||||
obs_data_set_bool(obj, "updateDuration", _updateDuration);
|
||||
_duration.Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
return true;
|
||||
}
|
||||
@@ -82,6 +184,10 @@ bool MacroActionSceneVisibility::Load(obs_data_t *obj)
|
||||
MacroAction::Load(obj);
|
||||
_scene.Load(obj);
|
||||
_source.Load(obj);
|
||||
_updateTransition = obs_data_get_bool(obj, "updateTransition");
|
||||
_transition.Load(obj);
|
||||
_updateDuration = obs_data_get_bool(obj, "updateDuration");
|
||||
_duration.Load(obj);
|
||||
_action = static_cast<MacroActionSceneVisibility::Action>(
|
||||
obs_data_get_int(obj, "action"));
|
||||
|
||||
@@ -141,10 +247,17 @@ MacroActionSceneVisibilityEdit::MacroActionSceneVisibilityEdit(
|
||||
SceneItemSelection::Type::ALL,
|
||||
},
|
||||
SceneItemSelectionWidget::NameClashMode::ALL)),
|
||||
_updateTransition(new QCheckBox(this)),
|
||||
_transitions(new TransitionSelectionWidget(this, false, false)),
|
||||
_updateDuration(new QCheckBox(this)),
|
||||
_duration(new DurationSelection(this, false)),
|
||||
_durationLayout(new QHBoxLayout),
|
||||
_actions(new QComboBox())
|
||||
{
|
||||
populateActionSelection(_actions);
|
||||
|
||||
_duration->SpinBox()->setSpecialValueText("-");
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
@@ -154,18 +267,49 @@ MacroActionSceneVisibilityEdit::MacroActionSceneVisibilityEdit(
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SceneItemChanged(const SceneItemSelection &)),
|
||||
this, SLOT(SourceChanged(const SceneItemSelection &)));
|
||||
QWidget::connect(_updateTransition, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(UpdateTransitionChanged(int)));
|
||||
QWidget::connect(_transitions,
|
||||
SIGNAL(TransitionChanged(const TransitionSelection &)),
|
||||
this,
|
||||
SLOT(TransitionChanged(const TransitionSelection &)));
|
||||
QWidget::connect(_updateDuration, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(UpdateDurationChanged(int)));
|
||||
QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)),
|
||||
this, SLOT(DurationChanged(const Duration &)));
|
||||
|
||||
auto layout = new QHBoxLayout;
|
||||
auto sceneItemLayout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.action.sceneVisibility.entry"),
|
||||
layout,
|
||||
"AdvSceneSwitcher.action.sceneVisibility.layout"),
|
||||
sceneItemLayout,
|
||||
{{"{{scenes}}", _scenes},
|
||||
{"{{sources}}", _sources},
|
||||
{"{{actions}}", _actions}});
|
||||
|
||||
auto transitionLayout = new QHBoxLayout;
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.sceneVisibility.layout.transition"),
|
||||
transitionLayout,
|
||||
{{"{{updateTransition}}", _updateTransition},
|
||||
{"{{transitions}}", _transitions}});
|
||||
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.sceneVisibility.layout.duration"),
|
||||
_durationLayout,
|
||||
{{"{{updateDuration}}", _updateDuration},
|
||||
{"{{duration}}", _duration}});
|
||||
|
||||
auto layout = new QVBoxLayout;
|
||||
layout->addLayout(sceneItemLayout);
|
||||
layout->addLayout(transitionLayout);
|
||||
layout->addLayout(_durationLayout);
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
SetWidgetVisibility();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
@@ -177,7 +321,11 @@ void MacroActionSceneVisibilityEdit::UpdateEntryData()
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_sources->SetSceneItem((_entryData->_source));
|
||||
_sources->SetSceneItem(_entryData->_source);
|
||||
_updateTransition->setChecked(_entryData->_updateTransition);
|
||||
_transitions->SetTransition(_entryData->_transition);
|
||||
_updateDuration->setChecked(_entryData->_updateDuration);
|
||||
_duration->SetDuration(_entryData->_duration);
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
|
||||
@@ -197,6 +345,34 @@ void MacroActionSceneVisibilityEdit::SourceChanged(
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::UpdateTransitionChanged(int state)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_updateTransition = state;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::TransitionChanged(
|
||||
const TransitionSelection &t)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_transition = t;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::UpdateDurationChanged(int state)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_updateDuration = state;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::DurationChanged(const Duration &dur)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_duration = dur;
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::ActionChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
@@ -204,4 +380,20 @@ void MacroActionSceneVisibilityEdit::ActionChanged(int value)
|
||||
static_cast<MacroActionSceneVisibility::Action>(value);
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::SetWidgetVisibility()
|
||||
{
|
||||
const bool hideDurationSelection =
|
||||
_entryData->_updateTransition &&
|
||||
IsFixedLengthTransition(
|
||||
_entryData->_transition.GetTransition());
|
||||
|
||||
SetLayoutVisible(_durationLayout, !hideDurationSelection);
|
||||
|
||||
_transitions->setEnabled(_entryData->_updateTransition);
|
||||
_duration->setEnabled(_entryData->_updateDuration);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
#include "duration-control.hpp"
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
#include "scene-item-selection.hpp"
|
||||
#include "transition-selection.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
@@ -20,6 +22,10 @@ public:
|
||||
|
||||
SceneSelection _scene;
|
||||
SceneItemSelection _source;
|
||||
bool _updateTransition = false;
|
||||
TransitionSelection _transition;
|
||||
bool _updateDuration = false;
|
||||
Duration _duration;
|
||||
|
||||
enum class Action {
|
||||
SHOW,
|
||||
@@ -53,17 +59,27 @@ public:
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const SceneItemSelection &);
|
||||
void UpdateTransitionChanged(int);
|
||||
void TransitionChanged(const TransitionSelection &);
|
||||
void UpdateDurationChanged(int);
|
||||
void DurationChanged(const Duration &seconds);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
SceneSelectionWidget *_scenes;
|
||||
SceneItemSelectionWidget *_sources;
|
||||
QCheckBox *_updateTransition;
|
||||
TransitionSelectionWidget *_transitions;
|
||||
QCheckBox *_updateDuration;
|
||||
DurationSelection *_duration;
|
||||
QHBoxLayout *_durationLayout;
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionSceneVisibility> _entryData;
|
||||
|
||||
private:
|
||||
std::shared_ptr<MacroActionSceneVisibility> _entryData;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "macro-action-transition.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "transition-helpers.hpp"
|
||||
|
||||
#include <obs-frontend-api.h>
|
||||
|
||||
@@ -75,26 +76,6 @@ static void obs_sceneitem_set_transition_duration(obs_sceneitem_t *item,
|
||||
}
|
||||
#endif
|
||||
|
||||
static void setSceneItemTransition(const OBSSceneItem &item,
|
||||
const OBSSourceAutoRelease &transition,
|
||||
bool show)
|
||||
{
|
||||
OBSDataAutoRelease settings = obs_source_get_settings(transition);
|
||||
if (!transition || !settings) {
|
||||
// Set transition to "None"
|
||||
obs_sceneitem_set_transition(item, show, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
// We cannot share the transition source between
|
||||
// scene items without introducing strange graphical
|
||||
// artifacts so we have to create new ones here
|
||||
OBSSourceAutoRelease transitionSource = obs_source_create_private(
|
||||
obs_source_get_id(transition), obs_source_get_name(transition),
|
||||
settings);
|
||||
obs_sceneitem_set_transition(item, show, transitionSource);
|
||||
}
|
||||
|
||||
void MacroActionTransition::SetSourceTransition(bool show)
|
||||
{
|
||||
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(27, 0, 0)
|
||||
@@ -103,7 +84,7 @@ void MacroActionTransition::SetSourceTransition(bool show)
|
||||
const auto items = _source.GetSceneItems(_scene);
|
||||
for (const auto &item : items) {
|
||||
if (_setTransitionType) {
|
||||
setSceneItemTransition(item, transition, show);
|
||||
SetSceneItemTransition(item, transition, show);
|
||||
}
|
||||
if (_setDuration) {
|
||||
obs_sceneitem_set_transition_duration(
|
||||
|
||||
@@ -55,17 +55,17 @@ void MacroConditionGameCapture::GetCalldataInfo(calldata_t *cd)
|
||||
if (!calldata_get_string(cd, "title", &title)) {
|
||||
blog(LOG_WARNING, "%s failed to get title", __func__);
|
||||
}
|
||||
_title = title;
|
||||
_title = title ? title : "";
|
||||
const char *className = "";
|
||||
if (!calldata_get_string(cd, "class", &className)) {
|
||||
blog(LOG_WARNING, "%s failed to get class", __func__);
|
||||
}
|
||||
_class = className;
|
||||
_class = className ? className : "";
|
||||
const char *executable = "";
|
||||
if (!calldata_get_string(cd, "executable", &executable)) {
|
||||
blog(LOG_WARNING, "%s failed to get executable", __func__);
|
||||
}
|
||||
_executable = executable;
|
||||
_executable = executable ? executable : "";
|
||||
}
|
||||
|
||||
void MacroConditionGameCapture::HookedSignalReceived(void *data, calldata_t *cd)
|
||||
|
||||
@@ -335,6 +335,12 @@ void SetSourceSetting(obs_source_t *source, const SourceSetting &setting,
|
||||
case OBS_DATA_OBJECT: {
|
||||
OBSDataAutoRelease json =
|
||||
obs_data_create_from_json(value.c_str());
|
||||
if (!json) {
|
||||
blog(LOG_WARNING,
|
||||
"not setting invalid data object settings value! (%s)",
|
||||
value.c_str());
|
||||
break;
|
||||
}
|
||||
obs_data_set_obj(data, id.c_str(), json);
|
||||
break;
|
||||
}
|
||||
|
||||
32
plugins/base/utils/transition-helpers.cpp
Normal file
32
plugins/base/utils/transition-helpers.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "transition-helpers.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
bool IsFixedLengthTransition(const OBSWeakSource &transition)
|
||||
{
|
||||
OBSSourceAutoRelease source = obs_weak_source_get_source(transition);
|
||||
return obs_transition_fixed(source);
|
||||
}
|
||||
|
||||
obs_source_t *SetSceneItemTransition(const OBSSceneItem &item,
|
||||
const OBSSourceAutoRelease &transition,
|
||||
bool show)
|
||||
{
|
||||
OBSDataAutoRelease settings = obs_source_get_settings(transition);
|
||||
if (!transition || !settings) {
|
||||
// Set transition to "None"
|
||||
obs_sceneitem_set_transition(item, show, nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We cannot share the transition source between
|
||||
// scene items without introducing strange graphical
|
||||
// artifacts so we have to create new ones here
|
||||
OBSSourceAutoRelease transitionSource = obs_source_create_private(
|
||||
obs_source_get_id(transition), obs_source_get_name(transition),
|
||||
settings);
|
||||
obs_sceneitem_set_transition(item, show, transitionSource);
|
||||
return transitionSource.Get();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
11
plugins/base/utils/transition-helpers.hpp
Normal file
11
plugins/base/utils/transition-helpers.hpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include <obs.hpp>
|
||||
|
||||
namespace advss {
|
||||
|
||||
bool IsFixedLengthTransition(const OBSWeakSource &transition);
|
||||
obs_source_t *SetSceneItemTransition(const OBSSceneItem &item,
|
||||
const OBSSourceAutoRelease &transition,
|
||||
bool show);
|
||||
|
||||
} // namespace advss
|
||||
@@ -70,7 +70,7 @@ struct URLInfo {
|
||||
std::string path;
|
||||
};
|
||||
|
||||
static URLInfo getURLInfo(const std::string &input)
|
||||
static URLInfo getURLInfo(const std::string &input, bool keepParams)
|
||||
{
|
||||
if (input.empty()) {
|
||||
return {};
|
||||
@@ -84,21 +84,35 @@ static URLInfo getURLInfo(const std::string &input)
|
||||
const QUrl url(urlInput);
|
||||
auto host =
|
||||
url.scheme().toStdString() + "://" + url.host().toStdString();
|
||||
int port = url.port();
|
||||
|
||||
const int port = url.port();
|
||||
if (port != -1) {
|
||||
host += ":" + std::to_string(port);
|
||||
}
|
||||
|
||||
auto path = url.path().toStdString();
|
||||
if (path.empty()) {
|
||||
path = "/";
|
||||
}
|
||||
|
||||
const auto query = url.query().toStdString();
|
||||
if (!query.empty()) {
|
||||
if (keepParams) {
|
||||
path += "?" + query;
|
||||
} else {
|
||||
blog(LOG_WARNING,
|
||||
"ignoring query parameters \"%s\" in URL field. "
|
||||
"Using parameter field values instead.",
|
||||
query.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return {host, path};
|
||||
}
|
||||
|
||||
bool MacroActionHttp::PerformAction()
|
||||
{
|
||||
const auto [host, path] = getURLInfo(_url);
|
||||
const auto [host, path] = getURLInfo(_url, !_setParams);
|
||||
|
||||
httplib::Client cli(host);
|
||||
setTimeout(cli, _timeout);
|
||||
|
||||
@@ -89,12 +89,24 @@ void EventSub::ConnectThread()
|
||||
|
||||
void EventSub::WaitAndReconnect()
|
||||
{
|
||||
if (_reconnecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
_reconnecting = true;
|
||||
|
||||
auto thread = std::thread([this]() {
|
||||
std::unique_lock<std::mutex> lock(_waitMtx);
|
||||
blog(LOG_INFO,
|
||||
"Twitch EventSub trying to reconnect to in %d seconds.",
|
||||
reconnectDelay);
|
||||
_cv.wait_for(lock, std::chrono::seconds(reconnectDelay));
|
||||
_reconnecting = false;
|
||||
|
||||
if (_disconnect) {
|
||||
return;
|
||||
}
|
||||
|
||||
Connect();
|
||||
});
|
||||
thread.detach();
|
||||
@@ -102,6 +114,10 @@ void EventSub::WaitAndReconnect()
|
||||
|
||||
void EventSub::Connect()
|
||||
{
|
||||
if (_reconnecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(_connectMtx);
|
||||
if (_connected) {
|
||||
vblog(LOG_INFO, "Twitch EventSub connect already in progress");
|
||||
@@ -465,8 +481,8 @@ void EventSub::StartServerMigrationClient(const std::string &url)
|
||||
const auto &data = msg->payload;
|
||||
|
||||
if (type == "session_welcome") {
|
||||
vblog(LOG_INFO,
|
||||
"Twitch EventSub migration successful - switching to new connection");
|
||||
blog(LOG_INFO,
|
||||
"Twitch EventSub migration successful - switching to new connection");
|
||||
OBSDataAutoRelease session =
|
||||
obs_data_get_obj(data, "session");
|
||||
_migrationSessionID =
|
||||
@@ -565,7 +581,7 @@ void EventSub::OnClose(connection_hdl hdl)
|
||||
blog(LOG_INFO, "Twitch EventSub connection closed: %s / %s (%d)",
|
||||
msg.c_str(), reason.c_str(), code);
|
||||
|
||||
if (_migrating) {
|
||||
if (!_migrating) {
|
||||
ClearActiveSubscriptions();
|
||||
}
|
||||
_connected = false;
|
||||
|
||||
@@ -110,6 +110,7 @@ private:
|
||||
std::condition_variable _cv;
|
||||
std::atomic_bool _connected{false};
|
||||
std::atomic_bool _disconnect{false};
|
||||
std::atomic_bool _reconnecting{false};
|
||||
|
||||
std::string _url;
|
||||
std::string _sessionID;
|
||||
|
||||
Reference in New Issue
Block a user