obs-studio icon indicating copy to clipboard operation
obs-studio copied to clipboard

frontend: Prevent setting transition during transitions

Open Warchamp7 opened this issue 3 months ago • 7 comments

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.

image

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.

Warchamp7 avatar Sep 13 '25 03:09 Warchamp7

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

exeldro avatar Sep 13 '25 04:09 exeldro

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

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.

Warchamp7 avatar Sep 13 '25 04:09 Warchamp7

Updated per the above feedback from Exeldro and rebased.

Warchamp7 avatar Sep 27 '25 04:09 Warchamp7

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".

PatTheMav avatar Oct 08 '25 14:10 PatTheMav

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".

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.

Warchamp7 avatar Oct 12 '25 02:10 Warchamp7

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".

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.

PatTheMav avatar Oct 15 '25 11:10 PatTheMav

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".

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.

Warchamp7 avatar Dec 09 '25 00:12 Warchamp7