frontend: Prevent setting transition during transitions
Description
Adds obs_is_transition_active to libobs and uses it in the frontend to prevent calling SetTransition during an active transition.
Motivation and Context
SetTransition updates the current transition source and effectively resets it back to the start. If this is called during a transition, it effectively interrupts it. As a result, the transition_stop signal never fires, since the transition that was running never actually ended.
Normally the UI dropdown itself is disabled and this cannot be done via the application window itself. However, it is possible via plugins, scripts, or OBS Websockets using SetCurrentSceneTransition. That request calls obs_frontend_set_current_transition which then invokes OBSBasic::SetTransition.
How Has This Been Tested?
I used a simple OBS Websocket script that calls SetCurrentSceneTransition, TriggerStudioModeTransition, SetCurrentSceneTransition in succession 100ms apart.
Without these changes, the transition controls get stuck as the transition never fires the ended event.
Types of changes
- Bug fix (non-breaking change which fixes an issue)
Checklist:
- [x] My code has been run through clang-format.
- [x] I have read the contributing document.
- [x] My code is not on the master branch.
- [x] The code has been tested.
- [x] All commit messages are properly formatted and commits squashed where appropriate.
- [x] I have included updates to all appropriate documentation.
I would expect the function name to be obs_transition_is_active instead of obs_is_transition_active, because it gets it for the transition and not global
I would expect the function name to be
obs_transition_is_activeinstead ofobs_is_transition_active, because it gets it for the transition and not global
Given it takes a parameter, I would personally expect it to return the active state of that parameter. Looking at the docs, this style seems to be a bit more of a C-ism so I can adjust it if preferred.
Updated per the above feedback from Exeldro and rebased.
SetTransition updates the current transition source and effectively resets it back to the start. If this is called during a transition, it effectively interrupts it.
So here's my question - why is it doing that? Is there a reason for this behaviour? As in: Are there scenarios where that is the expected and desired outcome?
Because if it isn't and setting up a transition is not supposed to interfere with a currently active transition anyway, why doesn't libobs behave that way by itself? Why does the caller need to check the internal state of libobs transition system and wait for it to be finished to set the "next" transition, ideally that should be "fire & forget".
SetTransition updates the current transition source and effectively resets it back to the start. If this is called during a transition, it effectively interrupts it.
So here's my question - why is it doing that? Is there a reason for this behaviour? As in: Are there scenarios where that is the expected and desired outcome?
Because if it isn't and setting up a transition is not supposed to interfere with a currently active transition anyway, why doesn't
libobsbehave that way by itself? Why does the caller need to check the internal state oflibobstransition system and wait for it to be finished to set the "next" transition, ideally that should be "fire & forget".
OBS is at all times "in" a transition. Often times it is simply at frame 1 and not actively changing. There is no guarantee a transition might even finish, if for example using the T Bar to go partially through a cross fade, and then returning to 0. The frontend essentially handles automating that advancement.
Unfortunately that logic exists in the frontend, so it's the frontend and frontend API that need to be aware that it should not try starting another "automated" transition while one is already running.
SetTransition updates the current transition source and effectively resets it back to the start. If this is called during a transition, it effectively interrupts it.
So here's my question - why is it doing that? Is there a reason for this behaviour? As in: Are there scenarios where that is the expected and desired outcome? Because if it isn't and setting up a transition is not supposed to interfere with a currently active transition anyway, why doesn't
libobsbehave that way by itself? Why does the caller need to check the internal state oflibobstransition system and wait for it to be finished to set the "next" transition, ideally that should be "fire & forget".OBS is at all times "in" a transition. Often times it is simply at frame 1 and not actively changing. There is no guarantee a transition might even finish, if for example using the T Bar to go partially through a cross fade, and then returning to 0. The frontend essentially handles automating that advancement.
Unfortunately that logic exists in the frontend, so it's the frontend and frontend API that need to be aware that it should not try starting another "automated" transition while one is already running.
This is all kinds of wrong, but sounds like yet another example of "everything is just bolted onto everything else" without any realistic chance of properly disentangling it.
SetTransition updates the current transition source and effectively resets it back to the start. If this is called during a transition, it effectively interrupts it.
So here's my question - why is it doing that? Is there a reason for this behaviour? As in: Are there scenarios where that is the expected and desired outcome? Because if it isn't and setting up a transition is not supposed to interfere with a currently active transition anyway, why doesn't
libobsbehave that way by itself? Why does the caller need to check the internal state oflibobstransition system and wait for it to be finished to set the "next" transition, ideally that should be "fire & forget".OBS is at all times "in" a transition. Often times it is simply at frame 1 and not actively changing. There is no guarantee a transition might even finish, if for example using the T Bar to go partially through a cross fade, and then returning to 0. The frontend essentially handles automating that advancement. Unfortunately that logic exists in the frontend, so it's the frontend and frontend API that need to be aware that it should not try starting another "automated" transition while one is already running.
This is all kinds of wrong, but sounds like yet another example of "everything is just bolted onto everything else" without any realistic chance of properly disentangling it.
Following up on this after unrelated discussions around transitions we had off-thread recently. I think architecturally, libobs should probably more gracefully handle a transition being initiated while another is active, which would mean properly emitting the stop signal if it is interrupted.
I still believe the UI and frontend API should prevent changing transitions while one is in motion, but I've now updated this PR with a second commit that properly signals transition_stop when an active transition is cancelled.
This also means the UI can now safely rely on transition_start/transition_stop for enabling/disabling the the UI.