From f10e25bb93adbf8c4ba80adad973eb3df2116146 Mon Sep 17 00:00:00 2001 From: Niko Fox <66900153+fauxnik@users.noreply.github.com> Date: Thu, 14 Aug 2025 23:51:14 -0700 Subject: [PATCH] Add get/set source visibility functions This exposes a javascript function for determining the visiblity of arbitrary OBS sources and another for modifying said visibility. These functions are available to browser sources with the requisite permissions: ReadUser or higher for get, Advanced or higher for set. --- README.md | 29 +++++++++++++++++++++++++++++ browser-app.cpp | 14 +++++++------- browser-client.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3e1732802..7be2f3ffa 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,24 @@ window.obsstudio.getCurrentTransition(function (transition) { }) ``` +#### Get source visibility +Permissions required: READ_USER +```js +/** + * @callback VisibilityCallback + * @param {boolean} visibility - True -> visible, False -> hidden + */ + +/** + * @param {string} scene - Name of the scene + * @param {string} source - Name of the source + * @param {VisibilityCallback} cb - The callback that receives the current visibility. + */ +window.obsstudio.getSourceVisible(scene, source, function (visibility) { + console.log(visibility) +}) +``` + #### Save the Replay Buffer Permissions required: BASIC ```js @@ -243,6 +261,17 @@ Permissions required: ADVANCED window.obsstudio.setCurrentTransition(name) ``` +#### Set source visibility +Permissions required: ADVANCED +```js +/** + * @param {string} scene - Name of the scene + * @param {string} source - Name of the source + * @param {boolean} visibility - True -> visible, False -> hidden + */ +window.obsstudio.setSourceVisible(scene, source, visibility) +``` + #### Start streaming Permissions required: ALL ```js diff --git a/browser-app.cpp b/browser-app.cpp index 7a6c893a9..ec090d3b4 100644 --- a/browser-app.cpp +++ b/browser-app.cpp @@ -99,13 +99,13 @@ void BrowserApp::OnBeforeCommandLineProcessing(const CefString &, CefRefPtr exposedFunctions = {"getControlLevel", "getCurrentScene", "getStatus", - "startRecording", "stopRecording", "startStreaming", - "stopStreaming", "pauseRecording", "unpauseRecording", - "startReplayBuffer", "stopReplayBuffer", "saveReplayBuffer", - "startVirtualcam", "stopVirtualcam", "getScenes", - "setCurrentScene", "getTransitions", "getCurrentTransition", - "setCurrentTransition"}; +std::vector exposedFunctions = {"getControlLevel", "getCurrentScene", "getStatus", + "startRecording", "stopRecording", "startStreaming", + "stopStreaming", "pauseRecording", "unpauseRecording", + "startReplayBuffer", "stopReplayBuffer", "saveReplayBuffer", + "startVirtualcam", "stopVirtualcam", "getScenes", + "setCurrentScene", "getTransitions", "getCurrentTransition", + "setCurrentTransition", "getSourceVisible", "setSourceVisible"}; void BrowserApp::OnContextCreated(CefRefPtr browser, CefRefPtr, CefRefPtr context) { diff --git a/browser-client.cpp b/browser-client.cpp index 9b334b476..1d42bc228 100644 --- a/browser-client.cpp +++ b/browser-client.cpp @@ -191,6 +191,32 @@ bool BrowserClient::OnProcessMessageReceived(CefRefPtr browser, CefR } else { obs_frontend_set_current_scene(source); } + } else if (name == "setSourceVisible") { + const std::string scene_name = input_args->GetString(1).ToString(); + const std::string source_name = input_args->GetString(2).ToString(); + const std::string visible = input_args->GetBool(3); + OBSSourceAutoRelease *scene = obs_get_source_by_name(scene_name.c_str()); + if (!scene) { + blog(LOG_WARNING, + "Browser source '%s' tried to set the visibility of a scene item in scene '%s' which doesn't exist", + obs_source_get_name(bs->source), scene_name.c_str()); + break; + } + if (!obs_source_is_scene(scene)) { + blog(LOG_WARNING, + "Browser source '%s' tried to set the visibility of a scene item in scene '%s' which isn't a scene", + obs_source_get_name(bs->source), scene_name.c_str()); + break; + } + obs_sceneitem_t *item = + obs_scene_find_source_recursive(obs_scene_from_source(scene), source_name.c_str()); + if (!item) { + blog(LOG_WARNING, + "Browser source '%s' tried to set the visibility of scene item '%s' which doesn't exist in scene '%s'", + obs_source_get_name(bs->source), source_name.c_str(), scene_name.c_str()); + break; + } + obs_sceneitem_set_visible(item, visible); } else if (name == "setCurrentTransition") { const std::string transition_name = input_args->GetString(1).ToString(); obs_frontend_source_list transitions = {}; @@ -244,6 +270,23 @@ bool BrowserClient::OnProcessMessageReceived(CefRefPtr browser, CefR json = {{"name", name}, {"width", obs_source_get_width(current_scene)}, {"height", obs_source_get_height(current_scene)}}; + } else if (name == "getSourceVisible") { + const std::string scene_name = input_args->GetString(1).ToString(); + const std::string source_name = input_args->GetString(2).ToString(); + OBSSourceAutoRelease *scene = obs_get_source_by_name(scene_name.c_str()); + + if (!scene) + return false; + + if (!obs_source_is_scene(scene)) + return false; + + obs_sceneitem_t *item = + obs_scene_find_source_recursive(obs_scene_from_source(scene), source_name.c_str()); + if (!item) + return false; + + json = obs_sceneitem_visible(item); } else if (name == "getTransitions") { struct obs_frontend_source_list list = {}; obs_frontend_get_transitions(&list);