Add scene groups and rework save and load (#103)

This commit is contained in:
WarmUpTill 2021-01-23 17:39:35 +01:00 committed by GitHub
parent 1f4679433e
commit d989c2b570
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 2182 additions and 636 deletions

View File

@ -52,6 +52,7 @@ set(advanced-scene-switcher_HEADERS
src/headers/utility.hpp
src/headers/curl-helper.hpp
src/headers/volume-control.hpp
src/headers/scene-group.hpp
src/headers/switch-audio.hpp
src/headers/switch-executable.hpp
src/headers/switch-file.hpp
@ -73,6 +74,7 @@ set(advanced-scene-switcher_SOURCES
src/advanced-scene-switcher.cpp
src/advanced-scene-switcher-module.c
src/switcher-data-structs.cpp
src/scene-group.cpp
src/switch-transitions.cpp
src/switch-screen-region.cpp
src/switch-priority.cpp

View File

@ -190,6 +190,23 @@ AdvSceneSwitcher.audioTab.entry="Wenn die Lautstärke von {{audioSources}} {{con
AdvSceneSwitcher.audioTab.multiMatchfallbackCondition="Wenn mehrere Einträge zutreffen ..."
AdvSceneSwitcher.audioTab.multiMatchfallback="... für {{duration}} wechsle zu {{scenes}} mit {{transitions}}"
; Scene Group Tab
AdvSceneSwitcher.sceneGroupTab.title="Szenengruppe"
AdvSceneSwitcher.sceneGroupTab.list="Szenengruppen"
AdvSceneSwitcher.sceneGroupTab.edit="Szenengruppe bearbeiten"
AdvSceneSwitcher.sceneGroupTab.edit.name="Name:"
AdvSceneSwitcher.sceneGroupTab.edit.type="Typ: {{type}}"
AdvSceneSwitcher.sceneGroupTab.type.count="Anzahl"
AdvSceneSwitcher.sceneGroupTab.type.time="Zeit"
AdvSceneSwitcher.sceneGroupTab.type.random="Zufall"
AdvSceneSwitcher.sceneGroupTab.edit.count="Schreite zur nächsten Szene in dieser Gruppe fort nach {{count}} Szenewechseln"
AdvSceneSwitcher.sceneGroupTab.edit.time="Schreite zur nächsten Szene in dieser Gruppe fort nach {{time}}"
AdvSceneSwitcher.sceneGroupTab.edit.random="Wähle eine zufällig Szene in der Liste aus"
AdvSceneSwitcher.sceneGroupTab.edit.repeat="Beginne von vorne wenn Ende der Szenenliste erreicht ist"
AdvSceneSwitcher.sceneGroupTab.add="Szenengruppe hinzufügen"
AdvSceneSwitcher.sceneGroupTab.defaultname="Szenengruppe %1"
AdvSceneSwitcher.sceneGroupTab.exists="Szenengruppen- oder Szenenname existiert bereits"
; Hotkey
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Starte den Erweiteren Szenenwechsler"
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Stoppe den Erweiteren Szenenwechsler"

View File

@ -190,6 +190,23 @@ AdvSceneSwitcher.audioTab.entry="When the volume of {{audioSources}} is {{condit
AdvSceneSwitcher.audioTab.multiMatchfallbackCondition="If multiple entries match ..."
AdvSceneSwitcher.audioTab.multiMatchfallback="... for {{duration}} switch to {{scenes}} using {{transitions}}"
; Scene Group Tab
AdvSceneSwitcher.sceneGroupTab.title="Scene Group"
AdvSceneSwitcher.sceneGroupTab.list="Scene Groups"
AdvSceneSwitcher.sceneGroupTab.edit="Edit Scene Groups"
AdvSceneSwitcher.sceneGroupTab.edit.name="Name:"
AdvSceneSwitcher.sceneGroupTab.edit.type="Type: {{type}}"
AdvSceneSwitcher.sceneGroupTab.type.count="Count"
AdvSceneSwitcher.sceneGroupTab.type.time="Time"
AdvSceneSwitcher.sceneGroupTab.type.random="Random"
AdvSceneSwitcher.sceneGroupTab.edit.count="Advance to next scene in list after {{count}} matches"
AdvSceneSwitcher.sceneGroupTab.edit.time="Advance to next scene in list after {{time}} has passed"
AdvSceneSwitcher.sceneGroupTab.edit.random="Choose next scene in list at random"
AdvSceneSwitcher.sceneGroupTab.edit.repeat="Start from beginning if end of scene list is reached"
AdvSceneSwitcher.sceneGroupTab.add="Add Scene Group"
AdvSceneSwitcher.sceneGroupTab.defaultname="Scene Group %1"
AdvSceneSwitcher.sceneGroupTab.exists="Scene Group or Scene name exists already"
; Hotkey
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Start the Advanced Scene Switcher"
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Stop the Advanced Scene Switcher"

View File

@ -378,7 +378,7 @@
<widget class="QComboBox" name="autoStopType"/>
</item>
<item>
<widget class="QLabel" name="label_3">
<widget class="QLabel" name="label_6">
<property name="text">
<string>AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStop2</string>
</property>
@ -3046,6 +3046,355 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="sceneGroupTab">
<attribute name="title">
<string>AdvSceneSwitcher.sceneGroupTab.title</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>AdvSceneSwitcher.sceneGroupTab.list</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_24">
<item>
<widget class="QListWidget" name="sceneGroups"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_54">
<item>
<widget class="QPushButton" name="sceneGroupAdd">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">addIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="sceneGroupRemove">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">removeIconSmall</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_117">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="Line" name="line_39">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_116">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="sceneGroupUp">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>../../../forms/images/up.svg</normaloff>../../../forms/images/up.svg</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string>upArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="sceneGroupDown">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>../../../forms/images/down.svg</normaloff>../../../forms/images/down.svg</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string>downArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_58">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="sceneGroupEdit">
<property name="title">
<string>AdvSceneSwitcher.sceneGroupTab.edit</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_25">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>AdvSceneSwitcher.sceneGroupTab.edit.name</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="sceneGroupName"/>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="sceneGroupTypeEdit"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QComboBox" name="sceneGroupSceneSelection"/>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="sceneGroupScenes"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_55">
<item>
<widget class="QPushButton" name="sceneGroupSceneAdd">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">addIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="sceneGroupSceneRemove">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">removeIconSmall</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_119">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="Line" name="line_40">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_118">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="sceneGroupSceneUp">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>../../../forms/images/up.svg</normaloff>../../../forms/images/up.svg</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string>upArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="sceneGroupSceneDown">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>../../../forms/images/down.svg</normaloff>../../../forms/images/down.svg</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string>downArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_59">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>

View File

@ -59,6 +59,7 @@ void AdvSceneSwitcher::loadUI()
setupFileTab();
setupTimeTab();
setupAudioTab();
setupSceneGroupTab();
setTabOrder();
@ -109,8 +110,11 @@ void addSelectionEntry(QComboBox *sel, const char *description,
}
void AdvSceneSwitcher::populateSceneSelection(QComboBox *sel, bool addPrevious,
bool addSceneGroup,
bool addSelect)
{
sel->clear();
if (addSelect)
addSelectionEntry(
sel, obs_module_text("AdvSceneSwitcher.selectScene"),
@ -128,6 +132,12 @@ void AdvSceneSwitcher::populateSceneSelection(QComboBox *sel, bool addPrevious,
if (addPrevious)
sel->addItem(obs_module_text(
"AdvSceneSwitcher.selectPreviousScene"));
if (addSceneGroup) {
for (auto &sg : switcher->sceneGroups) {
sel->addItem(QString::fromStdString(sg.name));
}
}
}
void AdvSceneSwitcher::populateTransitionSelection(QComboBox *sel,
@ -347,6 +357,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
obs_data_t *obj = obs_data_create();
switcher->saveSceneGroups(obj);
switcher->saveWindowTitleSwitches(obj);
switcher->saveScreenRegionSwitches(obj);
switcher->savePauseSwitches(obj);
@ -377,6 +388,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
if (switcher->versionChanged(obj, g_GIT_SHA1))
AdvSceneSwitcher::AskBackup(obj);
switcher->loadSceneGroups(obj);
switcher->loadWindowTitleSwitches(obj);
switcher->loadScreenRegionSwitches(obj);
switcher->loadPauseSwitches(obj);
@ -546,6 +558,11 @@ endLoop:
void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
bool &transitionOverrideOverride)
{
if (!scene && switcher->verbose) {
blog(LOG_INFO, "nothing to switch to");
return;
}
obs_source_t *source = obs_weak_source_get_source(scene);
obs_source_t *currentSource = obs_frontend_get_current_scene();

View File

@ -3,6 +3,8 @@
#include "headers/advanced-scene-switcher.hpp"
#include "headers/utility.hpp"
constexpr auto tab_count = 14;
QMetaObject::Connection inactivePluse;
void AdvSceneSwitcher::on_close_clicked()
@ -468,6 +470,9 @@ int findTabIndex(QTabWidget *tabWidget, int pos)
case 12:
tabName = "audioTab";
break;
case 13:
tabName = "sceneGroupTab";
break;
}
QWidget *page = tabWidget->findChild<QWidget *>(tabName);
@ -567,8 +572,8 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
// After fresh install of OBS the vector can be empty
// as save() might be called before first load()
if (switcher->tabOrder.size() < 13) {
switcher->tabOrder = std::vector<int>(13);
if (switcher->tabOrder.size() < tab_count) {
switcher->tabOrder = std::vector<int>(tab_count);
std::iota(switcher->tabOrder.begin(), switcher->tabOrder.end(),
0);
}
@ -586,6 +591,7 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
obs_data_set_int(obj, "idleTabPos", switcher->tabOrder[10]);
obs_data_set_int(obj, "sequenceTabPos", switcher->tabOrder[11]);
obs_data_set_int(obj, "audioTabPos", switcher->tabOrder[12]);
obs_data_set_int(obj, "sceneGroupTabPos", switcher->tabOrder[13]);
}
void SwitcherData::loadGeneralSettings(obs_data_t *obj)
@ -686,6 +692,7 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
obs_data_set_default_int(obj, "idleTabPos", 10);
obs_data_set_default_int(obj, "sequenceTabPos", 11);
obs_data_set_default_int(obj, "audioTabPos", 12);
obs_data_set_default_int(obj, "sceneGroupTabPos", 13);
switcher->tabOrder.emplace_back(
(int)(obs_data_get_int(obj, "generalTabPos")));
@ -713,6 +720,8 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
(int)(obs_data_get_int(obj, "sequenceTabPos")));
switcher->tabOrder.emplace_back(
(int)(obs_data_get_int(obj, "audioTabPos")));
switcher->tabOrder.emplace_back(
(int)(obs_data_get_int(obj, "sceneGroupTabPos")));
}
void SwitcherData::checkNoMatchSwitch(bool &match, OBSWeakSource &scene,

View File

@ -39,6 +39,7 @@ public:
void UpdateAutoStartScene(const QString &name);
void UpdateIdleDataTransition(const QString &name);
void UpdateIdleDataScene(const QString &name);
void SetEditSceneGroup(SceneGroup &sg);
void loadUI();
void setupGeneralTab();
@ -54,13 +55,17 @@ public:
void setupFileTab();
void setupTimeTab();
void setupAudioTab();
void setupSceneGroupTab();
void setTabOrder();
static bool DisplayMessage(QString msg, bool question = false);
static void AskBackup(obs_data_t *obj);
static void populateSceneSelection(QComboBox *sel,
bool addPrevious = false,
bool addSceneGroup = false,
bool addSelect = true);
static void populateTransitionSelection(QComboBox *sel,
bool addSelect = true);
static void populateWindowSelection(QComboBox *sel,
@ -81,6 +86,11 @@ public:
bool listMoveUp(QListWidget *list);
bool listMoveDown(QListWidget *list);
signals:
void SceneGroupAdded(const QString &name);
void SceneGroupRemoved(const QString &name);
void SceneGroupRenamed(const QString &oldName, const QString newName);
public slots:
void on_windowUp_clicked();
void on_windowDown_clicked();
@ -189,6 +199,18 @@ public slots:
void on_audioDown_clicked();
void on_audioFallback_toggled(bool on);
void on_sceneGroupAdd_clicked();
void on_sceneGroupRemove_clicked();
void on_sceneGroupUp_clicked();
void on_sceneGroupDown_clicked();
void on_sceneGroupName_editingFinished();
void on_sceneGroups_currentRowChanged(int idx);
void on_sceneGroupSceneAdd_clicked();
void on_sceneGroupSceneRemove_clicked();
void on_sceneGroupSceneUp_clicked();
void on_sceneGroupSceneDown_clicked();
void on_priorityUp_clicked();
void on_priorityDown_clicked();
void on_threadPriority_currentTextChanged(const QString &text);

107
src/headers/scene-group.hpp Normal file
View File

@ -0,0 +1,107 @@
#pragma once
#include <vector>
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QComboBox>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QCheckBox>
#include <obs.hpp>
auto constexpr invalid_scene_group_name = "invalid-scene-group";
enum class AdvanceCondition {
Count,
Time,
Random,
};
struct SceneGroup {
OBSWeakSource getNextScene();
OBSWeakSource getNextSceneCount();
OBSWeakSource getNextSceneTime();
OBSWeakSource getNextSceneRandom();
void advanceIdx();
std::string name = invalid_scene_group_name;
AdvanceCondition type = AdvanceCondition::Count;
std::vector<OBSWeakSource> scenes = {};
int count = 1;
double time = 0;
bool repeat = false;
size_t currentIdx = 0;
int currentCount = -1;
std::chrono::high_resolution_clock::time_point lastAdvTime;
OBSWeakSource lastRandomScene = nullptr;
inline SceneGroup(){};
inline SceneGroup(std::string name_) : name(name_){};
inline SceneGroup(std::string name_, AdvanceCondition type_,
std::vector<OBSWeakSource> scenes_, int count_,
double time_, bool repeat_)
: name(name_),
type(type_),
scenes(scenes_),
count(count_),
time(time_),
repeat(repeat_)
{
}
};
enum class SwitchTargetType {
Scene,
SceneGroup,
};
class SceneGroupEditWidget : public QWidget {
Q_OBJECT
public:
SceneGroupEditWidget();
void SetEditSceneGroup(SceneGroup *sg);
void ShowCurrentTypeEdit();
private slots:
void TypeChanged(int type);
void CountChanged(int count);
void TimeChanged(double time);
void RepeatChanged(int state);
private:
QComboBox *type;
QWidget *timeEdit;
QWidget *countEdit;
QSpinBox *count;
QDoubleSpinBox *time;
QLabel *random;
QCheckBox *repeat;
SceneGroup *sceneGroup = nullptr;
};
// Based on OBS's NameDialog
class SGNameDialog : public QDialog {
Q_OBJECT
public:
SGNameDialog(QWidget *parent);
// Returns true if user clicks OK, false otherwise
// userTextInput returns string that user typed into dialog
static bool AskForName(QWidget *parent, const QString &title,
const QString &text, std::string &userTextInput,
const QString &placeHolder = QString(""),
int maxSize = 170);
private:
QLabel *label;
QLineEdit *userText;
};

View File

@ -25,6 +25,8 @@ struct AudioSwitch : virtual SceneSwitcherEntry {
const char *getType() { return "audio"; }
bool initialized();
bool valid();
void save(obs_data_t *obj);
void load(obs_data_t *obj);
static void setVolumeLevel(void *data,
const float magnitude[MAX_AUDIO_CHANNELS],
const float peak[MAX_AUDIO_CHANNELS],
@ -32,10 +34,6 @@ struct AudioSwitch : virtual SceneSwitcherEntry {
void resetVolmeter();
AudioSwitch(){};
AudioSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
OBSWeakSource audioSource_, int volumeThreshold_,
audioCondition condition_, double duration_,
bool usePreviousScene_);
AudioSwitch(const AudioSwitch &other);
AudioSwitch(AudioSwitch &&other);
~AudioSwitch();
@ -46,6 +44,9 @@ struct AudioSwitch : virtual SceneSwitcherEntry {
struct AudioSwitchFallback : virtual SceneSwitcherEntry {
const char *getType() { return "audio_fallback"; }
void save(obs_data_t *obj);
void load(obs_data_t *obj);
bool enable = false;
double duration = 0;
unsigned int matchCount = 0;
@ -55,7 +56,7 @@ class AudioSwitchWidget : public SwitchWidget {
Q_OBJECT
public:
AudioSwitchWidget(AudioSwitch *s);
AudioSwitchWidget(QWidget *parent, AudioSwitch *s);
void UpdateVolmeterSource();
AudioSwitch *getSwitchData();
void setSwitchData(AudioSwitch *s);
@ -83,7 +84,7 @@ class AudioSwitchFallbackWidget : public SwitchWidget {
Q_OBJECT
public:
AudioSwitchFallbackWidget(AudioSwitchFallback *s);
AudioSwitchFallbackWidget(QWidget *parent, AudioSwitchFallback *s);
private slots:
void DurationChanged(double dur);

View File

@ -11,22 +11,15 @@ struct ExecutableSwitch : SceneSwitcherEntry {
bool inFocus = false;
const char *getType() { return "exec"; }
inline ExecutableSwitch(){};
inline ExecutableSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
const QString &exe_, bool inFocus_)
: SceneSwitcherEntry(scene_, transition_),
exe(exe_),
inFocus(inFocus_)
{
}
void save(obs_data_t *obj);
void load(obs_data_t *obj);
};
class ExecutableSwitchWidget : public SwitchWidget {
Q_OBJECT
public:
ExecutableSwitchWidget(ExecutableSwitch *s);
ExecutableSwitchWidget(QWidget *parent, ExecutableSwitch *s);
ExecutableSwitch *getSwitchData();
void setSwitchData(ExecutableSwitch *s);

View File

@ -23,29 +23,15 @@ struct FileSwitch : SceneSwitcherEntry {
size_t lastHash = 0;
const char *getType() { return "file"; }
inline FileSwitch(){};
inline FileSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
const char *file_, const char *text_, bool remote_,
bool useRegex_, bool useTime_,
bool onlyMatchIfChanged_)
: SceneSwitcherEntry(scene_, transition_),
file(file_),
text(text_),
remote(remote_),
useRegex(useRegex_),
useTime(useTime_),
onlyMatchIfChanged(onlyMatchIfChanged_),
lastMod()
{
}
void save(obs_data_t *obj);
void load(obs_data_t *obj);
};
class FileSwitchWidget : public SwitchWidget {
Q_OBJECT
public:
FileSwitchWidget(FileSwitch *s);
FileSwitchWidget(QWidget *parent, FileSwitch *s);
FileSwitch *getSwitchData();
void setSwitchData(FileSwitch *s);

View File

@ -3,6 +3,8 @@
#include <QComboBox>
struct SceneSwitcherEntry {
SwitchTargetType targetType = SwitchTargetType::Scene;
SceneGroup *group = nullptr;
OBSWeakSource scene = nullptr;
OBSWeakSource transition = nullptr;
bool usePreviousScene = false;
@ -10,7 +12,18 @@ struct SceneSwitcherEntry {
virtual const char *getType() = 0;
virtual bool initialized();
virtual bool valid();
virtual void logMatchScene();
virtual void logMatchSceneGroup();
virtual void logMatch();
virtual OBSWeakSource getScene();
virtual void save(obs_data_t *obj,
const char *targetTypeSaveName = "targetType",
const char *targetSaveName = "target",
const char *transitionSaveName = "transition");
virtual void load(obs_data_t *obj,
const char *targetTypeLoadName = "targetType",
const char *targetLoadName = "target",
const char *transitionLoadName = "transition");
inline SceneSwitcherEntry() {}
@ -23,6 +36,26 @@ struct SceneSwitcherEntry {
{
}
inline SceneSwitcherEntry(SceneGroup *group_, OBSWeakSource transition_,
bool usePreviousScene_ = false)
: group(group_),
transition(transition_),
usePreviousScene(usePreviousScene_)
{
}
inline SceneSwitcherEntry(SwitchTargetType targetType_,
SceneGroup *group_, OBSWeakSource scene_,
OBSWeakSource transition_,
bool usePreviousScene_ = false)
: targetType(targetType_),
group(group_),
scene(scene_),
transition(transition_),
usePreviousScene(usePreviousScene_)
{
}
virtual ~SceneSwitcherEntry() {}
};
@ -30,7 +63,8 @@ class SwitchWidget : public QWidget {
Q_OBJECT
public:
SwitchWidget(SceneSwitcherEntry *s, bool usePreviousScene = true);
SwitchWidget(QWidget *parent, SceneSwitcherEntry *s,
bool usePreviousScene = true, bool addSceneGroup = false);
virtual SceneSwitcherEntry *getSwitchData();
virtual void setSwitchData(SceneSwitcherEntry *s);
@ -39,6 +73,9 @@ public:
private slots:
void SceneChanged(const QString &text);
void TransitionChanged(const QString &text);
void SceneGroupAdd(const QString &name);
void SceneGroupRemove(const QString &name);
void SceneGroupRename(const QString &oldName, const QString &newName);
protected:
bool loading = true;

View File

@ -12,4 +12,6 @@ struct IdleData : SceneSwitcherEntry {
bool alreadySwitched = false;
const char *getType() { return "idle"; }
void save(obs_data_t *obj);
void load(obs_data_t *obj);
};

View File

@ -34,6 +34,8 @@ struct MediaSwitch : SceneSwitcherEntry {
const char *getType() { return "media"; }
bool initialized();
bool valid();
void save(obs_data_t *obj);
void load(obs_data_t *obj);
void clearSignalHandler();
void resetSignalHandler();
@ -41,10 +43,7 @@ struct MediaSwitch : SceneSwitcherEntry {
static void MediaEnded(void *data, calldata_t *);
inline MediaSwitch(){};
inline MediaSwitch(OBSWeakSource scene_, OBSWeakSource source_,
OBSWeakSource transition_, obs_media_state state_,
time_restriction restriction_, uint64_t time_,
bool usePreviousScene_);
MediaSwitch(const MediaSwitch &other);
MediaSwitch(MediaSwitch &&other);
~MediaSwitch();
@ -57,7 +56,7 @@ class MediaSwitchWidget : public SwitchWidget {
Q_OBJECT
public:
MediaSwitchWidget(MediaSwitch *s);
MediaSwitchWidget(QWidget *parent, MediaSwitch *s);
MediaSwitch *getSwitchData();
void setSwitchData(MediaSwitch *s);

View File

@ -44,7 +44,7 @@ class PauseEntryWidget : public SwitchWidget {
Q_OBJECT
public:
PauseEntryWidget(PauseEntry *s);
PauseEntryWidget(QWidget *parent, PauseEntry *s);
PauseEntry *getSwitchData();
void setSwitchData(PauseEntry *s);

View File

@ -6,20 +6,15 @@ struct RandomSwitch : SceneSwitcherEntry {
double delay = 0.0;
const char *getType() { return "random"; }
inline RandomSwitch() {}
inline RandomSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
double delay_)
: SceneSwitcherEntry(scene_, transition_), delay(delay_)
{
}
void save(obs_data_t *obj);
void load(obs_data_t *obj);
};
class RandomSwitchWidget : public SwitchWidget {
Q_OBJECT
public:
RandomSwitchWidget(RandomSwitch *s);
RandomSwitchWidget(QWidget *parent, RandomSwitch *s);
RandomSwitch *getSwitchData();
void setSwitchData(RandomSwitch *s);

View File

@ -10,25 +10,15 @@ struct ScreenRegionSwitch : SceneSwitcherEntry {
int minX = 0, minY = 0, maxX = 0, maxY = 0;
const char *getType() { return "region"; }
inline ScreenRegionSwitch(){};
inline ScreenRegionSwitch(OBSWeakSource scene_,
OBSWeakSource transition_, int minX_,
int minY_, int maxX_, int maxY_)
: SceneSwitcherEntry(scene_, transition_),
minX(minX_),
minY(minY_),
maxX(maxX_),
maxY(maxY_)
{
}
void save(obs_data_t *obj);
void load(obs_data_t *obj);
};
class ScreenRegionWidget : public SwitchWidget {
Q_OBJECT
public:
ScreenRegionWidget(ScreenRegionSwitch *s);
ScreenRegionWidget(QWidget *parent, ScreenRegionSwitch *s);
ScreenRegionSwitch *getSwitchData();
void setSwitchData(ScreenRegionSwitch *s);

View File

@ -22,27 +22,15 @@ struct SceneSequenceSwitch : SceneSwitcherEntry {
bool initialized();
bool valid();
void logSleep(int dur);
inline SceneSequenceSwitch(){};
inline SceneSequenceSwitch(OBSWeakSource startScene_,
OBSWeakSource scene_,
OBSWeakSource transition_, double delay_,
int delayMultiplier_, bool interruptible_,
bool usePreviousScene_)
: SceneSwitcherEntry(scene_, transition_, usePreviousScene_),
startScene(startScene_),
delay(delay_),
delayMultiplier(delayMultiplier_),
interruptible(interruptible_)
{
}
void save(obs_data_t *obj);
void load(obs_data_t *obj);
};
class SequenceWidget : public SwitchWidget {
Q_OBJECT
public:
SequenceWidget(SceneSequenceSwitch *s);
SequenceWidget(QWidget *parent, SceneSequenceSwitch *s);
SceneSequenceSwitch *getSwitchData();
void setSwitchData(SceneSequenceSwitch *s);

View File

@ -24,23 +24,15 @@ struct TimeSwitch : SceneSwitcherEntry {
QTime time = QTime(0, 0);
const char *getType() { return "time"; }
inline TimeSwitch(){};
inline TimeSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
timeTrigger trigger_, QTime time_,
bool usePreviousScene_)
: SceneSwitcherEntry(scene_, transition_, usePreviousScene_),
trigger(trigger_),
time(time_)
{
}
void save(obs_data_t *obj);
void load(obs_data_t *obj);
};
class TimeSwitchWidget : public SwitchWidget {
Q_OBJECT
public:
TimeSwitchWidget(TimeSwitch *s);
TimeSwitchWidget(QWidget *parent, TimeSwitch *s);
TimeSwitch *getSwitchData();
void setSwitchData(TimeSwitch *s);

View File

@ -33,7 +33,7 @@ class TransitionSwitchWidget : public SwitchWidget {
Q_OBJECT
public:
TransitionSwitchWidget(SceneTransition *s);
TransitionSwitchWidget(QWidget *parent, SceneTransition *s);
SceneTransition *getSwitchData();
void setSwitchData(SceneTransition *s);
@ -53,7 +53,7 @@ class DefTransitionSwitchWidget : public SwitchWidget {
Q_OBJECT
public:
DefTransitionSwitchWidget(DefaultSceneTransition *s);
DefTransitionSwitchWidget(QWidget *parent, DefaultSceneTransition *s);
DefaultSceneTransition *getSwitchData();
void setSwitchData(DefaultSceneTransition *s);

View File

@ -12,25 +12,15 @@ struct WindowSwitch : SceneSwitcherEntry {
bool focus = true;
const char *getType() { return "window"; }
inline WindowSwitch() {}
inline WindowSwitch(OBSWeakSource scene_, const char *window_,
OBSWeakSource transition_, bool fullscreen_,
bool maximized_, bool focus_)
: SceneSwitcherEntry(scene_, transition_),
window(window_),
fullscreen(fullscreen_),
maximized(maximized_),
focus(focus_)
{
}
void save(obs_data_t *obj);
void load(obs_data_t *obj);
};
class WindowSwitchWidget : public SwitchWidget {
Q_OBJECT
public:
WindowSwitchWidget(WindowSwitch *s);
WindowSwitchWidget(QWidget *parent, WindowSwitch *s);
WindowSwitch *getSwitchData();
void setSwitchData(WindowSwitch *s);

View File

@ -7,6 +7,7 @@
#include <QThread>
#include <curl/curl.h>
#include "scene-group.hpp"
#include "switch-audio.hpp"
#include "switch-executable.hpp"
#include "switch-file.hpp"
@ -114,6 +115,8 @@ struct SwitcherData {
std::deque<AudioSwitch> audioSwitches;
AudioSwitchFallback audioFallback;
std::deque<SceneGroup> sceneGroups;
std::vector<int> functionNamesByPriority = std::vector<int>{
default_priority_0, default_priority_1, default_priority_2,
default_priority_3, default_priority_4, default_priority_5,
@ -210,6 +213,7 @@ struct SwitcherData {
void saveMediaSwitches(obs_data_t *obj);
void saveTimeSwitches(obs_data_t *obj);
void saveAudioSwitches(obs_data_t *obj);
void saveSceneGroups(obs_data_t *obj);
void saveGeneralSettings(obs_data_t *obj);
void saveHotkeys(obs_data_t *obj);
void saveVersion(obs_data_t *obj, std::string currentVersion);
@ -227,6 +231,7 @@ struct SwitcherData {
void loadMediaSwitches(obs_data_t *obj);
void loadTimeSwitches(obs_data_t *obj);
void loadAudioSwitches(obs_data_t *obj);
void loadSceneGroups(obs_data_t *obj);
void loadGeneralSettings(obs_data_t *obj);
void loadHotkeys(obs_data_t *obj);

View File

@ -9,6 +9,13 @@
#include <obs-module.h>
#include <obs-frontend-api.h>
static inline bool SceneGroupValid(SceneGroup *group)
{
if (group)
return group->name != invalid_scene_group_name;
return false;
}
static inline bool WeakSourceValid(obs_weak_source_t *ws)
{
obs_source_t *source = obs_weak_source_get_source(ws);
@ -30,6 +37,25 @@ static inline std::string GetWeakSourceName(obs_weak_source_t *weak_source)
return name;
}
static inline SceneGroup *GetSceneGroupByName(const char *name)
{
if (!switcher)
return nullptr;
for (SceneGroup &sg : switcher->sceneGroups) {
if (sg.name == name) {
return &sg;
}
}
return nullptr;
}
static inline SceneGroup *GetSceneGroupByQString(const QString &name)
{
return GetSceneGroupByName(name.toUtf8().constData());
}
static inline OBSWeakSource GetWeakSourceByName(const char *name)
{
OBSWeakSource weak;

697
src/scene-group.cpp Normal file
View File

@ -0,0 +1,697 @@
#include <QVBoxLayout>
#include <QDialogButtonBox>
#include <random>
#include "headers/advanced-scene-switcher.hpp"
#include "headers/utility.hpp"
static QMetaObject::Connection addPulse;
SceneGroupEditWidget *typeEdit = nullptr;
void SceneGroup::advanceIdx()
{
currentIdx++;
if (currentIdx >= scenes.size()) {
if (repeat)
currentIdx = 0;
else
currentIdx = scenes.size() - 1;
}
}
OBSWeakSource SceneGroup::getNextSceneCount()
{
currentCount++;
if (currentCount >= count) {
advanceIdx();
currentCount = 0;
}
return scenes[currentIdx];
}
OBSWeakSource SceneGroup::getNextSceneTime()
{
if (lastAdvTime.time_since_epoch().count() == 0)
lastAdvTime = std::chrono::high_resolution_clock::now();
auto now = std::chrono::high_resolution_clock::now();
auto passedTime = std::chrono::duration_cast<std::chrono::milliseconds>(
now - lastAdvTime);
if (passedTime.count() >= time * 1000) {
advanceIdx();
lastAdvTime = now;
}
return scenes[currentIdx];
}
OBSWeakSource SceneGroup::getNextSceneRandom()
{
if (scenes.size() == 1)
return *scenes.begin();
std::vector<OBSWeakSource> rs(scenes);
std::random_device rng;
std::mt19937 urng(rng());
std::shuffle(rs.begin(), rs.end(), urng);
for (OBSWeakSource &s : rs) {
if (s == lastRandomScene)
continue;
lastRandomScene = s;
return s;
}
return nullptr;
}
OBSWeakSource SceneGroup::getNextScene()
{
if (scenes.empty())
return nullptr;
switch (type) {
case AdvanceCondition::Count:
return getNextSceneCount();
break;
case AdvanceCondition::Time:
return getNextSceneTime();
break;
case AdvanceCondition::Random:
return getNextSceneRandom();
break;
}
blog(LOG_INFO, "unknown scene group type!");
return nullptr;
}
bool sceneGroupNameExists(std::string name)
{
obs_source_t *source = obs_get_source_by_name(name.c_str());
if (source) {
obs_source_release(source);
return true;
}
for (SceneGroup &sg : switcher->sceneGroups) {
if (sg.name == name)
return true;
}
return (name == obs_module_text(
"AdvSceneSwitcher.selectPreviousScene") ||
(name == invalid_scene_group_name));
}
void AdvSceneSwitcher::on_sceneGroupAdd_clicked()
{
std::string name;
QString format{
obs_module_text("AdvSceneSwitcher.sceneGroupTab.defaultname")};
int i = 1;
QString placeHolderText = format.arg(i);
while ((sceneGroupNameExists(placeHolderText.toUtf8().constData()))) {
placeHolderText = format.arg(++i);
}
bool accepted = SGNameDialog::AskForName(
this, obs_module_text("AdvSceneSwitcher.sceneGroupTab.add"),
obs_module_text("AdvSceneSwitcher.sceneGroupTab.add"), name,
placeHolderText);
if (!accepted) {
return;
}
if (name.empty()) {
return;
}
if (sceneGroupNameExists(name)) {
DisplayMessage(obs_module_text(
"AdvSceneSwitcher.sceneGroupTab.exists"));
return;
}
{
std::lock_guard<std::mutex> lock(switcher->m);
switcher->sceneGroups.emplace_back(name);
}
QString text = QString::fromStdString(name);
QListWidgetItem *item = new QListWidgetItem(text, ui->sceneGroups);
item->setData(Qt::UserRole, text);
ui->sceneGroups->setCurrentItem(item);
ui->sceneGroupAdd->disconnect(addPulse);
emit SceneGroupAdded(QString::fromStdString(name));
}
void AdvSceneSwitcher::on_sceneGroupRemove_clicked()
{
QListWidgetItem *item = ui->sceneGroups->currentItem();
if (!item)
return;
QString name;
{
std::lock_guard<std::mutex> lock(switcher->m);
int idx = ui->sceneGroups->currentRow();
auto &sg = switcher->sceneGroups;
name = QString::fromStdString(sg[idx].name);
sg.erase(sg.begin() + idx);
}
delete item;
emit SceneGroupRemoved(name);
}
void AdvSceneSwitcher::on_sceneGroupUp_clicked()
{
int index = ui->sceneGroups->currentRow();
if (index != -1 && index != 0) {
ui->sceneGroups->insertItem(index - 1,
ui->sceneGroups->takeItem(index));
ui->sceneGroups->setCurrentRow(index - 1);
std::lock_guard<std::mutex> lock(switcher->m);
iter_swap(switcher->sceneGroups.begin() + index,
switcher->sceneGroups.begin() + index - 1);
}
}
void AdvSceneSwitcher::on_sceneGroupDown_clicked()
{
int index = ui->sceneGroups->currentRow();
if (index != -1 && index != ui->sceneGroups->count() - 1) {
ui->sceneGroups->insertItem(index + 1,
ui->sceneGroups->takeItem(index));
ui->sceneGroups->setCurrentRow(index + 1);
std::lock_guard<std::mutex> lock(switcher->m);
iter_swap(switcher->sceneGroups.begin() + index,
switcher->sceneGroups.begin() + index + 1);
}
}
SceneGroup *getSelectedSG(Ui_AdvSceneSwitcher *ui)
{
SceneGroup *currentSG = nullptr;
QListWidgetItem *sgItem = ui->sceneGroups->currentItem();
if (!sgItem)
return currentSG;
QString sgName = sgItem->data(Qt::UserRole).toString();
for (auto &sg : switcher->sceneGroups) {
if (sgName.compare(sg.name.c_str()) == 0) {
currentSG = &sg;
break;
}
}
return currentSG;
}
void AdvSceneSwitcher::on_sceneGroupName_editingFinished()
{
bool nameValid = true;
SceneGroup *currentSG = getSelectedSG(ui.get());
if (!currentSG)
return;
QString newName = ui->sceneGroupName->text();
QString oldName = QString::fromStdString(currentSG->name);
if (newName.isEmpty() || newName == oldName) {
nameValid = false;
}
if (nameValid && sceneGroupNameExists(newName.toUtf8().constData())) {
DisplayMessage(obs_module_text(
"AdvSceneSwitcher.sceneGroupTab.exists"));
nameValid = false;
}
{
std::lock_guard<std::mutex> lock(switcher->m);
if (nameValid) {
currentSG->name = newName.toUtf8().constData();
QListWidgetItem *sgItem =
ui->sceneGroups->currentItem();
sgItem->setData(Qt::UserRole, newName);
sgItem->setText(newName);
} else {
ui->sceneGroupName->setText(oldName);
}
}
emit SceneGroupRenamed(oldName, newName);
}
void AdvSceneSwitcher::SetEditSceneGroup(SceneGroup &sg)
{
ui->sceneGroupName->setText(sg.name.c_str());
ui->sceneGroupScenes->clear();
for (auto &s : sg.scenes) {
QString sceneName =
QString::fromStdString(GetWeakSourceName(s));
QVariant v = QVariant::fromValue(sceneName);
QListWidgetItem *item =
new QListWidgetItem(sceneName, ui->sceneGroupScenes);
item->setData(Qt::UserRole, v);
}
ui->sceneGroupEdit->setDisabled(false);
typeEdit->SetEditSceneGroup(&sg);
}
void AdvSceneSwitcher::on_sceneGroups_currentRowChanged(int idx)
{
if (loading)
return;
if (idx == -1) {
ui->sceneGroupEdit->setDisabled(true);
return;
}
QListWidgetItem *item = ui->sceneGroups->item(idx);
QString sgName = item->data(Qt::UserRole).toString();
for (auto &sg : switcher->sceneGroups) {
if (sgName.compare(sg.name.c_str()) == 0) {
SetEditSceneGroup(sg);
break;
}
}
}
void AdvSceneSwitcher::on_sceneGroupSceneAdd_clicked()
{
std::lock_guard<std::mutex> lock(switcher->m);
SceneGroup *currentSG = getSelectedSG(ui.get());
if (!currentSG)
return;
QString sceneName = ui->sceneGroupSceneSelection->currentText();
if (sceneName.isEmpty())
return;
OBSWeakSource source = GetWeakSourceByQString(sceneName);
if (!source)
return;
QVariant v = QVariant::fromValue(sceneName);
QListWidgetItem *item =
new QListWidgetItem(sceneName, ui->sceneGroupScenes);
item->setData(Qt::UserRole, v);
currentSG->scenes.emplace_back(source);
}
void AdvSceneSwitcher::on_sceneGroupSceneRemove_clicked()
{
std::lock_guard<std::mutex> lock(switcher->m);
SceneGroup *currentSG = getSelectedSG(ui.get());
if (!currentSG)
return;
int idx = ui->sceneGroupScenes->currentRow();
if (idx == -1)
return;
auto &scenes = currentSG->scenes;
scenes.erase(scenes.begin() + idx);
auto item = ui->sceneGroupScenes->currentItem();
delete item;
}
void AdvSceneSwitcher::on_sceneGroupSceneUp_clicked()
{
std::lock_guard<std::mutex> lock(switcher->m);
SceneGroup *currentSG = getSelectedSG(ui.get());
if (!currentSG)
return;
int index = ui->sceneGroupScenes->currentRow();
if (index != -1 && index != 0) {
ui->sceneGroupScenes->insertItem(
index - 1, ui->sceneGroupScenes->takeItem(index));
ui->sceneGroupScenes->setCurrentRow(index - 1);
iter_swap(currentSG->scenes.begin() + index,
currentSG->scenes.begin() + index - 1);
}
}
void AdvSceneSwitcher::on_sceneGroupSceneDown_clicked()
{
std::lock_guard<std::mutex> lock(switcher->m);
SceneGroup *currentSG = getSelectedSG(ui.get());
if (!currentSG)
return;
int index = ui->sceneGroupScenes->currentRow();
if (index != -1 && index != ui->sceneGroupScenes->count() - 1) {
ui->sceneGroupScenes->insertItem(
index + 1, ui->sceneGroupScenes->takeItem(index));
ui->sceneGroupScenes->setCurrentRow(index + 1);
iter_swap(currentSG->scenes.begin() + index,
currentSG->scenes.begin() + index + 1);
}
}
void SwitcherData::saveSceneGroups(obs_data_t *obj)
{
obs_data_array_t *sceneGroupArray = obs_data_array_create();
for (SceneGroup &sg : switcher->sceneGroups) {
obs_data_t *array_obj = obs_data_create();
obs_data_set_string(array_obj, "name", sg.name.c_str());
obs_data_set_int(array_obj, "type", static_cast<int>(sg.type));
obs_data_array_t *scenesArray = obs_data_array_create();
for (OBSWeakSource s : sg.scenes) {
obs_data_t *sceneArray_obj = obs_data_create();
obs_source_t *source = obs_weak_source_get_source(s);
if (source) {
const char *name = obs_source_get_name(source);
obs_data_set_string(sceneArray_obj, "scene",
name);
}
obs_source_release(source);
obs_data_array_push_back(scenesArray, sceneArray_obj);
obs_data_release(sceneArray_obj);
}
obs_data_set_array(array_obj, "scenes", scenesArray);
obs_data_array_release(scenesArray);
obs_data_set_int(array_obj, "count", sg.count);
obs_data_set_double(array_obj, "time", sg.time);
obs_data_set_bool(array_obj, "repeat", sg.repeat);
obs_data_array_push_back(sceneGroupArray, array_obj);
obs_data_release(array_obj);
}
obs_data_set_array(obj, "sceneGroups", sceneGroupArray);
obs_data_array_release(sceneGroupArray);
}
void SwitcherData::loadSceneGroups(obs_data_t *obj)
{
switcher->sceneGroups.clear();
obs_data_array_t *sceneGroupArray =
obs_data_get_array(obj, "sceneGroups");
size_t count = obs_data_array_count(sceneGroupArray);
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(sceneGroupArray, i);
const char *name = obs_data_get_string(array_obj, "name");
AdvanceCondition type = static_cast<AdvanceCondition>(
obs_data_get_int(array_obj, "type"));
std::vector<OBSWeakSource> scenes;
obs_data_array_t *scenesArray =
obs_data_get_array(array_obj, "scenes");
size_t scenesCount = obs_data_array_count(scenesArray);
for (size_t j = 0; j < scenesCount; j++) {
obs_data_t *scenesArray_obj =
obs_data_array_item(scenesArray, j);
const char *scene =
obs_data_get_string(scenesArray_obj, "scene");
scenes.emplace_back(GetWeakSourceByName(scene));
obs_data_release(scenesArray_obj);
}
obs_data_array_release(scenesArray);
int count = obs_data_get_int(array_obj, "count");
double time = obs_data_get_double(array_obj, "time");
bool repeat = obs_data_get_bool(array_obj, "repeat");
switcher->sceneGroups.emplace_back(name, type, scenes, count,
time, repeat);
obs_data_release(array_obj);
}
obs_data_array_release(sceneGroupArray);
}
void AdvSceneSwitcher::setupSceneGroupTab()
{
populateSceneSelection(ui->sceneGroupSceneSelection);
for (auto &sg : switcher->sceneGroups) {
QString text = QString::fromStdString(sg.name);
QListWidgetItem *item =
new QListWidgetItem(text, ui->sceneGroups);
item->setData(Qt::UserRole, text);
}
if (switcher->sceneGroups.size() == 0)
addPulse = PulseWidget(ui->sceneGroupAdd, QColor(Qt::green));
typeEdit = new SceneGroupEditWidget();
ui->sceneGroupTypeEdit->addWidget(typeEdit);
ui->sceneGroupEdit->setDisabled(true);
}
SGNameDialog::SGNameDialog(QWidget *parent) : QDialog(parent)
{
setModal(true);
setWindowModality(Qt::WindowModality::WindowModal);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setFixedWidth(555);
setMinimumHeight(100);
QVBoxLayout *layout = new QVBoxLayout;
setLayout(layout);
label = new QLabel(this);
layout->addWidget(label);
label->setText("Set Text");
userText = new QLineEdit(this);
layout->addWidget(userText);
QDialogButtonBox *buttonbox = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
layout->addWidget(buttonbox);
buttonbox->setCenterButtons(true);
connect(buttonbox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
}
static bool IsWhitespace(char ch)
{
return ch == ' ' || ch == '\t';
}
static void CleanWhitespace(std::string &str)
{
while (str.size() && IsWhitespace(str.back()))
str.erase(str.end() - 1);
while (str.size() && IsWhitespace(str.front()))
str.erase(str.begin());
}
bool SGNameDialog::AskForName(QWidget *parent, const QString &title,
const QString &text, std::string &userTextInput,
const QString &placeHolder, int maxSize)
{
if (maxSize <= 0 || maxSize > 32767)
maxSize = 170;
SGNameDialog dialog(parent);
dialog.setWindowTitle(title);
dialog.label->setText(text);
dialog.userText->setMaxLength(maxSize);
dialog.userText->setText(placeHolder);
dialog.userText->selectAll();
if (dialog.exec() != DialogCode::Accepted) {
return false;
}
userTextInput = dialog.userText->text().toUtf8().constData();
CleanWhitespace(userTextInput);
return true;
}
void populateTypeSelection(QComboBox *list)
{
list->addItem(
obs_module_text("AdvSceneSwitcher.sceneGroupTab.type.count"));
list->addItem(
obs_module_text("AdvSceneSwitcher.sceneGroupTab.type.time"));
list->addItem(
obs_module_text("AdvSceneSwitcher.sceneGroupTab.type.random"));
}
SceneGroupEditWidget::SceneGroupEditWidget()
{
//w->setContentsMargins(0, 0, 0, 0);
type = new QComboBox();
populateTypeSelection(type);
QWidget::connect(type, SIGNAL(currentIndexChanged(int)), this,
SLOT(TypeChanged(int)));
QHBoxLayout *typeLayout = new QHBoxLayout();
typeLayout->setContentsMargins(0, 0, 0, 0);
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{type}}", type}};
placeWidgets(
obs_module_text("AdvSceneSwitcher.sceneGroupTab.edit.type"),
typeLayout, widgetPlaceholders);
countEdit = new QWidget();
count = new QSpinBox();
count->setMinimum(1);
count->setMaximum(999);
QWidget::connect(count, SIGNAL(valueChanged(int)), this,
SLOT(CountChanged(int)));
QHBoxLayout *countLayout = new QHBoxLayout(countEdit);
countLayout->setContentsMargins(0, 0, 0, 0);
widgetPlaceholders = {{"{{count}}", count}};
placeWidgets(
obs_module_text("AdvSceneSwitcher.sceneGroupTab.edit.count"),
countLayout, widgetPlaceholders);
timeEdit = new QWidget();
time = new QDoubleSpinBox();
time->setMinimum(0.0);
time->setMaximum(99999999.00);
time->setSuffix("s");
QWidget::connect(time, SIGNAL(valueChanged(double)), this,
SLOT(TimeChanged(double)));
QHBoxLayout *timeLayout = new QHBoxLayout(timeEdit);
timeLayout->setContentsMargins(0, 0, 0, 0);
widgetPlaceholders = {{"{{time}}", time}};
placeWidgets(
obs_module_text("AdvSceneSwitcher.sceneGroupTab.edit.time"),
timeLayout, widgetPlaceholders);
repeat = new QCheckBox(
obs_module_text("AdvSceneSwitcher.sceneGroupTab.edit.repeat"));
QWidget::connect(repeat, SIGNAL(stateChanged(int)), this,
SLOT(RepeatChanged(int)));
random = new QLabel(
obs_module_text("AdvSceneSwitcher.sceneGroupTab.edit.random"));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addLayout(typeLayout);
mainLayout->addWidget(countEdit);
mainLayout->addWidget(timeEdit);
mainLayout->addWidget(repeat);
mainLayout->addWidget(random);
setLayout(mainLayout);
countEdit->setVisible(false);
timeEdit->setVisible(false);
repeat->setVisible(false);
random->setVisible(false);
sceneGroup = nullptr;
}
void SceneGroupEditWidget::ShowCurrentTypeEdit()
{
if (!sceneGroup)
return;
countEdit->setVisible(false);
timeEdit->setVisible(false);
repeat->setVisible(false);
random->setVisible(false);
switch (sceneGroup->type) {
case AdvanceCondition::Count:
countEdit->setVisible(true);
repeat->setVisible(true);
break;
case AdvanceCondition::Time:
timeEdit->setVisible(true);
repeat->setVisible(true);
break;
case AdvanceCondition::Random:
random->setVisible(true);
break;
}
}
void SceneGroupEditWidget::SetEditSceneGroup(SceneGroup *sg)
{
if (!sg)
return;
sceneGroup = sg;
type->setCurrentIndex(static_cast<int>(sg->type));
count->setValue(sg->count);
time->setValue(sg->time);
repeat->setChecked(sg->repeat);
ShowCurrentTypeEdit();
}
void SceneGroupEditWidget::TypeChanged(int type)
{
if (!sceneGroup)
return;
std::lock_guard<std::mutex> lock(switcher->m);
sceneGroup->type = static_cast<AdvanceCondition>(type);
ShowCurrentTypeEdit();
}
void SceneGroupEditWidget::CountChanged(int count)
{
if (!sceneGroup)
return;
std::lock_guard<std::mutex> lock(switcher->m);
sceneGroup->count = count;
}
void SceneGroupEditWidget::TimeChanged(double time)
{
if (!sceneGroup)
return;
std::lock_guard<std::mutex> lock(switcher->m);
sceneGroup->time = time;
}
void SceneGroupEditWidget::RepeatChanged(int state)
{
if (!sceneGroup)
return;
std::lock_guard<std::mutex> lock(switcher->m);
sceneGroup->repeat = state;
}

View File

@ -12,9 +12,10 @@ void AdvSceneSwitcher::on_audioAdd_clicked()
std::lock_guard<std::mutex> lock(switcher->m);
switcher->audioSwitches.emplace_back();
listAddClicked(ui->audioSwitches,
new AudioSwitchWidget(&switcher->audioSwitches.back()),
ui->audioAdd, &addPulse);
AudioSwitchWidget *sw =
new AudioSwitchWidget(this, &switcher->audioSwitches.back());
listAddClicked(ui->audioSwitches, sw, ui->audioAdd, &addPulse);
}
void AdvSceneSwitcher::on_audioRemove_clicked()
@ -92,8 +93,7 @@ void SwitcherData::checkAudioSwitchFallback(OBSWeakSource &scene,
if (durationReached) {
scene = (audioFallback.usePreviousScene) ? previousScene
: audioFallback.scene;
scene = audioFallback.getScene();
transition = audioFallback.transition;
if (verbose)
@ -150,7 +150,7 @@ void SwitcherData::checkAudioSwitch(bool &match, OBSWeakSource &scene,
break;
}
scene = (s.usePreviousScene) ? previousScene : s.scene;
scene = s.getScene();
transition = s.transition;
match = true;
@ -166,91 +166,21 @@ void SwitcherData::checkAudioSwitch(bool &match, OBSWeakSource &scene,
audioFallback.matchCount = 0;
}
void saveAudioFallback(obs_data_t *obj, AudioSwitchFallback &audioFallback)
{
obs_source_t *fallbackSceneSource =
obs_weak_source_get_source(audioFallback.scene);
obs_source_t *fallbackTransition =
obs_weak_source_get_source(audioFallback.transition);
const char *fallbackSceneName =
obs_source_get_name(fallbackSceneSource);
const char *fallbackTransitionName =
obs_source_get_name(fallbackTransition);
obs_data_set_bool(obj, "audioFallbackEnable", audioFallback.enable);
obs_data_set_string(obj, "audioFallbackScene",
audioFallback.usePreviousScene ? previous_scene_name
: fallbackSceneName);
obs_data_set_string(obj, "audioFallbackTransition",
fallbackTransitionName);
obs_data_set_double(obj, "audioFallbackDuration",
audioFallback.duration);
obs_source_release(fallbackSceneSource);
obs_source_release(fallbackTransition);
}
void SwitcherData::saveAudioSwitches(obs_data_t *obj)
{
obs_data_array_t *audioArray = obs_data_array_create();
for (AudioSwitch &s : switcher->audioSwitches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *sceneSource = obs_weak_source_get_source(s.scene);
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
obs_source_t *audioSrouce =
obs_weak_source_get_source(s.audioSource);
if ((s.usePreviousScene || sceneSource) && transition &&
audioSrouce) {
const char *sceneName =
obs_source_get_name(sceneSource);
const char *transitionName =
obs_source_get_name(transition);
const char *audioSourceName =
obs_source_get_name(audioSrouce);
obs_data_set_string(array_obj, "scene",
s.usePreviousScene
? previous_scene_name
: sceneName);
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_string(array_obj, "audioSource",
audioSourceName);
obs_data_set_int(array_obj, "volume",
s.volumeThreshold);
obs_data_set_int(array_obj, "condition", s.condition);
obs_data_set_double(array_obj, "duration", s.duration);
obs_data_array_push_back(audioArray, array_obj);
}
obs_source_release(sceneSource);
obs_source_release(transition);
obs_source_release(audioSrouce);
s.save(array_obj);
obs_data_array_push_back(audioArray, array_obj);
obs_data_release(array_obj);
}
obs_data_set_array(obj, "audioSwitches", audioArray);
obs_data_array_release(audioArray);
saveAudioFallback(obj, audioFallback);
}
void loadAudioFallback(obs_data_t *obj, AudioSwitchFallback &audioFallback)
{
const char *fallbackSceneName =
obs_data_get_string(obj, "audioFallbackScene");
const char *fallbackTransitionName =
obs_data_get_string(obj, "audioFallbackTransition");
audioFallback.enable = obs_data_get_bool(obj, "audioFallbackEnable");
audioFallback.duration =
obs_data_get_double(obj, "audioFallbackDuration");
audioFallback.scene = GetWeakSourceByName(fallbackSceneName);
audioFallback.transition =
GetWeakTransitionByName(fallbackTransitionName);
audioFallback.usePreviousScene =
strcmp(fallbackSceneName, previous_scene_name) == 0;
audioFallback.save(obj);
}
void SwitcherData::loadAudioSwitches(obs_data_t *obj)
@ -263,27 +193,14 @@ void SwitcherData::loadAudioSwitches(obs_data_t *obj)
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(audioArray, i);
const char *scene = obs_data_get_string(array_obj, "scene");
const char *transition =
obs_data_get_string(array_obj, "transition");
const char *audioSource =
obs_data_get_string(array_obj, "audioSource");
int vol = obs_data_get_int(array_obj, "volume");
audioCondition condition = (audioCondition)obs_data_get_int(
array_obj, "condition");
double duration = obs_data_get_double(array_obj, "duration");
switcher->audioSwitches.emplace_back(
GetWeakSourceByName(scene),
GetWeakTransitionByName(transition),
GetWeakSourceByName(audioSource), vol, condition,
duration, (strcmp(scene, previous_scene_name) == 0));
switcher->audioSwitches.emplace_back();
audioSwitches.back().load(array_obj);
obs_data_release(array_obj);
}
obs_data_array_release(audioArray);
loadAudioFallback(obj, audioFallback);
audioFallback.load(obj);
}
void AdvSceneSwitcher::setupAudioTab()
@ -292,7 +209,7 @@ void AdvSceneSwitcher::setupAudioTab()
QListWidgetItem *item;
item = new QListWidgetItem(ui->audioSwitches);
ui->audioSwitches->addItem(item);
AudioSwitchWidget *sw = new AudioSwitchWidget(&s);
AudioSwitchWidget *sw = new AudioSwitchWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->audioSwitches->setItemWidget(item, sw);
}
@ -301,7 +218,7 @@ void AdvSceneSwitcher::setupAudioTab()
addPulse = PulseWidget(ui->audioAdd, QColor(Qt::green));
AudioSwitchFallbackWidget *fb =
new AudioSwitchFallbackWidget(&switcher->audioFallback);
new AudioSwitchFallbackWidget(this, &switcher->audioFallback);
ui->audioFallbackLayout->addWidget(fb);
ui->audioFallback->setChecked(switcher->audioFallback.enable);
}
@ -354,22 +271,87 @@ bool AudioSwitch::valid()
(SceneSwitcherEntry::valid() && WeakSourceValid(audioSource));
}
AudioSwitch::AudioSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
OBSWeakSource audioSource_, int volumeThreshold_,
audioCondition condition_, double duration_,
bool usePreviousScene_)
: SceneSwitcherEntry(scene_, transition_, usePreviousScene_),
audioSource(audioSource_),
volumeThreshold(volumeThreshold_),
condition(condition_),
duration(duration_)
void AudioSwitch::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj);
obs_source_t *source = obs_weak_source_get_source(audioSource);
const char *audioSourceName = obs_source_get_name(source);
obs_data_set_string(obj, "audioSource", audioSourceName);
obs_source_release(source);
obs_data_set_int(obj, "volume", volumeThreshold);
obs_data_set_int(obj, "condition", condition);
obs_data_set_double(obj, "duration", duration);
}
// To be removed in future version
bool loadOldAudio(obs_data_t *obj, AudioSwitch *s)
{
if (!s)
return false;
const char *scene = obs_data_get_string(obj, "scene");
if (strcmp(scene, "") == 0)
return false;
s->scene = GetWeakSourceByName(scene);
const char *transition = obs_data_get_string(obj, "transition");
s->transition = GetWeakTransitionByName(transition);
const char *audioSource = obs_data_get_string(obj, "audioSource");
s->audioSource = GetWeakSourceByName(audioSource);
s->volumeThreshold = obs_data_get_int(obj, "volume");
s->condition = (audioCondition)obs_data_get_int(obj, "condition");
s->duration = obs_data_get_double(obj, "duration");
s->usePreviousScene = strcmp(scene, previous_scene_name) == 0;
return true;
}
void AudioSwitch::load(obs_data_t *obj)
{
if (loadOldAudio(obj, this))
return;
SceneSwitcherEntry::load(obj);
const char *audioSourceName = obs_data_get_string(obj, "audioSource");
audioSource = GetWeakSourceByName(audioSourceName);
volumeThreshold = obs_data_get_int(obj, "volume");
condition = (audioCondition)obs_data_get_int(obj, "condition");
duration = obs_data_get_double(obj, "duration");
volmeter = AddVolmeterToSource(this, audioSource);
}
void AudioSwitchFallback::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj, "audioFallbackTargetType",
"audioFallbackScene",
"audioFallbackTransition");
obs_data_set_bool(obj, "audioFallbackEnable", enable);
obs_data_set_double(obj, "audioFallbackDuration", duration);
}
void AudioSwitchFallback::load(obs_data_t *obj)
{
SceneSwitcherEntry::load(obj, "audioFallbackTargetType",
"audioFallbackScene",
"audioFallbackTransition");
enable = obs_data_get_bool(obj, "audioFallbackEnable");
duration = obs_data_get_double(obj, "audioFallbackDuration");
}
AudioSwitch::AudioSwitch(const AudioSwitch &other)
: SceneSwitcherEntry(other.scene, other.transition,
other.usePreviousScene),
: SceneSwitcherEntry(other.targetType, other.group, other.scene,
other.transition, other.usePreviousScene),
audioSource(other.audioSource),
volumeThreshold(other.volumeThreshold),
condition(other.condition),
@ -379,8 +361,8 @@ AudioSwitch::AudioSwitch(const AudioSwitch &other)
}
AudioSwitch::AudioSwitch(AudioSwitch &&other)
: SceneSwitcherEntry(other.scene, other.transition,
other.usePreviousScene),
: SceneSwitcherEntry(other.targetType, other.group, other.scene,
other.transition, other.usePreviousScene),
audioSource(other.audioSource),
volumeThreshold(other.volumeThreshold),
condition(other.condition),
@ -420,6 +402,8 @@ AudioSwitch &AudioSwitch::operator=(AudioSwitch &&other) noexcept
void swap(AudioSwitch &first, AudioSwitch &second)
{
std::swap(first.targetType, second.targetType);
std::swap(first.group, second.group);
std::swap(first.scene, second.scene);
std::swap(first.transition, second.transition);
std::swap(first.usePreviousScene, second.usePreviousScene);
@ -441,7 +425,8 @@ void populateConditionSelection(QComboBox *list)
obs_module_text("AdvSceneSwitcher.audioTab.condition.below"));
}
AudioSwitchWidget::AudioSwitchWidget(AudioSwitch *s) : SwitchWidget(s)
AudioSwitchWidget::AudioSwitchWidget(QWidget *parent, AudioSwitch *s)
: SwitchWidget(parent, s, true, true)
{
audioSources = new QComboBox();
condition = new QComboBox();
@ -584,8 +569,9 @@ void AudioSwitchWidget::DurationChanged(double dur)
switchData->duration = dur;
}
AudioSwitchFallbackWidget::AudioSwitchFallbackWidget(AudioSwitchFallback *s)
: SwitchWidget(s)
AudioSwitchFallbackWidget::AudioSwitchFallbackWidget(QWidget *parent,
AudioSwitchFallback *s)
: SwitchWidget(parent, s, true, true)
{
duration = new QDoubleSpinBox();

View File

@ -11,7 +11,7 @@ void AdvSceneSwitcher::on_executableAdd_clicked()
listAddClicked(ui->executables,
new ExecutableSwitchWidget(
&switcher->executableSwitches.back()),
this, &switcher->executableSwitches.back()),
ui->executableAdd, &addPulse);
}
@ -120,7 +120,7 @@ void SwitcherData::checkExeSwitch(bool &match, OBSWeakSource &scene,
if ((equals || matches) && (focus || ignore)) {
match = true;
scene = s.scene;
scene = s.getScene();
transition = s.transition;
if (verbose)
@ -136,24 +136,9 @@ void SwitcherData::saveExecutableSwitches(obs_data_t *obj)
for (ExecutableSwitch &s : switcher->executableSwitches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *source = obs_weak_source_get_source(s.scene);
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
s.save(array_obj);
obs_data_array_push_back(executableArray, array_obj);
if (source && transition) {
const char *sceneName = obs_source_get_name(source);
const char *transitionName =
obs_source_get_name(transition);
obs_data_set_string(array_obj, "scene", sceneName);
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_string(array_obj, "exefile",
s.exe.toUtf8());
obs_data_set_bool(array_obj, "infocus", s.inFocus);
obs_data_array_push_back(executableArray, array_obj);
}
obs_source_release(source);
obs_source_release(transition);
obs_data_release(array_obj);
}
obs_data_set_array(obj, "executableSwitches", executableArray);
@ -171,15 +156,8 @@ void SwitcherData::loadExecutableSwitches(obs_data_t *obj)
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(executableArray, i);
const char *scene = obs_data_get_string(array_obj, "scene");
const char *transition =
obs_data_get_string(array_obj, "transition");
const char *exe = obs_data_get_string(array_obj, "exefile");
bool infocus = obs_data_get_bool(array_obj, "infocus");
switcher->executableSwitches.emplace_back(
GetWeakSourceByName(scene),
GetWeakTransitionByName(transition), exe, infocus);
switcher->executableSwitches.emplace_back();
executableSwitches.back().load(array_obj);
obs_data_release(array_obj);
}
@ -192,7 +170,8 @@ void AdvSceneSwitcher::setupExecutableTab()
QListWidgetItem *item;
item = new QListWidgetItem(ui->executables);
ui->executables->addItem(item);
ExecutableSwitchWidget *sw = new ExecutableSwitchWidget(&s);
ExecutableSwitchWidget *sw =
new ExecutableSwitchWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->executables->setItemWidget(item, sw);
}
@ -201,8 +180,51 @@ void AdvSceneSwitcher::setupExecutableTab()
addPulse = PulseWidget(ui->executableAdd, QColor(Qt::green));
}
ExecutableSwitchWidget::ExecutableSwitchWidget(ExecutableSwitch *s)
: SwitchWidget(s, false)
void ExecutableSwitch::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj);
obs_data_set_string(obj, "exefile", exe.toUtf8());
obs_data_set_bool(obj, "infocus", inFocus);
}
// To be removed in future version
bool loadOldExe(obs_data_t *obj, ExecutableSwitch *s)
{
if (!s)
return false;
const char *scene = obs_data_get_string(obj, "scene");
if (strcmp(scene, "") == 0)
return false;
s->scene = GetWeakSourceByName(scene);
const char *transition = obs_data_get_string(obj, "transition");
s->transition = GetWeakTransitionByName(transition);
s->exe = obs_data_get_string(obj, "exefile");
s->inFocus = obs_data_get_bool(obj, "infocus");
s->usePreviousScene = strcmp(scene, previous_scene_name) == 0;
return true;
}
void ExecutableSwitch::load(obs_data_t *obj)
{
if (loadOldExe(obj, this))
return;
SceneSwitcherEntry::load(obj);
exe = obs_data_get_string(obj, "exefile");
inFocus = obs_data_get_bool(obj, "infocus");
}
ExecutableSwitchWidget::ExecutableSwitchWidget(QWidget *parent,
ExecutableSwitch *s)
: SwitchWidget(parent, s, false, true)
{
processes = new QComboBox();
requiresFocus = new QCheckBox(obs_module_text(

View File

@ -245,7 +245,7 @@ void SwitcherData::checkFileContent(bool &match, OBSWeakSource &scene,
}
if (equal) {
scene = s.scene;
scene = s.getScene();
transition = s.transition;
match = true;
@ -262,7 +262,8 @@ void AdvSceneSwitcher::on_fileAdd_clicked()
switcher->fileSwitches.emplace_back();
listAddClicked(ui->fileSwitches,
new FileSwitchWidget(&switcher->fileSwitches.back()),
new FileSwitchWidget(this,
&switcher->fileSwitches.back()),
ui->fileAdd, &addPulse);
}
@ -343,28 +344,9 @@ void SwitcherData::saveFileSwitches(obs_data_t *obj)
for (FileSwitch &s : switcher->fileSwitches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *source = obs_weak_source_get_source(s.scene);
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
s.save(array_obj);
obs_data_array_push_back(fileArray, array_obj);
if (source && transition) {
const char *sceneName = obs_source_get_name(source);
const char *transitionName =
obs_source_get_name(transition);
obs_data_set_string(array_obj, "scene", sceneName);
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_string(array_obj, "file", s.file.c_str());
obs_data_set_string(array_obj, "text", s.text.c_str());
obs_data_set_bool(array_obj, "remote", s.remote);
obs_data_set_bool(array_obj, "useRegex", s.useRegex);
obs_data_set_bool(array_obj, "useTime", s.useTime);
obs_data_set_bool(array_obj, "onlyMatchIfChanged",
s.onlyMatchIfChanged);
obs_data_array_push_back(fileArray, array_obj);
}
obs_source_release(source);
obs_source_release(transition);
obs_data_release(array_obj);
}
obs_data_set_array(obj, "fileSwitches", fileArray);
@ -386,21 +368,8 @@ void SwitcherData::loadFileSwitches(obs_data_t *obj)
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(fileArray, i);
const char *scene = obs_data_get_string(array_obj, "scene");
const char *transition =
obs_data_get_string(array_obj, "transition");
const char *file = obs_data_get_string(array_obj, "file");
const char *text = obs_data_get_string(array_obj, "text");
bool remote = obs_data_get_bool(array_obj, "remote");
bool useRegex = obs_data_get_bool(array_obj, "useRegex");
bool useTime = obs_data_get_bool(array_obj, "useTime");
bool onlyMatchIfChanged =
obs_data_get_bool(array_obj, "onlyMatchIfChanged");
switcher->fileSwitches.emplace_back(
GetWeakSourceByName(scene),
GetWeakTransitionByName(transition), file, text, remote,
useRegex, useTime, onlyMatchIfChanged);
switcher->fileSwitches.emplace_back();
fileSwitches.back().load(array_obj);
obs_data_release(array_obj);
}
@ -429,7 +398,7 @@ void AdvSceneSwitcher::setupFileTab()
QListWidgetItem *item;
item = new QListWidgetItem(ui->fileSwitches);
ui->fileSwitches->addItem(item);
FileSwitchWidget *sw = new FileSwitchWidget(&s);
FileSwitchWidget *sw = new FileSwitchWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->fileSwitches->setItemWidget(item, sw);
}
@ -452,7 +421,62 @@ void AdvSceneSwitcher::setupFileTab()
}
}
FileSwitchWidget::FileSwitchWidget(FileSwitch *s) : SwitchWidget(s, false)
void FileSwitch::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj);
obs_data_set_string(obj, "file", file.c_str());
obs_data_set_string(obj, "text", text.c_str());
obs_data_set_bool(obj, "remote", remote);
obs_data_set_bool(obj, "useRegex", useRegex);
obs_data_set_bool(obj, "useTime", useTime);
obs_data_set_bool(obj, "onlyMatchIfChanged", onlyMatchIfChanged);
}
// To be removed in future version
bool loadOldFile(obs_data_t *obj, FileSwitch *s)
{
if (!s)
return false;
const char *scene = obs_data_get_string(obj, "scene");
if (strcmp(scene, "") == 0)
return false;
s->scene = GetWeakSourceByName(scene);
const char *transition = obs_data_get_string(obj, "transition");
s->transition = GetWeakTransitionByName(transition);
s->file = obs_data_get_string(obj, "file");
s->text = obs_data_get_string(obj, "text");
s->remote = obs_data_get_bool(obj, "remote");
s->useRegex = obs_data_get_bool(obj, "useRegex");
s->useTime = obs_data_get_bool(obj, "useTime");
s->onlyMatchIfChanged = obs_data_get_bool(obj, "onlyMatchIfChanged");
s->usePreviousScene = strcmp(scene, previous_scene_name) == 0;
return true;
}
void FileSwitch::load(obs_data_t *obj)
{
if (loadOldFile(obj, this))
return;
SceneSwitcherEntry::load(obj);
file = obs_data_get_string(obj, "file");
text = obs_data_get_string(obj, "text");
remote = obs_data_get_bool(obj, "remote");
useRegex = obs_data_get_bool(obj, "useRegex");
useTime = obs_data_get_bool(obj, "useTime");
onlyMatchIfChanged = obs_data_get_bool(obj, "onlyMatchIfChanged");
}
FileSwitchWidget::FileSwitchWidget(QWidget *parent, FileSwitch *s)
: SwitchWidget(parent, s, false, true)
{
fileType = new QComboBox();
filePath = new QLineEdit();

View File

@ -3,17 +3,19 @@
bool SceneSwitcherEntry::initialized()
{
return (usePreviousScene || WeakSourceValid(scene)) && transition;
return (usePreviousScene || WeakSourceValid(scene) ||
SceneGroupValid(group)) &&
transition;
}
bool SceneSwitcherEntry::valid()
{
return !initialized() ||
((usePreviousScene || WeakSourceValid(scene)) &&
WeakSourceValid(transition));
return !initialized() || ((usePreviousScene || WeakSourceValid(scene) ||
SceneGroupValid(group)) &&
WeakSourceValid(transition));
}
void SceneSwitcherEntry::logMatch()
void SceneSwitcherEntry::logMatchScene()
{
const char *sceneName = previous_scene_name;
if (!usePreviousScene) {
@ -25,7 +27,152 @@ void SceneSwitcherEntry::logMatch()
sceneName);
}
SwitchWidget::SwitchWidget(SceneSwitcherEntry *s, bool usePreviousScene)
void SceneSwitcherEntry::logMatchSceneGroup()
{
if (group->scenes.empty()) {
blog(LOG_INFO,
"match for '%s' - but no scenes specified in '%s'",
getType(), group->name.c_str());
return;
}
const char *sceneName = previous_scene_name;
obs_source_t *s =
obs_weak_source_get_source(group->scenes[group->currentIdx]);
sceneName = obs_source_get_name(s);
obs_source_release(s);
blog(LOG_INFO, "match for '%s' - switch to scene '%s' using '%s'",
getType(), sceneName, group->name.c_str());
}
void SceneSwitcherEntry::logMatch()
{
if (targetType == SwitchTargetType::Scene) {
logMatchScene();
} else if (targetType == SwitchTargetType::SceneGroup) {
logMatchSceneGroup();
}
}
OBSWeakSource SceneSwitcherEntry::getScene()
{
if (targetType == SwitchTargetType::Scene) {
if (usePreviousScene && switcher)
return switcher->previousScene;
return scene;
} else if (targetType == SwitchTargetType::SceneGroup) {
return group->getNextScene();
}
return nullptr;
}
void SceneSwitcherEntry::save(obs_data_t *obj, const char *targetTypeSaveName,
const char *targetSaveName,
const char *transitionSaveName)
{
obs_data_set_int(obj, targetTypeSaveName, static_cast<int>(targetType));
const char *targetName = "";
if (targetType == SwitchTargetType::Scene) {
if (usePreviousScene) {
targetName = previous_scene_name;
} else {
obs_source_t *sceneSource =
obs_weak_source_get_source(scene);
targetName = obs_source_get_name(sceneSource);
obs_source_release(sceneSource);
}
} else if (targetType == SwitchTargetType::SceneGroup) {
targetName = group->name.c_str();
}
obs_data_set_string(obj, targetSaveName, targetName);
obs_source_t *transitionSource = obs_weak_source_get_source(transition);
const char *transitionName = obs_source_get_name(transitionSource);
obs_source_release(transitionSource);
obs_data_set_string(obj, transitionSaveName, transitionName);
}
void SceneSwitcherEntry::load(obs_data_t *obj, const char *targetTypeLoadName,
const char *targetLoadName,
const char *transitionLoadName)
{
targetType = static_cast<SwitchTargetType>(
obs_data_get_int(obj, targetTypeLoadName));
const char *targetName = obs_data_get_string(obj, targetLoadName);
if (targetType == SwitchTargetType::Scene) {
usePreviousScene = strcmp(targetName, previous_scene_name) == 0;
if (!usePreviousScene)
scene = GetWeakSourceByName(targetName);
} else if (targetType == SwitchTargetType::SceneGroup) {
group = GetSceneGroupByName(targetName);
}
const char *transitionName =
obs_data_get_string(obj, transitionLoadName);
transition = GetWeakTransitionByName(transitionName);
usePreviousScene = strcmp(targetName, previous_scene_name) == 0;
}
void SwitchWidget::SceneGroupAdd(const QString &name)
{
if (!scenes)
return;
scenes->addItem(name);
}
void SwitchWidget::SceneGroupRemove(const QString &name)
{
if (!scenes)
return;
int idx = scenes->findText(name);
if (idx == -1) {
return;
}
scenes->removeItem(idx);
if (switchData && switchData->group == GetSceneGroupByQString(name)) {
std::lock_guard<std::mutex> lock(switcher->m);
switchData->targetType = SwitchTargetType::Scene;
switchData->scene = nullptr;
}
scenes->setCurrentIndex(0);
}
void SwitchWidget::SceneGroupRename(const QString &oldName,
const QString &newName)
{
if (!scenes)
return;
bool renameSelected = scenes->currentText() == oldName;
int idx = scenes->findText(oldName);
if (idx == -1) {
return;
}
scenes->removeItem(idx);
scenes->insertItem(idx, newName);
if (renameSelected)
scenes->setCurrentIndex(scenes->findText(newName));
}
SwitchWidget::SwitchWidget(QWidget *parent, SceneSwitcherEntry *s,
bool usePreviousScene, bool addSceneGroup)
{
scenes = new QComboBox();
transitions = new QComboBox();
@ -42,16 +189,31 @@ SwitchWidget::SwitchWidget(SceneSwitcherEntry *s, bool usePreviousScene)
SIGNAL(currentTextChanged(const QString &)), this,
SLOT(TransitionChanged(const QString &)));
AdvSceneSwitcher::populateSceneSelection(scenes, usePreviousScene);
QWidget::connect(parent, SIGNAL(SceneGroupAdded(const QString &)), this,
SLOT(SceneGroupAdd(const QString &)));
QWidget::connect(parent, SIGNAL(SceneGroupRemoved(const QString &)),
this, SLOT(SceneGroupRemove(const QString &)));
QWidget::connect(
parent,
SIGNAL(SceneGroupRenamed(const QString &, const QString &)),
this, SLOT(SceneGroupRename(const QString &, const QString &)));
AdvSceneSwitcher::populateSceneSelection(scenes, usePreviousScene,
addSceneGroup);
AdvSceneSwitcher::populateTransitionSelection(transitions);
if (s) {
if (s->usePreviousScene)
if (s->usePreviousScene) {
scenes->setCurrentText(obs_module_text(
"AdvSceneSwitcher.selectPreviousScene"));
else
} else {
scenes->setCurrentText(
GetWeakSourceName(s->scene).c_str());
if (s->targetType == SwitchTargetType::SceneGroup &&
s->group)
scenes->setCurrentText(
QString::fromStdString(s->group->name));
}
transitions->setCurrentText(
GetWeakSourceName(s->transition).c_str());
}
@ -87,10 +249,20 @@ void SwitchWidget::SceneChanged(const QString &text)
if (loading || !switchData)
return;
std::lock_guard<std::mutex> lock(switcher->m);
switchData->usePreviousScene = isPreviousScene(text);
if (switchData->usePreviousScene)
if (switchData->usePreviousScene) {
switchData->targetType = SwitchTargetType::Scene;
return;
}
switchData->scene = GetWeakSourceByQString(text);
switchData->targetType = SwitchTargetType::Scene;
if (!switchData->scene) {
switchData->group = GetSceneGroupByQString(text);
switchData->targetType = SwitchTargetType::SceneGroup;
}
}
void SwitchWidget::TransitionChanged(const QString &text)

View File

@ -13,9 +13,7 @@ void SwitcherData::checkIdleSwitch(bool &match, OBSWeakSource &scene,
std::string title;
bool ignoreIdle = false;
//lock.unlock();
GetCurrentWindowTitle(title);
//lock.lock();
for (std::string &window : ignoreIdleWindows) {
if (window == title) {
@ -41,8 +39,7 @@ void SwitcherData::checkIdleSwitch(bool &match, OBSWeakSource &scene,
if (!ignoreIdle && secondsSinceLastInput() > idleData.time) {
if (idleData.alreadySwitched)
return;
scene = (idleData.usePreviousScene) ? previousScene
: idleData.scene;
scene = idleData.getScene();
transition = idleData.transition;
match = true;
idleData.alreadySwitched = true;
@ -222,17 +219,7 @@ void SwitcherData::saveIdleSwitches(obs_data_t *obj)
obs_data_set_array(obj, "ignoreIdleWindows", ignoreIdleWindowsArray);
obs_data_array_release(ignoreIdleWindowsArray);
std::string idleSceneName = GetWeakSourceName(switcher->idleData.scene);
std::string idleTransitionName =
GetWeakSourceName(switcher->idleData.transition);
obs_data_set_bool(obj, "idleEnable", switcher->idleData.idleEnable);
obs_data_set_string(obj, "idleSceneName",
switcher->idleData.usePreviousScene
? previous_scene_name
: idleSceneName.c_str());
obs_data_set_string(obj, "idleTransitionName",
idleTransitionName.c_str());
obs_data_set_int(obj, "idleTime", switcher->idleData.time);
idleData.save(obj);
}
void SwitcherData::loadIdleSwitches(obs_data_t *obj)
@ -255,23 +242,15 @@ void SwitcherData::loadIdleSwitches(obs_data_t *obj)
}
obs_data_array_release(ignoreIdleWindowsArray);
std::string idleSceneName = obs_data_get_string(obj, "idleSceneName");
std::string idleTransitionName =
obs_data_get_string(obj, "idleTransitionName");
switcher->idleData.scene = GetWeakSourceByName(idleSceneName.c_str());
switcher->idleData.transition =
GetWeakTransitionByName(idleTransitionName.c_str());
obs_data_set_default_bool(obj, "idleEnable", false);
switcher->idleData.idleEnable = obs_data_get_bool(obj, "idleEnable");
obs_data_set_default_int(obj, "idleTime", default_idle_time);
switcher->idleData.time = obs_data_get_int(obj, "idleTime");
switcher->idleData.usePreviousScene =
(idleSceneName == previous_scene_name);
idleData.load(obj);
}
void AdvSceneSwitcher::setupIdleTab()
{
populateSceneSelection(ui->idleScenes, true);
populateSceneSelection(ui->idleScenes, true, false);
populateTransitionSelection(ui->idleTransitions);
populateWindowSelection(ui->ignoreIdleWindowsWindows);
@ -305,3 +284,21 @@ void AdvSceneSwitcher::setupIdleTab()
ui->idleTransitions->setDisabled(true);
}
}
void IdleData::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj, "idleTargetType", "idleSceneName",
"idleTransitionName");
obs_data_set_bool(obj, "idleEnable", idleEnable);
obs_data_set_int(obj, "idleTime", time);
}
void IdleData::load(obs_data_t *obj)
{
SceneSwitcherEntry::load(obj, "idleTargetType", "idleSceneName",
"idleTransitionName");
idleEnable = obs_data_get_bool(obj, "idleEnable");
time = obs_data_get_int(obj, "idleTime");
}

View File

@ -13,7 +13,8 @@ void AdvSceneSwitcher::on_mediaAdd_clicked()
switcher->mediaSwitches.emplace_back();
listAddClicked(ui->mediaSwitches,
new MediaSwitchWidget(&switcher->mediaSwitches.back()),
new MediaSwitchWidget(this,
&switcher->mediaSwitches.back()),
ui->mediaAdd, &addPulse);
}
@ -173,9 +174,7 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
if (matched && !mediaSwitch.matched) {
match = true;
scene = (mediaSwitch.usePreviousScene)
? previousScene
: mediaSwitch.scene;
scene = mediaSwitch.getScene();
transition = mediaSwitch.transition;
if (verbose)
@ -195,33 +194,8 @@ void SwitcherData::saveMediaSwitches(obs_data_t *obj)
for (MediaSwitch &s : switcher->mediaSwitches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *source = obs_weak_source_get_source(s.source);
obs_source_t *sceneSource = obs_weak_source_get_source(s.scene);
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
if ((s.usePreviousScene || sceneSource) && source &&
transition) {
const char *sourceName = obs_source_get_name(source);
const char *sceneName =
obs_source_get_name(sceneSource);
const char *transitionName =
obs_source_get_name(transition);
obs_data_set_string(array_obj, "source", sourceName);
obs_data_set_string(array_obj, "scene",
s.usePreviousScene
? previous_scene_name
: sceneName);
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_int(array_obj, "state", s.state);
obs_data_set_int(array_obj, "restriction",
s.restriction);
obs_data_set_int(array_obj, "time", s.time);
obs_data_array_push_back(mediaArray, array_obj);
}
obs_source_release(source);
obs_source_release(sceneSource);
obs_source_release(transition);
s.save(array_obj);
obs_data_array_push_back(mediaArray, array_obj);
obs_data_release(array_obj);
}
@ -238,21 +212,8 @@ void SwitcherData::loadMediaSwitches(obs_data_t *obj)
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(mediaArray, i);
const char *source = obs_data_get_string(array_obj, "source");
const char *scene = obs_data_get_string(array_obj, "scene");
const char *transition =
obs_data_get_string(array_obj, "transition");
obs_media_state state =
(obs_media_state)obs_data_get_int(array_obj, "state");
time_restriction restriction =
(time_restriction)obs_data_get_int(array_obj,
"restriction");
uint64_t time = obs_data_get_int(array_obj, "time");
switcher->mediaSwitches.emplace_back(
GetWeakSourceByName(scene), GetWeakSourceByName(source),
GetWeakTransitionByName(transition), state, restriction,
time, (strcmp(scene, previous_scene_name) == 0));
switcher->mediaSwitches.emplace_back();
mediaSwitches.back().load(array_obj);
obs_data_release(array_obj);
}
@ -265,7 +226,7 @@ void AdvSceneSwitcher::setupMediaTab()
QListWidgetItem *item;
item = new QListWidgetItem(ui->mediaSwitches);
ui->mediaSwitches->addItem(item);
MediaSwitchWidget *sw = new MediaSwitchWidget(&s);
MediaSwitchWidget *sw = new MediaSwitchWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->mediaSwitches->setItemWidget(item, sw);
}
@ -285,6 +246,70 @@ bool MediaSwitch::valid()
(SceneSwitcherEntry::valid() && WeakSourceValid(source));
}
void MediaSwitch::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj);
obs_source_t *s = obs_weak_source_get_source(source);
const char *sourceName = obs_source_get_name(s);
obs_data_set_string(obj, "source", sourceName);
obs_source_release(s);
obs_data_set_int(obj, "state", state);
obs_data_set_int(obj, "restriction", restriction);
obs_data_set_int(obj, "time", time);
}
// To be removed in future version
bool loadOldMedia(obs_data_t *obj, MediaSwitch *s)
{
if (!s)
return false;
const char *scene = obs_data_get_string(obj, "scene");
if (strcmp(scene, "") == 0)
return false;
s->scene = GetWeakSourceByName(scene);
const char *transition = obs_data_get_string(obj, "transition");
s->transition = GetWeakTransitionByName(transition);
const char *source = obs_data_get_string(obj, "source");
s->source = GetWeakSourceByName(source);
s->state = (obs_media_state)obs_data_get_int(obj, "state");
s->restriction = (time_restriction)obs_data_get_int(obj, "restriction");
s->time = obs_data_get_int(obj, "time");
s->usePreviousScene = strcmp(scene, previous_scene_name) == 0;
return true;
}
void MediaSwitch::load(obs_data_t *obj)
{
if (loadOldMedia(obj, this))
return;
SceneSwitcherEntry::load(obj);
const char *sourceName = obs_data_get_string(obj, "source");
source = GetWeakSourceByName(sourceName);
state = (obs_media_state)obs_data_get_int(obj, "state");
restriction = (time_restriction)obs_data_get_int(obj, "restriction");
time = obs_data_get_int(obj, "time");
anyState = state == media_any_idx;
obs_source_t *mediasource = obs_weak_source_get_source(source);
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
signal_handler_connect(sh, "media_stopped", MediaStopped, this);
signal_handler_connect(sh, "media_ended", MediaEnded, this);
obs_source_release(mediasource);
}
void MediaSwitch::clearSignalHandler()
{
obs_source_t *mediasource = obs_weak_source_get_source(source);
@ -317,28 +342,9 @@ void MediaSwitch::MediaEnded(void *data, calldata_t *)
media->ended = true;
}
inline MediaSwitch::MediaSwitch(OBSWeakSource scene_, OBSWeakSource source_,
OBSWeakSource transition_,
obs_media_state state_,
time_restriction restriction_, uint64_t time_,
bool usePreviousScene_)
: SceneSwitcherEntry(scene_, transition_, usePreviousScene_),
source(source_),
state(state_),
restriction(restriction_),
time(time_)
{
anyState = state == media_any_idx;
obs_source_t *mediasource = obs_weak_source_get_source(source);
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
signal_handler_connect(sh, "media_stopped", MediaStopped, this);
signal_handler_connect(sh, "media_ended", MediaEnded, this);
obs_source_release(mediasource);
}
MediaSwitch::MediaSwitch(const MediaSwitch &other)
: SceneSwitcherEntry(other.scene, other.transition,
other.usePreviousScene),
: SceneSwitcherEntry(other.targetType, other.group, other.scene,
other.transition, other.usePreviousScene),
source(other.source),
state(other.state),
restriction(other.restriction),
@ -353,8 +359,8 @@ MediaSwitch::MediaSwitch(const MediaSwitch &other)
}
MediaSwitch::MediaSwitch(MediaSwitch &&other)
: SceneSwitcherEntry(other.scene, other.transition,
other.usePreviousScene),
: SceneSwitcherEntry(other.targetType, other.group, other.scene,
other.transition, other.usePreviousScene),
source(other.source),
state(other.state),
anyState(other.anyState),
@ -398,6 +404,8 @@ MediaSwitch &MediaSwitch::operator=(MediaSwitch &&other) noexcept
void swap(MediaSwitch &first, MediaSwitch &second)
{
std::swap(first.targetType, second.targetType);
std::swap(first.group, second.group);
std::swap(first.scene, second.scene);
std::swap(first.transition, second.transition);
std::swap(first.usePreviousScene, second.usePreviousScene);
@ -446,7 +454,8 @@ void populateTimeRestrictions(QComboBox *list)
"AdvSceneSwitcher.mediaTab.timeRestriction.remainLonger"));
}
MediaSwitchWidget::MediaSwitchWidget(MediaSwitch *s) : SwitchWidget(s)
MediaSwitchWidget::MediaSwitchWidget(QWidget *parent, MediaSwitch *s)
: SwitchWidget(parent, s, true, true)
{
mediaSources = new QComboBox();
states = new QComboBox();

View File

@ -11,7 +11,8 @@ void AdvSceneSwitcher::on_pauseAdd_clicked()
switcher->pauseEntries.emplace_back();
listAddClicked(ui->pauseEntries,
new PauseEntryWidget(&switcher->pauseEntries.back()),
new PauseEntryWidget(this,
&switcher->pauseEntries.back()),
ui->pauseAdd, &addPulse);
}
@ -307,7 +308,7 @@ void AdvSceneSwitcher::setupPauseTab()
QListWidgetItem *item;
item = new QListWidgetItem(ui->pauseEntries);
ui->pauseEntries->addItem(item);
PauseEntryWidget *sw = new PauseEntryWidget(&s);
PauseEntryWidget *sw = new PauseEntryWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->pauseEntries->setItemWidget(item, sw);
}
@ -343,7 +344,8 @@ void populatePauseTargets(QComboBox *list)
list->addItem(obs_module_text("AdvSceneSwitcher.audioTab.title"));
}
PauseEntryWidget::PauseEntryWidget(PauseEntry *s) : SwitchWidget(s, false)
PauseEntryWidget::PauseEntryWidget(QWidget *parent, PauseEntry *s)
: SwitchWidget(parent, s, false, false)
{
pauseTypes = new QComboBox();
pauseTargets = new QComboBox();

View File

@ -12,7 +12,8 @@ void AdvSceneSwitcher::on_randomAdd_clicked()
switcher->randomSwitches.emplace_back();
listAddClicked(ui->randomSwitches,
new RandomSwitchWidget(&switcher->randomSwitches.back()),
new RandomSwitchWidget(this,
&switcher->randomSwitches.back()),
ui->randomAdd, &addPulse);
}
@ -48,7 +49,7 @@ void SwitcherData::checkRandom(bool &match, OBSWeakSource &scene,
if (r.scene == lastRandomScene && randomSwitches.size() != 1)
continue;
scene = r.scene;
scene = r.getScene();
transition = r.transition;
delay = (int)r.delay * 1000;
match = true;
@ -66,22 +67,9 @@ void SwitcherData::saveRandomSwitches(obs_data_t *obj)
for (RandomSwitch &s : switcher->randomSwitches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *source = obs_weak_source_get_source(s.scene);
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
s.save(array_obj);
obs_data_array_push_back(randomArray, array_obj);
if (source && transition) {
const char *sceneName = obs_source_get_name(source);
const char *transitionName =
obs_source_get_name(transition);
obs_data_set_string(array_obj, "scene", sceneName);
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_double(array_obj, "delay", s.delay);
obs_data_array_push_back(randomArray, array_obj);
}
obs_source_release(source);
obs_source_release(transition);
obs_data_release(array_obj);
}
obs_data_set_array(obj, "randomSwitches", randomArray);
@ -99,14 +87,8 @@ void SwitcherData::loadRandomSwitches(obs_data_t *obj)
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(randomArray, i);
const char *scene = obs_data_get_string(array_obj, "scene");
const char *transition =
obs_data_get_string(array_obj, "transition");
double delay = obs_data_get_double(array_obj, "delay");
switcher->randomSwitches.emplace_back(
GetWeakSourceByName(scene),
GetWeakTransitionByName(transition), delay);
switcher->randomSwitches.emplace_back();
randomSwitches.back().load(array_obj);
obs_data_release(array_obj);
}
@ -119,7 +101,7 @@ void AdvSceneSwitcher::setupRandomTab()
QListWidgetItem *item;
item = new QListWidgetItem(ui->randomSwitches);
ui->randomSwitches->addItem(item);
RandomSwitchWidget *sw = new RandomSwitchWidget(&s);
RandomSwitchWidget *sw = new RandomSwitchWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->randomSwitches->setItemWidget(item, sw);
}
@ -134,7 +116,20 @@ void AdvSceneSwitcher::setupRandomTab()
ui->randomDisabledWarning->setVisible(false);
}
RandomSwitchWidget::RandomSwitchWidget(RandomSwitch *s) : SwitchWidget(s, false)
void RandomSwitch::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj, "targetType", "scene");
obs_data_set_double(obj, "delay", delay);
}
void RandomSwitch::load(obs_data_t *obj)
{
SceneSwitcherEntry::load(obj, "targetType", "scene");
delay = obs_data_get_double(obj, "delay");
}
RandomSwitchWidget::RandomSwitchWidget(QWidget *parent, RandomSwitch *s)
: SwitchWidget(parent, s, false, false)
{
delay = new QDoubleSpinBox();

View File

@ -67,10 +67,10 @@ void AdvSceneSwitcher::on_screenRegionAdd_clicked()
std::lock_guard<std::mutex> lock(switcher->m);
switcher->screenRegionSwitches.emplace_back();
listAddClicked(
ui->screenRegionSwitches,
new ScreenRegionWidget(&switcher->screenRegionSwitches.back()),
ui->screenRegionAdd, &addPulse);
listAddClicked(ui->screenRegionSwitches,
new ScreenRegionWidget(
this, &switcher->screenRegionSwitches.back()),
ui->screenRegionAdd, &addPulse);
}
void AdvSceneSwitcher::on_screenRegionRemove_clicked()
@ -148,7 +148,7 @@ void SwitcherData::checkScreenRegionSwitch(bool &match, OBSWeakSource &scene,
int regionSize = (s.maxX - s.minX) + (s.maxY - s.minY);
if (regionSize < minRegionSize) {
match = true;
scene = s.scene;
scene = s.getScene();
transition = s.transition;
minRegionSize = regionSize;
@ -173,25 +173,9 @@ void SwitcherData::saveScreenRegionSwitches(obs_data_t *obj)
for (ScreenRegionSwitch &s : switcher->screenRegionSwitches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *source = obs_weak_source_get_source(s.scene);
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
if (source && transition) {
const char *sceneName = obs_source_get_name(source);
const char *transitionName =
obs_source_get_name(transition);
obs_data_set_string(array_obj, "screenRegionScene",
sceneName);
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_int(array_obj, "minX", s.minX);
obs_data_set_int(array_obj, "minY", s.minY);
obs_data_set_int(array_obj, "maxX", s.maxX);
obs_data_set_int(array_obj, "maxY", s.maxY);
obs_data_array_push_back(screenRegionArray, array_obj);
}
obs_source_release(source);
obs_source_release(transition);
s.save(array_obj);
obs_data_array_push_back(screenRegionArray, array_obj);
obs_data_release(array_obj);
}
obs_data_set_array(obj, "screenRegion", screenRegionArray);
@ -210,19 +194,8 @@ void SwitcherData::loadScreenRegionSwitches(obs_data_t *obj)
obs_data_t *array_obj =
obs_data_array_item(screenRegionArray, i);
const char *scene =
obs_data_get_string(array_obj, "screenRegionScene");
const char *transition =
obs_data_get_string(array_obj, "transition");
int minX = obs_data_get_int(array_obj, "minX");
int minY = obs_data_get_int(array_obj, "minY");
int maxX = obs_data_get_int(array_obj, "maxX");
int maxY = obs_data_get_int(array_obj, "maxY");
switcher->screenRegionSwitches.emplace_back(
GetWeakSourceByName(scene),
GetWeakTransitionByName(transition), minX, minY, maxX,
maxY);
switcher->screenRegionSwitches.emplace_back();
screenRegionSwitches.back().load(array_obj);
obs_data_release(array_obj);
}
@ -235,7 +208,7 @@ void AdvSceneSwitcher::setupRegionTab()
QListWidgetItem *item;
item = new QListWidgetItem(ui->screenRegionSwitches);
ui->screenRegionSwitches->addItem(item);
ScreenRegionWidget *sw = new ScreenRegionWidget(&s);
ScreenRegionWidget *sw = new ScreenRegionWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->screenRegionSwitches->setItemWidget(item, sw);
}
@ -250,8 +223,57 @@ void AdvSceneSwitcher::setupRegionTab()
screenRegionTimer->start(1000);
}
ScreenRegionWidget::ScreenRegionWidget(ScreenRegionSwitch *s)
: SwitchWidget(s, false)
void ScreenRegionSwitch::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj);
obs_data_set_int(obj, "minX", minX);
obs_data_set_int(obj, "minY", minY);
obs_data_set_int(obj, "maxX", maxX);
obs_data_set_int(obj, "maxY", maxY);
}
// To be removed in future version
bool loadOldRegion(obs_data_t *obj, ScreenRegionSwitch *s)
{
if (!s)
return false;
const char *scene = obs_data_get_string(obj, "screenRegionScene");
if (strcmp(scene, "") == 0)
return false;
s->scene = GetWeakSourceByName(scene);
const char *transition = obs_data_get_string(obj, "transition");
s->transition = GetWeakTransitionByName(transition);
s->minX = obs_data_get_int(obj, "minX");
s->minY = obs_data_get_int(obj, "minY");
s->maxX = obs_data_get_int(obj, "maxX");
s->maxY = obs_data_get_int(obj, "maxY");
s->usePreviousScene = strcmp(scene, previous_scene_name) == 0;
return true;
}
void ScreenRegionSwitch::load(obs_data_t *obj)
{
if (loadOldRegion(obj, this))
return;
SceneSwitcherEntry::load(obj);
minX = obs_data_get_int(obj, "minX");
minY = obs_data_get_int(obj, "minY");
maxX = obs_data_get_int(obj, "maxX");
maxY = obs_data_get_int(obj, "maxY");
}
ScreenRegionWidget::ScreenRegionWidget(QWidget *parent, ScreenRegionSwitch *s)
: SwitchWidget(parent, s, false, true)
{
minX = new QSpinBox();
minY = new QSpinBox();

View File

@ -12,10 +12,10 @@ void AdvSceneSwitcher::on_sceneSequenceAdd_clicked()
std::lock_guard<std::mutex> lock(switcher->m);
switcher->sceneSequenceSwitches.emplace_back();
listAddClicked(
ui->sceneSequenceSwitches,
new SequenceWidget(&switcher->sceneSequenceSwitches.back()),
ui->sceneSequenceAdd, &addPulse);
listAddClicked(ui->sceneSequenceSwitches,
new SequenceWidget(
this, &switcher->sceneSequenceSwitches.back()),
ui->sceneSequenceAdd, &addPulse);
}
void AdvSceneSwitcher::on_sceneSequenceRemove_clicked()
@ -148,9 +148,7 @@ void AdvSceneSwitcher::on_sceneSequenceLoad_clicked()
close();
}
void matchInterruptible(SwitcherData *switcher, SceneSequenceSwitch &s,
bool &match, OBSWeakSource &scene,
OBSWeakSource &transition)
bool matchInterruptible(SwitcherData *switcher, SceneSequenceSwitch &s)
{
bool durationReached = s.matchCount * (switcher->interval / 1000.0) >=
s.delay;
@ -158,20 +156,16 @@ void matchInterruptible(SwitcherData *switcher, SceneSequenceSwitch &s,
s.matchCount++;
if (durationReached) {
match = true;
scene = (s.usePreviousScene) ? switcher->previousScene
: s.scene;
transition = s.transition;
if (switcher->verbose)
s.logMatch();
return true;
}
return false;
}
void matchUninterruptible(SwitcherData *switcher, SceneSequenceSwitch &s,
bool matchUninterruptible(SwitcherData *switcher, SceneSequenceSwitch &s,
obs_source_t *currentSource,
std::unique_lock<std::mutex> &lock, bool &match,
OBSWeakSource &scene, OBSWeakSource &transition)
std::unique_lock<std::mutex> &lock)
{
bool ret = false;
// scene was already active for the previous cycle so remove this time
int dur = s.delay * 1000 - switcher->interval;
if (dur > 0) {
@ -187,17 +181,13 @@ void matchUninterruptible(SwitcherData *switcher, SceneSequenceSwitch &s,
// only switch if user hasn't changed scene manually
if (currentSource == currentSource2) {
match = true;
scene = (s.usePreviousScene) ? switcher->previousScene
: s.scene;
transition = s.transition;
if (switcher->verbose)
s.logMatch();
ret = true;
} else if (switcher->verbose) {
blog(LOG_INFO, "sequence canceled");
}
obs_source_release(currentSource2);
return ret;
}
void SwitcherData::checkSceneSequence(bool &match, OBSWeakSource &scene,
@ -217,13 +207,20 @@ void SwitcherData::checkSceneSequence(bool &match, OBSWeakSource &scene,
if (s.startScene == ws) {
if (!match) {
if (s.interruptible) {
matchInterruptible(switcher, s, match,
scene, transition);
match = matchInterruptible(switcher, s);
} else {
matchUninterruptible(switcher, s,
currentSource,
lock, match, scene,
transition);
match = matchUninterruptible(
switcher, s, currentSource,
lock);
}
if (match) {
scene = (s.usePreviousScene)
? switcher->previousScene
: s.getScene();
transition = s.transition;
if (switcher->verbose)
s.logMatch();
}
}
} else {
@ -240,35 +237,9 @@ void SwitcherData::saveSceneSequenceSwitches(obs_data_t *obj)
for (SceneSequenceSwitch &s : switcher->sceneSequenceSwitches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *source1 =
obs_weak_source_get_source(s.startScene);
obs_source_t *source2 = obs_weak_source_get_source(s.scene);
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
if (source1 && (s.usePreviousScene || source2) && transition) {
const char *sceneName1 = obs_source_get_name(source1);
const char *sceneName2 = obs_source_get_name(source2);
const char *transitionName =
obs_source_get_name(transition);
obs_data_set_string(array_obj, "sceneRoundTripScene1",
sceneName1);
obs_data_set_string(array_obj, "sceneRoundTripScene2",
s.usePreviousScene
? previous_scene_name
: sceneName2);
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_double(array_obj, "delay", s.delay);
obs_data_set_int(array_obj, "delayMultiplier",
s.delayMultiplier);
obs_data_set_bool(array_obj, "interruptible",
s.interruptible);
obs_data_array_push_back(sceneSequenceArray, array_obj);
}
s.save(array_obj);
obs_data_array_push_back(sceneSequenceArray, array_obj);
obs_source_release(source1);
obs_source_release(source2);
obs_source_release(transition);
obs_data_release(array_obj);
}
obs_data_set_array(obj, "sceneRoundTrip", sceneSequenceArray);
@ -287,27 +258,8 @@ void SwitcherData::loadSceneSequenceSwitches(obs_data_t *obj)
obs_data_t *array_obj =
obs_data_array_item(sceneSequenceArray, i);
const char *scene1 =
obs_data_get_string(array_obj, "sceneRoundTripScene1");
const char *scene2 =
obs_data_get_string(array_obj, "sceneRoundTripScene2");
const char *transition =
obs_data_get_string(array_obj, "transition");
double delay = obs_data_get_double(array_obj, "delay");
int delayMultiplier =
obs_data_get_int(array_obj, "delayMultiplier");
if (delayMultiplier == 0 ||
(delayMultiplier != 1 && delayMultiplier % 60 != 0))
delayMultiplier = 1;
bool interruptible =
obs_data_get_bool(array_obj, "interruptible");
switcher->sceneSequenceSwitches.emplace_back(
GetWeakSourceByName(scene1),
GetWeakSourceByName(scene2),
GetWeakTransitionByName(transition), delay,
delayMultiplier, interruptible,
(strcmp(scene2, previous_scene_name) == 0));
switcher->sceneSequenceSwitches.emplace_back();
sceneSequenceSwitches.back().load(array_obj);
obs_data_release(array_obj);
}
@ -320,7 +272,7 @@ void AdvSceneSwitcher::setupSequenceTab()
QListWidgetItem *item;
item = new QListWidgetItem(ui->sceneSequenceSwitches);
ui->sceneSequenceSwitches->addItem(item);
SequenceWidget *sw = new SequenceWidget(&s);
SequenceWidget *sw = new SequenceWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->sceneSequenceSwitches->setItemWidget(item, sw);
}
@ -345,6 +297,76 @@ void SceneSequenceSwitch::logSleep(int dur)
blog(LOG_INFO, "sequence sleep %d", dur);
}
void SceneSequenceSwitch::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj);
obs_source_t *source = obs_weak_source_get_source(startScene);
const char *startSceneName = obs_source_get_name(source);
obs_data_set_string(obj, "startScene", startSceneName);
obs_source_release(source);
obs_data_set_double(obj, "delay", delay);
obs_data_set_int(obj, "delayMultiplier", delayMultiplier);
obs_data_set_bool(obj, "interruptible", interruptible);
}
// To be removed in future version
bool loadOldScequence(obs_data_t *obj, SceneSequenceSwitch *s)
{
if (!s)
return false;
const char *scene1 = obs_data_get_string(obj, "sceneRoundTripScene1");
if (strcmp(scene1, "") == 0)
return false;
s->startScene = GetWeakSourceByName(scene1);
const char *scene2 = obs_data_get_string(obj, "sceneRoundTripScene2");
s->scene = GetWeakSourceByName(scene2);
const char *transition = obs_data_get_string(obj, "transition");
s->transition = GetWeakTransitionByName(transition);
s->delay = obs_data_get_double(obj, "delay");
int delayMultiplier = obs_data_get_int(obj, "delayMultiplier");
if (delayMultiplier == 0 ||
(delayMultiplier != 1 && delayMultiplier % 60 != 0))
delayMultiplier = 1;
s->delayMultiplier = delayMultiplier;
s->interruptible = obs_data_get_bool(obj, "interruptible");
s->usePreviousScene = strcmp(scene2, previous_scene_name) == 0;
return true;
}
void SceneSequenceSwitch::load(obs_data_t *obj)
{
if (loadOldScequence(obj, this))
return;
SceneSwitcherEntry::load(obj);
const char *scene = obs_data_get_string(obj, "startScene");
startScene = GetWeakSourceByName(scene);
delay = obs_data_get_double(obj, "delay");
delayMultiplier = obs_data_get_int(obj, "delayMultiplier");
if (delayMultiplier == 0 ||
(delayMultiplier != 1 && delayMultiplier % 60 != 0))
delayMultiplier = 1;
interruptible = obs_data_get_bool(obj, "interruptible");
}
void populateDelayUnits(QComboBox *list)
{
list->addItem(obs_module_text("AdvSceneSwitcher.unit.secends"));
@ -352,7 +374,8 @@ void populateDelayUnits(QComboBox *list)
list->addItem(obs_module_text("AdvSceneSwitcher.unit.hours"));
}
SequenceWidget::SequenceWidget(SceneSequenceSwitch *s) : SwitchWidget(s)
SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s)
: SwitchWidget(parent, s, true, true)
{
delay = new QDoubleSpinBox();
delayUnits = new QComboBox();

View File

@ -10,7 +10,8 @@ void AdvSceneSwitcher::on_timeAdd_clicked()
switcher->timeSwitches.emplace_back();
listAddClicked(ui->timeSwitches,
new TimeSwitchWidget(&switcher->timeSwitches.back()),
new TimeSwitchWidget(this,
&switcher->timeSwitches.back()),
ui->timeAdd, &addPulse);
}
@ -121,7 +122,7 @@ void SwitcherData::checkTimeSwitch(bool &match, OBSWeakSource &scene,
match = checkRegularTime(s, interval);
if (match) {
scene = (s.usePreviousScene) ? previousScene : s.scene;
scene = s.getScene();
transition = s.transition;
match = true;
@ -138,28 +139,8 @@ void SwitcherData::saveTimeSwitches(obs_data_t *obj)
for (TimeSwitch &s : switcher->timeSwitches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *sceneSource = obs_weak_source_get_source(s.scene);
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
if ((s.usePreviousScene || sceneSource) && transition) {
const char *sceneName =
obs_source_get_name(sceneSource);
const char *transitionName =
obs_source_get_name(transition);
obs_data_set_string(array_obj, "scene",
s.usePreviousScene
? previous_scene_name
: sceneName);
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_int(array_obj, "trigger", s.trigger);
obs_data_set_string(
array_obj, "time",
s.time.toString().toStdString().c_str());
obs_data_array_push_back(timeArray, array_obj);
}
obs_source_release(sceneSource);
obs_source_release(transition);
s.save(array_obj);
obs_data_array_push_back(timeArray, array_obj);
obs_data_release(array_obj);
}
@ -177,18 +158,8 @@ void SwitcherData::loadTimeSwitches(obs_data_t *obj)
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(timeArray, i);
const char *scene = obs_data_get_string(array_obj, "scene");
const char *transition =
obs_data_get_string(array_obj, "transition");
timeTrigger trigger =
(timeTrigger)obs_data_get_int(array_obj, "trigger");
QTime time = QTime::fromString(
obs_data_get_string(array_obj, "time"));
switcher->timeSwitches.emplace_back(
GetWeakSourceByName(scene),
GetWeakTransitionByName(transition), trigger, time,
(strcmp(scene, previous_scene_name) == 0));
switcher->timeSwitches.emplace_back();
timeSwitches.back().load(array_obj);
obs_data_release(array_obj);
}
@ -201,7 +172,7 @@ void AdvSceneSwitcher::setupTimeTab()
QListWidgetItem *item;
item = new QListWidgetItem(ui->timeSwitches);
ui->timeSwitches->addItem(item);
TimeSwitchWidget *sw = new TimeSwitchWidget(&s);
TimeSwitchWidget *sw = new TimeSwitchWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->timeSwitches->setItemWidget(item, sw);
}
@ -210,6 +181,48 @@ void AdvSceneSwitcher::setupTimeTab()
addPulse = PulseWidget(ui->timeAdd, QColor(Qt::green));
}
void TimeSwitch::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj);
obs_data_set_int(obj, "trigger", trigger);
obs_data_set_string(obj, "time", time.toString().toStdString().c_str());
}
// To be removed in future version
bool loadOldTime(obs_data_t *obj, TimeSwitch *s)
{
if (!s)
return false;
const char *scene = obs_data_get_string(obj, "scene");
if (strcmp(scene, "") == 0)
return false;
s->scene = GetWeakSourceByName(scene);
const char *transition = obs_data_get_string(obj, "transition");
s->transition = GetWeakTransitionByName(transition);
s->trigger = (timeTrigger)obs_data_get_int(obj, "trigger");
s->time = QTime::fromString(obs_data_get_string(obj, "time"));
s->usePreviousScene = strcmp(scene, previous_scene_name) == 0;
return true;
}
void TimeSwitch::load(obs_data_t *obj)
{
if (loadOldTime(obj, this))
return;
SceneSwitcherEntry::load(obj);
trigger = (timeTrigger)obs_data_get_int(obj, "trigger");
time = QTime::fromString(obs_data_get_string(obj, "time"));
}
void populateTriggers(QComboBox *list)
{
list->addItem(obs_module_text("AdvSceneSwitcher.timeTab.anyDay"));
@ -227,7 +240,8 @@ void populateTriggers(QComboBox *list)
Qt::ToolTipRole);
}
TimeSwitchWidget::TimeSwitchWidget(TimeSwitch *s) : SwitchWidget(s)
TimeSwitchWidget::TimeSwitchWidget(QWidget *parent, TimeSwitch *s)
: SwitchWidget(parent, s, true, true)
{
triggers = new QComboBox();
time = new QTimeEdit();

View File

@ -8,9 +8,9 @@ void AdvSceneSwitcher::on_transitionsAdd_clicked()
std::lock_guard<std::mutex> lock(switcher->m);
switcher->sceneTransitions.emplace_back();
listAddClicked(
ui->sceneTransitions,
new TransitionSwitchWidget(&switcher->sceneTransitions.back()));
listAddClicked(ui->sceneTransitions,
new TransitionSwitchWidget(
this, &switcher->sceneTransitions.back()));
}
void AdvSceneSwitcher::on_transitionsRemove_clicked()
@ -77,6 +77,7 @@ void AdvSceneSwitcher::on_defaultTransitionsAdd_clicked()
listAddClicked(ui->defaultTransitions,
new DefTransitionSwitchWidget(
this,
&switcher->defaultSceneTransitions.back()));
}
@ -377,7 +378,8 @@ void AdvSceneSwitcher::setupTransitionsTab()
QListWidgetItem *item;
item = new QListWidgetItem(ui->sceneTransitions);
ui->sceneTransitions->addItem(item);
TransitionSwitchWidget *sw = new TransitionSwitchWidget(&s);
TransitionSwitchWidget *sw =
new TransitionSwitchWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->sceneTransitions->setItemWidget(item, sw);
}
@ -387,7 +389,7 @@ void AdvSceneSwitcher::setupTransitionsTab()
item = new QListWidgetItem(ui->defaultTransitions);
ui->defaultTransitions->addItem(item);
DefTransitionSwitchWidget *sw =
new DefTransitionSwitchWidget(&s);
new DefTransitionSwitchWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->defaultTransitions->setItemWidget(item, sw);
}
@ -407,8 +409,9 @@ bool SceneTransition::valid()
(SceneSwitcherEntry::valid() && WeakSourceValid(scene2));
}
TransitionSwitchWidget::TransitionSwitchWidget(SceneTransition *s)
: SwitchWidget(s, false)
TransitionSwitchWidget::TransitionSwitchWidget(QWidget *parent,
SceneTransition *s)
: SwitchWidget(parent, s, false)
{
scenes2 = new QComboBox();
@ -463,8 +466,9 @@ void TransitionSwitchWidget::Scene2Changed(const QString &text)
switchData->scene2 = GetWeakSourceByQString(text);
}
DefTransitionSwitchWidget::DefTransitionSwitchWidget(DefaultSceneTransition *s)
: SwitchWidget(s, false)
DefTransitionSwitchWidget::DefTransitionSwitchWidget(QWidget *parent,
DefaultSceneTransition *s)
: SwitchWidget(parent, s, false)
{
QHBoxLayout *mainLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {

View File

@ -10,7 +10,8 @@ void AdvSceneSwitcher::on_windowAdd_clicked()
switcher->windowSwitches.emplace_back();
listAddClicked(ui->windowSwitches,
new WindowSwitchWidget(&switcher->windowSwitches.back()),
new WindowSwitchWidget(this,
&switcher->windowSwitches.back()),
ui->windowAdd, &addPulse);
}
@ -234,7 +235,7 @@ void SwitcherData::checkWindowTitleSwitch(bool &match, OBSWeakSource &scene,
if (isRunning(s.window) &&
(fullscreen && (max && (focus || ignore)))) {
match = true;
scene = s.scene;
scene = s.getScene();
transition = s.transition;
if (verbose)
@ -250,26 +251,9 @@ void SwitcherData::saveWindowTitleSwitches(obs_data_t *obj)
for (WindowSwitch &s : switcher->windowSwitches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *source = obs_weak_source_get_source(s.scene);
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
if (source && transition) {
const char *sceneName = obs_source_get_name(source);
const char *transitionName =
obs_source_get_name(transition);
obs_data_set_string(array_obj, "scene", sceneName);
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_string(array_obj, "window_title",
s.window.c_str());
obs_data_set_bool(array_obj, "fullscreen",
s.fullscreen);
obs_data_set_bool(array_obj, "maximized", s.maximized);
obs_data_set_bool(array_obj, "focus", s.focus);
obs_data_array_push_back(windowTitleArray, array_obj);
}
obs_source_release(source);
obs_source_release(transition);
s.save(array_obj);
obs_data_array_push_back(windowTitleArray, array_obj);
obs_data_release(array_obj);
}
obs_data_set_array(obj, "switches", windowTitleArray);
@ -298,26 +282,8 @@ void SwitcherData::loadWindowTitleSwitches(obs_data_t *obj)
obs_data_t *array_obj =
obs_data_array_item(windowTitleArray, i);
const char *scene = obs_data_get_string(array_obj, "scene");
const char *transition =
obs_data_get_string(array_obj, "transition");
const char *window =
obs_data_get_string(array_obj, "window_title");
bool fullscreen = obs_data_get_bool(array_obj, "fullscreen");
#if __APPLE__
// TODO:
// not implemented on MacOS as I cannot test it
bool maximized = false;
#else
bool maximized = obs_data_get_bool(array_obj, "maximized");
#endif
bool focus = obs_data_get_bool(array_obj, "focus") ||
!obs_data_has_user_value(array_obj, "focus");
switcher->windowSwitches.emplace_back(
GetWeakSourceByName(scene), window,
GetWeakTransitionByName(transition), fullscreen,
maximized, focus);
switcher->windowSwitches.emplace_back();
windowSwitches.back().load(array_obj);
obs_data_release(array_obj);
}
@ -349,7 +315,7 @@ void AdvSceneSwitcher::setupTitleTab()
QListWidgetItem *item;
item = new QListWidgetItem(ui->windowSwitches);
ui->windowSwitches->addItem(item);
WindowSwitchWidget *sw = new WindowSwitchWidget(&s);
WindowSwitchWidget *sw = new WindowSwitchWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->windowSwitches->setItemWidget(item, sw);
}
@ -368,7 +334,70 @@ void AdvSceneSwitcher::setupTitleTab()
}
}
WindowSwitchWidget::WindowSwitchWidget(WindowSwitch *s) : SwitchWidget(s, false)
void WindowSwitch::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj);
obs_data_set_string(obj, "windowTitle", window.c_str());
obs_data_set_bool(obj, "fullscreen", fullscreen);
obs_data_set_bool(obj, "maximized", maximized);
obs_data_set_bool(obj, "focus", focus);
}
// To be removed in future version
bool loadOldWindow(obs_data_t *obj, WindowSwitch *s)
{
if (!s)
return false;
const char *scene = obs_data_get_string(obj, "scene");
if (strcmp(scene, "") == 0)
return false;
s->scene = GetWeakSourceByName(scene);
const char *transition = obs_data_get_string(obj, "transition");
s->transition = GetWeakTransitionByName(transition);
s->window = obs_data_get_string(obj, "window_title");
s->fullscreen = obs_data_get_bool(obj, "fullscreen");
#if __APPLE__
// TODO:
// not implemented on MacOS as I cannot test it
s->maximized = false;
#else
s->maximized = obs_data_get_bool(obj, "maximized");
#endif
s->focus = obs_data_get_bool(obj, "focus") ||
!obs_data_has_user_value(obj, "focus");
s->usePreviousScene = strcmp(scene, previous_scene_name) == 0;
return true;
}
void WindowSwitch::load(obs_data_t *obj)
{
if (loadOldWindow(obj, this))
return;
SceneSwitcherEntry::load(obj);
window = obs_data_get_string(obj, "windowTitle");
fullscreen = obs_data_get_bool(obj, "fullscreen");
#if __APPLE__
// TODO:
// not implemented on MacOS as I cannot test it
maximized = false;
#else
maximized = obs_data_get_bool(obj, "maximized");
#endif
focus = obs_data_get_bool(obj, "focus") ||
!obs_data_has_user_value(obj, "focus");
}
WindowSwitchWidget::WindowSwitchWidget(QWidget *parent, WindowSwitch *s)
: SwitchWidget(parent, s, false, true)
{
windows = new QComboBox();
fullscreen = new QCheckBox(

View File

@ -92,6 +92,12 @@ void SwitcherData::Prune()
if (!s.valid())
audioSwitches.erase(audioSwitches.begin() + i--);
}
for (auto &sg : sceneGroups) {
for (size_t i = 0; i < sg.scenes.size(); i++)
if (!WeakSourceValid(sg.scenes[i]))
sg.scenes.erase(sg.scenes.begin() + i--);
}
}
bool SwitcherData::versionChanged(obs_data_t *obj, std::string currentVersion)