From e82b7c0996cf471d299c8479d96e847fc9066570 Mon Sep 17 00:00:00 2001 From: jecks Date: Wed, 29 Oct 2025 11:09:01 -0400 Subject: [PATCH 1/8] implement obs frontend api for studio mode SWAP preview/program after transition --- frontend/OBSStudioAPI.cpp | 15 +++++++++++++++ frontend/OBSStudioAPI.hpp | 4 ++++ frontend/api/obs-frontend-api.cpp | 13 +++++++++++++ frontend/api/obs-frontend-api.h | 5 +++++ frontend/api/obs-frontend-internal.hpp | 3 +++ frontend/widgets/OBSBasic.hpp | 3 +++ frontend/widgets/OBSBasic_StudioMode.cpp | 2 +- frontend/widgets/OBSBasic_Transitions.cpp | 17 +++++++++++++++++ 8 files changed, 61 insertions(+), 1 deletion(-) diff --git a/frontend/OBSStudioAPI.cpp b/frontend/OBSStudioAPI.cpp index 7e8ab72bb9eff3..c87bfb24bb915f 100644 --- a/frontend/OBSStudioAPI.cpp +++ b/frontend/OBSStudioAPI.cpp @@ -565,6 +565,21 @@ void OBSStudioAPI::obs_frontend_set_current_preview_scene(obs_source_t *scene) Q_ARG(bool, false)); } } +bool OBSStudioAPI::obs_frontend_get_swap_scenes_mode(void) +{ + OBSBasic *main = OBSBasic::Get(); + if (!main) + return false; + return main->GetSwapScenesMode(); // implement GetSwapScenesMode() in OBSBasic +} + +void OBSStudioAPI::obs_frontend_set_swap_scenes_mode(bool enabled) +{ + OBSBasic *main = OBSBasic::Get(); + if (!main) + return; + main->SetSwapScenesMode(enabled); +} void OBSStudioAPI::obs_frontend_take_screenshot() { diff --git a/frontend/OBSStudioAPI.hpp b/frontend/OBSStudioAPI.hpp index e2a72c3a28be6a..7b477bc0b3a7b7 100644 --- a/frontend/OBSStudioAPI.hpp +++ b/frontend/OBSStudioAPI.hpp @@ -183,6 +183,10 @@ struct OBSStudioAPI : obs_frontend_callbacks { void obs_frontend_set_current_preview_scene(obs_source_t *scene) override; + bool obs_frontend_get_swap_scenes_mode(void) override; + + void obs_frontend_set_swap_scenes_mode(bool enabled) override; + void obs_frontend_take_screenshot(void) override; void obs_frontend_take_source_screenshot(obs_source_t *source) override; diff --git a/frontend/api/obs-frontend-api.cpp b/frontend/api/obs-frontend-api.cpp index fa72ba7968e2c0..d425f079aa93d7 100644 --- a/frontend/api/obs-frontend-api.cpp +++ b/frontend/api/obs-frontend-api.cpp @@ -504,6 +504,19 @@ void obs_frontend_take_source_screenshot(obs_source_t *source) c->obs_frontend_take_source_screenshot(source); } +bool obs_frontend_get_swap_scenes_mode(void) +{ + if (callbacks_valid()) + return c->obs_frontend_get_swap_scenes_mode(); + return false; +} + +void obs_frontend_set_swap_scenes_mode(bool enabled) +{ + if (callbacks_valid()) + c->obs_frontend_set_swap_scenes_mode(enabled); +} + obs_output_t *obs_frontend_get_virtualcam_output(void) { return !!callbacks_valid() ? c->obs_frontend_get_virtualcam_output() : nullptr; diff --git a/frontend/api/obs-frontend-api.h b/frontend/api/obs-frontend-api.h index cc50c7b1793e55..dc3f40535a88ab 100644 --- a/frontend/api/obs-frontend-api.h +++ b/frontend/api/obs-frontend-api.h @@ -41,6 +41,7 @@ enum obs_frontend_event { OBS_FRONTEND_EVENT_STUDIO_MODE_ENABLED, OBS_FRONTEND_EVENT_STUDIO_MODE_DISABLED, OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED, + OBS_FRONTEND_EVENT_SWAP_SCENES_MODE_CHANGED, OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP, OBS_FRONTEND_EVENT_FINISHED_LOADING, @@ -222,6 +223,10 @@ EXPORT bool obs_frontend_preview_enabled(void); EXPORT obs_source_t *obs_frontend_get_current_preview_scene(void); EXPORT void obs_frontend_set_current_preview_scene(obs_source_t *scene); +EXPORT bool obs_frontend_get_swap_scenes_mode(void); +EXPORT void obs_frontend_set_swap_scenes_mode(bool enabled); + + EXPORT void obs_frontend_take_screenshot(void); EXPORT void obs_frontend_take_source_screenshot(obs_source_t *source); diff --git a/frontend/api/obs-frontend-internal.hpp b/frontend/api/obs-frontend-internal.hpp index 1c08b8c44fa87d..ef829f19e5f3a6 100644 --- a/frontend/api/obs-frontend-internal.hpp +++ b/frontend/api/obs-frontend-internal.hpp @@ -102,6 +102,9 @@ struct obs_frontend_callbacks { virtual obs_source_t *obs_frontend_get_current_preview_scene(void) = 0; virtual void obs_frontend_set_current_preview_scene(obs_source_t *scene) = 0; + virtual bool obs_frontend_get_swap_scenes_mode(void) = 0; + virtual void obs_frontend_set_swap_scenes_mode(bool enabled) = 0; + virtual void on_load(obs_data_t *settings) = 0; virtual void on_preload(obs_data_t *settings) = 0; virtual void on_save(obs_data_t *settings) = 0; diff --git a/frontend/widgets/OBSBasic.hpp b/frontend/widgets/OBSBasic.hpp index ca213433e0beb8..83cec830eb639e 100644 --- a/frontend/widgets/OBSBasic.hpp +++ b/frontend/widgets/OBSBasic.hpp @@ -1583,10 +1583,13 @@ private slots: void CurrentTransitionChanged(const QString &uuid); void TransitionDurationChanged(const int &duration); + void SwapScenesModeChanged(bool enabled); public: int GetTransitionDuration(); int GetTbarPosition(); + bool GetSwapScenesMode() const { return swapScenesMode; } + void SetSwapScenesMode(bool enabled); /* ------------------------------------- * MARK: - OBSBasic_Updater diff --git a/frontend/widgets/OBSBasic_StudioMode.cpp b/frontend/widgets/OBSBasic_StudioMode.cpp index d492f8f298785c..2b743d62780819 100644 --- a/frontend/widgets/OBSBasic_StudioMode.cpp +++ b/frontend/widgets/OBSBasic_StudioMode.cpp @@ -126,7 +126,7 @@ void OBSBasic::CreateProgramOptions() }; auto toggleSwapScenesMode = [this]() { - swapScenesMode = !swapScenesMode; + SetSwapScenesMode(!swapScenesMode); }; auto toggleSceneDuplication = [this]() { diff --git a/frontend/widgets/OBSBasic_Transitions.cpp b/frontend/widgets/OBSBasic_Transitions.cpp index b76f433762fc73..3fd1056c809c19 100644 --- a/frontend/widgets/OBSBasic_Transitions.cpp +++ b/frontend/widgets/OBSBasic_Transitions.cpp @@ -263,6 +263,23 @@ void OBSBasic::TransitionFullyStopped() overridingTransition = false; } } +void OBSBasic::SetSwapScenesMode(bool enabled) + +{ + QMetaObject::invokeMethod(this, [this, enabled]() { + if (swapScenesMode == enabled) + return; + + + swapScenesMode = enabled; + + blog(LOG_INFO, "SwapScenesMode set to: %s", enabled ? "true" : "false"); +/* + emit SwapScenesModeChanged(enabled);*/ + + OnEvent(OBS_FRONTEND_EVENT_SWAP_SCENES_MODE_CHANGED); + }); +} void OBSBasic::TransitionToScene(OBSSource source, bool force, bool quickTransition, int quickDuration, bool black, bool manual) From 3eccb1c6d537e1b933d80b2bf69bb8a6e43f2050 Mon Sep 17 00:00:00 2001 From: jecks Date: Wed, 29 Oct 2025 11:16:51 -0400 Subject: [PATCH 2/8] implement obs frontend api for studio mode SWAP preview/program after transition --- frontend/OBSStudioAPI.cpp | 2 +- frontend/widgets/OBSBasic_Transitions.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/OBSStudioAPI.cpp b/frontend/OBSStudioAPI.cpp index c87bfb24bb915f..4a46b820754919 100644 --- a/frontend/OBSStudioAPI.cpp +++ b/frontend/OBSStudioAPI.cpp @@ -570,7 +570,7 @@ bool OBSStudioAPI::obs_frontend_get_swap_scenes_mode(void) OBSBasic *main = OBSBasic::Get(); if (!main) return false; - return main->GetSwapScenesMode(); // implement GetSwapScenesMode() in OBSBasic + return main->GetSwapScenesMode(); } void OBSStudioAPI::obs_frontend_set_swap_scenes_mode(bool enabled) diff --git a/frontend/widgets/OBSBasic_Transitions.cpp b/frontend/widgets/OBSBasic_Transitions.cpp index 3fd1056c809c19..73ffad2bdc1b21 100644 --- a/frontend/widgets/OBSBasic_Transitions.cpp +++ b/frontend/widgets/OBSBasic_Transitions.cpp @@ -274,8 +274,8 @@ void OBSBasic::SetSwapScenesMode(bool enabled) swapScenesMode = enabled; blog(LOG_INFO, "SwapScenesMode set to: %s", enabled ? "true" : "false"); -/* - emit SwapScenesModeChanged(enabled);*/ + + emit SwapScenesModeChanged(enabled); OnEvent(OBS_FRONTEND_EVENT_SWAP_SCENES_MODE_CHANGED); }); From c0889b1e3ce1c13bbadd4ce12aef983218f8c917 Mon Sep 17 00:00:00 2001 From: jecks Date: Wed, 29 Oct 2025 11:39:00 -0400 Subject: [PATCH 3/8] update api docs --- docs/sphinx/reference-frontend-api.rst | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/sphinx/reference-frontend-api.rst b/docs/sphinx/reference-frontend-api.rst index 7d234b7ac1d6a5..1fe56c8073b49d 100644 --- a/docs/sphinx/reference-frontend-api.rst +++ b/docs/sphinx/reference-frontend-api.rst @@ -167,6 +167,16 @@ Structures/Enumerations Triggered when the current preview scene has changed in studio mode. + - **OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED** + + Triggered when the current preview scene has changed in studio + mode. + + - **OBS_FRONTEND_EVENT_SWAP_SCENES_MODE_CHANGED** + + Triggered when the "Swap preview/program scenes after transitioning" + option in studio mode is toggled + - **OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP** Triggered when a scene collection has been completely unloaded, and @@ -820,6 +830,26 @@ Functions --------------------------------------- +.. function:: obs_frontend_set_swap_scenes_mode(bool enable) + + Toggles the "Swap preview/program scenes after transitioning" + behavior while in studio mode. Useful for instances where + both behaviors may be desirable depending on circumstance. + Does nothing when not using studio mode. + + :param enable: *true* to enable this mode, *false* to disable it + +--------------------------------------- + +.. function:: obs_frontend_get_swap_scenes_mode(void) + + Get the current value of "Swap preview/program scenes after transitioning" + option in studio mode. + + :return: *true* if the preview display is enabled, *false* otherwise + +--------------------------------------- + .. function:: void *obs_frontend_take_screenshot(void) Takes a screenshot of the main OBS output. From f319534ef59501a4cc99a0b9760466be4c412b47 Mon Sep 17 00:00:00 2001 From: jecks Date: Wed, 29 Oct 2025 11:40:28 -0400 Subject: [PATCH 4/8] update api docs --- docs/sphinx/reference-frontend-api.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/sphinx/reference-frontend-api.rst b/docs/sphinx/reference-frontend-api.rst index 1fe56c8073b49d..e0718dca4a79c8 100644 --- a/docs/sphinx/reference-frontend-api.rst +++ b/docs/sphinx/reference-frontend-api.rst @@ -167,11 +167,6 @@ Structures/Enumerations Triggered when the current preview scene has changed in studio mode. - - **OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED** - - Triggered when the current preview scene has changed in studio - mode. - - **OBS_FRONTEND_EVENT_SWAP_SCENES_MODE_CHANGED** Triggered when the "Swap preview/program scenes after transitioning" From 8eacf4a91eac9957d43bd272e7eb85a05c0143df Mon Sep 17 00:00:00 2001 From: jecks Date: Wed, 29 Oct 2025 11:41:59 -0400 Subject: [PATCH 5/8] update api docs --- docs/sphinx/reference-frontend-api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sphinx/reference-frontend-api.rst b/docs/sphinx/reference-frontend-api.rst index e0718dca4a79c8..89a3dc5fb2a305 100644 --- a/docs/sphinx/reference-frontend-api.rst +++ b/docs/sphinx/reference-frontend-api.rst @@ -841,7 +841,7 @@ Functions Get the current value of "Swap preview/program scenes after transitioning" option in studio mode. - :return: *true* if the preview display is enabled, *false* otherwise + :return: *true* if mode is enabled, *false* otherwise --------------------------------------- From 74ed04f0ccced723c7546c782d5a522f2fb2bed4 Mon Sep 17 00:00:00 2001 From: jecks Date: Sun, 2 Nov 2025 11:29:50 -0500 Subject: [PATCH 6/8] frontend-api: Clang format and code cleanup --- build-aux/.run-format.zsh | 2 +- frontend/OBSStudioAPI.cpp | 16 ++++++++-------- frontend/api/obs-frontend-api.h | 1 - frontend/widgets/OBSBasic_Transitions.cpp | 1 - 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/build-aux/.run-format.zsh b/build-aux/.run-format.zsh index ab74d28355d430..829f14c1733619 100755 --- a/build-aux/.run-format.zsh +++ b/build-aux/.run-format.zsh @@ -49,7 +49,7 @@ invoke_formatter() { exit 2 fi - if ! is-at-least ${formatter_version[-1]} 19.1.1; then + if ! is-at-least ${formatter_version[-1]} 19.1.8; then log_error "clang-format is more recent than version 19.1.1 (found ${formatter_version[-1]})." exit 2 fi diff --git a/frontend/OBSStudioAPI.cpp b/frontend/OBSStudioAPI.cpp index 4a46b820754919..7f66103e4e5c96 100644 --- a/frontend/OBSStudioAPI.cpp +++ b/frontend/OBSStudioAPI.cpp @@ -567,18 +567,18 @@ void OBSStudioAPI::obs_frontend_set_current_preview_scene(obs_source_t *scene) } bool OBSStudioAPI::obs_frontend_get_swap_scenes_mode(void) { - OBSBasic *main = OBSBasic::Get(); - if (!main) - return false; - return main->GetSwapScenesMode(); + OBSBasic *main = OBSBasic::Get(); + if (!main) + return false; + return main->GetSwapScenesMode(); } void OBSStudioAPI::obs_frontend_set_swap_scenes_mode(bool enabled) { - OBSBasic *main = OBSBasic::Get(); - if (!main) - return; - main->SetSwapScenesMode(enabled); + OBSBasic *main = OBSBasic::Get(); + if (!main) + return; + main->SetSwapScenesMode(enabled); } void OBSStudioAPI::obs_frontend_take_screenshot() diff --git a/frontend/api/obs-frontend-api.h b/frontend/api/obs-frontend-api.h index dc3f40535a88ab..a6e38c795fa277 100644 --- a/frontend/api/obs-frontend-api.h +++ b/frontend/api/obs-frontend-api.h @@ -226,7 +226,6 @@ EXPORT void obs_frontend_set_current_preview_scene(obs_source_t *scene); EXPORT bool obs_frontend_get_swap_scenes_mode(void); EXPORT void obs_frontend_set_swap_scenes_mode(bool enabled); - EXPORT void obs_frontend_take_screenshot(void); EXPORT void obs_frontend_take_source_screenshot(obs_source_t *source); diff --git a/frontend/widgets/OBSBasic_Transitions.cpp b/frontend/widgets/OBSBasic_Transitions.cpp index 73ffad2bdc1b21..849928729f5a4a 100644 --- a/frontend/widgets/OBSBasic_Transitions.cpp +++ b/frontend/widgets/OBSBasic_Transitions.cpp @@ -270,7 +270,6 @@ void OBSBasic::SetSwapScenesMode(bool enabled) if (swapScenesMode == enabled) return; - swapScenesMode = enabled; blog(LOG_INFO, "SwapScenesMode set to: %s", enabled ? "true" : "false"); From 52da1002caa240f6316eef7cdceff2418e6603e4 Mon Sep 17 00:00:00 2001 From: jecks Date: Sun, 2 Nov 2025 11:42:29 -0500 Subject: [PATCH 7/8] swapscene-api: fix debug log and API enum --- build-aux/.run-format.zsh | 2 +- frontend/api/obs-frontend-api.h | 3 ++- frontend/widgets/OBSBasic_Transitions.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/build-aux/.run-format.zsh b/build-aux/.run-format.zsh index 829f14c1733619..ab74d28355d430 100755 --- a/build-aux/.run-format.zsh +++ b/build-aux/.run-format.zsh @@ -49,7 +49,7 @@ invoke_formatter() { exit 2 fi - if ! is-at-least ${formatter_version[-1]} 19.1.8; then + if ! is-at-least ${formatter_version[-1]} 19.1.1; then log_error "clang-format is more recent than version 19.1.1 (found ${formatter_version[-1]})." exit 2 fi diff --git a/frontend/api/obs-frontend-api.h b/frontend/api/obs-frontend-api.h index a6e38c795fa277..4745c406b0184d 100644 --- a/frontend/api/obs-frontend-api.h +++ b/frontend/api/obs-frontend-api.h @@ -41,7 +41,6 @@ enum obs_frontend_event { OBS_FRONTEND_EVENT_STUDIO_MODE_ENABLED, OBS_FRONTEND_EVENT_STUDIO_MODE_DISABLED, OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED, - OBS_FRONTEND_EVENT_SWAP_SCENES_MODE_CHANGED, OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP, OBS_FRONTEND_EVENT_FINISHED_LOADING, @@ -66,6 +65,8 @@ enum obs_frontend_event { OBS_FRONTEND_EVENT_CANVAS_ADDED, OBS_FRONTEND_EVENT_CANVAS_REMOVED, + OBS_FRONTEND_EVENT_SWAP_SCENES_MODE_CHANGED, + }; /* ------------------------------------------------------------------------- */ diff --git a/frontend/widgets/OBSBasic_Transitions.cpp b/frontend/widgets/OBSBasic_Transitions.cpp index 849928729f5a4a..a8717f25bc8f7b 100644 --- a/frontend/widgets/OBSBasic_Transitions.cpp +++ b/frontend/widgets/OBSBasic_Transitions.cpp @@ -272,7 +272,7 @@ void OBSBasic::SetSwapScenesMode(bool enabled) swapScenesMode = enabled; - blog(LOG_INFO, "SwapScenesMode set to: %s", enabled ? "true" : "false"); + blog(LOG_INFO, "SwapScenesMode set to: %s", enabled ? "enabled" : "disabled"); emit SwapScenesModeChanged(enabled); From 8ac054b6aeb0ae9d5ac21dcac46081b0decc2e2f Mon Sep 17 00:00:00 2001 From: jecks Date: Sun, 2 Nov 2025 11:44:26 -0500 Subject: [PATCH 8/8] frontend-api: Delete extra line --- frontend/api/obs-frontend-api.h | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/api/obs-frontend-api.h b/frontend/api/obs-frontend-api.h index 4745c406b0184d..3597ce3d766571 100644 --- a/frontend/api/obs-frontend-api.h +++ b/frontend/api/obs-frontend-api.h @@ -66,7 +66,6 @@ enum obs_frontend_event { OBS_FRONTEND_EVENT_CANVAS_ADDED, OBS_FRONTEND_EVENT_CANVAS_REMOVED, OBS_FRONTEND_EVENT_SWAP_SCENES_MODE_CHANGED, - }; /* ------------------------------------------------------------------------- */