diff --git a/.clang-format b/.clang-format index 33e9770ab..a10cf9586 100644 --- a/.clang-format +++ b/.clang-format @@ -1,7 +1,6 @@ +# please use clang-format version 16 or later -# please use clang-format version 8 or later - -Standard: Cpp11 +Standard: c++17 AccessModifierOffset: -8 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false @@ -9,14 +8,14 @@ AlignConsecutiveDeclarations: false AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: true -#AllowAllArgumentsOnNextLine: false # requires clang-format 9 -#AllowAllConstructorInitializersOnNextLine: false # requires clang-format 9 +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: Inline AllowShortIfStatementsOnASingleLine: false -#AllowShortLambdasOnASingleLine: Inline # requires clang-format 9 +AllowShortLambdasOnASingleLine: Inline AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None @@ -45,7 +44,7 @@ BreakBeforeBraces: Custom BreakBeforeTernaryOperators: true BreakConstructorInitializers: BeforeColon BreakStringLiterals: false # apparently unpredictable -ColumnLimit: 80 +ColumnLimit: 120 CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 8 @@ -53,11 +52,12 @@ ContinuationIndentWidth: 8 Cpp11BracedListStyle: true DerivePointerAlignment: false DisableFormat: false -FixNamespaceComments: false -ForEachMacros: +FixNamespaceComments: true +ForEachMacros: - 'json_object_foreach' - 'json_object_foreach_safe' - 'json_array_foreach' + - 'HASH_ITER' IncludeBlocks: Preserve IndentCaseLabels: false IndentPPDirectives: None @@ -66,7 +66,7 @@ IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: true MaxEmptyLinesToKeep: 1 NamespaceIndentation: None -#ObjCBinPackProtocolList: Auto # requires clang-format 7 +ObjCBinPackProtocolList: Auto ObjCBlockIndentWidth: 8 ObjCSpaceAfterProperty: true ObjCSpaceBeforeProtocolList: true @@ -84,13 +84,13 @@ ReflowComments: false SortIncludes: false SortUsingDeclarations: false SpaceAfterCStyleCast: false -#SpaceAfterLogicalNot: false # requires clang-format 9 +SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: false SpaceBeforeAssignmentOperators: true -#SpaceBeforeCtorInitializerColon: true # requires clang-format 7 -#SpaceBeforeInheritanceColon: true # requires clang-format 7 +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements -#SpaceBeforeRangeBasedForLoopColon: true # requires clang-format 7 +SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false @@ -98,11 +98,111 @@ SpacesInCStyleCastParentheses: false SpacesInContainerLiterals: false SpacesInParentheses: false SpacesInSquareBrackets: false -#StatementMacros: # requires clang-format 8 -# - 'Q_OBJECT' +StatementMacros: + - 'Q_OBJECT' TabWidth: 8 -#TypenameMacros: # requires clang-format 9 -# - 'DARRAY' +TypenameMacros: + - 'DARRAY' UseTab: ForContinuationAndIndentation --- -Language: ObjC \ No newline at end of file +Language: ObjC +AccessModifierOffset: 2 +AlignArrayOfStructures: Right +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: false + AcrossComments: true +AllowShortBlocksOnASingleLine: Never +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: None +AttributeMacros: ['__unused', '__autoreleasing', '_Nonnull', '__bridge'] +BitFieldColonSpacing: Both +#BreakBeforeBraces: Webkit +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Never + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +BreakAfterAttributes: Never +BreakArrays: false +BreakBeforeConceptDeclarations: Allowed +BreakBeforeInlineASMColon: OnlyMultiline +BreakConstructorInitializers: AfterColon +BreakInheritanceList: AfterComma +ColumnLimit: 120 +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: true +IndentExternBlock: Indent +IndentGotoLabels: false +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: true +InsertBraces: false +InsertNewlineAtEOF: true +KeepEmptyLinesAtTheStartOfBlocks: false +LambdaBodyIndentation: Signature +NamespaceIndentation: All +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 4 +ObjCBreakBeforeNestedBlockParam: false +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +PPIndentWidth: -1 +PackConstructorInitializers: NextLine +QualifierAlignment: Leave +ReferenceAlignment: Right +RemoveSemicolon: false +RequiresClausePosition: WithPreceding +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: false +#SortUsingDeclarations: LexicographicNumeric +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInConditionalStatement: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +Standard: c++17 +TabWidth: 4 +UseTab: Never diff --git a/.github/actions/check-changes/action.yaml b/.github/actions/check-changes/action.yaml new file mode 100644 index 000000000..e5690b8a7 --- /dev/null +++ b/.github/actions/check-changes/action.yaml @@ -0,0 +1,82 @@ +name: Check For Changed Files +description: Checks for changed files compared to specific git reference and glob expression +inputs: + baseRef: + description: Git reference to check against + required: false + ref: + description: Git reference to check with + required: false + default: HEAD + checkGlob: + description: Glob expression to limit check to specific files + required: false + useFallback: + description: Use fallback compare against prior commit + required: false + default: 'true' + diffFilter: + description: git diff-filter string to use + required: false + default: '' +outputs: + hasChangedFiles: + value: ${{ steps.checks.outputs.hasChangedFiles }} + description: True if specified files were changed in comparison to specified git reference + changedFiles: + value: ${{ steps.checks.outputs.changedFiles }} + description: List of changed files +runs: + using: composite + steps: + - name: Check For Changed Files ✅ + shell: bash + id: checks + env: + GIT_BASE_REF: ${{ inputs.baseRef }} + GIT_REF: ${{ inputs.ref }} + GITHUB_EVENT_FORCED: ${{ github.event.forced }} + GITHUB_REF_BEFORE: ${{ github.event.before }} + USE_FALLBACK: ${{ inputs.useFallback }} + DIFF_FILTER: ${{ inputs.diffFilter }} + run: | + : Check for Changed Files ✅ + if [[ "${RUNNER_DEBUG}" ]]; then set -x; fi + shopt -s extglob + shopt -s dotglob + + # 4b825dc642cb6eb9a060e54bf8d69288fbee4904 is a "hidden" sha1 hash of + # the "empty tree", retrived via 'git hash-object -t tree /dev/null', + # and used here as a last-resort fallback to always provide a valid + # git ref. + + if [[ "${GIT_BASE_REF}" ]]; then + if ! git cat-file -e "${GIT_BASE_REF}" &> /dev/null; then + echo "::warning::Provided base reference ${GIT_BASE_REF} is invalid" + if [[ "${USE_FALLBACK}" == 'true' ]]; then + GIT_BASE_REF='HEAD~1' + fi + fi + else + if ! git cat-file -e ${GITHUB_REF_BEFORE} &> /dev/null; then + GITHUB_REF_BEFORE='4b825dc642cb6eb9a060e54bf8d69288fbee4904' + fi + + GIT_BASE_REF='HEAD~1' + case "${GITHUB_EVENT_NAME}" in + pull_request) GIT_BASE_REF="origin/${GITHUB_BASE_REF}" ;; + push) if [[ "${GITHUB_EVENT_FORCED}" != 'true' ]]; then GIT_BASE_REF="${GITHUB_REF_BEFORE}"; fi ;; + *) ;; + esac + fi + + changes=($(git diff --name-only --diff-filter="${DIFF_FILTER}" ${GIT_BASE_REF} ${GIT_REF} -- ${{ inputs.checkGlob }})) + + if (( ${#changes[@]} )); then + file_string="${changes[*]}" + echo "hasChangedFiles=true" >> $GITHUB_OUTPUT + echo "changedFiles=[\"${file_string// /\",\"}\"]" >> $GITHUB_OUTPUT + else + echo "hasChangedFiles=false" >> $GITHUB_OUTPUT + echo "changedFiles=[]" >> GITHUB_OUTPUT + fi diff --git a/.github/actions/run-clang-format/action.yaml b/.github/actions/run-clang-format/action.yaml new file mode 100644 index 000000000..94dea0840 --- /dev/null +++ b/.github/actions/run-clang-format/action.yaml @@ -0,0 +1,60 @@ +name: Run clang-format +description: Runs clang-format and checks for any changes introduced by it +inputs: + failCondition: + description: Controls whether failed checks also fail the workflow run + required: false + default: never + workingDirectory: + description: Working directory for checks + required: false + default: ${{ github.workspace }} +runs: + using: composite + steps: + - name: Check Runner Operating System 🏃‍♂️ + if: runner.os == 'Windows' + shell: bash + run: | + : Check Runner Operating System 🏃‍♂️ + echo "::notice::run-clang-format action requires a macOS-based or Linux-based runner." + exit 2 + + - name: Check for Changed Files ✅ + uses: ./.github/actions/check-changes + id: checks + with: + checkGlob: "'*.c' '*.h' '*.cpp' '*.hpp' '*.m' '*.mm'" + diffFilter: 'ACM' + + - name: Install Dependencies 🛍️ + if: runner.os == 'Linux' && fromJSON(steps.checks.outputs.hasChangedFiles) + shell: bash + run: | + : Install Dependencies 🛍️ + echo ::group::Install Dependencies + eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" + echo "/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin" >> $GITHUB_PATH + echo "/home/linuxbrew/.linuxbrew/opt/clang-format@17/bin" >> $GITHUB_PATH + brew install --quiet zsh + echo ::endgroup:: + + - name: Run clang-format 🐉 + if: fromJSON(steps.checks.outputs.hasChangedFiles) + id: result + shell: zsh --no-rcs --errexit --pipefail {0} + working-directory: ${{ inputs.workingDirectory }} + env: + CHANGED_FILES: ${{ steps.checks.outputs.changedFiles }} + run: | + : Run clang-format 🐉 + if (( ${+RUNNER_DEBUG} )) setopt XTRACE + + print ::group::Install clang-format-17 + brew install --quiet obsproject/tools/clang-format@17 + print ::endgroup:: + + print ::group::Run clang-format-17 + local -a changes=(${(s:,:)CHANGED_FILES//[\[\]\'\"]/}) + ./build-aux/run-clang-format --fail-${{ inputs.failCondition }} --check ${changes} + print ::endgroup:: diff --git a/.github/workflows/check-format.yaml b/.github/workflows/check-format.yaml new file mode 100644 index 000000000..0b9a3674c --- /dev/null +++ b/.github/workflows/check-format.yaml @@ -0,0 +1,15 @@ +name: Check Code Formatting 🛠️ +on: + workflow_call: +jobs: + clang-format: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: clang-format Check 🐉 + id: clang-format + uses: ./.github/actions/run-clang-format + with: + failCondition: error diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml deleted file mode 100644 index 5baf0ddf8..000000000 --- a/.github/workflows/clang-format.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Clang Format Check - -on: [push, pull_request] - -jobs: - ubuntu64: - runs-on: ubuntu-22.04 - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: 'recursive' - - - name: Install clang format - run: | - sudo apt-get install -y clang-format-13 - - - name: Check the Formatting - run: | - ./formatcode.sh - ./CI/check-format.sh diff --git a/.github/workflows/pr-pull.yaml b/.github/workflows/pr-pull.yaml new file mode 100644 index 000000000..b2ffa34c3 --- /dev/null +++ b/.github/workflows/pr-pull.yaml @@ -0,0 +1,20 @@ +name: Pull +run-name: ${{ github.event.pull_request.title }} pull request run 🚀 +on: + workflow_dispatch: + pull_request: + paths-ignore: + - '**.md' + branches: [master] + types: [ opened, synchronize, reopened ] +permissions: + contents: read +concurrency: + group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}' + cancel-in-progress: true +jobs: + check-format: + name: Format 🔍 + uses: ./.github/workflows/check-format.yaml + permissions: + contents: read diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml new file mode 100644 index 000000000..c6f8521ce --- /dev/null +++ b/.github/workflows/push.yaml @@ -0,0 +1,20 @@ +name: Push +run-name: ${{ github.ref_name }} push run 🚀 +on: + push: + paths-ignore: + - '**.md' + branches: + - master + - 'release/**' + tags: + - '*' +permissions: + contents: write +jobs: + check-format: + name: Format 🔍 + if: github.ref_name == 'master' + uses: ./.github/workflows/check-format.yaml + permissions: + contents: read diff --git a/CI/check-format.sh b/CI/check-format.sh deleted file mode 100755 index 7642c190a..000000000 --- a/CI/check-format.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -dirty=$(git ls-files --modified) - -set +x -if [[ $dirty ]]; then - echo "=================================" - echo "Files were not formatted properly" - echo "$dirty" - echo "=================================" - exit 1 -fi \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 554979af4..f88e1a434 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,5 @@ cmake_minimum_required(VERSION 3.16...3.25) -legacy_check() - option(ENABLE_BROWSER "Enable browser source plugin (required Chromium Embedded Framework)" OFF) if(NOT ENABLE_BROWSER) @@ -11,8 +9,8 @@ if(NOT ENABLE_BROWSER) return() endif() -find_package(CEF REQUIRED 95) -find_package(nlohmann_json REQUIRED) +find_package(CEF 95 REQUIRED) +find_package(nlohmann_json 3.11 REQUIRED) add_library(obs-browser MODULE) add_library(OBS::browser ALIAS obs-browser) @@ -33,7 +31,6 @@ target_sources( cef-headers.hpp deps/base64/base64.cpp deps/base64/base64.hpp - deps/obs-websocket-api/obs-websocket-api.h deps/signal-restore.cpp deps/signal-restore.hpp deps/wide-string.cpp @@ -53,7 +50,7 @@ target_sources(obs-browser PRIVATE ${obs-browser_SOURCES}) target_include_directories(obs-browser PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/deps") target_compile_features(obs-browser PRIVATE cxx_std_17) -target_link_libraries(obs-browser PRIVATE OBS::libobs OBS::frontend-api nlohmann_json::nlohmann_json) +target_link_libraries(obs-browser PRIVATE OBS::libobs OBS::frontend-api OBS::websocket-api nlohmann_json::nlohmann_json) if(OS_WINDOWS) include(cmake/os-windows.cmake) diff --git a/FindCEF.cmake b/FindCEF.cmake deleted file mode 100644 index 00d020328..000000000 --- a/FindCEF.cmake +++ /dev/null @@ -1,160 +0,0 @@ -include(FindPackageHandleStandardArgs) - -set_property(CACHE CEF_ROOT_DIR PROPERTY HELPSTRING - "Path to CEF distributed build") -if(NOT DEFINED CEF_ROOT_DIR OR CEF_ROOT_DIR STREQUAL "") - message( - FATAL_ERROR - "CEF_ROOT_DIR is not set - if ENABLE_BROWSER is enabled, a CEF distribution with compiled wrapper library is required.\n" - "Please download a CEF distribution for your appropriate architecture and specify CEF_ROOT_DIR to its location" - ) -endif() - -find_path(CEF_INCLUDE_DIR "include/cef_version.h" HINTS "${CEF_ROOT_DIR}") - -if(OS_MACOS) - find_library( - CEF_LIBRARY - NAMES cef libcef cef.lib libcef.o "Chromium Embedded Framework" - NO_DEFAULT_PATH - PATHS "${CEF_ROOT_DIR}" "${CEF_ROOT_DIR}/Release") - - find_library( - CEFWRAPPER_LIBRARY - NAMES cef_dll_wrapper libcef_dll_wrapper - NO_DEFAULT_PATH - PATHS "${CEF_ROOT_DIR}/build/libcef_dll/Release" - "${CEF_ROOT_DIR}/build/libcef_dll_wrapper/Release" - "${CEF_ROOT_DIR}/build/libcef_dll" - "${CEF_ROOT_DIR}/build/libcef_dll_wrapper") - -elseif(OS_POSIX) - find_library( - CEF_LIBRARY - NAMES libcef.so "Chromium Embedded Framework" - NO_DEFAULT_PATH - PATHS "${CEF_ROOT_DIR}" "${CEF_ROOT_DIR}/Release") - - find_library( - CEFWRAPPER_LIBRARY - NAMES libcef_dll_wrapper.a - NO_DEFAULT_PATH - PATHS "${CEF_ROOT_DIR}/build/libcef_dll_wrapper" - "${CEF_ROOT_DIR}/libcef_dll_wrapper") - -else() - find_library( - CEF_LIBRARY - NAMES cef libcef cef.lib libcef.o "Chromium Embedded Framework" - PATHS "${CEF_ROOT_DIR}" "${CEF_ROOT_DIR}/Release") - - find_library( - CEFWRAPPER_LIBRARY - NAMES cef_dll_wrapper libcef_dll_wrapper - PATHS "${CEF_ROOT_DIR}/build/libcef_dll/Release" - "${CEF_ROOT_DIR}/build/libcef_dll_wrapper/Release" - "${CEF_ROOT_DIR}/build/libcef_dll" - "${CEF_ROOT_DIR}/build/libcef_dll_wrapper") - - if(OS_WINDOWS) - find_library( - CEFWRAPPER_LIBRARY_DEBUG - NAMES cef_dll_wrapper libcef_dll_wrapper - PATHS "${CEF_ROOT_DIR}/build/libcef_dll/Debug" - "${CEF_ROOT_DIR}/build/libcef_dll_wrapper/Debug") - endif() -endif() - -mark_as_advanced(CEFWRAPPER_LIBRARY CEFWRAPPER_LIBRARY_DEBUG) - -if(NOT CEF_LIBRARY) - message( - WARNING - " Could NOT find Chromium Embedded Framework library (missing: CEF_LIBRARY)" - ) - set(CEF_FOUND FALSE) - return() -endif() - -if(NOT CEFWRAPPER_LIBRARY) - message( - WARNING - " Could NOT find Chromium Embedded Framework wrapper library (missing: CEFWRAPPER_LIBRARY)" - ) - set(CEF_FOUND FALSE) - return() -endif() - -message( - STATUS - "Found Chromium Embedded Framework: ${CEF_LIBRARY};${CEF_WRAPPER_LIBRARY}") - -if(OS_WINDOWS) - set(CEF_LIBRARIES ${CEF_LIBRARY} ${CEFWRAPPER_LIBRARY}) - -elseif(OS_MACOS) - if(BROWSER_LEGACY) - set(CEF_LIBRARIES ${CEFWRAPPER_LIBRARY} ${CEF_LIBRARY}) - else() - set(CEF_LIBRARIES ${CEFWRAPPER_LIBRARY}) - endif() -else() - set(CEF_LIBRARIES ${CEF_LIBRARY} optimized ${CEFWRAPPER_LIBRARY}) - - if(CEFWRAPPER_LIBRARY_DEBUG) - list(APPEND CEF_LIBRARIES debug ${CEFWRAPPER_LIBRARY_DEBUG}) - endif() -endif() - -find_package_handle_standard_args(CEF DEFAULT_MSG CEF_LIBRARY - CEFWRAPPER_LIBRARY CEF_INCLUDE_DIR) - -mark_as_advanced(CEF_LIBRARY CEF_WRAPPER_LIBRARY CEF_LIBRARIES CEF_INCLUDE_DIR) - -if(NOT TARGET CEF::Wrapper) - if(IS_ABSOLUTE "${CEF_LIBRARIES}") - add_library(CEF::Wrapper UNKNOWN IMPORTED) - add_library(CEF::Library UNKNOWN IMPORTED) - - set_target_properties(CEF::Wrapper PROPERTIES IMPORTED_LOCATION - ${CEFWRAPPER_LIBRARY}) - - set_target_properties(CEF::Library PROPERTIES IMPORTED_LOCATION - ${CEF_LIBRARY}) - - if(DEFINED CEFWRAPPER_LIBRARY_DEBUG) - add_library(CEF::Wrapper_Debug UNKNOWN IMPORTED) - set_target_properties( - CEF::Wrapper_Debug PROPERTIES IMPORTED_LOCATION - ${CEFWRAPPER_LIBRARY_DEBUG}) - endif() - else() - add_library(CEF::Wrapper INTERFACE IMPORTED) - add_library(CEF::Library INTERFACE IMPORTED) - - set_target_properties(CEF::Wrapper PROPERTIES IMPORTED_LIBNAME - ${CEFWRAPPER_LIBRARY}) - - set_target_properties(CEF::Library PROPERTIES IMPORTED_LIBNAME - ${CEF_LIBRARY}) - - if(DEFINED CEFWRAPPER_LIBRARY_DEBUG) - add_library(CEF::Wrapper_Debug INTERFACE IMPORTED) - set_target_properties( - CEF::Wrapper_Debug PROPERTIES IMPORTED_LIBNAME - ${CEFWRAPPER_LIBRARY_DEBUG}) - endif() - endif() - - set_target_properties(CEF::Wrapper PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - "${CEF_INCLUDE_DIR}") - - set_target_properties(CEF::Library PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - "${CEF_INCLUDE_DIR}") - - if(DEFINED CEFWRAPPER_LIBRARY_DEBUG) - set_target_properties( - CEF::Wrapper_Debug PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - "${CEF_INCLUDE_DIR}") - endif() -endif() diff --git a/browser-app.cpp b/browser-app.cpp index 6bd6cc659..2f994adb3 100644 --- a/browser-app.cpp +++ b/browser-app.cpp @@ -58,9 +58,7 @@ CefRefPtr BrowserApp::GetBrowserProcessHandler() void BrowserApp::OnRegisterCustomSchemes(CefRawPtr registrar) { - registrar->AddCustomScheme("http", - CEF_SCHEME_OPTION_STANDARD | - CEF_SCHEME_OPTION_CORS_ENABLED); + registrar->AddCustomScheme("http", CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED); } void BrowserApp::AddFlag(bool flag) @@ -69,8 +67,7 @@ void BrowserApp::AddFlag(bool flag) this->media_flags.push(flag); } -void BrowserApp::OnBeforeChildProcessLaunch( - CefRefPtr command_line) +void BrowserApp::OnBeforeChildProcessLaunch(CefRefPtr command_line) { #ifdef _WIN32 std::string pid = std::to_string(GetCurrentProcessId()); @@ -95,8 +92,7 @@ void BrowserApp::OnBeforeChildProcessLaunch( } } -void BrowserApp::OnBeforeCommandLineProcessing( - const CefString &, CefRefPtr command_line) +void BrowserApp::OnBeforeCommandLineProcessing(const CefString &, CefRefPtr command_line) { if (!shared_texture_available) { bool enableGPU = command_line->HasSwitch("enable-gpu"); @@ -109,20 +105,22 @@ void BrowserApp::OnBeforeCommandLineProcessing( if (command_line->HasSwitch("disable-features")) { // Don't override existing, as this can break OSR - std::string disableFeatures = - command_line->GetSwitchValue("disable-features"); + std::string disableFeatures = command_line->GetSwitchValue("disable-features"); disableFeatures += ",HardwareMediaKeyHandling"; +#ifdef _WIN32 + disableFeatures += ",EnableWindowsGamingInputDataFetcher"; +#endif disableFeatures += ",WebBluetooth"; - command_line->AppendSwitchWithValue("disable-features", - disableFeatures); + command_line->AppendSwitchWithValue("disable-features", disableFeatures); } else { - command_line->AppendSwitchWithValue("disable-features", - "WebBluetooth," - "HardwareMediaKeyHandling"); + command_line->AppendSwitchWithValue("disable-features", "WebBluetooth," +#ifdef _WIN32 + "EnableWindowsGamingInputDataFetcher," +#endif + "HardwareMediaKeyHandling"); } - command_line->AppendSwitchWithValue("autoplay-policy", - "no-user-gesture-required"); + command_line->AppendSwitchWithValue("autoplay-policy", "no-user-gesture-required"); std::lock_guard guard(flag_mutex); if (this->media_flag != -1) { @@ -141,37 +139,31 @@ void BrowserApp::OnBeforeCommandLineProcessing( } #ifdef __APPLE__ command_line->AppendSwitch("use-mock-keychain"); +#elif !defined(_WIN32) + command_line->AppendSwitchWithValue("ozone-platform", wayland ? "wayland" : "x11"); #endif } -std::vector exposedFunctions = { - "getControlLevel", "getCurrentScene", "getStatus", - "startRecording", "stopRecording", "startStreaming", - "stopStreaming", "pauseRecording", "unpauseRecording", - "startReplayBuffer", "stopReplayBuffer", "saveReplayBuffer", - "startVirtualcam", "stopVirtualcam", "getScenes", - "setCurrentScene", "getTransitions", "getCurrentTransition", - "setCurrentTransition"}; - -void BrowserApp::OnContextCreated(CefRefPtr browser, - CefRefPtr, - CefRefPtr context) +std::vector exposedFunctions = {"getControlLevel", "getCurrentScene", "getStatus", + "startRecording", "stopRecording", "startStreaming", + "stopStreaming", "pauseRecording", "unpauseRecording", + "startReplayBuffer", "stopReplayBuffer", "saveReplayBuffer", + "startVirtualcam", "stopVirtualcam", "getScenes", + "setCurrentScene", "getTransitions", "getCurrentTransition", + "setCurrentTransition"}; + +void BrowserApp::OnContextCreated(CefRefPtr browser, CefRefPtr, CefRefPtr context) { CefRefPtr globalObj = context->GetGlobal(); - CefRefPtr obsStudioObj = - CefV8Value::CreateObject(nullptr, nullptr); - globalObj->SetValue("obsstudio", obsStudioObj, - V8_PROPERTY_ATTRIBUTE_NONE); + CefRefPtr obsStudioObj = CefV8Value::CreateObject(nullptr, nullptr); + globalObj->SetValue("obsstudio", obsStudioObj, V8_PROPERTY_ATTRIBUTE_NONE); - CefRefPtr pluginVersion = - CefV8Value::CreateString(OBS_BROWSER_VERSION_STRING); - obsStudioObj->SetValue("pluginVersion", pluginVersion, - V8_PROPERTY_ATTRIBUTE_NONE); + CefRefPtr pluginVersion = CefV8Value::CreateString(OBS_BROWSER_VERSION_STRING); + obsStudioObj->SetValue("pluginVersion", pluginVersion, V8_PROPERTY_ATTRIBUTE_NONE); for (std::string name : exposedFunctions) { - CefRefPtr func = - CefV8Value::CreateFunction(name, this); + CefRefPtr func = CefV8Value::CreateFunction(name, this); obsStudioObj->SetValue(name, func, V8_PROPERTY_ATTRIBUTE_NONE); } @@ -185,23 +177,24 @@ void BrowserApp::OnContextCreated(CefRefPtr browser, #endif } -void BrowserApp::ExecuteJSFunction(CefRefPtr browser, - const char *functionName, - CefV8ValueList arguments) +void BrowserApp::ExecuteJSFunction(CefRefPtr browser, const char *functionName, CefV8ValueList arguments) { std::vector names; browser->GetFrameNames(names); for (auto &name : names) { - CefRefPtr frame = browser->GetFrame(name); + CefRefPtr frame = +#if CHROME_VERSION_BUILD >= 6261 + browser->GetFrameByName(name); +#else + browser->GetFrame(name); +#endif CefRefPtr context = frame->GetV8Context(); context->Enter(); CefRefPtr globalObj = context->GetGlobal(); - CefRefPtr obsStudioObj = - globalObj->GetValue("obsstudio"); - CefRefPtr jsFunction = - obsStudioObj->GetValue(functionName); + CefRefPtr obsStudioObj = globalObj->GetValue("obsstudio"); + CefRefPtr jsFunction = obsStudioObj->GetValue(functionName); if (jsFunction && jsFunction->IsFunction()) jsFunction->ExecuteFunction(nullptr, arguments); @@ -211,9 +204,7 @@ void BrowserApp::ExecuteJSFunction(CefRefPtr browser, } #if !ENABLE_WASHIDDEN -void BrowserApp::SetFrameDocumentVisibility(CefRefPtr browser, - CefRefPtr frame, - bool isVisible) +void BrowserApp::SetFrameDocumentVisibility(CefRefPtr browser, CefRefPtr frame, bool isVisible) { UNUSED_PARAMETER(browser); @@ -226,15 +217,10 @@ void BrowserApp::SetFrameDocumentVisibility(CefRefPtr browser, CefRefPtr documentObject = globalObj->GetValue("document"); if (!!documentObject) { - documentObject->SetValue("hidden", - CefV8Value::CreateBool(!isVisible), - V8_PROPERTY_ATTRIBUTE_READONLY); + documentObject->SetValue("hidden", CefV8Value::CreateBool(!isVisible), V8_PROPERTY_ATTRIBUTE_READONLY); - documentObject->SetValue( - "visibilityState", - CefV8Value::CreateString(isVisible ? "visible" - : "hidden"), - V8_PROPERTY_ATTRIBUTE_READONLY); + documentObject->SetValue("visibilityState", CefV8Value::CreateString(isVisible ? "visible" : "hidden"), + V8_PROPERTY_ATTRIBUTE_READONLY); std::string script = "new CustomEvent('visibilitychange', {});"; @@ -243,28 +229,24 @@ void BrowserApp::SetFrameDocumentVisibility(CefRefPtr browser, /* Create the CustomEvent object * We have to use eval to invoke the new operator */ - bool success = context->Eval(script, frame->GetURL(), 0, - returnValue, exception); + bool success = context->Eval(script, frame->GetURL(), 0, returnValue, exception); if (success) { CefV8ValueList arguments; arguments.push_back(returnValue); - CefRefPtr dispatchEvent = - documentObject->GetValue("dispatchEvent"); + CefRefPtr dispatchEvent = documentObject->GetValue("dispatchEvent"); /* Dispatch visibilitychange event on the document * object */ - dispatchEvent->ExecuteFunction(documentObject, - arguments); + dispatchEvent->ExecuteFunction(documentObject, arguments); } } context->Exit(); } -void BrowserApp::SetDocumentVisibility(CefRefPtr browser, - bool isVisible) +void BrowserApp::SetDocumentVisibility(CefRefPtr browser, bool isVisible) { /* This method might be called before OnContextCreated * call is made. We'll save the requested visibility @@ -328,9 +310,7 @@ CefRefPtr CefValueToCefV8Value(CefRefPtr value) dict->GetKeys(keys); for (unsigned int i = 0; i < keys.size(); i++) { CefString key = keys[i]; - result->SetValue( - key, CefValueToCefV8Value(dict->GetValue(key)), - V8_PROPERTY_ATTRIBUTE_NONE); + result->SetValue(key, CefValueToCefV8Value(dict->GetValue(key)), V8_PROPERTY_ATTRIBUTE_NONE); } } break; case VTYPE_LIST: { @@ -338,18 +318,15 @@ CefRefPtr CefValueToCefV8Value(CefRefPtr value) size_t size = list->GetSize(); result = CefV8Value::CreateArray((int)size); for (size_t i = 0; i < size; i++) { - result->SetValue((int)i, CefValueToCefV8Value( - list->GetValue(i))); + result->SetValue((int)i, CefValueToCefV8Value(list->GetValue(i))); } } break; } return result; } -bool BrowserApp::OnProcessMessageReceived(CefRefPtr browser, - CefRefPtr frame, - CefProcessId source_process, - CefRefPtr message) +bool BrowserApp::OnProcessMessageReceived(CefRefPtr browser, CefRefPtr frame, + CefProcessId source_process, CefRefPtr message) { UNUSED_PARAMETER(frame); DCHECK(source_process == PID_BROWSER); @@ -373,8 +350,7 @@ bool BrowserApp::OnProcessMessageReceived(CefRefPtr browser, ExecuteJSFunction(browser, "onActiveChange", arguments); } else if (message->GetName() == "DispatchJSEvent") { - nlohmann::json payloadJson = nlohmann::json::parse( - args->GetString(1).ToString(), nullptr, false); + nlohmann::json payloadJson = nlohmann::json::parse(args->GetString(1).ToString(), nullptr, false); nlohmann::json wrapperJson; if (args->GetSize() > 1) @@ -391,7 +367,12 @@ bool BrowserApp::OnProcessMessageReceived(CefRefPtr browser, std::vector names; browser->GetFrameNames(names); for (auto &name : names) { - CefRefPtr frame = browser->GetFrame(name); + CefRefPtr frame = +#if CHROME_VERSION_BUILD >= 6261 + browser->GetFrameByName(name); +#else + browser->GetFrame(name); +#endif CefRefPtr context = frame->GetV8Context(); context->Enter(); @@ -403,22 +384,19 @@ bool BrowserApp::OnProcessMessageReceived(CefRefPtr browser, /* Create the CustomEvent object * We have to use eval to invoke the new operator */ - context->Eval(script, browser->GetMainFrame()->GetURL(), - 0, returnValue, exception); + context->Eval(script, browser->GetMainFrame()->GetURL(), 0, returnValue, exception); CefV8ValueList arguments; arguments.push_back(returnValue); - CefRefPtr dispatchEvent = - globalObj->GetValue("dispatchEvent"); + CefRefPtr dispatchEvent = globalObj->GetValue("dispatchEvent"); dispatchEvent->ExecuteFunction(nullptr, arguments); context->Exit(); } } else if (message->GetName() == "executeCallback") { - CefRefPtr context = - browser->GetMainFrame()->GetV8Context(); + CefRefPtr context = browser->GetMainFrame()->GetV8Context(); context->Enter(); @@ -426,8 +404,7 @@ bool BrowserApp::OnProcessMessageReceived(CefRefPtr browser, int callbackID = arguments->GetInt(0); CefString jsonString = arguments->GetString(1); - CefRefPtr json = - CefParseJSON(arguments->GetString(1).ToString(), {}); + CefRefPtr json = CefParseJSON(arguments->GetString(1).ToString(), {}); CefRefPtr callback = callbackMap[callbackID]; CefV8ValueList args; @@ -453,13 +430,11 @@ bool BrowserApp::OnProcessMessageReceived(CefRefPtr browser, bool IsValidFunction(std::string function) { std::vector::iterator iterator; - iterator = std::find(exposedFunctions.begin(), exposedFunctions.end(), - function); + iterator = std::find(exposedFunctions.begin(), exposedFunctions.end(), function); return iterator != exposedFunctions.end(); } -bool BrowserApp::Execute(const CefString &name, CefRefPtr, - const CefV8ValueList &arguments, +bool BrowserApp::Execute(const CefString &name, CefRefPtr, const CefV8ValueList &arguments, CefRefPtr &, CefString &) { if (IsValidFunction(name.ToString())) { @@ -468,8 +443,7 @@ bool BrowserApp::Execute(const CefString &name, CefRefPtr, callbackMap[callbackId] = arguments[0]; } - CefRefPtr msg = - CefProcessMessage::Create(name); + CefRefPtr msg = CefProcessMessage::Create(name); CefRefPtr args = msg->GetArgumentList(); args->SetInt(0, callbackId); @@ -482,20 +456,16 @@ bool BrowserApp::Execute(const CefString &name, CefRefPtr, pos = l + 1; if (arguments[l]->IsString()) - args->SetString(pos, - arguments[l]->GetStringValue()); + args->SetString(pos, arguments[l]->GetStringValue()); else if (arguments[l]->IsInt()) args->SetInt(pos, arguments[l]->GetIntValue()); else if (arguments[l]->IsBool()) - args->SetBool(pos, - arguments[l]->GetBoolValue()); + args->SetBool(pos, arguments[l]->GetBoolValue()); else if (arguments[l]->IsDouble()) - args->SetDouble(pos, - arguments[l]->GetDoubleValue()); + args->SetDouble(pos, arguments[l]->GetDoubleValue()); } - CefRefPtr browser = - CefV8Context::GetCurrentContext()->GetBrowser(); + CefRefPtr browser = CefV8Context::GetCurrentContext()->GetBrowser(); SendBrowserProcessMessage(browser, PID_BROWSER, msg); } else { @@ -515,8 +485,7 @@ void QueueBrowserTask(CefRefPtr browser, BrowserFunc func) std::lock_guard lock(messageObject.browserTaskMutex); messageObject.browserTasks.emplace_back(browser, func); - QMetaObject::invokeMethod(&messageObject, "ExecuteNextBrowserTask", - Qt::QueuedConnection); + QMetaObject::invokeMethod(&messageObject, "ExecuteNextBrowserTask", Qt::QueuedConnection); } bool MessageObject::ExecuteNextBrowserTask() @@ -543,8 +512,7 @@ void MessageObject::ExecuteTask(MessageTask task) void MessageObject::DoCefMessageLoop(int ms) { if (ms) - QTimer::singleShot((int)ms + 2, - []() { CefDoMessageLoopWork(); }); + QTimer::singleShot((int)ms + 2, []() { CefDoMessageLoopWork(); }); else CefDoMessageLoopWork(); } @@ -556,13 +524,16 @@ void MessageObject::Process() void ProcessCef() { - QMetaObject::invokeMethod(&messageObject, "DoCefMessageLoop", - Qt::QueuedConnection, Q_ARG(int, (int)0)); + QMetaObject::invokeMethod(&messageObject, "DoCefMessageLoop", Qt::QueuedConnection, Q_ARG(int, (int)0)); } #define MAX_DELAY (1000 / 30) +#if CHROME_VERSION_BUILD < 5938 void BrowserApp::OnScheduleMessagePumpWork(int64 delay_ms) +#else +void BrowserApp::OnScheduleMessagePumpWork(int64_t delay_ms) +#endif { if (delay_ms < 0) delay_ms = 0; @@ -570,14 +541,11 @@ void BrowserApp::OnScheduleMessagePumpWork(int64 delay_ms) delay_ms = MAX_DELAY; if (!frameTimer.isActive()) { - QObject::connect(&frameTimer, &QTimer::timeout, &messageObject, - &MessageObject::Process); + QObject::connect(&frameTimer, &QTimer::timeout, &messageObject, &MessageObject::Process); frameTimer.setSingleShot(false); frameTimer.start(33); } - QMetaObject::invokeMethod(&messageObject, "DoCefMessageLoop", - Qt::QueuedConnection, - Q_ARG(int, (int)delay_ms)); + QMetaObject::invokeMethod(&messageObject, "DoCefMessageLoop", Qt::QueuedConnection, Q_ARG(int, (int)delay_ms)); } #endif diff --git a/browser-app.hpp b/browser-app.hpp index c5fdeca23..fd6df4c26 100644 --- a/browser-app.hpp +++ b/browser-app.hpp @@ -37,18 +37,14 @@ typedef std::function MessageTask; class MessageObject : public QObject { Q_OBJECT - friend void QueueBrowserTask(CefRefPtr browser, - BrowserFunc func); + friend void QueueBrowserTask(CefRefPtr browser, BrowserFunc func); struct Task { CefRefPtr browser; BrowserFunc func; inline Task() {} - inline Task(CefRefPtr browser_, BrowserFunc func_) - : browser(browser_), func(func_) - { - } + inline Task(CefRefPtr browser_, BrowserFunc func_) : browser(browser_), func(func_) {} }; std::mutex browserTaskMutex; @@ -64,25 +60,28 @@ public slots: extern void QueueBrowserTask(CefRefPtr browser, BrowserFunc func); #endif -class BrowserApp : public CefApp, - public CefRenderProcessHandler, - public CefBrowserProcessHandler, - public CefV8Handler { +class BrowserApp : public CefApp, public CefRenderProcessHandler, public CefBrowserProcessHandler, public CefV8Handler { - void ExecuteJSFunction(CefRefPtr browser, - const char *functionName, - CefV8ValueList arguments); + void ExecuteJSFunction(CefRefPtr browser, const char *functionName, CefV8ValueList arguments); typedef std::map> CallbackMap; bool shared_texture_available; CallbackMap callbackMap; int callbackId; +#if !defined(__APPLE__) && !defined(_WIN32) + bool wayland; +#endif public: - inline BrowserApp(bool shared_texture_available_ = false) +#if defined(__APPLE__) || defined(_WIN32) + inline BrowserApp(bool shared_texture_available_ = false) : shared_texture_available(shared_texture_available_), media_flag(-1) +#else + inline BrowserApp(bool shared_texture_available_ = false, bool wayland_ = false) : shared_texture_available(shared_texture_available_), + wayland(wayland_), media_flag(-1) +#endif { } @@ -90,44 +89,35 @@ class BrowserApp : public CefApp, int media_flag; std::mutex flag_mutex; std::queue media_flags; - virtual CefRefPtr - GetRenderProcessHandler() override; - virtual CefRefPtr - GetBrowserProcessHandler() override; - virtual void OnBeforeChildProcessLaunch( - CefRefPtr command_line) override; - virtual void OnRegisterCustomSchemes( - CefRawPtr registrar) override; - virtual void OnBeforeCommandLineProcessing( - const CefString &process_type, - CefRefPtr command_line) override; - virtual void OnContextCreated(CefRefPtr browser, - CefRefPtr frame, + + virtual CefRefPtr GetRenderProcessHandler() override; + virtual CefRefPtr GetBrowserProcessHandler() override; + virtual void OnBeforeChildProcessLaunch(CefRefPtr command_line) override; + virtual void OnRegisterCustomSchemes(CefRawPtr registrar) override; + virtual void OnBeforeCommandLineProcessing(const CefString &process_type, + CefRefPtr command_line) override; + virtual void OnContextCreated(CefRefPtr browser, CefRefPtr frame, CefRefPtr context) override; - virtual bool - OnProcessMessageReceived(CefRefPtr browser, - CefRefPtr frame, - CefProcessId source_process, - CefRefPtr message) override; - virtual bool Execute(const CefString &name, - CefRefPtr object, - const CefV8ValueList &arguments, - CefRefPtr &retval, - CefString &exception) override; + virtual bool OnProcessMessageReceived(CefRefPtr browser, CefRefPtr frame, + CefProcessId source_process, + CefRefPtr message) override; + virtual bool Execute(const CefString &name, CefRefPtr object, const CefV8ValueList &arguments, + CefRefPtr &retval, CefString &exception) override; #ifdef ENABLE_BROWSER_QT_LOOP +#if CHROME_VERSION_BUILD < 5938 virtual void OnScheduleMessagePumpWork(int64 delay_ms) override; +#else + virtual void OnScheduleMessagePumpWork(int64_t delay_ms) override; +#endif QTimer frameTimer; #endif #if !ENABLE_WASHIDDEN std::unordered_map browserVis; - void SetFrameDocumentVisibility(CefRefPtr browser, - CefRefPtr frame, - bool isVisible); - void SetDocumentVisibility(CefRefPtr browser, - bool isVisible); + void SetFrameDocumentVisibility(CefRefPtr browser, CefRefPtr frame, bool isVisible); + void SetDocumentVisibility(CefRefPtr browser, bool isVisible); #endif IMPLEMENT_REFCOUNTING(BrowserApp); diff --git a/browser-client.cpp b/browser-client.cpp index 5148fdc88..a233b3ab3 100644 --- a/browser-client.cpp +++ b/browser-client.cpp @@ -68,9 +68,10 @@ CefRefPtr BrowserClient::GetRequestHandler() return this; } -CefRefPtr BrowserClient::GetResourceRequestHandler( - CefRefPtr, CefRefPtr, - CefRefPtr request, bool, bool, const CefString &, bool &) +CefRefPtr BrowserClient::GetResourceRequestHandler(CefRefPtr, + CefRefPtr, + CefRefPtr request, bool, bool, + const CefString &, bool &) { if (request->GetHeaderByName("origin") == "null") { return this; @@ -79,38 +80,48 @@ CefRefPtr BrowserClient::GetResourceRequestHandler( return nullptr; } -CefResourceRequestHandler::ReturnValue -BrowserClient::OnBeforeResourceLoad(CefRefPtr, CefRefPtr, - CefRefPtr, - CefRefPtr) +void BrowserClient::OnRenderProcessTerminated(CefRefPtr, TerminationStatus, int, + const CefString &error_string) +{ + if (!valid()) + return; + + std::string str_text = error_string; + + const char *sourceName = ""; + + if (bs && bs->source) + sourceName = obs_source_get_name(bs->source); + + blog(LOG_ERROR, "[obs-browser: '%s'] Webpage has crashed unexpectedly! Reason: '%s'", sourceName, + str_text.c_str()); +} + +CefResourceRequestHandler::ReturnValue BrowserClient::OnBeforeResourceLoad(CefRefPtr, CefRefPtr, + CefRefPtr, + CefRefPtr) { return RV_CONTINUE; } #endif -bool BrowserClient::OnBeforePopup(CefRefPtr, CefRefPtr, - const CefString &, const CefString &, - cef_window_open_disposition_t, bool, - const CefPopupFeatures &, CefWindowInfo &, - CefRefPtr &, CefBrowserSettings &, - CefRefPtr &, bool *) +bool BrowserClient::OnBeforePopup(CefRefPtr, CefRefPtr, const CefString &, const CefString &, + cef_window_open_disposition_t, bool, const CefPopupFeatures &, CefWindowInfo &, + CefRefPtr &, CefBrowserSettings &, CefRefPtr &, bool *) { /* block popups */ return true; } -void BrowserClient::OnBeforeContextMenu(CefRefPtr, - CefRefPtr, - CefRefPtr, +void BrowserClient::OnBeforeContextMenu(CefRefPtr, CefRefPtr, CefRefPtr, CefRefPtr model) { /* remove all context menu contributions */ model->Clear(); } -bool BrowserClient::OnProcessMessageReceived( - CefRefPtr browser, CefRefPtr, CefProcessId, - CefRefPtr message) +bool BrowserClient::OnProcessMessageReceived(CefRefPtr browser, CefRefPtr, CefProcessId, + CefRefPtr message) { const std::string &name = message->GetName(); CefRefPtr input_args = message->GetArgumentList(); @@ -147,35 +158,27 @@ bool BrowserClient::OnProcessMessageReceived( } else if (name == "stopReplayBuffer") { obs_frontend_replay_buffer_stop(); } else if (name == "setCurrentScene") { - const std::string scene_name = - input_args->GetString(1).ToString(); - OBSSourceAutoRelease source = - obs_get_source_by_name(scene_name.c_str()); + const std::string scene_name = input_args->GetString(1).ToString(); + OBSSourceAutoRelease source = obs_get_source_by_name(scene_name.c_str()); if (!source) { blog(LOG_WARNING, "Browser source '%s' tried to switch to scene '%s' which doesn't exist", - obs_source_get_name(bs->source), - scene_name.c_str()); + obs_source_get_name(bs->source), scene_name.c_str()); } else if (!obs_source_is_scene(source)) { - blog(LOG_WARNING, - "Browser source '%s' tried to switch to '%s' which isn't a scene", - obs_source_get_name(bs->source), - scene_name.c_str()); + blog(LOG_WARNING, "Browser source '%s' tried to switch to '%s' which isn't a scene", + obs_source_get_name(bs->source), scene_name.c_str()); } else { obs_frontend_set_current_scene(source); } } else if (name == "setCurrentTransition") { - const std::string transition_name = - input_args->GetString(1).ToString(); + const std::string transition_name = input_args->GetString(1).ToString(); obs_frontend_source_list transitions = {}; obs_frontend_get_transitions(&transitions); OBSSourceAutoRelease transition; for (size_t i = 0; i < transitions.sources.num; i++) { - obs_source_t *source = - transitions.sources.array[i]; - if (obs_source_get_name(source) == - transition_name) { + obs_source_t *source = transitions.sources.array[i]; + if (obs_source_get_name(source) == transition_name) { transition = obs_source_get_ref(source); break; } @@ -188,8 +191,7 @@ bool BrowserClient::OnProcessMessageReceived( else blog(LOG_WARNING, "Browser source '%s' tried to change the current transition to '%s' which doesn't exist", - obs_source_get_name(bs->source), - transition_name.c_str()); + obs_source_get_name(bs->source), transition_name.c_str()); } [[fallthrough]]; case ControlLevel::Basic: @@ -204,14 +206,12 @@ bool BrowserClient::OnProcessMessageReceived( std::vector scenes_vector; for (size_t i = 0; i < list.sources.num; i++) { obs_source_t *source = list.sources.array[i]; - scenes_vector.push_back( - obs_source_get_name(source)); + scenes_vector.push_back(obs_source_get_name(source)); } json = scenes_vector; obs_frontend_source_list_free(&list); } else if (name == "getCurrentScene") { - OBSSourceAutoRelease current_scene = - obs_frontend_get_current_scene(); + OBSSourceAutoRelease current_scene = obs_frontend_get_current_scene(); if (!current_scene) return false; @@ -222,22 +222,19 @@ bool BrowserClient::OnProcessMessageReceived( json = {{"name", name}, {"width", obs_source_get_width(current_scene)}, - {"height", - obs_source_get_height(current_scene)}}; + {"height", obs_source_get_height(current_scene)}}; } else if (name == "getTransitions") { struct obs_frontend_source_list list = {}; obs_frontend_get_transitions(&list); std::vector transitions_vector; for (size_t i = 0; i < list.sources.num; i++) { obs_source_t *source = list.sources.array[i]; - transitions_vector.push_back( - obs_source_get_name(source)); + transitions_vector.push_back(obs_source_get_name(source)); } json = transitions_vector; obs_frontend_source_list_free(&list); } else if (name == "getCurrentTransition") { - OBSSourceAutoRelease source = - obs_frontend_get_current_transition(); + OBSSourceAutoRelease source = obs_frontend_get_current_transition(); json = obs_source_get_name(source); } [[fallthrough]]; @@ -245,12 +242,9 @@ bool BrowserClient::OnProcessMessageReceived( if (name == "getStatus") { json = {{"recording", obs_frontend_recording_active()}, {"streaming", obs_frontend_streaming_active()}, - {"recordingPaused", - obs_frontend_recording_paused()}, - {"replaybuffer", - obs_frontend_replay_buffer_active()}, - {"virtualcam", - obs_frontend_virtualcam_active()}}; + {"recordingPaused", obs_frontend_recording_paused()}, + {"replaybuffer", obs_frontend_replay_buffer_active()}, + {"virtualcam", obs_frontend_virtualcam_active()}}; } [[fallthrough]]; case ControlLevel::None: @@ -262,8 +256,7 @@ bool BrowserClient::OnProcessMessageReceived( UNUSED_PARAMETER(name); #endif - CefRefPtr msg = - CefProcessMessage::Create("executeCallback"); + CefRefPtr msg = CefProcessMessage::Create("executeCallback"); CefRefPtr execute_args = msg->GetArgumentList(); execute_args->SetInt(0, input_args->GetInt(0)); @@ -281,18 +274,15 @@ void BrowserClient::GetViewRect(CefRefPtr, CefRect &rect) return; } - rect.Set(0, 0, bs->width < 1 ? 1 : bs->width, - bs->height < 1 ? 1 : bs->height); + rect.Set(0, 0, bs->width < 1 ? 1 : bs->width, bs->height < 1 ? 1 : bs->height); } bool BrowserClient::OnTooltip(CefRefPtr, CefString &text) { #if BROWSER_FRONTEND_API_SUPPORT_ENABLED std::string str_text = text; - QMetaObject::invokeMethod( - QCoreApplication::instance()->thread(), [str_text]() { - QToolTip::showText(QCursor::pos(), str_text.c_str()); - }); + QMetaObject::invokeMethod(QCoreApplication::instance()->thread(), + [str_text]() { QToolTip::showText(QCursor::pos(), str_text.c_str()); }); return true; #define DISABLE_DEFAULT_TOOLTIP #endif @@ -302,9 +292,8 @@ bool BrowserClient::OnTooltip(CefRefPtr, CefString &text) #endif } -void BrowserClient::OnPaint(CefRefPtr, PaintElementType type, - const RectList &, const void *buffer, int width, - int height) +void BrowserClient::OnPaint(CefRefPtr, PaintElementType type, const RectList &, const void *buffer, + int width, int height) { if (type != PET_VIEW) { // TODO Overlay texture on top of bs->texture @@ -329,16 +318,13 @@ void BrowserClient::OnPaint(CefRefPtr, PaintElementType type, if (!bs->texture && width && height) { obs_enter_graphics(); - bs->texture = gs_texture_create(width, height, GS_BGRA, 1, - (const uint8_t **)&buffer, - GS_DYNAMIC); + bs->texture = gs_texture_create(width, height, GS_BGRA, 1, (const uint8_t **)&buffer, GS_DYNAMIC); bs->width = width; bs->height = height; obs_leave_graphics(); } else { obs_enter_graphics(); - gs_texture_set_image(bs->texture, (const uint8_t *)buffer, - width * 4, false); + gs_texture_set_image(bs->texture, (const uint8_t *)buffer, width * 4, false); obs_leave_graphics(); } } @@ -349,21 +335,17 @@ void BrowserClient::UpdateExtraTexture() if (bs->texture) { const uint32_t cx = gs_texture_get_width(bs->texture); const uint32_t cy = gs_texture_get_height(bs->texture); - const gs_color_format format = - gs_texture_get_color_format(bs->texture); - const gs_color_format linear_format = - gs_generalize_format(format); + const gs_color_format format = gs_texture_get_color_format(bs->texture); + const gs_color_format linear_format = gs_generalize_format(format); if (linear_format != format) { - if (!bs->extra_texture || - bs->last_format != linear_format || - bs->last_cx != cx || bs->last_cy != cy) { + if (!bs->extra_texture || bs->last_format != linear_format || bs->last_cx != cx || + bs->last_cy != cy) { if (bs->extra_texture) { gs_texture_destroy(bs->extra_texture); bs->extra_texture = nullptr; } - bs->extra_texture = gs_texture_create( - cx, cy, linear_format, 1, nullptr, 0); + bs->extra_texture = gs_texture_create(cx, cy, linear_format, 1, nullptr, 0); bs->last_cx = cx; bs->last_cy = cy; bs->last_format = linear_format; @@ -378,9 +360,12 @@ void BrowserClient::UpdateExtraTexture() } } -void BrowserClient::OnAcceleratedPaint(CefRefPtr, - PaintElementType type, const RectList &, +void BrowserClient::OnAcceleratedPaint(CefRefPtr, PaintElementType type, const RectList &, +#if CHROME_VERSION_BUILD >= 6367 + const CefAcceleratedPaintInfo &info) +#else void *shared_handle) +#endif { if (type != PET_VIEW) { // TODO Overlay texture on top of bs->texture @@ -391,7 +376,7 @@ void BrowserClient::OnAcceleratedPaint(CefRefPtr, return; } -#ifndef _WIN32 +#if !defined(_WIN32) && CHROME_VERSION_BUILD < 6367 if (shared_handle == bs->last_handle) return; #endif @@ -406,28 +391,37 @@ void BrowserClient::OnAcceleratedPaint(CefRefPtr, bs->texture = nullptr; } -#if defined(__APPLE__) && CHROME_VERSION_BUILD > 4183 - bs->texture = gs_texture_create_from_iosurface( - (IOSurfaceRef)(uintptr_t)shared_handle); +#if defined(__APPLE__) && CHROME_VERSION_BUILD > 6367 + bs->texture = gs_texture_create_from_iosurface((IOSurfaceRef)(uintptr_t)info.shared_texture_io_surface); +#elif defined(__APPLE__) && CHROME_VERSION_BUILD > 4183 + bs->texture = gs_texture_create_from_iosurface((IOSurfaceRef)(uintptr_t)shared_handle); #elif defined(_WIN32) && CHROME_VERSION_BUILD > 4183 bs->texture = +#if CHROME_VERSION_BUILD >= 6367 + gs_texture_open_nt_shared((uint32_t)(uintptr_t)info.shared_texture_handle); +#else gs_texture_open_nt_shared((uint32_t)(uintptr_t)shared_handle); +#endif //if (bs->texture) // gs_texture_acquire_sync(bs->texture, 1, INFINITE); #else - bs->texture = - gs_texture_open_shared((uint32_t)(uintptr_t)shared_handle); + bs->texture = gs_texture_open_shared((uint32_t)(uintptr_t)shared_handle); #endif UpdateExtraTexture(); obs_leave_graphics(); +#if defined(__APPLE__) && CHROME_VERSION_BUILD >= 6367 + bs->last_handle = info.shared_texture_io_surface; +#elif CHROME_VERSION_BUILD >= 6367 + bs->last_handle = info.shared_texture_handle; +#else bs->last_handle = shared_handle; +#endif } #ifdef CEF_ON_ACCELERATED_PAINT2 -void BrowserClient::OnAcceleratedPaint2(CefRefPtr, - PaintElementType type, const RectList &, +void BrowserClient::OnAcceleratedPaint2(CefRefPtr, PaintElementType type, const RectList &, void *shared_handle, bool new_texture) { if (type != PET_VIEW) { @@ -451,15 +445,12 @@ void BrowserClient::OnAcceleratedPaint2(CefRefPtr, } #if defined(__APPLE__) && CHROME_VERSION_BUILD > 4183 - bs->texture = gs_texture_create_from_iosurface( - (IOSurfaceRef)(uintptr_t)shared_handle); + bs->texture = gs_texture_create_from_iosurface((IOSurfaceRef)(uintptr_t)shared_handle); #elif defined(_WIN32) && CHROME_VERSION_BUILD > 4183 - bs->texture = - gs_texture_open_nt_shared((uint32_t)(uintptr_t)shared_handle); + bs->texture = gs_texture_open_nt_shared((uint32_t)(uintptr_t)shared_handle); #else - bs->texture = - gs_texture_open_shared((uint32_t)(uintptr_t)shared_handle); + bs->texture = gs_texture_open_shared((uint32_t)(uintptr_t)shared_handle); #endif UpdateExtraTexture(); obs_leave_graphics(); @@ -499,8 +490,7 @@ static speaker_layout GetSpeakerLayout(CefAudioHandler::ChannelLayout cefLayout) } #if CHROME_VERSION_BUILD >= 4103 -void BrowserClient::OnAudioStreamStarted(CefRefPtr browser, - const CefAudioParameters ¶ms_, +void BrowserClient::OnAudioStreamStarted(CefRefPtr browser, const CefAudioParameters ¶ms_, int channels_) { UNUSED_PARAMETER(browser); @@ -510,9 +500,7 @@ void BrowserClient::OnAudioStreamStarted(CefRefPtr browser, frames_per_buffer = params_.frames_per_buffer; } -void BrowserClient::OnAudioStreamPacket(CefRefPtr browser, - const float **data, int frames, - int64_t pts) +void BrowserClient::OnAudioStreamPacket(CefRefPtr browser, const float **data, int frames, int64_t pts) { UNUSED_PARAMETER(browser); if (!valid()) { @@ -537,8 +525,7 @@ void BrowserClient::OnAudioStreamStopped(CefRefPtr browser) UNUSED_PARAMETER(browser); } -void BrowserClient::OnAudioStreamError(CefRefPtr browser, - const CefString &message) +void BrowserClient::OnAudioStreamError(CefRefPtr browser, const CefString &message) { UNUSED_PARAMETER(browser); UNUSED_PARAMETER(message); @@ -566,8 +553,7 @@ static CefAudioHandler::ChannelLayout Convert2CEFSpeakerLayout(int channels) } } -bool BrowserClient::GetAudioParameters(CefRefPtr browser, - CefAudioParameters ¶ms) +bool BrowserClient::GetAudioParameters(CefRefPtr browser, CefAudioParameters ¶ms) { UNUSED_PARAMETER(browser); int channels = (int)audio_output_get_channels(obs_get_audio()); @@ -577,8 +563,7 @@ bool BrowserClient::GetAudioParameters(CefRefPtr browser, return true; } #elif CHROME_VERSION_BUILD < 4103 -void BrowserClient::OnAudioStreamStarted(CefRefPtr browser, int id, - int, ChannelLayout channel_layout, +void BrowserClient::OnAudioStreamStarted(CefRefPtr browser, int id, int, ChannelLayout channel_layout, int sample_rate, int) { UNUSED_PARAMETER(browser); @@ -588,8 +573,7 @@ void BrowserClient::OnAudioStreamStarted(CefRefPtr browser, int id, AudioStream &stream = bs->audio_streams[id]; if (!stream.source) { - stream.source = obs_source_create_private("audio_line", nullptr, - nullptr); + stream.source = obs_source_create_private("audio_line", nullptr, nullptr); obs_source_add_active_child(bs->source, stream.source); @@ -602,8 +586,7 @@ void BrowserClient::OnAudioStreamStarted(CefRefPtr browser, int id, stream.sample_rate = sample_rate; } -void BrowserClient::OnAudioStreamPacket(CefRefPtr browser, int id, - const float **data, int frames, +void BrowserClient::OnAudioStreamPacket(CefRefPtr browser, int id, const float **data, int frames, int64_t pts) { UNUSED_PARAMETER(browser); @@ -645,8 +628,7 @@ void BrowserClient::OnAudioStreamStopped(CefRefPtr browser, int id) for (size_t i = 0; i < bs->audio_sources.size(); i++) { obs_source_t *source = bs->audio_sources[i]; if (source == stream.source) { - bs->audio_sources.erase( - bs->audio_sources.begin() + i); + bs->audio_sources.erase(bs->audio_sources.begin() + i); break; } } @@ -655,16 +637,14 @@ void BrowserClient::OnAudioStreamStopped(CefRefPtr browser, int id) } #endif -void BrowserClient::OnLoadEnd(CefRefPtr, CefRefPtr frame, - int) +void BrowserClient::OnLoadEnd(CefRefPtr, CefRefPtr frame, int) { if (!valid()) { return; } if (frame->IsMain() && bs->css.length()) { - std::string uriEncodedCSS = - CefURIEncode(bs->css, false).ToString(); + std::string uriEncodedCSS = CefURIEncode(bs->css, false).ToString(); std::string script; script += "const obsCSS = document.createElement('style');"; @@ -677,9 +657,7 @@ void BrowserClient::OnLoadEnd(CefRefPtr, CefRefPtr frame, } } -bool BrowserClient::OnConsoleMessage(CefRefPtr, - cef_log_severity_t level, - const CefString &message, +bool BrowserClient::OnConsoleMessage(CefRefPtr, cef_log_severity_t level, const CefString &message, const CefString &source, int line) { int errorLevel = LOG_INFO; @@ -702,7 +680,7 @@ bool BrowserClient::OnConsoleMessage(CefRefPtr, if (bs && bs->source) sourceName = obs_source_get_name(bs->source); - blog(errorLevel, "[obs-browser: '%s'] %s: %s (%s:%d)", sourceName, code, - message.ToString().c_str(), source.ToString().c_str(), line); + blog(errorLevel, "[obs-browser: '%s'] %s: %s (%s:%d)", sourceName, code, message.ToString().c_str(), + source.ToString().c_str(), line); return false; } diff --git a/browser-client.hpp b/browser-client.hpp index cbff1201e..051102c35 100644 --- a/browser-client.hpp +++ b/browser-client.hpp @@ -56,8 +56,7 @@ class BrowserClient : public CefClient, ChannelLayout channel_layout; int frames_per_buffer; #endif - inline BrowserClient(BrowserSource *bs_, bool sharing_avail, - bool reroute_audio_, + inline BrowserClient(BrowserSource *bs_, bool sharing_avail, bool reroute_audio_, ControlLevel webpage_control_level_) : sharing_available(sharing_avail), reroute_audio(reroute_audio_), @@ -74,114 +73,86 @@ class BrowserClient : public CefClient, #if CHROME_VERSION_BUILD >= 4638 virtual CefRefPtr GetRequestHandler() override; #endif - virtual CefRefPtr - GetContextMenuHandler() override; + virtual CefRefPtr GetContextMenuHandler() override; virtual CefRefPtr GetAudioHandler() override; - virtual bool - OnProcessMessageReceived(CefRefPtr browser, - CefRefPtr frame, - CefProcessId source_process, - CefRefPtr message) override; + virtual bool OnProcessMessageReceived(CefRefPtr browser, CefRefPtr frame, + CefProcessId source_process, + CefRefPtr message) override; /* CefDisplayHandler */ - virtual bool OnConsoleMessage(CefRefPtr browser, - cef_log_severity_t level, - const CefString &message, - const CefString &source, - int line) override; - virtual bool OnTooltip(CefRefPtr browser, - CefString &text) override; + virtual bool OnConsoleMessage(CefRefPtr browser, cef_log_severity_t level, const CefString &message, + const CefString &source, int line) override; + virtual bool OnTooltip(CefRefPtr browser, CefString &text) override; /* CefLifeSpanHandler */ - virtual bool - OnBeforePopup(CefRefPtr browser, CefRefPtr frame, - const CefString &target_url, - const CefString &target_frame_name, - cef_window_open_disposition_t target_disposition, - bool user_gesture, const CefPopupFeatures &popupFeatures, - CefWindowInfo &windowInfo, CefRefPtr &client, - CefBrowserSettings &settings, - CefRefPtr &extra_info, - bool *no_javascript_access) override; + virtual bool OnBeforePopup(CefRefPtr browser, CefRefPtr frame, + const CefString &target_url, const CefString &target_frame_name, + cef_window_open_disposition_t target_disposition, bool user_gesture, + const CefPopupFeatures &popupFeatures, CefWindowInfo &windowInfo, + CefRefPtr &client, CefBrowserSettings &settings, + CefRefPtr &extra_info, bool *no_javascript_access) override; #if CHROME_VERSION_BUILD >= 4638 /* CefRequestHandler */ - virtual CefRefPtr GetResourceRequestHandler( - CefRefPtr browser, CefRefPtr frame, - CefRefPtr request, bool is_navigation, - bool is_download, const CefString &request_initiator, - bool &disable_default_handling) override; + virtual CefRefPtr + GetResourceRequestHandler(CefRefPtr browser, CefRefPtr frame, + CefRefPtr request, bool is_navigation, bool is_download, + const CefString &request_initiator, bool &disable_default_handling) override; + virtual void OnRenderProcessTerminated(CefRefPtr browser, TerminationStatus status, int error_code, + const CefString &error_string) override; /* CefResourceRequestHandler */ - virtual CefResourceRequestHandler::ReturnValue - OnBeforeResourceLoad(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr request, - CefRefPtr callback) override; + virtual CefResourceRequestHandler::ReturnValue OnBeforeResourceLoad(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr callback) override; #endif /* CefContextMenuHandler */ - virtual void - OnBeforeContextMenu(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr params, - CefRefPtr model) override; + virtual void OnBeforeContextMenu(CefRefPtr browser, CefRefPtr frame, + CefRefPtr params, + CefRefPtr model) override; /* CefRenderHandler */ - virtual void GetViewRect(CefRefPtr browser, - CefRect &rect) override; - virtual void OnPaint(CefRefPtr browser, - PaintElementType type, const RectList &dirtyRects, - const void *buffer, int width, - int height) override; + virtual void GetViewRect(CefRefPtr browser, CefRect &rect) override; + virtual void OnPaint(CefRefPtr browser, PaintElementType type, const RectList &dirtyRects, + const void *buffer, int width, int height) override; #ifdef ENABLE_BROWSER_SHARED_TEXTURE - virtual void OnAcceleratedPaint(CefRefPtr browser, - PaintElementType type, + virtual void OnAcceleratedPaint(CefRefPtr browser, PaintElementType type, const RectList &dirtyRects, +#if CHROME_VERSION_BUILD >= 6367 + const CefAcceleratedPaintInfo &info) override; +#else void *shared_handle) override; +#endif #ifdef CEF_ON_ACCELERATED_PAINT2 - virtual void OnAcceleratedPaint2(CefRefPtr browser, - PaintElementType type, - const RectList &dirtyRects, - void *shared_handle, - bool new_texture) override; + virtual void OnAcceleratedPaint2(CefRefPtr browser, PaintElementType type, + const RectList &dirtyRects, void *shared_handle, bool new_texture) override; #endif #endif #if CHROME_VERSION_BUILD >= 4103 - virtual void OnAudioStreamPacket(CefRefPtr browser, - const float **data, int frames, + virtual void OnAudioStreamPacket(CefRefPtr browser, const float **data, int frames, int64_t pts) override; - virtual void - OnAudioStreamStopped(CefRefPtr browser) override; + virtual void OnAudioStreamStopped(CefRefPtr browser) override; - virtual void OnAudioStreamStarted(CefRefPtr browser, - const CefAudioParameters ¶ms, + virtual void OnAudioStreamStarted(CefRefPtr browser, const CefAudioParameters ¶ms, int channels) override; - virtual void OnAudioStreamError(CefRefPtr browser, - const CefString &message) override; + virtual void OnAudioStreamError(CefRefPtr browser, const CefString &message) override; const int kFramesPerBuffer = 1024; - virtual bool GetAudioParameters(CefRefPtr browser, - CefAudioParameters ¶ms) override; + virtual bool GetAudioParameters(CefRefPtr browser, CefAudioParameters ¶ms) override; #else - virtual void OnAudioStreamPacket(CefRefPtr browser, - int audio_stream_id, - const float **data, int frames, - int64_t pts) override; + virtual void OnAudioStreamPacket(CefRefPtr browser, int audio_stream_id, const float **data, + int frames, int64_t pts) override; - virtual void OnAudioStreamStopped(CefRefPtr browser, - int audio_stream_id); + virtual void OnAudioStreamStopped(CefRefPtr browser, int audio_stream_id); - virtual void OnAudioStreamStarted(CefRefPtr browser, - int audio_stream_id, int channels, - ChannelLayout channel_layout, - int sample_rate, + virtual void OnAudioStreamStarted(CefRefPtr browser, int audio_stream_id, int channels, + ChannelLayout channel_layout, int sample_rate, int frames_per_buffer) override; #endif /* CefLoadHandler */ - virtual void OnLoadEnd(CefRefPtr browser, - CefRefPtr frame, - int httpStatusCode) override; + virtual void OnLoadEnd(CefRefPtr browser, CefRefPtr frame, int httpStatusCode) override; IMPLEMENT_REFCOUNTING(BrowserClient); }; diff --git a/browser-scheme.cpp b/browser-scheme.cpp index db745aef0..88d51d584 100644 --- a/browser-scheme.cpp +++ b/browser-scheme.cpp @@ -21,10 +21,8 @@ #include #if !ENABLE_LOCAL_FILE_URL_SCHEME -CefRefPtr -BrowserSchemeHandlerFactory::Create(CefRefPtr browser, - CefRefPtr, const CefString &, - CefRefPtr request) +CefRefPtr BrowserSchemeHandlerFactory::Create(CefRefPtr browser, CefRefPtr, + const CefString &, CefRefPtr request) { if (!browser || !request) return nullptr; @@ -35,10 +33,7 @@ BrowserSchemeHandlerFactory::Create(CefRefPtr browser, std::string path = CefString(&parts.path); path = CefURIDecode(path, true, cef_uri_unescape_rule_t::UU_SPACES); - path = CefURIDecode( - path, true, - cef_uri_unescape_rule_t:: - UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS); + path = CefURIDecode(path, true, cef_uri_unescape_rule_t::UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS); std::string fileExtension = path.substr(path.find_last_of(".") + 1); @@ -48,11 +43,9 @@ BrowserSchemeHandlerFactory::Create(CefRefPtr browser, fileExtension = "woff"; #ifdef _WIN32 - CefRefPtr stream = - CefStreamReader::CreateForFile(path.substr(1)); + CefRefPtr stream = CefStreamReader::CreateForFile(path.substr(1)); #else - CefRefPtr stream = - CefStreamReader::CreateForFile(path); + CefRefPtr stream = CefStreamReader::CreateForFile(path); #endif if (stream) { diff --git a/browser-scheme.hpp b/browser-scheme.hpp index 6a183a02a..2b7f6fdd2 100644 --- a/browser-scheme.hpp +++ b/browser-scheme.hpp @@ -31,9 +31,8 @@ #if !ENABLE_LOCAL_FILE_URL_SCHEME class BrowserSchemeHandlerFactory : public CefSchemeHandlerFactory { public: - virtual CefRefPtr - Create(CefRefPtr browser, CefRefPtr, - const CefString &, CefRefPtr request) override; + virtual CefRefPtr Create(CefRefPtr browser, CefRefPtr, + const CefString &, CefRefPtr request) override; IMPLEMENT_REFCOUNTING(BrowserSchemeHandlerFactory); }; diff --git a/browser-version.h b/browser-version.h index 22263dbc1..4e2a18b22 100644 --- a/browser-version.h +++ b/browser-version.h @@ -1,23 +1,19 @@ #pragma once #define OBS_BROWSER_VERSION_MAJOR 2 -#define OBS_BROWSER_VERSION_MINOR 23 +#define OBS_BROWSER_VERSION_MINOR 24 #define OBS_BROWSER_VERSION_PATCH 6 #ifndef MAKE_SEMANTIC_VERSION -#define MAKE_SEMANTIC_VERSION(major, minor, patch) \ - ((major << 24) | (minor << 16) | patch) +#define MAKE_SEMANTIC_VERSION(major, minor, patch) ((major << 24) | (minor << 16) | patch) #endif -#define OBS_BROWSER_VERSION_INT \ - MAKE_SEMANTIC_VERSION(OBS_BROWSER_VERSION_MAJOR, \ - OBS_BROWSER_VERSION_MINOR, \ - OBS_BROWSER_VERSION_PATCH) +#define OBS_BROWSER_VERSION_INT \ + MAKE_SEMANTIC_VERSION(OBS_BROWSER_VERSION_MAJOR, OBS_BROWSER_VERSION_MINOR, OBS_BROWSER_VERSION_PATCH) #define OBS_BROWSER_MACRO_STR_(x) #x #define OBS_BROWSER_MACRO_STR(x) OBS_BROWSER_MACRO_STR_(x) -#define OBS_BROWSER_VERSION_STRING \ - OBS_BROWSER_MACRO_STR(OBS_BROWSER_VERSION_MAJOR) \ - "." OBS_BROWSER_MACRO_STR(OBS_BROWSER_VERSION_MINOR) "." OBS_BROWSER_MACRO_STR( \ - OBS_BROWSER_VERSION_PATCH) +#define OBS_BROWSER_VERSION_STRING \ + OBS_BROWSER_MACRO_STR(OBS_BROWSER_VERSION_MAJOR) \ + "." OBS_BROWSER_MACRO_STR(OBS_BROWSER_VERSION_MINOR) "." OBS_BROWSER_MACRO_STR(OBS_BROWSER_VERSION_PATCH) diff --git a/build-aux/.functions/log_debug b/build-aux/.functions/log_debug new file mode 100644 index 000000000..6a477a181 --- /dev/null +++ b/build-aux/.functions/log_debug @@ -0,0 +1,3 @@ +if (( ! ${+_loglevel} )) typeset -g _loglevel=1 + +if (( _loglevel > 2 )) print -PR -e -- "${CI:+::debug::}%F{220}DEBUG: ${@}%f" diff --git a/build-aux/.functions/log_error b/build-aux/.functions/log_error new file mode 100644 index 000000000..f1c7b4364 --- /dev/null +++ b/build-aux/.functions/log_error @@ -0,0 +1,3 @@ +local icon=' ✖︎ ' + +print -u2 -PR "${CI:+::error::}%F{1} ${icon} %f ${@}" diff --git a/build-aux/.functions/log_group b/build-aux/.functions/log_group new file mode 100644 index 000000000..7b6aca978 --- /dev/null +++ b/build-aux/.functions/log_group @@ -0,0 +1,16 @@ +autoload -Uz log_info + +if (( ! ${+_log_group} )) typeset -g _log_group=0 + +if (( ${+CI} )) { + if (( _log_group )) { + print "::endgroup::" + typeset -g _log_group=0 + } + if (( # )) { + print "::group::${@}" + typeset -g _log_group=1 + } +} else { + if (( # )) log_info ${@} +} diff --git a/build-aux/.functions/log_info b/build-aux/.functions/log_info new file mode 100644 index 000000000..d437c292d --- /dev/null +++ b/build-aux/.functions/log_info @@ -0,0 +1,7 @@ +if (( ! ${+_loglevel} )) typeset -g _loglevel=1 + +if (( _loglevel > 0 )) { + local icon=' =>' + + print -PR "%F{4} ${(r:5:)icon}%f %B${@}%b" +} diff --git a/build-aux/.functions/log_output b/build-aux/.functions/log_output new file mode 100644 index 000000000..4d9b52f39 --- /dev/null +++ b/build-aux/.functions/log_output @@ -0,0 +1,7 @@ +if (( ! ${+_loglevel} )) typeset -g _loglevel=1 + +if (( _loglevel > 0 )) { + local icon='' + + print -PR " ${(r:5:)icon} ${@}" +} diff --git a/build-aux/.functions/log_status b/build-aux/.functions/log_status new file mode 100644 index 000000000..950e68187 --- /dev/null +++ b/build-aux/.functions/log_status @@ -0,0 +1,7 @@ +if (( ! ${+_loglevel} )) typeset -g _loglevel=1 + +if (( _loglevel > 0 )) { + local icon=' >' + + print -PR "%F{2} ${(r:5:)icon}%f ${@}" +} diff --git a/build-aux/.functions/log_warning b/build-aux/.functions/log_warning new file mode 100644 index 000000000..ceff982a9 --- /dev/null +++ b/build-aux/.functions/log_warning @@ -0,0 +1,7 @@ +if (( ! ${+_loglevel} )) typeset -g _loglevel=1 + +if (( _loglevel > 0 )) { + local icon=' =>' + + print -PR "${CI:+::warning::}%F{3} ${(r:5:)icon} ${@}%f" +} diff --git a/build-aux/.functions/set_loglevel b/build-aux/.functions/set_loglevel new file mode 100644 index 000000000..e32f4bb35 --- /dev/null +++ b/build-aux/.functions/set_loglevel @@ -0,0 +1,17 @@ +autoload -Uz log_debug log_error + +local -r _usage="Usage: %B${0}%b + +Set log level, following levels are supported: 0 (quiet), 1 (normal), 2 (verbose), 3 (debug)" + +if (( ! # )); then + log_error 'Called without arguments.' + log_output ${_usage} + return 2 +elif (( ${1} >= 4 )); then + log_error 'Called with loglevel > 3.' + log_output ${_usage} +fi + +typeset -g -i -r _loglevel=${1} +log_debug "Log level set to '${1}'" diff --git a/build-aux/.run-format.zsh b/build-aux/.run-format.zsh new file mode 100755 index 000000000..26c92f8f1 --- /dev/null +++ b/build-aux/.run-format.zsh @@ -0,0 +1,271 @@ +#!/usr/bin/env zsh + +builtin emulate -L zsh +setopt EXTENDED_GLOB +setopt PUSHD_SILENT +setopt ERR_EXIT +setopt ERR_RETURN +setopt NO_UNSET +setopt PIPE_FAIL +setopt NO_AUTO_PUSHD +setopt NO_PUSHD_IGNORE_DUPS +setopt FUNCTION_ARGZERO + +## Enable for script debugging +# setopt WARN_CREATE_GLOBAL +# setopt WARN_NESTED_VAR +# setopt XTRACE + +autoload -Uz is-at-least && if ! is-at-least 5.2; then + print -u2 -PR "%F{1}${funcstack[1]##*/}:%f Running on Zsh version %B${ZSH_VERSION}%b, but Zsh %B5.2%b is the minimum supported version. Upgrade zsh to fix this issue." + exit 1 +fi + +invoke_formatter() { + if (( # < 1 )) { + log_error "Usage invoke_formatter [formatter_name]" + exit 2 + } + + local formatter="${1}" + shift + local -a source_files=(${@}) + + case ${formatter} { + clang) + if (( ${+commands[clang-format-17]} )) { + local formatter=clang-format-17 + } elif (( ${+commands[clang-format]} )) { + local formatter=clang-format + } else { + log_error "No viable clang-format version found (required 17.0.3)" + exit 2 + } + + local -a formatter_version=($(${formatter} --version)) + + if ! is-at-least 17.0.3 ${formatter_version[-1]}; then + log_error "clang-format is not version 17.0.3 or above (found ${formatter_version[-1]}." + exit 2 + fi + + if ! is-at-least ${formatter_version[-1]} 17.0.3; then + log_error "clang-format is more recent than version 17.0.3 (found ${formatter_version[-1]})." + exit 2 + fi + + if (( ! #source_files )) source_files=((libobs|libobs-*|UI|plugins|deps|shared)/**/*.(c|cpp|h|hpp|m|mm)(.N)) + + source_files=(${source_files:#*/(obs-websocket/deps|decklink/*/decklink-sdk|mac-syphon/syphon-framework|libdshowcapture)/*}) + + local -a format_args=(-style=file -fallback-style=none) + if (( _loglevel > 2 )) format_args+=(--verbose) + + check_files() { + local -i num_failures=0 + local -a source_files=($@) + local file + local -a format_args=(-style=file -fallback-style=none) + if (( _loglevel > 2 )) format_args+=(--verbose) + + local -a command=(${formatter} ${format_args}) + + for file (${source_files}) { + if ! ${command} "${file}" | diff -q "${file}" - &> /dev/null; then + log_error "${file} requires formatting changes." + if (( fail_on_error == 2 )) return 2; + num_failures=$(( num_failures + 1 )) + fi + } + if (( num_failures && fail_on_error == 1 )) return 2 + } + + format_files() { + local -a source_files=($@) + + if (( ${#source_files} )) { + local -a format_args=(-style=file -fallback-style=none -i) + if (( _loglevel > 2 )) format_args+=(--verbose) + + "${formatter}" ${format_args} ${source_files} + } + } + ;; + gersemi) + local formatter=gersemi + if (( ${+commands[gersemi]} )) { + local gersemi_version=($(gersemi --version)) + + if ! is-at-least 0.12.0 ${gersemi_version[2]}; then + log_error "gersemi is not version 0.12.0 or above (found ${gersemi_version[2]}." + exit 2 + fi + } + + if (( ! #source_files )) source_files=(CMakeLists.txt (libobs|libobs-*|UI|plugins|deps|shared|cmake|test)/**/(CMakeLists.txt|*.cmake)(.N)) + + source_files=(${source_files:#*/(jansson|decklink/*/decklink-sdk|obs-websocket|obs-browser|libdshowcapture)/*}) + source_files=(${source_files:#(cmake/Modules/*|*/legacy.cmake)}) + + check_files() { + local -i num_failures=0 + local -a source_files=($@) + local file + local -a command=(${formatter} -c --no-cache ${source_files}) + + if (( ${#source_files} )) { + while read -r line; do + local -a line_tokens=(${(z)line}) + file=${line_tokens[1]//*obs-studio\//} + + log_error "${file} requires formatting changes." + + if (( fail_on_error == 2 )) return 2 + num_failures=$(( num_failures + 1 )) + done < <(${command} 2>&1) + + if (( num_failures && fail_on_error == 1 )) return 2 + } + } + + format_files() { + local -a source_files=($@) + + if (( ${#source_files} )) { + "${formatter}" -i ${source_files} + } + } + ;; + swift) + local formatter=swift-format + if (( ${+commands[swift-format]} )) { + local swift_format_version=$(swift-format --version) + + if ! is-at-least 508.0.0 ${swift_format_version}; then + log_error "swift-format is not version 508.0.0 or above (found ${swift_format_version})." + exit 2 + fi + } else { + log_error "No viable swift-format version found (required 508.0.0)" + exit 2 + } + + if (( ! #source_files )) source_files=((libobs|libobs-*|UI|plugins)/**/*.swift(.N)) + + check_files() { + local -i num_failures=0 + local -a source_files=($@) + local file + local -a format_args=() + + local -a command=(${formatter} ${format_args}) + + for file (${source_files}) { + if ! "${command}" "${file}" | diff -q "${file}" - &> /dev/null; then + log_error "${file} requires formatting changes." + if (( fail_on_error == 2 )) return 2; + num_failures=$(( num_failures + 1 )) + fi + } + if (( num_failures && fail_on_error == 1 )) return 2 + } + + format_files() { + local -a source_files=($@) + + if (( ${#source_files} )) { + local -a format_args=(-i) + + "${formatter}" ${format_args} ${source_files} + } + } + ;; + *) log_error "Invalid formatter specified: ${1}. Valid options are clang-format, gersemi, and swift-format."; exit 2 ;; + } + + local file + local -i num_failures=0 + if (( check_only )) { + if (( ${+functions[check_files]} )) { + check_files ${source_files} + } else { + log_error "No format check function defined for formatter '${formatter}'" + exit 2 + } + } else { + if (( ${+functions[format_files]} )) { + format_files ${source_files} + } else { + log_error "No format function defined for formatter '${formatter}'" + exit 2 + } + } +} + +run_format() { + if (( ! ${+SCRIPT_HOME} )) typeset -g SCRIPT_HOME=${ZSH_ARGZERO:A:h} + if (( ! ${+FORMATTER_NAME} )) typeset -g FORMATTER_NAME=${${(s:-:)ZSH_ARGZERO:t:r}[2]} + + typeset -g host_os=${${(L)$(uname -s)}//darwin/macos} + local -i fail_on_error=0 + local -i check_only=0 + local -i verbosity=1 + local -r _version='1.0.0' + + fpath=("${SCRIPT_HOME}/.functions" ${fpath}) + autoload -Uz set_loglevel log_info log_error log_output log_status log_warning + + local -r _usage=" +Usage: %B${functrace[1]%:*}%b