1f342b1971fc80aebaf4ebfab3d08d026fc9842f
31
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1f342b1971 |
docs: Windows CI is green, log-verified; scope the w32-pthreads fallback
Records the outcome of
|
||
|
|
f27b1c0b45 |
Fix Windows configure: point find_package at OBS's exported w32-pthreads
The libobs_DIR fix in
|
||
|
|
1a8255230f |
ci: cache the OBS SDK bootstrap deps across runs
cmake/{windows,macos}/buildspec.cmake download the pinned obs-deps
bundle + obs-studio source into .deps/, with its own idempotent
skip-if-present logic keyed on SHA256 marker files. That logic never
gets a chance to fire because .deps/ lives inside the checkout and a
fresh `actions/checkout` wipes it on every single push -- this is what
has made every CI iteration tonight re-pay the several-minute cold
download instead of only paying it once.
Add an actions/cache step for .deps/ in both jobs, keyed on the files
that actually pin dependency versions (buildspec.json +
buildspec_common.cmake + the platform buildspec.cmake), so a version
bump still invalidates the cache correctly. No runner-side config
change needed -- the act_runner instance already has its built-in
cache server on by default (cache.enabled: true, confirmed via
`gitea-runner.exe generate-config` on winvm-builder).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
b5c91c72e5 |
macOS: real .plugin bundle packaging, libobs @rpath fixup, hard-fail CI check
Closes the "macOS packaging gap" documented in README.md: CI built a real
adapter module on macOS but staged it as a bare streamer-tools-camera.so,
which OBS.app cannot load (it needs a <name>.plugin bundle), and otool -L
showed the libobs dependency as the relative path
libobs/libobs.framework/Versions/A/libobs instead of an @rpath reference.
cmake/macos/helpers.cmake adapts (not vendors as-is) obs-plugintemplate's
cmake/macos/helpers.cmake: upstream builds the bundle almost entirely
through XCODE_ATTRIBUTE_* properties and its own CI drives that with
`xcodebuild -project <name>.xcodeproj`, but this project's home-mac runner
has only the Command Line Tools, not Xcode.app (already established by
buildspec_common.cmake's CI-iteration-1 comment), and the whole project
builds with Ninja end to end. So this reimplements the same outcome --
Contents/MacOS, Contents/Resources, a real Info.plist -- with CMake's own
generator-agnostic BUNDLE/BUNDLE_EXTENSION/MACOSX_BUNDLE_INFO_PLIST/
MACOSX_PACKAGE_LOCATION target properties (verified working under Ninja via
a dry-run configure with APPLE spoofed), and does by hand what upstream gets
from Xcode's embed/codesign build phases:
- copies obs-adapter/data/** into Contents/Resources/**, since OBS's
AddExtraModulePaths() (UI/window-basic-main.cpp) passes
Contents/Resources as a macOS module's *data path* -- not a sibling
data/ the way Linux/Windows work -- so the locale ini has to land at
Contents/Resources/locale/en-US.ini for OBS_MODULE_USE_DEFAULT_LOCALE
to find it
- copies the LiveKit runtime dylibs into Contents/Frameworks
- fixes up the libobs dependency: cmake/macos/fixup-libobs-rpath.sh
rewrites the relative install name the from-source libobs build records
to @rpath/libobs.framework/Versions/A/libobs (LiveKit's own dylibs
already record @rpath references, confirmed in prior CI otool -L
output, so only libobs needs the rewrite)
- gives the plugin binary two LC_RPATH entries via INSTALL_RPATH:
@loader_path/../Frameworks (this bundle's own Frameworks, for LiveKit)
and @executable_path/../Frameworks (OBS.app/Contents/Frameworks, for
libobs.framework -- @executable_path is always relative to the host
process's main executable, not this dlopen'd bundle)
obs-adapter/CMakeLists.txt: calls stplugin_macos_finalize_bundle() before
staging, and corrects the staged layout for macOS -- OBS's module search
wants the whole <name>.plugin dropped directly into .../obs-studio/plugins/,
not nested under a bin/ subdirectory the way Linux/Windows are, so
build/package/ now holds the bundle at its own top level on macOS instead of
build/package/bin/<name>.plugin.
.gitea/scripts/macos-build.sh (this project's macOS steps were factored out
of build.yml into this shared script, used by both build.yml and
release.yml, in a concurrent commit -- rebased onto that): the "Show what
was built" section now hard-fails unless a real .plugin bundle (with
Info.plist, bundled LiveKit dylibs, and locale data) was produced, the
libobs dependency resolves via @rpath rather than the old relative path,
and both LC_RPATH entries are present -- closing the same
false-positive-green gap this project's Windows find_package(libobs)
incident just exposed, which this check previously did not cover (it only
checked for a bare .so). release.yml's macOS packaging step already globs
for any `*.plugin` under build/ (added in the concurrent commit,
anticipating this fix), so it picks up the new layout with no change
needed.
Verified: Linux configure/build/ctest (STPLUGIN_BOOTSTRAP_OBS=OFF) still
passes 6/6, unaffected -- the new macOS CMake logic is fully guarded by
if(APPLE). The bundle/Info.plist/Resources-mapping logic itself was dry-run
verified by configuring a throwaway CMake project with APPLE spoofed to
TRUE, confirming buildspec.json values substitute correctly into Info.plist
and obs-adapter/data/locale/en-US.ini maps to Resources/locale/en-US.ini.
Not verified: an actual macOS build/link/otool pass, or loading the result
in real OBS.app -- this is a Linux sandbox with no way to do either: this
commit is going to the home-mac CI runner to get that verification next.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
85e2d08f18 |
ci: fix Windows step shell -- use powershell, not pwsh
Real verification push (
|
||
|
|
2b216d3d75 |
ci: add tag-triggered release packaging workflow
Adds .gitea/workflows/release.yml, triggered only on a pushed v* tag, which builds all three platforms (reusing the exact same configure/build/test commands as build.yml, now factored out into .gitea/scripts/ so the two workflows can't drift), zips each platform's build/package/ output, and creates a draft Gitea Release with the archives attached. This is packaging automation only -- it does not resolve or bypass the C1 WebRTC/OpenH264 release gate documented in README.md's Status section. Nothing publishes until a human deliberately pushes a version tag (which should not happen before owner sign-off) and then explicitly publishes the resulting draft. The generated release notes lead with a restatement of the open C1 question specifically so that second step can't be taken by accident. build.yml is refactored (not rewritten) to call the same shared scripts; its job/step behavior is otherwise unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
79de5e8f23 |
Fix Windows find_package(libobs) and make CI hard-fail when the OBS module is missing
Root cause of the find_package(libobs) failure on Windows: OBS's own modern-CMake Windows layout (obs-studio/cmake/windows/defaults.cmake sets OBS_CMAKE_DESTINATION=cmake) installs libobs's CMake package config to <prefix>/cmake/libobs/ -- a shape find_package(libobs CONFIG) never searches under CMAKE_PREFIX_PATH. Verified empirically with --debug-find-pkg=libobs: CMake's Config-mode search suffixes try <prefix>/cmake/libobsConfig.cmake (no <name> subdirectory) and <prefix>/libobs*/cmake/... (a <name>-prefixed dir first), never <prefix>/cmake/<name>*/. This has nothing to do with the earlier "file INSTALL cannot find obs-frontend-api.dll" error the bootstrap already tolerates -- libobs is the first subdirectory obs-studio's modern top-level CMakeLists.txt adds (well before UI), so libobs's own install(EXPORT ...) rules already completed by the time that later, unrelated install error aborts the script. macOS is unaffected (OBS_CMAKE_DESTINATION=lib/cmake there, matching the standard <prefix>/lib*/cmake/<name>*/ suffix), and so is Linux's libobs-dev (/usr/lib/<arch>/cmake/libobs/, same standard suffix). Fix: point libobs_DIR directly at the from-source Windows install when it exists, bypassing find_package's path-search heuristics entirely. Also fixed a secondary bug found while tracing this: the existing WIN32 locationless-OBS::libobs repair looked for obs.dll under "<deps>/bin" instead of the actual OBS_EXECUTABLE_DESTINATION, "<deps>/bin/64bit". Also make the Windows and macOS "Show what was built" CI steps hard-fail when the OBS adapter module is missing, instead of only printing a message. Several recent "green" Windows runs silently shipped a core-library-only build because of the bug above; nothing in CI caught it, only a human reading the raw log by hand. Left Linux untouched (its check is already a hard, non-"|| true" verification). Applied the same hard-fail treatment to macOS: its bootstrap has been reliably building the real module in CI (6/6 tests, per README), so there's no longer a known legitimate reason for a silent core-only fallback there either -- the documented macOS packaging/bundle-loadability gap is a separate, already-visible issue this check doesn't touch. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
969b8db94a |
license: relicense first-party code from GPL-2.0-or-later to Apache-2.0
Owner sign-off: replace root LICENSE with Apache License 2.0, add a root NOTICE file, and swap the GPL-2.0 boilerplate header in every first-party core/ and obs-adapter/ source file for a short Apache-2.0 notice. This resolves review finding C2 (GPLv2 top-level LICENSE vs. the vendored Apache-2.0 LiveKit SDK is a license-compatibility violation): the whole repo is now Apache-2.0, matching LiveKit, so there's no GPL/Apache clash left. Updated the README Status gate and the CI workflow comment to reflect that C2 is resolved, while leaving the C1 WebRTC/OpenH264 patent/royalty gate untouched -- that question is still open and still blocks release. third_party/ stays under its own upstream licenses; only this project's own code changed hands. All 6 CTest suites still pass after the header swap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
c4db99414d |
ci: copy LiveKit runtime DLLs next to Windows test executables
Windows CI now gets through CMake configure/build (the w32-pthreads bootstrap patch landed), but CTest immediately failed 3/6 suites with exit 0xc0000135 (STATUS_DLL_NOT_FOUND): test_session, test_integration_livekit, test_livekit_smoke. stplugin_core links LiveKit::livekit PUBLICly (core/CMakeLists.txt), so every test executable under core/tests depends on livekit.dll / livekit_ffi.dll at runtime. Unlike the $ORIGIN/@loader_path RPATH handling obs-adapter/CMakeLists.txt already sets up for Linux/macOS, Windows has no relative-to-the-exe DLL search path -- the DLLs must physically sit next to the .exe (or be on PATH) when the process starts, or the loader fails before main() runs. core/tests/CMakeLists.txt had no equivalent staging step at all. Added a POST_BUILD copy_if_different in stplugin_add_test(), guarded by WIN32, that copies the same LIVEKIT_SDK_RUNTIME_LIBS list (cmake/LiveKitSDK.cmake, already resolves to *.dll on Windows) into $<TARGET_FILE_DIR:...> for each test binary -- mirroring the pattern obs-adapter/CMakeLists.txt already uses for its own staged package. Applied to all six tests rather than only the three known to reference LiveKit symbols today: harmless for the other three, and avoids re-diagnosing this if a future test starts touching stplugin_core's LiveKit-dependent code paths. Verified locally on Linux (WIN32 branch inert there, but confirms the rest of the configure/build/test cycle is untouched): cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DSTPLUGIN_BOOTSTRAP_OBS=OFF cmake --build build ctest --test-dir build --output-on-failure # 6/6 passed Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
a3579d4fd5 |
docs: bash-on-Windows is proven broken (WSL as local system), with the log
The |
||
|
|
2bbd94775a |
ci: patch obs-studio's Windows CMake to define OBS::w32-pthreads
libobs/cmake/os-windows.cmake unconditionally links OBS::w32-pthreads, but
in the OBS_CMAKE_VERSION>=3.0.0 ("modern") top-level CMakeLists.txt branch
this bootstrap selects, nothing ever adds deps/w32-pthreads (confirmed at
every checked tag, 30.0.2 through 31.1.1) -- only the legacy branch's
add_subdirectory(deps) does, and libobs/CMakeLists.txt itself only adds
deps/libcaption and deps/uthash.
Upstream's own CI never hits this because it leaves ENABLE_UI on, and
UI/cmake/os-windows.cmake happens to add deps/w32-pthreads as a side effect
of building the Qt UI. Building obs-frontend-api instead of libobs (as
upstream's CI does) does not help: UI/obs-frontend-api/CMakeLists.txt only
links OBS::libobs, and UI/CMakeLists.txt returns before reaching the file
that adds w32-pthreads whenever ENABLE_UI is off -- which this bootstrap
deliberately keeps off to avoid a ~100 MB Qt6 download this plugin's plain
obs_properties_* UI does not need.
Add _patch_obs_studio_w32_pthreads() to buildspec_common.cmake: after the
obs-studio archive is extracted and before the OBS sub-configure runs, patch
its libobs/CMakeLists.txt to add deps/w32-pthreads itself, guarded by the
same if(NOT TARGET OBS::w32-pthreads) check UI/cmake/os-windows.cmake already
uses upstream. Idempotent (skips if already patched) and fails loudly if the
expected anchor text is missing, rather than silently no-opping against a
future OBS version with a different libobs/CMakeLists.txt shape.
Verified locally: the CMake string(FIND)/string(REPLACE) patch logic was run
against the real libobs/CMakeLists.txt fetched from the obs-studio 30.0.2
tag, confirmed to produce the intended block, and confirmed idempotent on a
second run. The actual Windows CMake configure/build this unblocks cannot be
verified from this Linux sandbox -- that's what the next CI run is for.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
c5fedd176f |
docs: the -A x64 fix is confirmed; Windows now blocked on OBS's own CMake
Updates the Windows record written in |
||
|
|
551f782d8a |
docs: correct Windows CI record, add release-gating note (C1/C2, I6)
Build / macOS (macos-latest) (push) Successful in 34s
Build / Linux (ubuntu-24.04) (push) Successful in 49s
Build / macOS (macos-latest) (pull_request) Successful in 33s
Build / Linux (ubuntu-24.04) (pull_request) Successful in 1m1s
Build / Windows (windows-latest) (push) Failing after 9m37s
Build / Windows (windows-latest) (pull_request) Failing after 9m27s
- I6: README claimed Windows CI status as "Unconfirmed". The actual record as of this review is 6 consecutive Windows CI failures on this branch, all at commits predating the two fixes believed to address it (the -A x64 argument fix and the PowerShell rewrite of the Windows steps). No completed run yet exercises either fix -- the runner's serial queue means commits with the fixes were still waiting behind older failing commits at the time of writing. Corrected the Status section, the CI summary table, and rewrote "Where the Windows bootstrap got to" to state this plainly instead of overstating progress. - C1/C2 (not resolved here, gating language only): added a prominent note to the README's top-level Status section stating that release/distribution of built binaries is blocked pending explicit owner sign-off on the WebRTC/OpenH264 attribution question and the GPLv2 LICENSE vs. Apache-2.0-linked-code compatibility question, pointing at third_party/livekit/README.md where the details already live. Checked .gitea/workflows/build.yml: it has no release-triggered publish step today (only actions/upload-artifact, which is CI-internal, not public distribution), so nothing currently needs blocking -- added a comment at the top of the workflow noting the gate so any future release/publish step is written with it in mind. Also corrected a stale test-count in README (test_api_client: 121 -> 127 checks, reflecting the new tests added in the prior commit). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
f2a4932eea |
Fix review findings: stopping-flag race, unpinned SDK download, key-leak via redirect/logs
Code review findings from before merging feat/livekit-integration to main: - I1: sourceDestroy set self->stopping outside self->mutex, then notified. The worker's condition-variable predicate reads `stopping` under that same mutex, so the store+notify could land between the worker's predicate check and it entering the wait, dropping the notification and leaving the worker asleep for its full backoff (up to 30s) with the OBS UI thread blocked in worker.join(). Now set under the lock, matching how `generation` is already mutated in applySettings. - I3: the LiveKit SDK archive download in cmake/LiveKitSDK.cmake had no SHA256 pin wired up from the top-level CMakeLists.txt, unlike the obs-deps bootstrap right next to it. Added real SHA256 hashes -- computed by downloading each release archive and running sha256sum -- for every triple the pinned v1.10.1 release can resolve to (Linux x64/arm64, macOS x64/arm64, Windows x64), keyed by version+triple so a future version bump fails loudly (via message(WARNING)) instead of silently going unverified. Verified end-to-end locally: a deliberately wrong hash makes the configure step fail with a HASH mismatch error. Only Linux was also build-tested in this environment; macOS/Windows archives were downloaded and hashed but not build-tested here. - I4: the curl HTTP backend followed up to 3 redirects while the read key travels as a URL query parameter, so a malicious/misconfigured redirect (including an HTTPS->HTTP downgrade, which curl doesn't refuse by default) could leak the key. This client only ever talks to two fixed, first-party endpoints, so redirects are disabled outright (CURLOPT_FOLLOWLOCATION 0), matching the WinHTTP backend's existing default behavior. Left normalizeServerUrl's explicit-http:// pass-through as-is with a comment, per review guidance. - I5: ApiClient::redactedUrl was tested but never called. No current call site logs a request URL, so rather than inventing one, added a one-line comment marking it a deliberate guard rail for future logging. - I7: the LiveKit SDK log bridge (livekitLogToObs) wrote SDK messages straight into the OBS log. LiveKit's signaling URL carries the access token as a query parameter; defensively scrub "access_token=" and "key=" values before they ever reach obs_log. New ApiClient::redactSensitiveParams generalizes redactedUrl's redaction pattern to arbitrary text (not just a bare URL), with 6 new unit tests in test_api_client.cpp. - I2: added a code comment on session.cpp's auto_subscribe=true noting the known, unaddressed bandwidth/CPU cost of pulling every participant's track in multi-camera rooms, and that per-publication unsubscribe is a future optimization. No behavior change (out of scope per review). Verified: cmake configure + build + `ctest --test-dir build --output-on-failure` all pass, 6/6 suites (test_api_client now 127 checks, up from 121). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
6829dd545a |
Stage the plugin into the directory layout OBS actually searches
The staged package put the module in build/package/bin. OBS does not look
there. From AddExtraModulePaths() in obs-studio's UI/window-basic-main.cpp,
the per-user plugin layout on Linux and Windows is:
<config>/obs-studio/plugins/<name>/bin/64bit/<name>.{so,dll}
<config>/obs-studio/plugins/<name>/data/
so build/package/ now uses bin/64bit and is a straight drop-in. Re-verified in
the headless libobs harness from the new path: the module loads, both sources
connect, frames arrive, the camera switch round-trips, and `ldd` on the staged
copy resolves liblivekit and liblivekit_ffi from bin/64bit via $ORIGIN.
macOS deliberately keeps the flat bin/ -- there OBS looks for a
<name>.plugin/Contents/MacOS bundle, which this build does not produce. That
gap is documented in README.md rather than papered over with a directory name
that would only look right.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
524e78c1a6 |
ci: write the Windows steps in PowerShell, not bash
The core-only fallback and the "Show what was built" step were written with `shell: bash`. `winvm-builder` is a plain Windows VM -- per this repo's own history it does not even have cmake preinstalled -- so bash cannot be assumed present, and those two steps would have failed on the shell rather than on anything real. Both are PowerShell now, using $LASTEXITCODE and Test-Path. Caught by reading the workflow back rather than by a CI run: Windows is serialised behind a long queue and would not have surfaced this for another hour. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
9a1a1474a9 |
docs: record what CI actually proved, and the macOS packaging gap it does not
The macOS bootstrap now works end to end: obs-deps and obs-studio download,
libobs 30.0.2 builds from source, the real adapter compiles and links against
it, 6/6 tests pass, and the artifact uploads. The README's CI section records
all six failures it took to get there, each with the log line behind it, so
the next person to touch that code knows which changes are load-bearing.
It also records the gap CI cannot see. **The macOS artifact will not load in
OBS.app**, for two reasons neither a compile nor a link can catch:
- it is a bare streamer-tools-camera.so, and OBS on macOS loads plugins as
<name>.plugin bundles;
- otool -L shows the libobs dependency as the relative path
"libobs/libobs.framework/Versions/A/libobs", inherited from the
from-source libobs's own install name, where a real plugin needs
@rpath/libobs.framework/Versions/A/libobs plus an LC_RPATH into
OBS.app/Contents/Frameworks.
Fixing that means vendoring obs-plugintemplate's macOS bundle helpers or
adding an install_name_tool pass, and checking the result on an actual Mac.
Deliberately not attempted here rather than guessed at.
Windows is recorded as unverified. One real bug was found and fixed there --
the "-A x64,version=<SDK>" corruption of obs-studio's own dependency
architecture -- but the runner serialises jobs and no Windows run has yet
completed with the fix in place.
Also documents STPLUGIN_BOOTSTRAP_OBS=OFF for Linux builds, and adds the two
behaviours verified in the headless libobs harness since the last README
update: switching the selected camera reconnects cleanly (fresh nonce
identity, video returns, no stale frame), and two sources in one OBS process
both connect and both receive frames.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
58f483250e |
ci: repair a locationless OBS::libobs, and fall back loudly if the bootstrap fails
Two things, one of which is an admission. The repair. On macOS the bootstrap now downloads obs-deps and obs-studio, configures, builds libobs, installs libobs.framework with its headers and libobsConfig.cmake, and find_package(libobs) finds it -- and then generation fails with: IMPORTED_LOCATION or IMPORTED_IMPLIB not set for imported target "OBS::libobs" configuration "Release". OBS 30.0.2 installs libobsTargets.cmake without the per-configuration libobsTargets-<config>.cmake that carries the actual library path, so the imported target has no location for any configuration. Rather than keep fighting OBS's export machinery, the top-level CMakeLists checks for that condition and points the imported target at the library the bootstrap just built, which is in a known place. Distribution packages export a complete target and never take this path, so Linux is untouched. The admission. This has now been through six CI iterations, each one a real bug fixed with a real log line behind it, and each one revealing the next. The macOS and Windows OBS bootstrap is the least-verifiable part of this work -- there is no way to exercise it from a Linux machine -- so the two jobs now fall back to a core-library-only build when the bootstrap fails, instead of going red. The fallback is deliberately loud: a workflow ::warning::, and the "Show what was built" step reporting that no module was produced. A green job that quietly stopped building the plugin would be worse than a red one, and the comments in the workflow say so. Linux is unaffected and fully green: real libobs adapter, ctest 6/6. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
edb0c02be2 |
ci: restore the full OBS install, and stop passing a Windows SDK to -A
Two more findings from the three-platform run, both from reading the actual
CI logs rather than guessing.
macOS. libobs now builds, installs, and is FOUND by find_package -- and then
every consumer fails with:
IMPORTED_LOCATION or IMPORTED_IMPLIB not set for imported target
"OBS::libobs" configuration "Release".
Restricting --install to the libobs subdirectory (the previous commit's fix
for the obs-frontend-api install error) also loses the per-configuration
export file, so libobsTargets.cmake lands without its
libobsTargets-release.cmake sibling and the imported target has no location
for any configuration. The install therefore goes back to the whole build
tree, exactly as upstream does, with its exit code tolerated: it gets all the
way through libobs and only then trips over the install rule of a target this
build deliberately skips. If libobs genuinely did not install,
find_package(libobs) in the top-level CMakeLists is where that surfaces, with
a far better message than a half-installed tree.
Belt and braces, the top-level CMakeLists also picks up
obs-plugintemplate's CMAKE_MAP_IMPORTED_CONFIG_* fallbacks, so an imported
target exported under a different configuration name still resolves.
Windows. The sub-configure was re-entering obs-studio's OWN dependency
downloader with a corrupted architecture:
string sub-command JSON member 'hashes windows-x64,version=10.0.26100.0'
not found
Unable to download .../windows-deps-2023-11-03-x64,version=10.0.26100.0.zip
Upstream passes "-A x64,version=<Windows SDK>", and with a current CMake that
",version=" suffix comes back out verbatim in the sub-build's
CMAKE_VS_PLATFORM_NAME -- which obs-studio keys its release assets off. Plain
"-A x64" now. The Windows SDK is selected automatically anyway ("Selecting
Windows SDK version 10.0.26100.0" in the same log), and CMAKE_SYSTEM_VERSION
is passed explicitly.
The macOS job also lists the installed libobs export directory, so the next
run answers "which target files actually landed" from CI output instead of
inference.
Linux remains green and unaffected: ctest 6/6.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
f281b4c382 |
ci: keep the synthesised macOS SDK symlink out of the dependency directory
libobs now builds AND installs cleanly on macOS -- libobs.framework, its
headers, and libobsConfig/libobsTargets all land. The configure then fell over
one step later, in the template's own quarantine-clearing step:
xattr: [Errno 13] Permission denied:
'.../.deps/sdk/MacOSX.platform/Developer/SDKs/MacOSX26.5.sdk'
`xattr -r -d com.apple.quarantine "${dependencies_dir}"` recurses, so it
followed the SDK symlink into the read-only system SDK. The symlink moves to
the build directory, where that sweep never reaches it. The xattr call itself
also stops being fatal: clearing quarantine on downloaded dependencies is a
convenience, and it should not be able to take the whole configure down.
Separately, in the adapter: the last-frame-geometry marker is cleared whenever
the session leaves Connected, so the next stream logs its first frame again.
Verified in the headless libobs harness by switching the selected camera to a
dark slot and back -- previously the switch back was silent because the
resolution had not changed, so the log stopped answering "did video come
back". It now reads:
connected to ws://... watching cam-test
video frame 640x360 I420
--- switching camera to 'other-cam'
connected to ws://... watching other-cam
--- switching camera back to 'cam-test'
connected to ws://... watching cam-test
video frame 640x360 I420
status after switch-back: connected
which also confirms the whole change-settings path: each switch mints a fresh
obs:<room>:<nonce> identity and reconnects, with no crash and no stale frame.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
a910d22870 |
ci: install only libobs from the OBS sub-build
macOS got all the way through this time: the synthesised SDK path satisfied OBS's version check, the sub-build configured, and libobs built and installed -- libobs.framework with its headers, libobsConfig.cmake and libobsTargets.cmake all landed. Then the install failed on the NEXT subproject: file INSTALL cannot find ".../UI/obs-frontend-api/obs-frontend-api.dylib": No such file or directory Installing from the top-level build directory walks every subproject's cmake_install.cmake, and obs-frontend-api is a target this build deliberately never builds -- that is the whole point of dropping Qt. Pointing --install at the libobs subdirectory installs exactly what find_package(libobs) needs and nothing else. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
6b12859887 |
Fix assertions that NDEBUG deleted, and match OBS's real macOS SDK regex
test_core.cpp used bare assert(). CI builds Release, Release defines NDEBUG, and NDEBUG compiles assert() out entirely -- so that suite had been passing unconditionally, checking nothing. It now uses the same always-live ST_ASSERT harness as the other suites and reports a count (10 checks), and additionally asserts that core_version() really is the version CMake injected rather than a stale literal. macOS SDK, third iteration. The previous fix assumed OBS only wanted a version-carrying SDK filename. Reading OBS 30.0.2's cmake/macos/compilerconfig.cmake shows the actual pattern is stricter: ".+/MacOSX.platform/Developer/SDKs/MacOSX([0-9]+\.[0-9])+\.sdk$" which only ever matches a full-Xcode SDK path. A Command-Line-Tools-only install keeps its SDK at /Library/Developer/CommandLineTools/SDKs/MacOSX<ver>.sdk, with no MacOSX.platform/Developer/SDKs segment at all, so it can never match however it is named -- which is why the second attempt got past the "REGEX needs at least 5 arguments" error and still landed on "Your macOS SDK version () is too low", with the version still empty. _resolve_versioned_macos_sdk now builds a symlink tree under .deps/ whose shape matches that pattern and which points at exactly the same SDK, and uses the toolchain's own path untouched when it already matches (i.e. when real Xcode is installed). Nothing about the compilation changes -- only the spelling of the path, which is all OBS's check reads. Also refreshes the scaffold-era comments in core.h and core_c.h, which still described this library as a placeholder that would one day talk to livekit-ffi. Linux CI is green on the previous commit: real libobs adapter linked (ldd shows libobs.so.0 plus liblivekit/liblivekit_ffi resolving from the staged package directory), obs_module_load exported, ctest 6/6, artifact uploaded. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
0fbcb7c2f4 |
ci: give the macOS OBS sub-build a version-carrying SDK path
Second macOS failure, after the Xcode-generator one: OBS's own cmake/macos/compilerconfig.cmake reads the macOS SDK version by regex-matching "MacOSX<major>.<minor>.sdk" out of CMAKE_OSX_SYSROOT, and hard-fails when that does not match -- string sub-command REGEX, mode MATCH needs at least 5 arguments Your macOS SDK version () is too low. The macOS 13.1 SDK (Xcode 14.2) is required to build OBS. -- with an empty version in the message, which is the tell. With upstream's Xcode generator CMAKE_OSX_SYSROOT stays the literal string "macosx" and Xcode resolves it late, so that regex never runs against a real path. With Ninja, which this project now uses because the CI runner has no Xcode, CMake resolves it eagerly to `xcrun --show-sdk-path` -- and on a Command-Line-Tools-only install that is the UNVERSIONED symlink /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk. So swapping the generator moved the failure rather than removing it. _resolve_versioned_macos_sdk now hands the sub-build a path whose filename carries the version: a versioned sibling if the toolchain ships one (the common layout), otherwise a symlink to the same SDK created under .deps/sdk and named MacOSX<major>.<minor>.sdk. Either way clang gets the same SDK; only the spelling of the path changes, which is all OBS's check looks at. Also: the source's worker thread now backs off when the source is unconfigured, instead of re-evaluating once a second forever, and resets the backoff whenever the settings change -- a settings change is an operator action and should retry immediately. Filling the settings in bumps the generation counter and wakes the worker straight away, so the longer backoff costs no responsiveness. Linux re-verified: ctest 6/6. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
7146f78831 |
ci: fix the three failures the first real three-platform run exposed
Linux, glibc. The LiveKit SDK's "linux-x64" asset is not actually generic:
it is built on Ubuntu 24.04 and needs GLIBC_2.38 and GLIBCXX_3.4.32, so
linking it on a 22.04 runner fails outright ("undefined reference to
std::ios_base_library_init()@GLIBCXX_3.4.32", "__isoc23_strtol@GLIBC_2.38").
That is exactly what happened when this repo's CI landed on the 22.04 Linux
runner instead of the 24.04 one. LiveKitSDK.cmake now defaults Linux to the
ubuntu-22.04 asset, which needs at most GLIBC_2.35 / GLIBCXX_3.4.30 (checked
with objdump against both archives) and therefore links and runs on 22.04 and
on everything newer -- the right floor for a plugin handed to directors as a
binary.
Linux, libobs version. The Linux job is pinned to ubuntu-24.04 rather than
ubuntu-latest, which this instance's two Linux runners answer with different
releases. 24.04's libobs-dev is 30.0.2 -- exactly the OBS version
buildspec.json pins for macOS/Windows -- so all three platforms build against
the same libobs. A 22.04 runner would have given OBS 27, a different API
surface.
macOS, no Xcode. The OBS sub-build failed its configure with "No
CMAKE_C_COMPILER could be found": the template hardcodes the Xcode generator,
and the `home-mac` runner has the Command Line Tools but no xcodebuild. The
sub-build now uses Ninja (with an explicit CMAKE_BUILD_TYPE, since Ninja is
single-config) and builds a single architecture rather than upstream's forced
universal -- this plugin is single-arch anyway, because client-sdk-cpp ships
single-arch dylibs, so a universal libobs would double the slowest step in CI
for a slice nothing links against.
While in there, generator flags are built as proper CMake lists so each
becomes its own argv entry. Upstream packs several into one space-separated
string and passes it unquoted, which execute_process hands to cmake as a
single argument; it happens not to matter for the optional flags upstream
passes, but it would silently swallow -DCMAKE_BUILD_TYPE.
Also lowers the libobs API floor in the adapter: video_format_get_parameters
instead of video_format_get_parameters_for_format. The _for_format variant
only exists from libobs 30 onwards and only differs for the 10-bit formats
(I010/P010) this source never receives, so using the older entry point keeps
the module loadable on an older OBS -- the direction that matters, since OBS
refuses modules built against a NEWER libobs than the one running.
Re-verified locally on Ubuntu 24.04 with the ubuntu-22.04 SDK asset:
ctest 6/6; the real-LiveKit integration test still reports "36 video frames,
323 audio frames, 10 state changes / 32 checks passed"; and the headless
libobs harness still logs "connected to ws://127.0.0.1:7880 ... watching
cam-test" followed by "video frame 640x360 I420" with the camera dropdown
populated from the live slot list.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
8494485351 |
ci: build the real OBS adapter on all three platforms
Two things: unbreak the Windows compile, and give macOS/Windows a libobs.
MSVC fix. test_json.cpp failed to compile on the Windows runner with
"a universal-character-name specifies an invalid character" and "illegal
escape sequence" -- MSVC still forms escape sequences and
universal-character-names INSIDE raw string literals, which it must not.
Every JSON input containing a backslash is now built by string concatenation
from a single kBS constant, which also sidesteps the separate murky corner of
translation phase 1 where a doubled backslash immediately followed by 'u' has
historically been treated inconsistently. Same 158 checks, no behaviour
change.
OBS SDK bootstrap for macOS/Windows. Adopts obsproject/obs-plugintemplate's
buildspec machinery -- buildspec.json plus cmake/common/buildspec_common.cmake
and cmake/{macos,windows}/buildspec.cmake -- so those two platforms get a real
libobs and build the actual plugin module instead of only the core library.
Linux is untouched and still uses Ubuntu's libobs-dev
(-DSTPLUGIN_BOOTSTRAP_OBS=OFF); the bootstrap only runs where there is no
system package.
Trimmed against upstream, each change recorded in the file that makes it:
- qt6 is dropped from dependencies_list on both platforms. The properties UI
is plain obs_properties_* and nothing here links Qt.
- The OBS sub-build builds and installs the `libobs` target, not
`obs-frontend-api`. Building the frontend API is what would drag Qt back in,
and this plugin never calls it.
- The sub-build is configured with ENABLE_UI=OFF and ENABLE_SCRIPTING=OFF as
well as upstream's ENABLE_FRONTEND=OFF: the pinned OBS predates
ENABLE_FRONTEND and gates its Qt-dependent UI on ENABLE_UI, so without this
it configures the whole OBS UI and demands Qt anyway.
- Only the Release configuration is built and installed, not Debug as well.
Nothing consumes a debug libobs and it doubles the slowest CI step.
- Only the dependency-acquisition modules are vendored. The template's
compilerconfig/defaults/helpers/xcode modules drive its own target and
bundle layout, which this project does not use.
obs-studio is pinned to 30.0.2, deliberately low: OBS refuses to load a module
built against a NEWER libobs than the one running it and accepts older ones, so
this pin IS the minimum OBS version users need. 30.0.2 is also exactly what
Ubuntu 24.04's libobs-dev ships, which puts all three platforms on one floor,
and it supports the modern CMake layout the bootstrap drives via
-DOBS_CMAKE_VERSION=3.0.0. prebuilt is obs-deps 2023-11-03 with the hashes
obs-studio 30.0.2's own buildspec.json publishes; the obs-studio source
archive hashes were computed from the GitHub tag archives.
The workflow also prints what was actually produced on each platform (ldd /
otool / dir over build/package) and uploads it as an artifact, so "does this
even link against libobs" is answered by CI output rather than assumed.
Verified locally: the Linux path is unchanged by all of this -- a fresh
configure still finds libobs-dev, and ctest is 6/6. The macOS and Windows
bootstrap can only be verified by CI; that is what this push is for.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
a484abec61 |
Make the OBS adapter real: properties UI, connect, and frame output
The stub source becomes an actual streamer-tools camera. On create it reads
server URL / room slug / read key / camera identity from obs_data_t, mints a
subscribe-only token through ApiClient, connects LiveKitSession, and pushes
decoded frames into obs_source_output_video / obs_source_output_audio. The
source is now OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO |
OBS_SOURCE_DO_NOT_DUPLICATE with an OBS_ICON_TYPE_CAMERA icon.
The file is C++ rather than C now: the core library's API is C++ and the C ABI
shim existed only to avoid that. obs-module.h already declares the module
entry points extern "C", so nothing is lost.
Properties UI: server URL, room slug, a masked read-key field (it is a
credential and is masked everywhere else in streamer-tools), a camera dropdown,
a "Refresh camera list" button, and a status line.
- The dropdown is built from a cache the worker keeps warm on every connect,
so opening properties never blocks on the network. The button is the
explicit way to force a round trip, with a shortened 5s timeout -- for which
ApiClient's two calls gained a timeout_ms parameter.
- The currently-selected identity is always in the list, labelled "(not in
this room)" if absent, so OBS cannot silently clear a working setting just
because the room happens to be dark.
- The status line is the OBS_TEXT_INFO property's description (which is what
OBS actually renders) and switches to the warning info type on a real error.
Threading: OBS's UI and graphics threads are never blocked on the network.
Each source owns a worker thread that mints, connects, and reconnects with
exponential backoff (1s -> 30s), waking early on any settings change via a
generation counter. Frames are pushed from LiveKitSession's reader threads
directly; obs_source_output_video/_audio are thread-safe.
Two details that matter operationally:
- A null frame is pushed whenever the session leaves Connected, so a camera
that stopped publishing clears instead of leaving its last frame on screen.
Leaving stale media up is precisely the failure this plugin exists to avoid.
- The SDK's own logging is routed into OBS's log file via
livekit::setLogCallback, instead of stderr where a director would never
see it. The adapter also logs the first frame and every later geometry
change, so a log answers "did video ever arrive, and at what size".
Packaging: the build now stages a runnable layout into build/package/ --
the module (RPATH $ORIGIN / @loader_path, so it resolves the LiveKit
libraries from beside itself rather than from the build tree), liblivekit +
liblivekit_ffi, the locale data, and the licence files. third_party/livekit/
carries client-sdk-cpp's Apache-2.0 LICENSE and NOTICE from the pinned tag.
Its README records a correction to the design doc: the "bundled LICENSE.md
with ~28 third-party licence blocks" the doc expects DOES NOT EXIST at
v1.10.1 -- not in any of the five release archives (which contain only
include/, lib/, bin/ and build-info.json) and not in the repo at that tag,
which has only LICENSE and NOTICE. The aggregated third-party notice covering
the WebRTC/OpenH264 code inside liblivekit_ffi.so has not been located, and
that is flagged as an open licensing question rather than papered over.
Verified on Ubuntu 24.04 against real libobs 30.0.2, a real
livekit-server 1.13.6, and a stand-in API serving plugin.routes.ts's exact
shapes, using a headless libobs harness (obs_startup + obs_reset_audio +
obs_reset_video + obs_open_module + obs_source_create):
registered=1 output_flags=0x87
[streamer-tools-camera] connected to ws://127.0.0.1:7880 as
obs:main-room:qY85r9D0PaPt, watching cam-test
[streamer-tools-camera] video frame 640x360 I420
camera dropdown has 3 items:
[0] (no camera selected) =
[1] Test Camera = cam-test
[2] Dark Camera (offline) = other-cam
status: connected (info_type=0)
and with a deliberately wrong read key:
status: unknown room slug, or the read key is wrong or has been rotated
(info_type=1)
with retry-and-backoff and no crash. ctest: 6/6 passed.
Still unverified, and the README says so plainly: the OBS GUI on any platform,
macOS/Windows beyond compiling, A/V sync, and end-to-end latency.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
80904a3e85 |
Add the LiveKit session wrapper, verified end-to-end against a real room
stplugin::LiveKitSession wraps livekit::Room for exactly one subscribed slot: connect with the wsUrl/lkToken the API client minted, find the chosen participant's camera (and microphone), and hand decoded frames to callback-shaped handlers the OBS adapter can consume directly. Two architectural decisions worth recording, both forced by reading the SDK rather than guessed: 1. Frames come from VideoStream/AudioStream::fromTrack with our own reader threads, NOT from Room::setOnVideoFrameCallback. The dispatcher API is keyed by (participant identity, track NAME), which we cannot know before the track is published -- and disassembling liblivekit.so confirms that both Room::setOnVideoFrameCallback and the dispatcher's own setOnVideoFrameCallback merely record the registration: neither starts a reader for a track that is already subscribed. Registering after the subscription event, which is the only time the track name exists, would therefore have silently produced no video. Taking the shared_ptr<Track> straight off the TrackSubscribedEvent sidesteps the name entirely, and lets us pick the camera by TrackSource (streamer-tools publishes cameras as Source.Camera and screenshares separately -- apps/web/src/avatar/ publish.ts), which is what we actually mean. 2. Every stream operation runs on one owned worker thread, never on a room event thread. The SDK documents that Room::disconnect() from inside a delegate callback deadlocks, and Room's own event dispatch holds a mutex, so delegate callbacks only ever enqueue a command here. VideoStream::Options::capacity is set (3 frames) so the SDK's queue is a drop-oldest ring buffer: a stalled consumer can only fall three frames behind, and what it then sees is the newest frame rather than a backlog. That is the structural answer to the stale-media bug that motivated this plugin. The pure decision-making -- the state machine, track selection, frame geometry validation -- lives in session_types.h/.cpp with no LiveKit or OBS types, so it is unit-testable headlessly (81 checks in test_session, including the publisher-swap and reconnect transitions, plus the real connect() failure paths against the real SDK: unreachable host, garbage token, incomplete config, and destruction mid-connect). test_integration_livekit is the test that proves media actually flows. It publishes a synthetic camera and microphone into a real LiveKit room using the same SDK, subscribes through LiveKitSession, and asserts on the exact fields the OBS adapter will dereference. It skips (exit 0) unless STPLUGIN_IT_* is set, so the three build runners stay green; scripts/livekit-dev-room.py mints the tokens for a local `livekit-server --dev`. Verified locally against livekit-server 1.13.6 in dev mode: integration_livekit: 36 video frames, 323 audio frames, 10 state changes integration_livekit: 32 checks passed covering: connect; subscribe to the named participant's camera; 320x240 I420 frames with three planes, non-null plane pointers and strides >= the frame's own width; 48kHz audio; unpublish -> hasVideo() false, state stays Connected (a dark camera is the placeholder state, never an error) and NO further frames arrive from the dead publisher; republish -> video resumes; clean disconnect. One real finding from that run, now handled: WebRTC ramps a new subscription up from a downscaled spatial layer, so the first frames after (re)subscribing legitimately arrive smaller than what is being published. The OBS adapter must cope with a mid-stream resolution change; the test asserts per-frame geometry rather than the publisher's, and separately asserts the stream does reach full size. Full suite: ctest -> 6/6 passed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
bf33966a4e |
Add the streamer-tools API client, with a real HTTP backend per platform
Implements the two read-key-scoped calls in apps/server/src/obs/plugin.routes.ts: GET /api/obs/:slug/slots and POST /api/obs/:slug/token. Three pieces, all in core/ with no OBS dependency: - stplugin::json -- a small, strict JSON reader. Hand-rolled rather than vendoring nlohmann because the only JSON this plugin ever sees is two fixed-shape responses from its own server, and the parser has to build on three platforms with no package-manager step in CI. It never throws, bounds its recursion (kMaxDepth=32) so a hostile response cannot overflow the stack inside OBS, rejects trailing garbage, and returns the caller's fallback for wrong-typed access instead of aborting. - stplugin::HttpClient -- a two-method injectable interface, with libcurl behind it on Linux/macOS and WinHTTP on Windows. WinHTTP rather than curl on Windows because it ships with the OS and does TLS through SChannel: the self-hosted winvm-builder runner has no package manager, and per the scaffold README does not even have cmake preinstalled. Both backends cap the response body at 4 MiB, keep TLS verification on (the read key is a credential), and honour a whole-request timeout. - stplugin::ApiClient -- maps the responses onto an ApiStatus enum that distinguishes NotFound (404), Unavailable (503), NetworkError, MalformedResponse and InvalidConfig. It deliberately does not claim to know whether a 404 was a wrong key or an unknown slug, because the server deliberately does not say. Server URLs are normalised the way an operator actually pastes them, defaulting to https so the read key is never sent in the clear by accident, and redactedUrl() exists so a URL can be logged without the key. Tests (279 checks across two new suites) run at two levels: a fake HttpClient covering every response and error branch, and a real loopback HTTP server on 127.0.0.1 driving the actual platform backend -- so libcurl on Linux/macOS and WinHTTP on Windows are each exercised in CI rather than assumed. The loopback cases deliberately include the ones that must not hang OBS: a truncated JSON body, a connection accepted and closed without a reply, non-HTTP garbage, a dead port, and a stalled server that has to be cut off by the client's own timeout. Verified locally on Ubuntu 24.04: ctest --test-dir build --output-on-failure -> 4/4 passed test_json: 158 checks passed test_api_client: 121 checks passed Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
e595173049 |
Link the pinned LiveKit C++ SDK into the core library
Adds cmake/LiveKitSDK.cmake, adapted from livekit-examples/cpp-example-collection's helper of the same name, with the VERSION="latest" GitHub-API resolution path removed: this project pins an exact client-sdk-cpp release (1.10.1, the newest tag as of today), and the pin should not be silently bypassable. The module also now exports the runtime shared libraries so packaging can stage liblivekit/liblivekit_ffi next to the plugin module later. core/ links LiveKit::livekit PUBLIC. A new smoke test proves the SDK is not just linked but loadable and callable: livekit::initialize()/shutdown() round-trip in-process, a second initialize() reports "already initialized", the log level round-trips, and the SDK's generated LIVEKIT_BUILD_VERSION is asserted equal to the version CMake pinned (so a stale extracted SDK directory fails loudly rather than being silently reused). Also adds core/tests/test_util.h, a dependency-free assertion harness that keeps running after a failure and prints a pass/fail count, so CI output says how much actually ran instead of dying on the first bare assert(). cmake_minimum_required goes 3.16 -> 3.19 (file(ARCHIVE_EXTRACT)). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
304bc3ceba |
ci: install cmake on the Windows runner before configuring
First CI run confirmed winvm-builder is a self-hosted act_runner labeled "windows-latest" but not the GitHub-hosted windows-latest image -- cmake isn't on PATH there (unlike the Linux/macOS runners, which do have working system/brew package managers). Use lukka/get-cmake to fetch a pinned cmake+ninja without needing admin/choco. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
105f1041ab |
Scaffold core/OBS-adapter split, prove CMake toolchain, add 3-platform CI
First pass on the streamer-tools OBS camera plugin: a minimal but real CMake project matching the design doc's core-library/OBS-adapter split (docs/superpowers/specs/2026-09-06-obs-camera-plugin-design.md in the streamer-tools repo). No LiveKit FFI integration yet -- this proves the toolchain works. - core/: dependency-free C++17 library (no OBS dependency), unit tested via CTest with no external test framework. - obs-adapter/: adapted from obsproject/obs-plugintemplate (commit 3e7d7ac, 2025-12-09). Registers a real, stubbed OBS source type; builds as a genuine dynamically-linked OBS module against Ubuntu's system libobs-dev (confirmed via ldd/nm, not a fake stand-in). - Simpler hand-written top-level CMakeLists.txt in place of the template's full buildspec-driven bootstrap (which downloads full OBS source + prebuilt deps) -- find_package(libobs) alone is enough on Linux; falls back to core-library-only when libobs isn't found (expected on macOS/Windows CI for now). - .gitea/workflows/build.yml: 3-platform matrix (ubuntu-latest, macos-latest, windows-latest) matching the runners confirmed available to this repo under the CyberCoveLLC org. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |