From 70a3ae02455cb223504acdf644bbc27bff28b69f Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sun, 8 May 2022 03:49:22 +0200 Subject: [PATCH] Fix waiting for transition to complete with fixed duration transitions --- src/macro-action-scene-switch.cpp | 73 ++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/src/macro-action-scene-switch.cpp b/src/macro-action-scene-switch.cpp index 33a8b1d5..607e6d78 100644 --- a/src/macro-action-scene-switch.cpp +++ b/src/macro-action-scene-switch.cpp @@ -2,6 +2,8 @@ #include "headers/advanced-scene-switcher.hpp" #include "headers/utility.hpp" +using namespace std::chrono_literals; + const std::string MacroActionSwitchScene::id = "scene_switch"; bool MacroActionSwitchScene::_registered = MacroActionFactory::Register( @@ -9,7 +11,21 @@ bool MacroActionSwitchScene::_registered = MacroActionFactory::Register( {MacroActionSwitchScene::Create, MacroActionSwitchSceneEdit::Create, "AdvSceneSwitcher.action.switchScene"}); -void waitForTransitionChange(int duration) +void waitForTransitionChange(OBSWeakSource &transition) +{ + const auto time = 100ms; + obs_source_t *source = obs_weak_source_get_source(transition); + std::unique_lock lock(switcher->m); + bool stillTransitioning = true; + while (stillTransitioning && !switcher->abortMacroWait) { + switcher->macroTransitionCv.wait_for(lock, time); + float t = obs_transition_get_time(source); + stillTransitioning = t < 1.0f && t > 0.0f; + } + obs_source_release(source); +} + +void waitForTransitionChangeFixedDuration(int duration) { duration += 200; // It seems to be necessary to add a small buffer auto time = std::chrono::high_resolution_clock::now() + @@ -25,7 +41,7 @@ void waitForTransitionChange(int duration) } } -int getTransitionOverrideDuration(OBSWeakSource scene) +int getTransitionOverrideDuration(OBSWeakSource &scene) { int duration = 0; obs_source_t *source = obs_weak_source_get_source(scene); @@ -39,11 +55,41 @@ int getTransitionOverrideDuration(OBSWeakSource scene) return duration; } -int getExpectedTransitionDuration(OBSWeakSource scene, double duration) +bool isUsingFixedLengthTransition(OBSWeakSource &transition) { - int overrideDuration = getTransitionOverrideDuration(scene); - if (overrideDuration && !switcher->transitionOverrideOverride) { - return overrideDuration; + obs_source_t *source = obs_weak_source_get_source(transition); + bool ret = obs_transition_fixed(source); + obs_source_release(source); + return ret; +} + +OBSWeakSource getOverrideTransition(OBSWeakSource &scene) +{ + OBSWeakSource transition; + obs_source_t *source = obs_weak_source_get_source(scene); + obs_data_t *data = obs_source_get_private_settings(source); + transition = GetWeakTransitionByName( + obs_data_get_string(data, "transition")); + obs_data_release(data); + obs_source_release(source); + return transition; +} + +int getExpectedTransitionDuration(OBSWeakSource &scene, OBSWeakSource &t, + double duration) +{ + OBSWeakSource transition = t; + if (!switcher->transitionOverrideOverride) { + auto overrideTransition = getOverrideTransition(scene); + if (overrideTransition) { + transition = overrideTransition; + if (!isUsingFixedLengthTransition(transition)) { + return getTransitionOverrideDuration(scene); + } + } + } + if (isUsingFixedLengthTransition(transition)) { + return -1; // no API is available to access the fixed duration } if (duration != 0) { return duration * 1000; @@ -54,12 +100,19 @@ int getExpectedTransitionDuration(OBSWeakSource scene, double duration) bool MacroActionSwitchScene::PerformAction() { auto scene = _scene.GetScene(); - switchScene({scene, _transition.GetTransition(), - (int)(_duration.seconds * 1000)}, + auto transition = _transition.GetTransition(); + switchScene({scene, transition, (int)(_duration.seconds * 1000)}, obs_frontend_preview_program_mode_active()); if (_blockUntilTransitionDone && scene) { - waitForTransitionChange(getExpectedTransitionDuration( - scene, _duration.seconds)); + const int expectedTransitionDuration = + getExpectedTransitionDuration(scene, transition, + _duration.seconds); + if (expectedTransitionDuration < 0) { + waitForTransitionChange(transition); + } else { + waitForTransitionChangeFixedDuration( + expectedTransitionDuration); + } return !switcher->abortMacroWait; } return true;