From 33ec6b80fcb38754276bd3e8b84d0e6e42bdd03c Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Wed, 4 Sep 2024 13:37:45 -0700 Subject: [PATCH 01/17] remove qt deps from browser source --- CMakeLists.txt | 2 +- cmake/os-macos.cmake | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bef54262e..803c74b1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ find_package(nlohmann_json REQUIRED) add_library(obs-browser MODULE) add_library(OBS::browser ALIAS obs-browser) -option(ENABLE_BROWSER_PANELS "Enable Qt web browser panel support" ON) +option(ENABLE_BROWSER_PANELS "Enable Qt web browser panel support" OFF) mark_as_advanced(ENABLE_BROWSER_PANELS) set(obs-browser_SOURCES diff --git a/cmake/os-macos.cmake b/cmake/os-macos.cmake index e6a2bb196..e0ce376ea 100644 --- a/cmake/os-macos.cmake +++ b/cmake/os-macos.cmake @@ -1,15 +1,13 @@ -find_qt(COMPONENTS Widgets) - find_library(COREFOUNDATION CoreFoundation) find_library(APPKIT AppKit) mark_as_advanced(COREFOUNDATION APPKIT) -target_compile_definitions(obs-browser PRIVATE ENABLE_BROWSER_SHARED_TEXTURE ENABLE_BROWSER_QT_LOOP) +target_compile_definitions(obs-browser PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0.3) target_compile_options(obs-browser PRIVATE -Wno-error=unqualified-std-cast-call) endif() -target_link_libraries(obs-browser PRIVATE Qt::Widgets ${COREFOUNDATION} ${APPKIT} CEF::Wrapper) +target_link_libraries(obs-browser PRIVATE ${COREFOUNDATION} ${APPKIT} CEF::Wrapper) set(helper_basename browser-helper) set(helper_output_name "obs64 Helper") From 1d5600e5b8f7ff3df043d9737ffd6cb3062d28ba Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Wed, 18 Dec 2024 15:24:17 -0800 Subject: [PATCH 02/17] merge fix --- cmake/os-windows.cmake | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cmake/os-windows.cmake b/cmake/os-windows.cmake index db3c18760..db976356c 100644 --- a/cmake/os-windows.cmake +++ b/cmake/os-windows.cmake @@ -4,27 +4,27 @@ target_compile_definitions(obs-browser PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) target_link_libraries(obs-browser PRIVATE CEF::Wrapper CEF::Library d3d11 dxgi) target_link_options(obs-browser PRIVATE /IGNORE:4099) -add_executable(obs-browser-helper WIN32 EXCLUDE_FROM_ALL) -add_executable(OBS::browser-helper ALIAS obs-browser-helper) +add_executable(obs-browser-page WIN32 EXCLUDE_FROM_ALL) +add_executable(OBS::browser-helper ALIAS obs-browser-page) target_sources( - obs-browser-helper + obs-browser-page PRIVATE # cmake-format: sortable browser-app.cpp browser-app.hpp cef-headers.hpp obs-browser-page.manifest obs-browser-page/obs-browser-page-main.cpp) -target_include_directories(obs-browser-helper PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/deps" +target_include_directories(obs-browser-page PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/deps" "${CMAKE_CURRENT_SOURCE_DIR}/obs-browser-page") -target_compile_options(obs-browser-helper PRIVATE $,/MTd,/MT>) -target_compile_definitions(obs-browser-helper PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) +target_compile_options(obs-browser-page PRIVATE $,/MTd,/MT>) +target_compile_definitions(obs-browser-page PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) -target_link_libraries(obs-browser-helper PRIVATE CEF::Wrapper CEF::Library nlohmann_json::nlohmann_json) -target_link_options(obs-browser-helper PRIVATE /IGNORE:4099 /SUBSYSTEM:WINDOWS) +target_link_libraries(obs-browser-page PRIVATE CEF::Wrapper CEF::Library nlohmann_json::nlohmann_json) +target_link_options(obs-browser-page PRIVATE /IGNORE:4099 /SUBSYSTEM:WINDOWS) set(OBS_EXECUTABLE_DESTINATION "${OBS_PLUGIN_DESTINATION}") set_target_properties_obs( - obs-browser-helper + obs-browser-page PROPERTIES FOLDER plugins/obs-browser PREFIX "" OUTPUT_NAME obs-browser-page) From 800a9830601cbcd0f90493f3d876eaf1e0117f7a Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Thu, 19 Dec 2024 15:47:17 -0800 Subject: [PATCH 03/17] merge fix --- cmake/os-windows.cmake | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/cmake/os-windows.cmake b/cmake/os-windows.cmake index db976356c..a1c829e86 100644 --- a/cmake/os-windows.cmake +++ b/cmake/os-windows.cmake @@ -4,27 +4,32 @@ target_compile_definitions(obs-browser PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) target_link_libraries(obs-browser PRIVATE CEF::Wrapper CEF::Library d3d11 dxgi) target_link_options(obs-browser PRIVATE /IGNORE:4099) -add_executable(obs-browser-page WIN32 EXCLUDE_FROM_ALL) -add_executable(OBS::browser-helper ALIAS obs-browser-page) +add_executable(obs-browser-helper WIN32 EXCLUDE_FROM_ALL) +add_executable(OBS::browser-helper ALIAS obs-browser-helper) target_sources( - obs-browser-page + obs-browser-helper PRIVATE # cmake-format: sortable browser-app.cpp browser-app.hpp cef-headers.hpp obs-browser-page.manifest obs-browser-page/obs-browser-page-main.cpp) -target_include_directories(obs-browser-page PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/deps" +target_include_directories(obs-browser-helper PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/deps" "${CMAKE_CURRENT_SOURCE_DIR}/obs-browser-page") -target_compile_options(obs-browser-page PRIVATE $,/MTd,/MT>) -target_compile_definitions(obs-browser-page PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) +target_compile_options(obs-browser-helper PRIVATE $,/MTd,/MT>) +target_compile_definitions(obs-browser-helper PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) -target_link_libraries(obs-browser-page PRIVATE CEF::Wrapper CEF::Library nlohmann_json::nlohmann_json) -target_link_options(obs-browser-page PRIVATE /IGNORE:4099 /SUBSYSTEM:WINDOWS) +target_link_libraries(obs-browser-helper PRIVATE CEF::Wrapper CEF::Library nlohmann_json::nlohmann_json) +target_link_options(obs-browser-helper PRIVATE /IGNORE:4099 /SUBSYSTEM:WINDOWS) + +message(STATUS "Buiding browser source plugin helper for Windows") set(OBS_EXECUTABLE_DESTINATION "${OBS_PLUGIN_DESTINATION}") set_target_properties_obs( - obs-browser-page + obs-browser-helper PROPERTIES FOLDER plugins/obs-browser PREFIX "" OUTPUT_NAME obs-browser-page) + +#make it dependence for obs-browser +add_dependencies(obs-browser obs-browser-helper) \ No newline at end of file From 4c311183ef840454ef9fd6e286ac723e78124813 Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Wed, 4 Jun 2025 12:10:20 -0700 Subject: [PATCH 04/17] way to send message to browser source --- browser-app.cpp | 7 +++++-- browser-client.cpp | 23 ++++++++++++++++++++++- obs-browser-plugin.cpp | 5 +++++ obs-browser-source.cpp | 14 +++++++++++++- obs-browser-source.hpp | 1 + 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/browser-app.cpp b/browser-app.cpp index 6bd6cc659..788d04912 100644 --- a/browser-app.cpp +++ b/browser-app.cpp @@ -151,7 +151,7 @@ std::vector exposedFunctions = { "startReplayBuffer", "stopReplayBuffer", "saveReplayBuffer", "startVirtualcam", "stopVirtualcam", "getScenes", "setCurrentScene", "getTransitions", "getCurrentTransition", - "setCurrentTransition"}; + "setCurrentTransition","obsSourceMessage"}; void BrowserApp::OnContextCreated(CefRefPtr browser, CefRefPtr, @@ -412,7 +412,10 @@ bool BrowserApp::OnProcessMessageReceived(CefRefPtr browser, CefRefPtr dispatchEvent = globalObj->GetValue("dispatchEvent"); dispatchEvent->ExecuteFunction(nullptr, arguments); - + if (!dispatchEvent || !dispatchEvent->IsFunction()) { + } else { + dispatchEvent->ExecuteFunction(nullptr, arguments); + } context->Exit(); } diff --git a/browser-client.cpp b/browser-client.cpp index 5148fdc88..51a9e4992 100644 --- a/browser-client.cpp +++ b/browser-client.cpp @@ -115,7 +115,7 @@ bool BrowserClient::OnProcessMessageReceived( const std::string &name = message->GetName(); CefRefPtr input_args = message->GetArgumentList(); nlohmann::json json; - + blog(LOG_INFO, "BrowserClient::OnProcessMessageReceived: %s", name.c_str()); if (!valid()) { return false; } @@ -259,6 +259,27 @@ bool BrowserClient::OnProcessMessageReceived( } } #else + switch (webpage_control_level) { + case ControlLevel::All: + + [[fallthrough]]; + case ControlLevel::Advanced: + + [[fallthrough]]; + case ControlLevel::Basic: + + [[fallthrough]]; + case ControlLevel::ReadUser: + + [[fallthrough]]; + case ControlLevel::ReadObs: + + [[fallthrough]]; + case ControlLevel::None: + if (name == "getControlLevel") { + json = (int)webpage_control_level; + } + } UNUSED_PARAMETER(name); #endif diff --git a/obs-browser-plugin.cpp b/obs-browser-plugin.cpp index aab7da79c..807d3f41d 100644 --- a/obs-browser-plugin.cpp +++ b/obs-browser-plugin.cpp @@ -619,6 +619,11 @@ void RegisterBrowserSource() bs->Refresh(); bs->SetActive(true); }; + info.message = [](void *data, obs_data_t *settings) { + BrowserSource *bs = static_cast(data); + const char *message = obs_data_get_string(settings, "message"); + bs->SendMessage(message); + }; info.deactivate = [](void *data) { static_cast(data)->SetActive(false); }; diff --git a/obs-browser-source.cpp b/obs-browser-source.cpp index 7f2058735..f8ab9b0e5 100644 --- a/obs-browser-source.cpp +++ b/obs-browser-source.cpp @@ -154,7 +154,7 @@ void BrowserSource::Destroy() void BrowserSource::ExecuteOnBrowser(BrowserFunc func, bool async) { - if (!async) { + if (!async) { #ifdef ENABLE_BROWSER_QT_LOOP if (QThread::currentThread() == qApp->thread()) { if (!!cefBrowser) @@ -477,6 +477,18 @@ void BrowserSource::SetActive(bool active) DispatchJSEvent("obsSourceActiveChanged", json.dump(), this); } +void BrowserSource::SendMessage(const char* message) +{ + if (destroying) + return; + + blog(LOG_INFO, "BrowserSource::SendMessage: %s", message); + + nlohmann::json json; + json["message"] = message; + DispatchJSEvent("obsSourceMessage", json.dump(), this); +} + void BrowserSource::Refresh() { ExecuteOnBrowser( diff --git a/obs-browser-source.hpp b/obs-browser-source.hpp index 86f12d495..484398a26 100644 --- a/obs-browser-source.hpp +++ b/obs-browser-source.hpp @@ -150,6 +150,7 @@ struct BrowserSource { void SendKeyClick(const struct obs_key_event *event, bool key_up); void SetShowing(bool showing); void SetActive(bool active); + void SendMessage(const char* message); void Refresh(); #if defined(BROWSER_EXTERNAL_BEGIN_FRAME_ENABLED) && \ From c49f1281b936f0c32a8805cae446eb707625e817 Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Mon, 9 Jun 2025 17:29:06 -0700 Subject: [PATCH 05/17] bring messages from bs to fe --- browser-app.cpp | 2 +- browser-client.cpp | 16 ++++++++++------ obs-browser-plugin.cpp | 23 ++++++++++++++++++++++- obs-browser-source.cpp | 6 +++--- obs-browser-source.hpp | 3 ++- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/browser-app.cpp b/browser-app.cpp index 788d04912..1866ac7e8 100644 --- a/browser-app.cpp +++ b/browser-app.cpp @@ -151,7 +151,7 @@ std::vector exposedFunctions = { "startReplayBuffer", "stopReplayBuffer", "saveReplayBuffer", "startVirtualcam", "stopVirtualcam", "getScenes", "setCurrentScene", "getTransitions", "getCurrentTransition", - "setCurrentTransition","obsSourceMessage"}; + "setCurrentTransition","obsSourceMessage", "messageToApp"}; void BrowserApp::OnContextCreated(CefRefPtr browser, CefRefPtr, diff --git a/browser-client.cpp b/browser-client.cpp index 51a9e4992..c9abbb7a6 100644 --- a/browser-client.cpp +++ b/browser-client.cpp @@ -115,7 +115,7 @@ bool BrowserClient::OnProcessMessageReceived( const std::string &name = message->GetName(); CefRefPtr input_args = message->GetArgumentList(); nlohmann::json json; - blog(LOG_INFO, "BrowserClient::OnProcessMessageReceived: %s", name.c_str()); + blog(LOG_INFO, "[BrowserMessage] OnProcessMessageReceived: %s", name.c_str()); if (!valid()) { return false; } @@ -261,23 +261,27 @@ bool BrowserClient::OnProcessMessageReceived( #else switch (webpage_control_level) { case ControlLevel::All: - + [[fallthrough]]; case ControlLevel::Advanced: - + [[fallthrough]]; case ControlLevel::Basic: - + [[fallthrough]]; case ControlLevel::ReadUser: - + [[fallthrough]]; case ControlLevel::ReadObs: - + [[fallthrough]]; case ControlLevel::None: if (name == "getControlLevel") { json = (int)webpage_control_level; + } else if (name =="messageToApp") { + const std::string message = input_args->GetString(1).ToString(); + blog(LOG_INFO, "[BrowserMessage] messageToApp called: arguments %d, arg2 %s", input_args->GetSize(), message.c_str()); + bs->messagesToApp.push_back(message); } } UNUSED_PARAMETER(name); diff --git a/obs-browser-plugin.cpp b/obs-browser-plugin.cpp index 807d3f41d..138f21f49 100644 --- a/obs-browser-plugin.cpp +++ b/obs-browser-plugin.cpp @@ -322,6 +322,26 @@ static obs_missing_files_t *browser_source_missingfiles(void *data) return files; } +static obs_data_array_t *browser_source_get_messages(void *data) +{ + BrowserSource *bs = static_cast(data); + obs_data_array_t *messages = nullptr; + + if (bs && !bs->messagesToApp.empty()) { + + messages = obs_data_array_create(); + for (const auto &message : bs->messagesToApp) { + obs_data_t *msg_data = obs_data_create(); + obs_data_set_string(msg_data, "message", message.c_str()); + obs_data_array_push_back(messages, msg_data); + obs_data_release(msg_data); + } + bs->messagesToApp.clear(); + } + + return messages; +} + static CefRefPtr app; static void BrowserInit(obs_data_t *settings_obs) @@ -622,8 +642,9 @@ void RegisterBrowserSource() info.message = [](void *data, obs_data_t *settings) { BrowserSource *bs = static_cast(data); const char *message = obs_data_get_string(settings, "message"); - bs->SendMessage(message); + bs->MessageToBrowser(message); }; + info.get_messages = browser_source_get_messages; info.deactivate = [](void *data) { static_cast(data)->SetActive(false); }; diff --git a/obs-browser-source.cpp b/obs-browser-source.cpp index f8ab9b0e5..b0607b4c4 100644 --- a/obs-browser-source.cpp +++ b/obs-browser-source.cpp @@ -477,16 +477,16 @@ void BrowserSource::SetActive(bool active) DispatchJSEvent("obsSourceActiveChanged", json.dump(), this); } -void BrowserSource::SendMessage(const char* message) +void BrowserSource::MessageToBrowser(const char* message) { if (destroying) return; - blog(LOG_INFO, "BrowserSource::SendMessage: %s", message); + blog(LOG_INFO, "[BrowserMessage] MessageToBrowser: %s", message); nlohmann::json json; json["message"] = message; - DispatchJSEvent("obsSourceMessage", json.dump(), this); + DispatchJSEvent("MessageFromApp", json.dump(), this); } void BrowserSource::Refresh() diff --git a/obs-browser-source.hpp b/obs-browser-source.hpp index 484398a26..65629ec96 100644 --- a/obs-browser-source.hpp +++ b/obs-browser-source.hpp @@ -62,6 +62,7 @@ struct BrowserSource { bool create_browser = false; std::recursive_mutex lockBrowser; CefRefPtr cefBrowser; + std::vector messagesToApp; std::string url; std::string css; @@ -150,7 +151,7 @@ struct BrowserSource { void SendKeyClick(const struct obs_key_event *event, bool key_up); void SetShowing(bool showing); void SetActive(bool active); - void SendMessage(const char* message); + void MessageToBrowser(const char* message); void Refresh(); #if defined(BROWSER_EXTERNAL_BEGIN_FRAME_ENABLED) && \ From 414238e0a046fb120d747e3d6828b8ee078271f5 Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Wed, 4 Sep 2024 13:37:45 -0700 Subject: [PATCH 06/17] remove qt deps from browser source --- cmake/os-macos.cmake | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/cmake/os-macos.cmake b/cmake/os-macos.cmake index 6ae8ec3e0..2acff0a35 100644 --- a/cmake/os-macos.cmake +++ b/cmake/os-macos.cmake @@ -1,17 +1,13 @@ -# We currently do not use Qt in obs-studio-node so its' best to leave this off. OBS.app is a QtApplication so this makes sense for them. -#find_package(Qt6 REQUIRED Widgets) +find_library(COREFOUNDATION CoreFoundation) +find_library(APPKIT AppKit) +mark_as_advanced(COREFOUNDATION APPKIT) -# Do not turn on ENABLE_BROWSER_QT_LOOP. Once again, obs-studio-node is not a Qt app. We could make it one kinda easily as long as the exact same -# binaries we use to build obs-browser is packed up and shipped along like libobs.framework. But for now we dont need the ENABLE_BROWSER_QT_LOOP flag target_compile_definitions(obs-browser PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) - if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0.3) target_compile_options(obs-browser PRIVATE -Wno-error=unqualified-std-cast-call) endif() -# Streamlabs removed Qt::Widgets. Our obs-browser does not use Qt framework -target_link_libraries(obs-browser PRIVATE CEF::Wrapper "$" - "$") +target_link_libraries(obs-browser PRIVATE ${COREFOUNDATION} ${APPKIT} CEF::Wrapper) set(helper_basename browser-helper) set(helper_output_name "obs64 Helper") # See cef_types.h documentation for browser_subprocess_path setting From fd55f712aed278fc33e41ed766fd2a60c113122d Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Wed, 18 Dec 2024 15:24:17 -0800 Subject: [PATCH 07/17] merge fix --- cmake/os-windows.cmake | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cmake/os-windows.cmake b/cmake/os-windows.cmake index a1c829e86..657aafafb 100644 --- a/cmake/os-windows.cmake +++ b/cmake/os-windows.cmake @@ -4,29 +4,29 @@ target_compile_definitions(obs-browser PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) target_link_libraries(obs-browser PRIVATE CEF::Wrapper CEF::Library d3d11 dxgi) target_link_options(obs-browser PRIVATE /IGNORE:4099) -add_executable(obs-browser-helper WIN32 EXCLUDE_FROM_ALL) -add_executable(OBS::browser-helper ALIAS obs-browser-helper) +add_executable(obs-browser-page WIN32 EXCLUDE_FROM_ALL) +add_executable(OBS::browser-helper ALIAS obs-browser-page) target_sources( - obs-browser-helper + obs-browser-page PRIVATE # cmake-format: sortable browser-app.cpp browser-app.hpp cef-headers.hpp obs-browser-page.manifest obs-browser-page/obs-browser-page-main.cpp) -target_include_directories(obs-browser-helper PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/deps" +target_include_directories(obs-browser-page PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/deps" "${CMAKE_CURRENT_SOURCE_DIR}/obs-browser-page") -target_compile_options(obs-browser-helper PRIVATE $,/MTd,/MT>) -target_compile_definitions(obs-browser-helper PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) +target_compile_options(obs-browser-page PRIVATE $,/MTd,/MT>) +target_compile_definitions(obs-browser-page PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) -target_link_libraries(obs-browser-helper PRIVATE CEF::Wrapper CEF::Library nlohmann_json::nlohmann_json) -target_link_options(obs-browser-helper PRIVATE /IGNORE:4099 /SUBSYSTEM:WINDOWS) +target_link_libraries(obs-browser-page PRIVATE CEF::Wrapper CEF::Library nlohmann_json::nlohmann_json) +target_link_options(obs-browser-page PRIVATE /IGNORE:4099 /SUBSYSTEM:WINDOWS) message(STATUS "Buiding browser source plugin helper for Windows") set(OBS_EXECUTABLE_DESTINATION "${OBS_PLUGIN_DESTINATION}") set_target_properties_obs( - obs-browser-helper + obs-browser-page PROPERTIES FOLDER plugins/obs-browser PREFIX "" OUTPUT_NAME obs-browser-page) From dc2acb941178cdc218a39f3d0a0cf36434dff3c0 Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Thu, 19 Dec 2024 15:47:17 -0800 Subject: [PATCH 08/17] merge fix --- cmake/os-windows.cmake | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/cmake/os-windows.cmake b/cmake/os-windows.cmake index 657aafafb..226d4ffe7 100644 --- a/cmake/os-windows.cmake +++ b/cmake/os-windows.cmake @@ -4,29 +4,31 @@ target_compile_definitions(obs-browser PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) target_link_libraries(obs-browser PRIVATE CEF::Wrapper CEF::Library d3d11 dxgi) target_link_options(obs-browser PRIVATE /IGNORE:4099) -add_executable(obs-browser-page WIN32 EXCLUDE_FROM_ALL) -add_executable(OBS::browser-helper ALIAS obs-browser-page) +add_executable(obs-browser-helper WIN32 EXCLUDE_FROM_ALL) +add_executable(OBS::browser-helper ALIAS obs-browser-helper) target_sources( - obs-browser-page + obs-browser-helper PRIVATE # cmake-format: sortable browser-app.cpp browser-app.hpp cef-headers.hpp obs-browser-page.manifest obs-browser-page/obs-browser-page-main.cpp) -target_include_directories(obs-browser-page PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/deps" +target_include_directories(obs-browser-helper PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/deps" "${CMAKE_CURRENT_SOURCE_DIR}/obs-browser-page") -target_compile_options(obs-browser-page PRIVATE $,/MTd,/MT>) -target_compile_definitions(obs-browser-page PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) +target_compile_options(obs-browser-helper PRIVATE $,/MTd,/MT>) +target_compile_definitions(obs-browser-helper PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) -target_link_libraries(obs-browser-page PRIVATE CEF::Wrapper CEF::Library nlohmann_json::nlohmann_json) -target_link_options(obs-browser-page PRIVATE /IGNORE:4099 /SUBSYSTEM:WINDOWS) +target_link_libraries(obs-browser-helper PRIVATE CEF::Wrapper CEF::Library nlohmann_json::nlohmann_json) +target_link_options(obs-browser-helper PRIVATE /IGNORE:4099 /SUBSYSTEM:WINDOWS) + +message(STATUS "Buiding browser source plugin helper for Windows") message(STATUS "Buiding browser source plugin helper for Windows") set(OBS_EXECUTABLE_DESTINATION "${OBS_PLUGIN_DESTINATION}") set_target_properties_obs( - obs-browser-page + obs-browser-helper PROPERTIES FOLDER plugins/obs-browser PREFIX "" OUTPUT_NAME obs-browser-page) From 5c0ada055dc05bd6b6e7d4fcc9e10c8e14570884 Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Wed, 4 Jun 2025 12:10:20 -0700 Subject: [PATCH 09/17] way to send message to browser source --- browser-app.cpp | 7 +++++-- browser-client.cpp | 23 ++++++++++++++++++++++- obs-browser-plugin.cpp | 5 +++++ obs-browser-source.cpp | 14 +++++++++++++- obs-browser-source.hpp | 1 + 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/browser-app.cpp b/browser-app.cpp index 6bd6cc659..788d04912 100644 --- a/browser-app.cpp +++ b/browser-app.cpp @@ -151,7 +151,7 @@ std::vector exposedFunctions = { "startReplayBuffer", "stopReplayBuffer", "saveReplayBuffer", "startVirtualcam", "stopVirtualcam", "getScenes", "setCurrentScene", "getTransitions", "getCurrentTransition", - "setCurrentTransition"}; + "setCurrentTransition","obsSourceMessage"}; void BrowserApp::OnContextCreated(CefRefPtr browser, CefRefPtr, @@ -412,7 +412,10 @@ bool BrowserApp::OnProcessMessageReceived(CefRefPtr browser, CefRefPtr dispatchEvent = globalObj->GetValue("dispatchEvent"); dispatchEvent->ExecuteFunction(nullptr, arguments); - + if (!dispatchEvent || !dispatchEvent->IsFunction()) { + } else { + dispatchEvent->ExecuteFunction(nullptr, arguments); + } context->Exit(); } diff --git a/browser-client.cpp b/browser-client.cpp index 5148fdc88..51a9e4992 100644 --- a/browser-client.cpp +++ b/browser-client.cpp @@ -115,7 +115,7 @@ bool BrowserClient::OnProcessMessageReceived( const std::string &name = message->GetName(); CefRefPtr input_args = message->GetArgumentList(); nlohmann::json json; - + blog(LOG_INFO, "BrowserClient::OnProcessMessageReceived: %s", name.c_str()); if (!valid()) { return false; } @@ -259,6 +259,27 @@ bool BrowserClient::OnProcessMessageReceived( } } #else + switch (webpage_control_level) { + case ControlLevel::All: + + [[fallthrough]]; + case ControlLevel::Advanced: + + [[fallthrough]]; + case ControlLevel::Basic: + + [[fallthrough]]; + case ControlLevel::ReadUser: + + [[fallthrough]]; + case ControlLevel::ReadObs: + + [[fallthrough]]; + case ControlLevel::None: + if (name == "getControlLevel") { + json = (int)webpage_control_level; + } + } UNUSED_PARAMETER(name); #endif diff --git a/obs-browser-plugin.cpp b/obs-browser-plugin.cpp index d9b4a9e73..0f58518e4 100644 --- a/obs-browser-plugin.cpp +++ b/obs-browser-plugin.cpp @@ -632,6 +632,11 @@ void RegisterBrowserSource() bs->Refresh(); bs->SetActive(true); }; + info.message = [](void *data, obs_data_t *settings) { + BrowserSource *bs = static_cast(data); + const char *message = obs_data_get_string(settings, "message"); + bs->SendMessage(message); + }; info.deactivate = [](void *data) { static_cast(data)->SetActive(false); }; diff --git a/obs-browser-source.cpp b/obs-browser-source.cpp index 7f2058735..f8ab9b0e5 100644 --- a/obs-browser-source.cpp +++ b/obs-browser-source.cpp @@ -154,7 +154,7 @@ void BrowserSource::Destroy() void BrowserSource::ExecuteOnBrowser(BrowserFunc func, bool async) { - if (!async) { + if (!async) { #ifdef ENABLE_BROWSER_QT_LOOP if (QThread::currentThread() == qApp->thread()) { if (!!cefBrowser) @@ -477,6 +477,18 @@ void BrowserSource::SetActive(bool active) DispatchJSEvent("obsSourceActiveChanged", json.dump(), this); } +void BrowserSource::SendMessage(const char* message) +{ + if (destroying) + return; + + blog(LOG_INFO, "BrowserSource::SendMessage: %s", message); + + nlohmann::json json; + json["message"] = message; + DispatchJSEvent("obsSourceMessage", json.dump(), this); +} + void BrowserSource::Refresh() { ExecuteOnBrowser( diff --git a/obs-browser-source.hpp b/obs-browser-source.hpp index 86f12d495..484398a26 100644 --- a/obs-browser-source.hpp +++ b/obs-browser-source.hpp @@ -150,6 +150,7 @@ struct BrowserSource { void SendKeyClick(const struct obs_key_event *event, bool key_up); void SetShowing(bool showing); void SetActive(bool active); + void SendMessage(const char* message); void Refresh(); #if defined(BROWSER_EXTERNAL_BEGIN_FRAME_ENABLED) && \ From c719430d5ebc8599ceb22f38c5be4e8ec057a24c Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Mon, 9 Jun 2025 17:29:06 -0700 Subject: [PATCH 10/17] bring messages from bs to fe --- browser-app.cpp | 2 +- browser-client.cpp | 16 ++++++++++------ obs-browser-plugin.cpp | 23 ++++++++++++++++++++++- obs-browser-source.cpp | 6 +++--- obs-browser-source.hpp | 3 ++- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/browser-app.cpp b/browser-app.cpp index 788d04912..1866ac7e8 100644 --- a/browser-app.cpp +++ b/browser-app.cpp @@ -151,7 +151,7 @@ std::vector exposedFunctions = { "startReplayBuffer", "stopReplayBuffer", "saveReplayBuffer", "startVirtualcam", "stopVirtualcam", "getScenes", "setCurrentScene", "getTransitions", "getCurrentTransition", - "setCurrentTransition","obsSourceMessage"}; + "setCurrentTransition","obsSourceMessage", "messageToApp"}; void BrowserApp::OnContextCreated(CefRefPtr browser, CefRefPtr, diff --git a/browser-client.cpp b/browser-client.cpp index 51a9e4992..c9abbb7a6 100644 --- a/browser-client.cpp +++ b/browser-client.cpp @@ -115,7 +115,7 @@ bool BrowserClient::OnProcessMessageReceived( const std::string &name = message->GetName(); CefRefPtr input_args = message->GetArgumentList(); nlohmann::json json; - blog(LOG_INFO, "BrowserClient::OnProcessMessageReceived: %s", name.c_str()); + blog(LOG_INFO, "[BrowserMessage] OnProcessMessageReceived: %s", name.c_str()); if (!valid()) { return false; } @@ -261,23 +261,27 @@ bool BrowserClient::OnProcessMessageReceived( #else switch (webpage_control_level) { case ControlLevel::All: - + [[fallthrough]]; case ControlLevel::Advanced: - + [[fallthrough]]; case ControlLevel::Basic: - + [[fallthrough]]; case ControlLevel::ReadUser: - + [[fallthrough]]; case ControlLevel::ReadObs: - + [[fallthrough]]; case ControlLevel::None: if (name == "getControlLevel") { json = (int)webpage_control_level; + } else if (name =="messageToApp") { + const std::string message = input_args->GetString(1).ToString(); + blog(LOG_INFO, "[BrowserMessage] messageToApp called: arguments %d, arg2 %s", input_args->GetSize(), message.c_str()); + bs->messagesToApp.push_back(message); } } UNUSED_PARAMETER(name); diff --git a/obs-browser-plugin.cpp b/obs-browser-plugin.cpp index 0f58518e4..b9ecc8bc4 100644 --- a/obs-browser-plugin.cpp +++ b/obs-browser-plugin.cpp @@ -322,6 +322,26 @@ static obs_missing_files_t *browser_source_missingfiles(void *data) return files; } +static obs_data_array_t *browser_source_get_messages(void *data) +{ + BrowserSource *bs = static_cast(data); + obs_data_array_t *messages = nullptr; + + if (bs && !bs->messagesToApp.empty()) { + + messages = obs_data_array_create(); + for (const auto &message : bs->messagesToApp) { + obs_data_t *msg_data = obs_data_create(); + obs_data_set_string(msg_data, "message", message.c_str()); + obs_data_array_push_back(messages, msg_data); + obs_data_release(msg_data); + } + bs->messagesToApp.clear(); + } + + return messages; +} + static CefRefPtr app; static void BrowserInit(obs_data_t *settings_obs) @@ -635,8 +655,9 @@ void RegisterBrowserSource() info.message = [](void *data, obs_data_t *settings) { BrowserSource *bs = static_cast(data); const char *message = obs_data_get_string(settings, "message"); - bs->SendMessage(message); + bs->MessageToBrowser(message); }; + info.get_messages = browser_source_get_messages; info.deactivate = [](void *data) { static_cast(data)->SetActive(false); }; diff --git a/obs-browser-source.cpp b/obs-browser-source.cpp index f8ab9b0e5..b0607b4c4 100644 --- a/obs-browser-source.cpp +++ b/obs-browser-source.cpp @@ -477,16 +477,16 @@ void BrowserSource::SetActive(bool active) DispatchJSEvent("obsSourceActiveChanged", json.dump(), this); } -void BrowserSource::SendMessage(const char* message) +void BrowserSource::MessageToBrowser(const char* message) { if (destroying) return; - blog(LOG_INFO, "BrowserSource::SendMessage: %s", message); + blog(LOG_INFO, "[BrowserMessage] MessageToBrowser: %s", message); nlohmann::json json; json["message"] = message; - DispatchJSEvent("obsSourceMessage", json.dump(), this); + DispatchJSEvent("MessageFromApp", json.dump(), this); } void BrowserSource::Refresh() diff --git a/obs-browser-source.hpp b/obs-browser-source.hpp index 484398a26..65629ec96 100644 --- a/obs-browser-source.hpp +++ b/obs-browser-source.hpp @@ -62,6 +62,7 @@ struct BrowserSource { bool create_browser = false; std::recursive_mutex lockBrowser; CefRefPtr cefBrowser; + std::vector messagesToApp; std::string url; std::string css; @@ -150,7 +151,7 @@ struct BrowserSource { void SendKeyClick(const struct obs_key_event *event, bool key_up); void SetShowing(bool showing); void SetActive(bool active); - void SendMessage(const char* message); + void MessageToBrowser(const char* message); void Refresh(); #if defined(BROWSER_EXTERNAL_BEGIN_FRAME_ENABLED) && \ From 57f4f41b83e651ff9e373fa9539752bfebec5837 Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Tue, 15 Jul 2025 21:41:35 +0200 Subject: [PATCH 11/17] fix naming --- browser-app.cpp | 2 +- obs-browser-source.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/browser-app.cpp b/browser-app.cpp index 1866ac7e8..018656957 100644 --- a/browser-app.cpp +++ b/browser-app.cpp @@ -151,7 +151,7 @@ std::vector exposedFunctions = { "startReplayBuffer", "stopReplayBuffer", "saveReplayBuffer", "startVirtualcam", "stopVirtualcam", "getScenes", "setCurrentScene", "getTransitions", "getCurrentTransition", - "setCurrentTransition","obsSourceMessage", "messageToApp"}; + "setCurrentTransition","messageFromApp", "messageToApp"}; void BrowserApp::OnContextCreated(CefRefPtr browser, CefRefPtr, diff --git a/obs-browser-source.cpp b/obs-browser-source.cpp index b0607b4c4..870e19426 100644 --- a/obs-browser-source.cpp +++ b/obs-browser-source.cpp @@ -486,7 +486,7 @@ void BrowserSource::MessageToBrowser(const char* message) nlohmann::json json; json["message"] = message; - DispatchJSEvent("MessageFromApp", json.dump(), this); + DispatchJSEvent("messageFromApp", json.dump(), this); } void BrowserSource::Refresh() From 94a60bccd46bba0351ed48c4fd32f1ebf8dac2de Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Wed, 6 Aug 2025 20:42:30 +0200 Subject: [PATCH 12/17] add debugging --- browser-app.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/browser-app.cpp b/browser-app.cpp index 018656957..01a90a006 100644 --- a/browser-app.cpp +++ b/browser-app.cpp @@ -35,6 +35,8 @@ #endif #endif +#include "include/cef_command_line.h" + #if defined(USE_UI_LOOP) && defined(__APPLE__) #include "browser-mac.h" #endif @@ -139,6 +141,8 @@ void BrowserApp::OnBeforeCommandLineProcessing( "enable-media-stream", "1"); } } + command_line->AppendSwitchWithValue("remote-debugging-port", "9222"); + command_line->AppendSwitchWithValue("remote-allow-origins", "http://localhost:9222"); #ifdef __APPLE__ command_line->AppendSwitch("use-mock-keychain"); #endif From ad376a5fde3a25e8b2cf7cba5d16360026d0ee81 Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Fri, 12 Sep 2025 16:00:47 -0700 Subject: [PATCH 13/17] Revert "remove qt deps from browser source" This reverts commit 414238e0a046fb120d747e3d6828b8ee078271f5. --- cmake/os-macos.cmake | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cmake/os-macos.cmake b/cmake/os-macos.cmake index 2acff0a35..6ae8ec3e0 100644 --- a/cmake/os-macos.cmake +++ b/cmake/os-macos.cmake @@ -1,13 +1,17 @@ -find_library(COREFOUNDATION CoreFoundation) -find_library(APPKIT AppKit) -mark_as_advanced(COREFOUNDATION APPKIT) +# We currently do not use Qt in obs-studio-node so its' best to leave this off. OBS.app is a QtApplication so this makes sense for them. +#find_package(Qt6 REQUIRED Widgets) +# Do not turn on ENABLE_BROWSER_QT_LOOP. Once again, obs-studio-node is not a Qt app. We could make it one kinda easily as long as the exact same +# binaries we use to build obs-browser is packed up and shipped along like libobs.framework. But for now we dont need the ENABLE_BROWSER_QT_LOOP flag target_compile_definitions(obs-browser PRIVATE ENABLE_BROWSER_SHARED_TEXTURE) + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0.3) target_compile_options(obs-browser PRIVATE -Wno-error=unqualified-std-cast-call) endif() -target_link_libraries(obs-browser PRIVATE ${COREFOUNDATION} ${APPKIT} CEF::Wrapper) +# Streamlabs removed Qt::Widgets. Our obs-browser does not use Qt framework +target_link_libraries(obs-browser PRIVATE CEF::Wrapper "$" + "$") set(helper_basename browser-helper) set(helper_output_name "obs64 Helper") # See cef_types.h documentation for browser_subprocess_path setting From 232f54709d0894d6d5ee07c70783dd5d7a0f8c80 Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Fri, 12 Sep 2025 16:13:49 -0700 Subject: [PATCH 14/17] add mutex --- browser-client.cpp | 3 ++- cmake/os-windows.cmake | 2 -- obs-browser-plugin.cpp | 20 +++++++++++--------- obs-browser-source.cpp | 2 +- obs-browser-source.hpp | 1 + 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/browser-client.cpp b/browser-client.cpp index c9abbb7a6..85d98a181 100644 --- a/browser-client.cpp +++ b/browser-client.cpp @@ -278,9 +278,10 @@ bool BrowserClient::OnProcessMessageReceived( case ControlLevel::None: if (name == "getControlLevel") { json = (int)webpage_control_level; - } else if (name =="messageToApp") { + } else if (name == "messageToApp") { const std::string message = input_args->GetString(1).ToString(); blog(LOG_INFO, "[BrowserMessage] messageToApp called: arguments %d, arg2 %s", input_args->GetSize(), message.c_str()); + std::lock_guard lock(bs->messagesToAppMutex); bs->messagesToApp.push_back(message); } } diff --git a/cmake/os-windows.cmake b/cmake/os-windows.cmake index 226d4ffe7..a1c829e86 100644 --- a/cmake/os-windows.cmake +++ b/cmake/os-windows.cmake @@ -24,8 +24,6 @@ target_link_options(obs-browser-helper PRIVATE /IGNORE:4099 /SUBSYSTEM:WINDOWS) message(STATUS "Buiding browser source plugin helper for Windows") -message(STATUS "Buiding browser source plugin helper for Windows") - set(OBS_EXECUTABLE_DESTINATION "${OBS_PLUGIN_DESTINATION}") set_target_properties_obs( obs-browser-helper diff --git a/obs-browser-plugin.cpp b/obs-browser-plugin.cpp index b9ecc8bc4..78dfae21c 100644 --- a/obs-browser-plugin.cpp +++ b/obs-browser-plugin.cpp @@ -327,16 +327,18 @@ static obs_data_array_t *browser_source_get_messages(void *data) BrowserSource *bs = static_cast(data); obs_data_array_t *messages = nullptr; - if (bs && !bs->messagesToApp.empty()) { - - messages = obs_data_array_create(); - for (const auto &message : bs->messagesToApp) { - obs_data_t *msg_data = obs_data_create(); - obs_data_set_string(msg_data, "message", message.c_str()); - obs_data_array_push_back(messages, msg_data); - obs_data_release(msg_data); + if (bs) { + std::lock_guard lock(bs->messagesToAppMutex); + if (!bs->messagesToApp.empty()) { + messages = obs_data_array_create(); + for (const auto &message : bs->messagesToApp) { + obs_data_t *msg_data = obs_data_create(); + obs_data_set_string(msg_data, "message", message.c_str()); + obs_data_array_push_back(messages, msg_data); + obs_data_release(msg_data); + } + bs->messagesToApp.clear(); } - bs->messagesToApp.clear(); } return messages; diff --git a/obs-browser-source.cpp b/obs-browser-source.cpp index 870e19426..5a71fc130 100644 --- a/obs-browser-source.cpp +++ b/obs-browser-source.cpp @@ -154,7 +154,7 @@ void BrowserSource::Destroy() void BrowserSource::ExecuteOnBrowser(BrowserFunc func, bool async) { - if (!async) { + if (!async) { #ifdef ENABLE_BROWSER_QT_LOOP if (QThread::currentThread() == qApp->thread()) { if (!!cefBrowser) diff --git a/obs-browser-source.hpp b/obs-browser-source.hpp index 65629ec96..b385e267d 100644 --- a/obs-browser-source.hpp +++ b/obs-browser-source.hpp @@ -63,6 +63,7 @@ struct BrowserSource { std::recursive_mutex lockBrowser; CefRefPtr cefBrowser; std::vector messagesToApp; + std::mutex messagesToAppMutex; std::string url; std::string css; From 9717316b195082fdbc35a441df6f90cfae383664 Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Fri, 12 Sep 2025 16:58:10 -0700 Subject: [PATCH 15/17] fix type in printf --- browser-client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser-client.cpp b/browser-client.cpp index 85d98a181..eb6eeaea9 100644 --- a/browser-client.cpp +++ b/browser-client.cpp @@ -280,7 +280,7 @@ bool BrowserClient::OnProcessMessageReceived( json = (int)webpage_control_level; } else if (name == "messageToApp") { const std::string message = input_args->GetString(1).ToString(); - blog(LOG_INFO, "[BrowserMessage] messageToApp called: arguments %d, arg2 %s", input_args->GetSize(), message.c_str()); + blog(LOG_INFO, "[BrowserMessage] messageToApp called: arguments %zu, arg2 %s", input_args->GetSize(), message.c_str()); std::lock_guard lock(bs->messagesToAppMutex); bs->messagesToApp.push_back(message); } From 1920596d0861a7821509c962a30d94be603c3fdd Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Mon, 15 Sep 2025 09:15:43 -0700 Subject: [PATCH 16/17] codestyle --- browser-app.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/browser-app.cpp b/browser-app.cpp index 01a90a006..187a13c30 100644 --- a/browser-app.cpp +++ b/browser-app.cpp @@ -415,9 +415,8 @@ bool BrowserApp::OnProcessMessageReceived(CefRefPtr browser, CefRefPtr dispatchEvent = globalObj->GetValue("dispatchEvent"); - dispatchEvent->ExecuteFunction(nullptr, arguments); - if (!dispatchEvent || !dispatchEvent->IsFunction()) { - } else { + + If (dispatchEvent && dispatchEvent->IsFunction()) { dispatchEvent->ExecuteFunction(nullptr, arguments); } context->Exit(); From cc4f75da0ca170bb8d7bea88ae277d9836a1ef80 Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Mon, 15 Sep 2025 10:04:37 -0700 Subject: [PATCH 17/17] codestyle fix --- browser-app.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser-app.cpp b/browser-app.cpp index 187a13c30..fe7a28a79 100644 --- a/browser-app.cpp +++ b/browser-app.cpp @@ -416,7 +416,7 @@ bool BrowserApp::OnProcessMessageReceived(CefRefPtr browser, CefRefPtr dispatchEvent = globalObj->GetValue("dispatchEvent"); - If (dispatchEvent && dispatchEvent->IsFunction()) { + if (dispatchEvent && dispatchEvent->IsFunction()) { dispatchEvent->ExecuteFunction(nullptr, arguments); } context->Exit();