Rework Media condition

* Split state and time check
* Improve signal handling
* Prevent exponential memory groth when using the "any" / "all" check
* Improve layout
This commit is contained in:
WarmUpTill
2024-07-25 12:11:37 +02:00
committed by WarmUpTill
parent bedb3b8dc6
commit 240c47975c
9 changed files with 215 additions and 146 deletions

View File

@@ -159,7 +159,7 @@ AdvSceneSwitcher.condition.media.source="Quelle"
AdvSceneSwitcher.condition.media.anyOnScene="Beliebige Medienquelle in"
AdvSceneSwitcher.condition.media.allOnScene="Alle Medienquellen in"
AdvSceneSwitcher.condition.media.inconsistencyInfo="Leider verhalten sich nicht alle Medien-Quell-Typen gleich (z.B. Medien-Quelle vs. VLC-Video-Quelle \"Gestoppt\"-Status).\nBitte experimentieren, was in eurem Setup funktioniert!"
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}Status ist{{states}}und{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}Status ist{{states}}und{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.video="Video"
AdvSceneSwitcher.condition.video.condition.match="entspricht genau"
AdvSceneSwitcher.condition.video.condition.differ="stimmt nicht überein"

View File

@@ -307,11 +307,14 @@ AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{condition
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
AdvSceneSwitcher.condition.media="Media"
AdvSceneSwitcher.condition.media.checkType.state="State matches"
AdvSceneSwitcher.condition.media.checkType.time="Time restriction matches"
AdvSceneSwitcher.condition.media.source="Source"
AdvSceneSwitcher.condition.media.anyOnScene="Any media source on"
AdvSceneSwitcher.condition.media.allOnScene="All media sources on"
AdvSceneSwitcher.condition.media.inconsistencyInfo="Unfortunately not all media source types behave the same (e.g. Media Source vs. VLC Video Source \"Stopped\" state).\nSo please experiment what works for your setup!"
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}state is{{states}}and{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.media.layout="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}{{states}}{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}state is{{states}}and{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.video="Video"
AdvSceneSwitcher.condition.video.condition.match="exactly matches"
AdvSceneSwitcher.condition.video.condition.differ="does not match"

View File

@@ -128,7 +128,7 @@ AdvSceneSwitcher.condition.media="Medios"
AdvSceneSwitcher.condition.media.anyOnScene="Cualquier fuente multimedia activada"
AdvSceneSwitcher.condition.media.allOnScene="Todas las fuentes de medios activadas"
AdvSceneSwitcher.condition.media.inconsistencyInfo="Desafortunadamente, no todos los tipos de fuentes de medios se comportan de la misma manera (p. ej., fuente de medios frente a estado \"Detenido\" de fuente de video VLC).\n¡Así que experimente lo que funciona para su configuración!"
AdvSceneSwitcher.condition.media.entry="El estado de{{sourceTypes}}{{mediaSources}}{{scenes}}es{{states}}y{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.media.layout.legacy="El estado de{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}es{{states}}y{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.video="Video"
AdvSceneSwitcher.condition.video.condition.match="coincide exactamente"
AdvSceneSwitcher.condition.video.condition.differ="no coincide"

View File

@@ -196,7 +196,7 @@ AdvSceneSwitcher.condition.media.source="Source"
AdvSceneSwitcher.condition.media.anyOnScene="Toute source média sur la scène"
AdvSceneSwitcher.condition.media.allOnScene="Toutes les sources média sur la scène"
AdvSceneSwitcher.condition.media.inconsistencyInfo="Malheureusement, toutes les sources média ne se comportent pas de la même manière (par exemple, l'état \"Arrêté\" de la source Media par rapport à la source Vidéo VLC).\nPar conséquent, veuillez expérimenter ce qui fonctionne le mieux pour votre configuration !"
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}l'état est{{states}}et{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}l'état est{{states}}et{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.video="Vidéo"
AdvSceneSwitcher.condition.video.condition.match="correspond exactement à"
AdvSceneSwitcher.condition.video.condition.differ="ne correspond pas à"

View File

@@ -311,7 +311,7 @@ AdvSceneSwitcher.condition.media.source="ソース"
AdvSceneSwitcher.condition.media.anyOnScene="あらゆるメディアソース"
AdvSceneSwitcher.condition.media.allOnScene="すべてのメディアソースはこちら"
AdvSceneSwitcher.condition.media.inconsistencyInfo="残念ながら、すべてのメディア ソース タイプが同じように動作するわけではありません (例: メディア ソースと VLC ビデオ ソースの \"Stopped\" 状態)。\nそのため、ご自身のセットアップに適したものを試してみてください。"
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}の状態は{{states}}かつ{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}の状態は{{states}}かつ{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.video="動画"
AdvSceneSwitcher.condition.video.condition.match="完全一致"
AdvSceneSwitcher.condition.video.condition.differ="合わない"

View File

@@ -117,7 +117,7 @@ AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFil
AdvSceneSwitcher.condition.media="Medya"
AdvSceneSwitcher.condition.media.anyOnScene="Herhangi bir medya kaynağı"
AdvSceneSwitcher.condition.media.allOnScene="Tüm medya kaynakları "
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}durumu{{states}}ve{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}durumu{{states}}ve{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.video="Video"
AdvSceneSwitcher.condition.video.condition.match="Tam olarak eşleşir"
AdvSceneSwitcher.condition.video.condition.differ="Eşleştirme"

View File

@@ -184,7 +184,7 @@ AdvSceneSwitcher.condition.media.source="源"
AdvSceneSwitcher.condition.media.anyOnScene="任何媒体源"
AdvSceneSwitcher.condition.media.allOnScene="所有媒体源"
AdvSceneSwitcher.condition.media.inconsistencyInfo="不幸的是并非所有媒体源类型的行为都相同例如媒体源与VLC视频源“停止”状态。\n所以请尝试适合您的设置"
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}} 的状态是 {{states}}{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}的状态是{{states}}{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.video="视频"
AdvSceneSwitcher.condition.video.condition.match="完全匹配"
AdvSceneSwitcher.condition.video.condition.differ="不匹配"

View File

@@ -52,16 +52,6 @@ static const std::map<MacroConditionMedia::State, std::string> mediaStates = {
"AdvSceneSwitcher.mediaTab.states.any"},
};
MacroConditionMedia::~MacroConditionMedia()
{
OBSSourceAutoRelease mediasource =
obs_weak_source_get_source(_source.GetSource());
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
signal_handler_disconnect(sh, "media_stopped", MediaStopped, this);
signal_handler_disconnect(sh, "media_ended", MediaEnded, this);
signal_handler_disconnect(sh, "media_next", MediaNext, this);
}
bool MacroConditionMedia::CheckTime()
{
OBSSourceAutoRelease s =
@@ -71,7 +61,7 @@ bool MacroConditionMedia::CheckTime()
bool match = false;
switch (_restriction) {
switch (_timeRestriction) {
case Time::TIME_RESTRICTION_NONE:
match = true;
break;
@@ -152,7 +142,21 @@ bool MacroConditionMedia::CheckMediaMatch()
if (!_source.GetSource()) {
return false;
}
bool matched = CheckState() && CheckTime();
bool matched = false;
switch (_checkType) {
case CheckType::STATE:
matched = CheckState();
break;
case CheckType::TIME:
matched = CheckTime();
break;
case CheckType::LEGACY:
matched = CheckState() && CheckTime();
break;
default:
break;
}
// reset for next check
_stopped = false;
@@ -168,16 +172,50 @@ void MacroConditionMedia::HandleSceneChange()
_lastConfigureScene = GetCurrentScene();
}
MacroConditionMedia::MacroConditionMedia(const MacroConditionMedia &other)
: MacroCondition(other.GetMacro()),
_sourceType(other._sourceType),
_checkType(other._checkType),
_state(other._state),
_timeRestriction(other._timeRestriction),
_scene(other._scene),
_source(other._source),
_rawSource(other._rawSource),
_sourceGroup(),
_time(other._time),
_lastConfigureScene(other._lastConfigureScene)
{
ResetSignalHandler();
}
MacroConditionMedia &
MacroConditionMedia::operator=(const MacroConditionMedia &other)
{
_sourceType = other._sourceType;
_checkType = other._checkType;
_state = other._state;
_timeRestriction = other._timeRestriction;
_scene = other._scene;
_source = other._source;
_rawSource = other._rawSource;
_time = other._time;
_lastConfigureScene = other._lastConfigureScene;
ResetSignalHandler();
return *this;
}
bool MacroConditionMedia::CheckCondition()
{
bool match = false;
switch (_sourceType) {
case Type::ANY:
case SourceType::ANY:
for (auto &source : _sourceGroup) {
match = match || source.CheckCondition();
}
break;
case Type::ALL: {
case SourceType::ALL: {
bool res = true;
for (auto &source : _sourceGroup) {
res = res && source.CheckCondition();
@@ -185,7 +223,7 @@ bool MacroConditionMedia::CheckCondition()
match = res;
break;
}
case Type::SOURCE:
case SourceType::SOURCE:
match = CheckMediaMatch();
break;
default:
@@ -205,10 +243,12 @@ bool MacroConditionMedia::Save(obs_data_t *obj) const
_source.Save(obj);
_scene.Save(obj);
obs_data_set_int(obj, "sourceType", static_cast<int>(_sourceType));
obs_data_set_int(obj, "checkType", static_cast<int>(_checkType));
obs_data_set_int(obj, "state", static_cast<int>(_state));
obs_data_set_int(obj, "restriction", static_cast<int>(_restriction));
obs_data_set_int(obj, "restriction",
static_cast<int>(_timeRestriction));
_time.Save(obj);
obs_data_set_int(obj, "version", 0);
obs_data_set_int(obj, "version", 1);
return true;
}
@@ -245,7 +285,7 @@ void MacroConditionMedia::UpdateMediaSourcesOfSceneList()
for (auto &source : mediaSources) {
MacroConditionMedia cond(*this);
cond._sourceType = Type::SOURCE;
cond._sourceType = SourceType::SOURCE;
cond._source.SetSource(source);
_sourceGroup.push_back(cond);
}
@@ -256,28 +296,31 @@ bool MacroConditionMedia::Load(obs_data_t *obj)
MacroCondition::Load(obj);
_source.Load(obj);
_scene.Load(obj);
_sourceType = static_cast<Type>(obs_data_get_int(obj, "sourceType"));
_state = static_cast<MacroConditionMedia::State>(
obs_data_get_int(obj, "state"));
_restriction = static_cast<MacroConditionMedia::Time>(
obs_data_get_int(obj, "restriction"));
_sourceType =
static_cast<SourceType>(obs_data_get_int(obj, "sourceType"));
_state = static_cast<State>(obs_data_get_int(obj, "state"));
_checkType = static_cast<CheckType>(obs_data_get_int(obj, "checkType"));
_timeRestriction =
static_cast<Time>(obs_data_get_int(obj, "restriction"));
_time.Load(obj);
if (_sourceType == Type::SOURCE) {
OBSSourceAutoRelease mediasource =
obs_weak_source_get_source(_source.GetSource());
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);
signal_handler_connect(sh, "media_next", MediaNext, this);
if (_sourceType == SourceType::SOURCE) {
ResetSignalHandler();
}
UpdateMediaSourcesOfSceneList();
if (!obs_data_has_user_value(obj, "version")) {
if (_state ==
MacroConditionMedia::State::OBS_MEDIA_STATE_ENDED) {
_state = MacroConditionMedia::State::PLAYLIST_ENDED;
if (_state == State::OBS_MEDIA_STATE_ENDED) {
_state = State::PLAYLIST_ENDED;
}
}
if (obs_data_get_int(obj, "version") < 1) {
if (IsUsingLegacyCheck()) {
_checkType = CheckType::LEGACY;
} else if (_state == State::ANY) {
_checkType = CheckType::TIME;
} else {
_checkType = CheckType::STATE;
}
}
return true;
@@ -286,16 +329,16 @@ bool MacroConditionMedia::Load(obs_data_t *obj)
std::string MacroConditionMedia::GetShortDesc() const
{
switch (_sourceType) {
case Type::SOURCE:
case SourceType::SOURCE:
return _source.ToString();
case Type::ANY:
case SourceType::ANY:
if (_scene.GetScene(false)) {
return obs_module_text(
"AdvSceneSwitcher.condition.media.anyOnScene") +
std::string(" ") + _scene.ToString();
}
break;
case Type::ALL:
case SourceType::ALL:
if (_scene.GetScene(false)) {
return obs_module_text(
"AdvSceneSwitcher.condition.media.allOnScene") +
@@ -308,27 +351,21 @@ std::string MacroConditionMedia::GetShortDesc() const
return "";
}
void MacroConditionMedia::ClearSignalHandler()
bool MacroConditionMedia::IsUsingLegacyCheck() const
{
OBSSourceAutoRelease mediasource =
obs_weak_source_get_source(_source.GetSource());
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
signal_handler_disconnect(sh, "media_stopped", MediaStopped, this);
signal_handler_disconnect(sh, "media_ended", MediaEnded, this);
signal_handler_disconnect(sh, "media_next", MediaNext, this);
return _state != State::ANY &&
_timeRestriction != Time::TIME_RESTRICTION_NONE;
}
void MacroConditionMedia::ResetSignalHandler()
{
_signals.clear();
OBSSourceAutoRelease mediasource =
obs_weak_source_get_source(_source.GetSource());
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
signal_handler_disconnect(sh, "media_stopped", MediaStopped, this);
signal_handler_disconnect(sh, "media_ended", MediaEnded, this);
signal_handler_disconnect(sh, "media_next", MediaNext, this);
signal_handler_connect(sh, "media_stopped", MediaStopped, this);
signal_handler_connect(sh, "media_ended", MediaEnded, this);
signal_handler_connect(sh, "media_next", MediaNext, this);
_signals.emplace_back(sh, "media_stopped", MediaStopped, this);
_signals.emplace_back(sh, "media_ended", MediaEnded, this);
_signals.emplace_back(sh, "media_next", MediaNext, this);
}
void MacroConditionMedia::MediaStopped(void *data, calldata_t *)
@@ -361,17 +398,28 @@ void MacroConditionMedia::MediaNext(void *data, calldata_t *)
media->_next = true;
}
static void populateMediaTimes(QComboBox *list)
static void populateSateSelection(QComboBox *list, bool addLegacyEntries)
{
for (auto entry : mediaTimeRestrictions) {
list->addItem(obs_module_text(entry.second.c_str()));
for (const auto &[value, name] : mediaStates) {
if (value == MacroConditionMedia::State::ANY &&
!addLegacyEntries) {
continue;
}
list->addItem(obs_module_text(name.c_str()),
static_cast<int>(value));
}
}
static void populateMediaStates(QComboBox *list)
static void populateTimeRestrictionSelection(QComboBox *list,
bool addLegacyEntries)
{
for (auto entry : mediaStates) {
list->addItem(obs_module_text(entry.second.c_str()));
for (const auto &[value, name] : mediaTimeRestrictions) {
if (value == MacroConditionMedia::Time::TIME_RESTRICTION_NONE &&
!addLegacyEntries) {
continue;
}
list->addItem(obs_module_text(name.c_str()),
static_cast<int>(value));
}
}
@@ -380,19 +428,33 @@ static void populateSourceTypes(QComboBox *list)
list->clear();
list->addItem(
obs_module_text("AdvSceneSwitcher.condition.media.source"),
static_cast<int>(MacroConditionMedia::Type::SOURCE));
static_cast<int>(MacroConditionMedia::SourceType::SOURCE));
list->addItem(
obs_module_text("AdvSceneSwitcher.condition.media.anyOnScene"),
static_cast<int>(MacroConditionMedia::Type::ANY));
static_cast<int>(MacroConditionMedia::SourceType::ANY));
list->addItem(
obs_module_text("AdvSceneSwitcher.condition.media.allOnScene"),
static_cast<int>(MacroConditionMedia::Type::ALL));
static_cast<int>(MacroConditionMedia::SourceType::ALL));
}
static void populateCheckTypes(QComboBox *list)
{
list->clear();
list->addItem(
obs_module_text(
"AdvSceneSwitcher.condition.media.checkType.state"),
static_cast<int>(MacroConditionMedia::CheckType::STATE));
list->addItem(
obs_module_text(
"AdvSceneSwitcher.condition.media.checkType.time"),
static_cast<int>(MacroConditionMedia::CheckType::TIME));
}
MacroConditionMediaEdit::MacroConditionMediaEdit(
QWidget *parent, std::shared_ptr<MacroConditionMedia> entryData)
: QWidget(parent),
_sourceTypes(new QComboBox()),
_checkTypes(new QComboBox()),
_scenes(new SceneSelectionWidget(window(), true, true, true, true,
true)),
_sources(new SourceSelectionWidget(this, QStringList(), true)),
@@ -409,6 +471,8 @@ MacroConditionMediaEdit::MacroConditionMediaEdit(
QWidget::connect(_sourceTypes, SIGNAL(currentIndexChanged(int)), this,
SLOT(SourceTypeChanged(int)));
QWidget::connect(_checkTypes, SIGNAL(currentIndexChanged(int)), this,
SLOT(CheckTypeChanged(int)));
QWidget::connect(_sources,
SIGNAL(SourceChanged(const SourceSelection &)), this,
SLOT(SourceChanged(const SourceSelection &)));
@@ -422,20 +486,28 @@ MacroConditionMediaEdit::MacroConditionMediaEdit(
SLOT(TimeChanged(const Duration &)));
populateSourceTypes(_sourceTypes);
populateMediaStates(_states);
populateMediaTimes(_timeRestrictions);
populateCheckTypes(_checkTypes);
const bool isUsingLegacyCheck = entryData->_checkType ==
MacroConditionMedia::CheckType::LEGACY;
populateSateSelection(_states, isUsingLegacyCheck);
populateTimeRestrictionSelection(_timeRestrictions, isUsingLegacyCheck);
auto layout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{sourceTypes}}", _sourceTypes},
{"{{checkTypes}}", _checkTypes},
{"{{mediaSources}}", _sources},
{"{{scenes}}", _scenes},
{"{{states}}", _states},
{"{{timeRestrictions}}", _timeRestrictions},
{"{{time}}", _time},
};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.condition.media.entry"),
layout, widgetPlaceholders);
PlaceWidgets(
obs_module_text(
isUsingLegacyCheck
? "AdvSceneSwitcher.condition.media.layout.legacy"
: "AdvSceneSwitcher.condition.media.layout"),
layout, widgetPlaceholders);
setLayout(layout);
_entryData = entryData;
@@ -445,15 +517,12 @@ MacroConditionMediaEdit::MacroConditionMediaEdit(
void MacroConditionMediaEdit::SourceTypeChanged(int idx)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_sourceType = static_cast<MacroConditionMedia::Type>(
GUARD_LOADING_AND_LOCK();
_entryData->_sourceType = static_cast<MacroConditionMedia::SourceType>(
_sourceTypes->itemData(idx).toInt());
if (_entryData->_sourceType == MacroConditionMedia::Type::SOURCE) {
if (_entryData->_sourceType ==
MacroConditionMedia::SourceType::SOURCE) {
_entryData->_sourceGroup.clear();
}
@@ -464,16 +533,19 @@ void MacroConditionMediaEdit::SourceTypeChanged(int idx)
SetWidgetVisibility();
}
void MacroConditionMediaEdit::CheckTypeChanged(int idx)
{
GUARD_LOADING_AND_LOCK();
_entryData->_checkType = static_cast<MacroConditionMedia::CheckType>(
_checkTypes->itemData(idx).toInt());
SetWidgetVisibility();
}
void MacroConditionMediaEdit::SourceChanged(const SourceSelection &source)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_sourceGroup.clear();
_entryData->_sourceType = MacroConditionMedia::Type::SOURCE;
_entryData->ClearSignalHandler();
_entryData->_sourceType = MacroConditionMedia::SourceType::SOURCE;
_entryData->_source = source;
_entryData->ResetSignalHandler();
emit HeaderInfoChanged(
@@ -483,40 +555,20 @@ void MacroConditionMediaEdit::SourceChanged(const SourceSelection &source)
void MacroConditionMediaEdit::SceneChanged(const SceneSelection &s)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = s;
_entryData->UpdateMediaSourcesOfSceneList();
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
}
MacroConditionMedia::State getMediaStateFromIdx(int idx)
{
if (idx < static_cast<int>(
MacroConditionMedia::State::LAST_OBS_MEDIA_STATE)) {
return static_cast<MacroConditionMedia::State>(idx);
} else {
return static_cast<MacroConditionMedia::State>(
idx -
static_cast<int>(
MacroConditionMedia::State::LAST_OBS_MEDIA_STATE) +
custom_media_states_offset);
}
}
void MacroConditionMediaEdit::StateChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_state = getMediaStateFromIdx(index);
if (_entryData->_sourceType != MacroConditionMedia::Type::SOURCE) {
GUARD_LOADING_AND_LOCK();
_entryData->_state = static_cast<MacroConditionMedia::State>(
_states->itemData(index).toInt());
if (_entryData->_sourceType !=
MacroConditionMedia::SourceType::SOURCE) {
_entryData->UpdateMediaSourcesOfSceneList();
}
}
@@ -527,7 +579,9 @@ void MacroConditionMediaEdit::TimeRestrictionChanged(int index)
return;
}
if (static_cast<MacroConditionMedia::Time>(index) ==
const auto timeRestriction = static_cast<MacroConditionMedia::Time>(
_timeRestrictions->itemData(index).toInt());
if (timeRestriction ==
MacroConditionMedia::Time::TIME_RESTRICTION_NONE) {
_time->setDisabled(true);
} else {
@@ -535,9 +589,9 @@ void MacroConditionMediaEdit::TimeRestrictionChanged(int index)
}
auto lock = LockContext();
_entryData->_restriction =
static_cast<MacroConditionMedia::Time>(index);
if (_entryData->_sourceType != MacroConditionMedia::Type::SOURCE) {
_entryData->_timeRestriction = timeRestriction;
if (_entryData->_sourceType !=
MacroConditionMedia::SourceType::SOURCE) {
_entryData->UpdateMediaSourcesOfSceneList();
}
}
@@ -550,7 +604,8 @@ void MacroConditionMediaEdit::TimeChanged(const Duration &dur)
auto lock = LockContext();
_entryData->_time = dur;
if (_entryData->_sourceType != MacroConditionMedia::Type::SOURCE) {
if (_entryData->_sourceType !=
MacroConditionMedia::SourceType::SOURCE) {
_entryData->UpdateMediaSourcesOfSceneList();
}
}
@@ -558,20 +613,25 @@ void MacroConditionMediaEdit::TimeChanged(const Duration &dur)
void MacroConditionMediaEdit::SetWidgetVisibility()
{
_sources->setVisible(_entryData->_sourceType ==
MacroConditionMedia::Type::SOURCE);
MacroConditionMedia::SourceType::SOURCE);
_scenes->setVisible(_entryData->_sourceType !=
MacroConditionMedia::Type::SOURCE);
}
MacroConditionMedia::SourceType::SOURCE);
static int getIdxFromMediaState(MacroConditionMedia::State state)
{
if (state < MacroConditionMedia::State::LAST_OBS_MEDIA_STATE) {
return static_cast<int>(state);
} else {
return static_cast<int>(state) - custom_media_states_offset +
static_cast<int>(
MacroConditionMedia::State::LAST_OBS_MEDIA_STATE);
if (_entryData->_checkType == MacroConditionMedia::CheckType::LEGACY) {
_checkTypes->hide();
return;
}
_states->setVisible(_entryData->_checkType ==
MacroConditionMedia::CheckType::STATE);
_timeRestrictions->setVisible(_entryData->_checkType ==
MacroConditionMedia::CheckType::TIME);
_time->setVisible(_entryData->_checkType ==
MacroConditionMedia::CheckType::TIME);
adjustSize();
updateGeometry();
}
void MacroConditionMediaEdit::UpdateEntryData()
@@ -580,15 +640,18 @@ void MacroConditionMediaEdit::UpdateEntryData()
return;
}
_checkTypes->setCurrentIndex(_checkTypes->findData(
static_cast<int>(_entryData->_checkType)));
_sourceTypes->setCurrentIndex(_sourceTypes->findData(
static_cast<int>(_entryData->_sourceType)));
_sources->SetSource(_entryData->_source);
_scenes->SetScene(_entryData->_scene);
_states->setCurrentIndex(getIdxFromMediaState(_entryData->_state));
_timeRestrictions->setCurrentIndex(
static_cast<int>(_entryData->_restriction));
_states->setCurrentIndex(
_states->findData(static_cast<int>(_entryData->_state)));
_timeRestrictions->setCurrentIndex(_timeRestrictions->findData(
static_cast<int>(_entryData->_timeRestriction)));
_time->SetDuration(_entryData->_time);
if (_entryData->_restriction ==
if (_entryData->_timeRestriction ==
MacroConditionMedia::Time::TIME_RESTRICTION_NONE) {
_time->setDisabled(true);
}

View File

@@ -5,18 +5,18 @@
#include "source-selection.hpp"
#include <limits>
#include <obs.hpp>
#include <QWidget>
#include <QComboBox>
#include <QCheckBox>
namespace advss {
constexpr auto custom_media_states_offset = 100;
class MacroConditionMedia : public MacroCondition {
public:
MacroConditionMedia(Macro *m) : MacroCondition(m) {}
~MacroConditionMedia();
MacroConditionMedia(const MacroConditionMedia &);
MacroConditionMedia &operator=(const MacroConditionMedia &);
bool CheckCondition();
bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj);
@@ -26,19 +26,17 @@ public:
{
return std::make_shared<MacroConditionMedia>(m);
}
void ClearSignalHandler();
void ResetSignalHandler();
void UpdateMediaSourcesOfSceneList();
static void MediaStopped(void *data, calldata_t *);
static void MediaEnded(void *data, calldata_t *);
static void MediaNext(void *data, calldata_t *);
enum class Type {
SOURCE,
ANY,
ALL,
};
Type _sourceType = Type::SOURCE;
enum class SourceType { SOURCE, ANY, ALL };
SourceType _sourceType = SourceType::SOURCE;
enum class CheckType { STATE, TIME, LEGACY = 1000 };
CheckType _checkType = CheckType::STATE;
enum class State {
// OBS's internal states
@@ -53,19 +51,19 @@ public:
// Just a marker
LAST_OBS_MEDIA_STATE,
// states added for use in the plugin
PLAYLIST_ENDED = custom_media_states_offset,
ANY,
PLAYLIST_ENDED = 100,
ANY
};
State _state = State::OBS_MEDIA_STATE_NONE;
State _state = State::OBS_MEDIA_STATE_PLAYING;
enum class Time {
TIME_RESTRICTION_NONE,
TIME_RESTRICTION_SHORTER,
TIME_RESTRICTION_LONGER,
TIME_RESTRICTION_REMAINING_SHORTER,
TIME_RESTRICTION_REMAINING_LONGER,
TIME_RESTRICTION_REMAINING_LONGER
};
Time _restriction = Time::TIME_RESTRICTION_NONE;
Time _timeRestriction = Time::TIME_RESTRICTION_REMAINING_SHORTER;
SceneSelection _scene;
SourceSelection _source;
@@ -74,12 +72,15 @@ public:
Duration _time;
private:
bool IsUsingLegacyCheck() const;
bool CheckTime();
bool CheckState();
bool CheckPlaylistEnd(const obs_media_state);
bool CheckMediaMatch();
void HandleSceneChange();
std::vector<OBSSignal> _signals;
bool _stopped = false;
bool _ended = false;
bool _next = false;
@@ -110,6 +111,7 @@ public:
}
private slots:
void CheckTypeChanged(int);
void SourceTypeChanged(int);
void SourceChanged(const SourceSelection &);
void SceneChanged(const SceneSelection &);
@@ -121,6 +123,7 @@ signals:
protected:
QComboBox *_sourceTypes;
QComboBox *_checkTypes;
SceneSelectionWidget *_scenes;
SourceSelectionWidget *_sources;
QComboBox *_states;