diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui
index c0d11a2c..dfb9033e 100644
--- a/forms/advanced-scene-switcher.ui
+++ b/forms/advanced-scene-switcher.ui
@@ -2001,100 +2001,6 @@
Media
- -
-
-
-
-
-
- When
-
-
-
- -
-
-
- -
-
-
- state is
-
-
-
- -
-
-
- -
-
-
- and
-
-
-
- -
-
-
- -
-
-
- ms
-
-
- 0
-
-
- 1000000
-
-
-
- -
-
-
- switch to
-
-
-
- -
-
-
-
- 100
- 0
-
-
-
-
- -
-
-
- using the
-
-
-
- -
-
-
- -
-
-
- transition
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp
index 2c4bd60e..a56e7781 100644
--- a/src/headers/advanced-scene-switcher.hpp
+++ b/src/headers/advanced-scene-switcher.hpp
@@ -181,12 +181,10 @@ public slots:
void on_fileUp_clicked();
void on_fileDown_clicked();
- void on_mediaSwitches_currentRowChanged(int idx);
void on_mediaAdd_clicked();
void on_mediaRemove_clicked();
void on_mediaUp_clicked();
void on_mediaDown_clicked();
- void on_mediaTimeRestrictions_currentIndexChanged(int idx);
void on_timeSwitches_currentRowChanged(int idx);
void on_timeAdd_clicked();
diff --git a/src/headers/switch-media.hpp b/src/headers/switch-media.hpp
index 8b9f1a2f..be15f755 100644
--- a/src/headers/switch-media.hpp
+++ b/src/headers/switch-media.hpp
@@ -1,5 +1,4 @@
#pragma once
-#include
#include "utility.hpp"
#include "switch-generic.hpp"
@@ -15,36 +14,57 @@ typedef enum {
} time_restriction;
struct MediaSwitch : SceneSwitcherEntry {
- OBSWeakSource source;
- obs_media_state state;
- time_restriction restriction;
- int64_t time;
- bool matched;
- std::string mediaSwitchStr;
+ OBSWeakSource source = nullptr;
+ obs_media_state state = OBS_MEDIA_STATE_NONE;
+ time_restriction restriction = TIME_RESTRICTION_NONE;
+ int64_t time = 0;
- const char *getType() { return "meida"; }
-
- bool valid()
- {
- return (usePreviousScene || WeakSourceValid(scene)) &&
- WeakSourceValid(source) && WeakSourceValid(transition);
- }
+ const char *getType() { return "media"; }
+ bool initialized();
+ bool valid();
+ inline MediaSwitch(){};
inline MediaSwitch(OBSWeakSource scene_, OBSWeakSource source_,
OBSWeakSource transition_, obs_media_state state_,
time_restriction restriction_, uint64_t time_,
- bool usePreviousScene_, std::string mediaSwitchStr_)
+ bool usePreviousScene_)
: SceneSwitcherEntry(scene_, transition_, usePreviousScene_),
source(source_),
state(state_),
restriction(restriction_),
- time(time_),
- mediaSwitchStr(mediaSwitchStr_)
+ time(time_)
{
}
};
-static inline QString
-MakeMediaSwitchName(const QString &source, const QString &scene,
- const QString &transition, obs_media_state state,
- time_restriction restriction, uint64_t time);
+class MediaSwitchWidget : public SwitchWidget {
+ Q_OBJECT
+
+public:
+ MediaSwitchWidget(MediaSwitch *s);
+ MediaSwitch *getSwitchData();
+ void setSwitchData(MediaSwitch *s);
+
+ static void swapSwitchData(MediaSwitchWidget *s1,
+ MediaSwitchWidget *s2);
+
+private slots:
+ void SourceChanged(const QString &text);
+ void StateChanged(int index);
+ void TimeRestrictionChanged(int index);
+ void TimeChanged(int time);
+
+private:
+ QComboBox *meidaSources;
+ QComboBox *states;
+ QComboBox *timeRestrictions;
+ QSpinBox *time;
+
+ QLabel *whenLabel;
+ QLabel *stateLabel;
+ QLabel *andLabel;
+ QLabel *switchLabel;
+ QLabel *usingLabel;
+
+ MediaSwitch *switchData;
+};
diff --git a/src/headers/switcher-data-structs.hpp b/src/headers/switcher-data-structs.hpp
index 53688c6e..11b7be23 100644
--- a/src/headers/switcher-data-structs.hpp
+++ b/src/headers/switcher-data-structs.hpp
@@ -20,7 +20,6 @@
#include "switch-window.hpp"
#include "swtich-sequence.hpp"
-
constexpr auto default_interval = 300;
constexpr auto previous_scene_name = "Previous Scene";
@@ -94,7 +93,7 @@ struct SwitcherData {
std::vector sceneTransitions;
std::vector defaultSceneTransitions;
- std::vector mediaSwitches;
+ std::deque mediaSwitches;
std::vector timeSwitches;
QDateTime liveTime;
@@ -147,8 +146,8 @@ struct SwitcherData {
void autoStartStreamRecording();
bool checkPause();
void checkSceneSequence(bool &match, OBSWeakSource &scene,
- OBSWeakSource &transition,
- std::unique_lock &lock);
+ OBSWeakSource &transition,
+ std::unique_lock &lock);
void checkIdleSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition);
void checkWindowTitleSwitch(bool &match, OBSWeakSource &scene,
diff --git a/src/switch-media.cpp b/src/switch-media.cpp
index b5e7e552..7afbb332 100644
--- a/src/switch-media.cpp
+++ b/src/switch-media.cpp
@@ -1,69 +1,17 @@
#include "headers/advanced-scene-switcher.hpp"
-void SceneSwitcher::on_mediaSwitches_currentRowChanged(int idx)
-{
- if (loading)
- return;
- if (idx == -1)
- return;
-
- QListWidgetItem *item = ui->mediaSwitches->item(idx);
-
- QString mediaSceneStr = item->data(Qt::UserRole).toString();
-
- std::lock_guard lock(switcher->m);
- for (auto &s : switcher->mediaSwitches) {
- if (mediaSceneStr.compare(s.mediaSwitchStr.c_str()) == 0) {
- QString sceneName = GetWeakSourceName(s.scene).c_str();
- QString sourceName =
- GetWeakSourceName(s.source).c_str();
- QString transitionName =
- GetWeakSourceName(s.transition).c_str();
- ui->mediaScenes->setCurrentText(sceneName);
- ui->mediaSources->setCurrentText(sourceName);
- ui->mediaTransitions->setCurrentText(transitionName);
- ui->mediaStates->setCurrentIndex(s.state);
- ui->mediaTimeRestrictions->setCurrentIndex(
- s.restriction);
- ui->mediaTime->setValue(s.time);
- break;
- }
- }
-}
-
void SceneSwitcher::on_mediaAdd_clicked()
{
- QString sourceName = ui->mediaSources->currentText();
- QString sceneName = ui->mediaScenes->currentText();
- QString transitionName = ui->mediaTransitions->currentText();
- obs_media_state state =
- (obs_media_state)ui->mediaStates->currentIndex();
- time_restriction restriction =
- (time_restriction)ui->mediaTimeRestrictions->currentIndex();
- uint64_t time = ui->mediaTime->value();
-
- if (sceneName.isEmpty() || transitionName.isEmpty() ||
- sourceName.isEmpty())
- return;
-
- OBSWeakSource source = GetWeakSourceByQString(sourceName);
- OBSWeakSource scene = GetWeakSourceByQString(sceneName);
- OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
-
- QString switchText = MakeMediaSwitchName(sourceName, sceneName,
- transitionName, state,
- restriction, time);
- QVariant v = QVariant::fromValue(switchText);
-
- QListWidgetItem *item =
- new QListWidgetItem(switchText, ui->mediaSwitches);
- item->setData(Qt::UserRole, v);
-
std::lock_guard lock(switcher->m);
- switcher->mediaSwitches.emplace_back(
- scene, source, transition, state, restriction, time,
- (sceneName == QString(previous_scene_name)),
- switchText.toUtf8().constData());
+ switcher->mediaSwitches.emplace_back();
+
+ QListWidgetItem *item;
+ item = new QListWidgetItem(ui->mediaSwitches);
+ ui->mediaSwitches->addItem(item);
+ MediaSwitchWidget *sw =
+ new MediaSwitchWidget(&switcher->mediaSwitches.back());
+ item->setSizeHint(sw->minimumSizeHint());
+ ui->mediaSwitches->setItemWidget(item, sw);
}
void SceneSwitcher::on_mediaRemove_clicked()
@@ -72,20 +20,11 @@ void SceneSwitcher::on_mediaRemove_clicked()
if (!item)
return;
- std::string mediaStr =
- item->data(Qt::UserRole).toString().toUtf8().constData();
{
std::lock_guard lock(switcher->m);
+ int idx = ui->mediaSwitches->currentRow();
auto &switches = switcher->mediaSwitches;
-
- for (auto it = switches.begin(); it != switches.end(); ++it) {
- auto &s = *it;
-
- if (s.mediaSwitchStr == mediaStr) {
- switches.erase(it);
- break;
- }
- }
+ switches.erase(switches.begin() + idx);
}
delete item;
@@ -94,50 +33,50 @@ void SceneSwitcher::on_mediaRemove_clicked()
void SceneSwitcher::on_mediaUp_clicked()
{
int index = ui->mediaSwitches->currentRow();
- if (index != -1 && index != 0) {
- ui->mediaSwitches->insertItem(
- index - 1, ui->mediaSwitches->takeItem(index));
- ui->mediaSwitches->setCurrentRow(index - 1);
+ if (!listMoveUp(ui->mediaSwitches))
+ return;
- std::lock_guard lock(switcher->m);
+ MediaSwitchWidget *s1 =
+ (MediaSwitchWidget *)ui->mediaSwitches->itemWidget(
+ ui->mediaSwitches->item(index));
+ MediaSwitchWidget *s2 =
+ (MediaSwitchWidget *)ui->mediaSwitches->itemWidget(
+ ui->mediaSwitches->item(index - 1));
+ MediaSwitchWidget::swapSwitchData(s1, s2);
- iter_swap(switcher->mediaSwitches.begin() + index,
- switcher->mediaSwitches.begin() + index - 1);
- }
+ std::lock_guard lock(switcher->m);
+
+ std::swap(switcher->mediaSwitches[index],
+ switcher->mediaSwitches[index - 1]);
}
void SceneSwitcher::on_mediaDown_clicked()
{
int index = ui->mediaSwitches->currentRow();
- if (index != -1 && index != ui->mediaSwitches->count() - 1) {
- ui->mediaSwitches->insertItem(
- index + 1, ui->mediaSwitches->takeItem(index));
- ui->mediaSwitches->setCurrentRow(index + 1);
- std::lock_guard lock(switcher->m);
-
- iter_swap(switcher->mediaSwitches.begin() + index,
- switcher->mediaSwitches.begin() + index + 1);
- }
-}
-
-void SceneSwitcher::on_mediaTimeRestrictions_currentIndexChanged(int idx)
-{
- if (idx == -1)
+ if (!listMoveDown(ui->mediaSwitches))
return;
- if ((time_restriction)ui->mediaTimeRestrictions->currentIndex() ==
- TIME_RESTRICTION_NONE) {
- ui->mediaTime->setDisabled(true);
- } else {
- ui->mediaTime->setDisabled(false);
- }
+ MediaSwitchWidget *s1 =
+ (MediaSwitchWidget *)ui->mediaSwitches->itemWidget(
+ ui->mediaSwitches->item(index));
+ MediaSwitchWidget *s2 =
+ (MediaSwitchWidget *)ui->mediaSwitches->itemWidget(
+ ui->mediaSwitches->item(index + 1));
+ MediaSwitchWidget::swapSwitchData(s1, s2);
+
+ std::lock_guard lock(switcher->m);
+
+ std::swap(switcher->mediaSwitches[index],
+ switcher->mediaSwitches[index + 1]);
}
void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition)
{
for (MediaSwitch &mediaSwitch : mediaSwitches) {
+ if (!mediaSwitch.initialized())
+ continue;
obs_source_t *source =
obs_weak_source_get_source(mediaSwitch.source);
auto duration = obs_source_media_get_duration(source);
@@ -158,7 +97,7 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
TIME_RESTRICTION_REMAINING_LONGER &&
duration > time &&
duration - time > mediaSwitch.time));
- if (matched && !mediaSwitch.matched) {
+ if (matched) {
match = true;
scene = (mediaSwitch.usePreviousScene)
? previousScene
@@ -167,8 +106,8 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
if (verbose)
mediaSwitch.logMatch();
+ break;
}
- mediaSwitch.matched = matched;
obs_source_release(source);
}
}
@@ -233,17 +172,10 @@ void SwitcherData::loadMediaSwitches(obs_data_t *obj)
"restriction");
uint64_t time = obs_data_get_int(array_obj, "time");
- std::string mediaStr = MakeMediaSwitchName(source, scene,
- transition, state,
- restriction, time)
- .toUtf8()
- .constData();
-
switcher->mediaSwitches.emplace_back(
GetWeakSourceByName(scene), GetWeakSourceByName(source),
GetWeakTransitionByName(transition), state, restriction,
- time, (strcmp(scene, previous_scene_name) == 0),
- mediaStr);
+ time, (strcmp(scene, previous_scene_name) == 0));
obs_data_release(array_obj);
}
@@ -252,81 +184,175 @@ void SwitcherData::loadMediaSwitches(obs_data_t *obj)
void SceneSwitcher::setupMediaTab()
{
- populateSceneSelection(ui->mediaScenes, true);
- populateTransitionSelection(ui->mediaTransitions);
- populateMediaSelection(ui->mediaSources);
-
- ui->mediaStates->addItem("None");
- ui->mediaStates->addItem("Playing");
- ui->mediaStates->addItem("Opening");
- ui->mediaStates->addItem("Buffering");
- ui->mediaStates->addItem("Paused");
- ui->mediaStates->addItem("Stopped");
- ui->mediaStates->addItem("Ended");
- ui->mediaStates->addItem("Error");
-
- ui->mediaTimeRestrictions->addItem("None");
- ui->mediaTimeRestrictions->addItem("Time shorter");
- ui->mediaTimeRestrictions->addItem("Time longer");
- ui->mediaTimeRestrictions->addItem("Time remaining shorter");
- ui->mediaTimeRestrictions->addItem("Time remaining longer");
-
for (auto &s : switcher->mediaSwitches) {
std::string sourceName = GetWeakSourceName(s.source);
std::string sceneName = (s.usePreviousScene)
? previous_scene_name
: GetWeakSourceName(s.scene);
std::string transitionName = GetWeakSourceName(s.transition);
- QString listText = MakeMediaSwitchName(
- sourceName.c_str(), sceneName.c_str(),
- transitionName.c_str(), s.state, s.restriction, s.time);
- QListWidgetItem *item =
- new QListWidgetItem(listText, ui->mediaSwitches);
- item->setData(Qt::UserRole, listText);
+ QListWidgetItem *item;
+ item = new QListWidgetItem(ui->mediaSwitches);
+ ui->mediaSwitches->addItem(item);
+ MediaSwitchWidget *sw = new MediaSwitchWidget(&s);
+ item->setSizeHint(sw->minimumSizeHint());
+ ui->mediaSwitches->setItemWidget(item, sw);
}
}
-static inline QString
-MakeMediaSwitchName(const QString &source, const QString &scene,
- const QString &transition, obs_media_state state,
- time_restriction restriction, uint64_t time)
+bool MediaSwitch::initialized()
{
- QString switchName = QStringLiteral("Switch to ") + scene +
- QStringLiteral(" using ") + transition +
- QStringLiteral(" if ") + source +
- QStringLiteral(" state is ");
- if (state == OBS_MEDIA_STATE_NONE) {
- switchName += QStringLiteral("none");
- } else if (state == OBS_MEDIA_STATE_PLAYING) {
- switchName += QStringLiteral("playing");
- } else if (state == OBS_MEDIA_STATE_OPENING) {
- switchName += QStringLiteral("opening");
- } else if (state == OBS_MEDIA_STATE_BUFFERING) {
- switchName += QStringLiteral("buffering");
- } else if (state == OBS_MEDIA_STATE_PAUSED) {
- switchName += QStringLiteral("paused");
- } else if (state == OBS_MEDIA_STATE_STOPPED) {
- switchName += QStringLiteral("stopped");
- } else if (state == OBS_MEDIA_STATE_ENDED) {
- switchName += QStringLiteral("ended");
- } else if (state == OBS_MEDIA_STATE_ERROR) {
- switchName += QStringLiteral("error");
- }
- if (restriction == TIME_RESTRICTION_SHORTER) {
- switchName += QStringLiteral(" and time shorter than ");
- } else if (restriction == TIME_RESTRICTION_LONGER) {
- switchName += QStringLiteral(" and time longer than ");
- } else if (restriction == TIME_RESTRICTION_REMAINING_SHORTER) {
- switchName +=
- QStringLiteral(" and time remaining shorter than ");
- } else if (restriction == TIME_RESTRICTION_REMAINING_LONGER) {
- switchName +=
- QStringLiteral(" and time remaining longer than ");
- }
- if (restriction != TIME_RESTRICTION_NONE) {
- switchName += std::to_string(time).c_str();
- switchName += QStringLiteral(" ms");
- }
- return switchName;
+ return SceneSwitcherEntry::initialized() && source;
+}
+
+bool MediaSwitch::valid()
+{
+ return !initialized() ||
+ (SceneSwitcherEntry::valid() && WeakSourceValid(source));
+}
+
+void populateMediaStates(QComboBox *list)
+{
+ list->addItem("None");
+ list->addItem("Playing");
+ list->addItem("Opening");
+ list->addItem("Buffering");
+ list->addItem("Paused");
+ list->addItem("Stopped");
+ list->addItem("Ended");
+ list->addItem("Error");
+}
+
+void populateTimeRestrictions(QComboBox *list)
+{
+ list->addItem("None");
+ list->addItem("Time shorter");
+ list->addItem("Time longer");
+ list->addItem("Time remaining shorter");
+ list->addItem("Time remaining longer");
+}
+
+MediaSwitchWidget::MediaSwitchWidget(MediaSwitch *s) : SwitchWidget(s)
+{
+ meidaSources = new QComboBox();
+ states = new QComboBox();
+ timeRestrictions = new QComboBox();
+ time = new QSpinBox();
+
+ whenLabel = new QLabel("When");
+ stateLabel = new QLabel("state is");
+ andLabel = new QLabel("and");
+ switchLabel = new QLabel("switch to");
+ usingLabel = new QLabel("using");
+
+ time->setSuffix("ms");
+ time->setMaximum(99999999);
+ time->setMinimum(0);
+
+ QWidget::connect(meidaSources,
+ SIGNAL(currentTextChanged(const QString &)), this,
+ SLOT(SourceChanged(const QString &)));
+ QWidget::connect(states, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(StateChanged(int)));
+ QWidget::connect(timeRestrictions, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(TimeRestrictionChanged(int)));
+ QWidget::connect(states, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(StateChanged(const QString &)));
+ QWidget::connect(time, SIGNAL(valueChanged(int)), this,
+ SLOT(TimeChanged(int)));
+
+ SceneSwitcher::populateMediaSelection(meidaSources);
+ populateMediaStates(states);
+ populateTimeRestrictions(timeRestrictions);
+
+ if (s) {
+ meidaSources->setCurrentText(
+ GetWeakSourceName(s->source).c_str());
+ states->setCurrentIndex(s->state);
+ timeRestrictions->setCurrentIndex(s->restriction);
+ time->setValue(s->time);
+ if (s->restriction == TIME_RESTRICTION_NONE)
+ time->setDisabled(true);
+ }
+
+ setStyleSheet("* { background-color: transparent; }");
+
+ QHBoxLayout *mainLayout = new QHBoxLayout;
+
+ mainLayout->addWidget(whenLabel);
+ mainLayout->addWidget(meidaSources);
+ mainLayout->addWidget(stateLabel);
+ mainLayout->addWidget(states);
+ mainLayout->addWidget(andLabel);
+ mainLayout->addWidget(timeRestrictions);
+ mainLayout->addWidget(time);
+ mainLayout->addWidget(switchLabel);
+ mainLayout->addWidget(scenes);
+ mainLayout->addWidget(usingLabel);
+ mainLayout->addWidget(transitions);
+ mainLayout->addStretch();
+
+ setLayout(mainLayout);
+
+ switchData = s;
+
+ loading = false;
+}
+
+MediaSwitch *MediaSwitchWidget::getSwitchData()
+{
+ return switchData;
+}
+
+void MediaSwitchWidget::setSwitchData(MediaSwitch *s)
+{
+ switchData = s;
+}
+
+void MediaSwitchWidget::swapSwitchData(MediaSwitchWidget *s1,
+ MediaSwitchWidget *s2)
+{
+ SwitchWidget::swapSwitchData(s1, s2);
+
+ MediaSwitch *t = s1->getSwitchData();
+ s1->setSwitchData(s2->getSwitchData());
+ s2->setSwitchData(t);
+}
+
+void MediaSwitchWidget::SourceChanged(const QString &text)
+{
+ if (loading || !switchData)
+ return;
+ std::lock_guard lock(switcher->m);
+ switchData->source = GetWeakSourceByQString(text);
+}
+
+void MediaSwitchWidget::StateChanged(int index)
+{
+ if (loading || !switchData)
+ return;
+ std::lock_guard lock(switcher->m);
+ switchData->state = (obs_media_state)index;
+}
+
+void MediaSwitchWidget::TimeRestrictionChanged(int index)
+{
+ if (loading || !switchData)
+ return;
+
+ if ((time_restriction)index == TIME_RESTRICTION_NONE)
+ time->setDisabled(true);
+ else
+ time->setDisabled(false);
+
+ std::lock_guard lock(switcher->m);
+ switchData->restriction = (time_restriction)index;
+}
+
+void MediaSwitchWidget::TimeChanged(int time)
+{
+ if (loading || !switchData)
+ return;
+ std::lock_guard lock(switcher->m);
+ switchData->time = time;
}