From 240c47975c51c686935c3510e6c290323b641c7f Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Thu, 25 Jul 2024 12:11:37 +0200 Subject: [PATCH] Rework Media condition * Split state and time check * Improve signal handling * Prevent exponential memory groth when using the "any" / "all" check * Improve layout --- data/locale/de-DE.ini | 2 +- data/locale/en-US.ini | 5 +- data/locale/es-ES.ini | 2 +- data/locale/fr-FR.ini | 2 +- data/locale/ja-JP.ini | 2 +- data/locale/tr-TR.ini | 2 +- data/locale/zh-CN.ini | 2 +- plugins/base/macro-condition-media.cpp | 311 +++++++++++++++---------- plugins/base/macro-condition-media.hpp | 33 +-- 9 files changed, 215 insertions(+), 146 deletions(-) diff --git a/data/locale/de-DE.ini b/data/locale/de-DE.ini index 0e1e2a12..356e8118 100644 --- a/data/locale/de-DE.ini +++ b/data/locale/de-DE.ini @@ -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" diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index c0882b26..844296e0 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -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" diff --git a/data/locale/es-ES.ini b/data/locale/es-ES.ini index 4d147368..8edb4329 100644 --- a/data/locale/es-ES.ini +++ b/data/locale/es-ES.ini @@ -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" diff --git a/data/locale/fr-FR.ini b/data/locale/fr-FR.ini index c5d27ccd..e88bb759 100644 --- a/data/locale/fr-FR.ini +++ b/data/locale/fr-FR.ini @@ -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 à" diff --git a/data/locale/ja-JP.ini b/data/locale/ja-JP.ini index 1adf4b92..680fff84 100644 --- a/data/locale/ja-JP.ini +++ b/data/locale/ja-JP.ini @@ -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="合わない" diff --git a/data/locale/tr-TR.ini b/data/locale/tr-TR.ini index 4f8f32be..d8d968ed 100644 --- a/data/locale/tr-TR.ini +++ b/data/locale/tr-TR.ini @@ -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" diff --git a/data/locale/zh-CN.ini b/data/locale/zh-CN.ini index f50b0b5d..a7899361 100644 --- a/data/locale/zh-CN.ini +++ b/data/locale/zh-CN.ini @@ -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="不匹配" diff --git a/plugins/base/macro-condition-media.cpp b/plugins/base/macro-condition-media.cpp index 0e5a1124..77426c78 100644 --- a/plugins/base/macro-condition-media.cpp +++ b/plugins/base/macro-condition-media.cpp @@ -52,16 +52,6 @@ static const std::map 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(_sourceType)); + obs_data_set_int(obj, "checkType", static_cast(_checkType)); obs_data_set_int(obj, "state", static_cast(_state)); - obs_data_set_int(obj, "restriction", static_cast(_restriction)); + obs_data_set_int(obj, "restriction", + static_cast(_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(obs_data_get_int(obj, "sourceType")); - _state = static_cast( - obs_data_get_int(obj, "state")); - _restriction = static_cast( - obs_data_get_int(obj, "restriction")); + _sourceType = + static_cast(obs_data_get_int(obj, "sourceType")); + _state = static_cast(obs_data_get_int(obj, "state")); + _checkType = static_cast(obs_data_get_int(obj, "checkType")); + _timeRestriction = + static_cast