# streamer-tools OBS Camera Plugin - OBS adapter # # Thin glue only, per the design doc: source registration, the properties UI, # and pushing frames into OBS. All real logic lives in ../core. Only added to # the build when find_package(libobs) succeeds (see top-level CMakeLists.txt). set(STPLUGIN_PROJECT_NAME "streamer-tools-camera") set(STPLUGIN_PROJECT_VERSION "${PROJECT_VERSION}") configure_file( src/plugin-support.c.in ${CMAKE_CURRENT_BINARY_DIR}/plugin-support.c @ONLY ) add_library(${STPLUGIN_PROJECT_NAME} MODULE src/plugin-main.cpp ${CMAKE_CURRENT_BINARY_DIR}/plugin-support.c ) target_include_directories(${STPLUGIN_PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR} ) target_link_libraries(${STPLUGIN_PROJECT_NAME} PRIVATE OBS::libobs stplugin_core ) set_target_properties(${STPLUGIN_PROJECT_NAME} PROPERTIES PREFIX "" OUTPUT_NAME ${STPLUGIN_PROJECT_NAME} ) # The module has to find liblivekit / liblivekit_ffi next to itself once it is # installed into an OBS plugin directory, not at the build-tree path CMake's # default RPATH would bake in. # BUILD_WITH_INSTALL_RPATH is ON deliberately: the artifact that ships is a # straight copy of the built module (see the staging step below), so the # build-tree RPATH must never be baked in -- it would work on the build # machine and nowhere else. # # APPLE's rpath (and its whole bundle shape) is handled by # stplugin_macos_finalize_bundle() below instead -- a bundle needs two # rpaths (its own Contents/Frameworks *and* the host OBS.app's # Contents/Frameworks for libobs.framework), not the single flat # "@loader_path" this used to set back when macOS staged a bare .so. See # cmake/macos/helpers.cmake. if(UNIX AND NOT APPLE) set_target_properties(${STPLUGIN_PROJECT_NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH ON INSTALL_RPATH "$ORIGIN" ) endif() # --- macOS: turn the flat MODULE library into a real OBS.app-loadable # .plugin bundle (Contents/MacOS, Contents/Resources, Info.plist, # Contents/Frameworks for the bundled LiveKit dylibs, and the libobs # @rpath fixup). Closes the "macOS packaging gap" in README.md. Must run # before the staging step below, which copies the finished bundle directory # -- add_custom_command(POST_BUILD) commands attached to the same target run # in the order they were registered. if(APPLE) include(helpers) stplugin_macos_finalize_bundle(${STPLUGIN_PROJECT_NAME}) endif() # --- staged, runnable layout ------------------------------------------------ # Everything a human needs to copy into an OBS plugin directory ends up under # build/package/, with the LiveKit shared libraries and the licence files # beside the module. Without this the module loads on the build machine only, # via the build-tree RPATH. set(STPLUGIN_PACKAGE_DIR "${CMAKE_BINARY_DIR}/package") # The binary subdirectory matches what OBS actually searches. From # AddExtraModulePaths() in obs-studio's UI/window-basic-main.cpp, the # per-user plugin layout on Linux and Windows is # /obs-studio/plugins//bin/64bit/.{so,dll} # /obs-studio/plugins//data/ # so staging into bin/64bit makes build/package/ a straight drop-in. # # macOS is a COMPLETELY different shape, not just "bin without 64bit": the # same AddExtraModulePaths() passes GetConfigPath(..., # "obs-studio/plugins/%module%.plugin") as the base, then # obs_add_module_path(base + "/Contents/MacOS", base + "/Contents/Resources") # -- i.e. OBS wants the ENTIRE .plugin bundle dropped directly into # .../obs-studio/plugins/, not nested under a bin/ subdirectory the way # Linux/Windows are. So build/package/ on macOS holds the bundle itself at # its top level (build/package/.plugin), not build/package/bin/.... # stplugin_macos_finalize_bundle() (cmake/macos/helpers.cmake) makes # ${STPLUGIN_PROJECT_NAME} an actual BUNDLE target for APPLE and also copies # obs-adapter/data/** into Contents/Resources/** -- see that file for why # Contents/Resources (not a sibling data/) is where OBS looks for this # module's data on macOS. if(APPLE) add_custom_command(TARGET ${STPLUGIN_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${STPLUGIN_PACKAGE_DIR}" COMMAND ${CMAKE_COMMAND} -E rm -rf "${STPLUGIN_PACKAGE_DIR}/${STPLUGIN_PROJECT_NAME}.plugin" COMMAND ${CMAKE_COMMAND} -E copy_directory "$" "${STPLUGIN_PACKAGE_DIR}/${STPLUGIN_PROJECT_NAME}.plugin" COMMENT "Staging the ${STPLUGIN_PROJECT_NAME}.plugin bundle into ${STPLUGIN_PACKAGE_DIR}" VERBATIM ) else() set(STPLUGIN_PACKAGE_BIN_DIR "${STPLUGIN_PACKAGE_DIR}/bin/64bit") add_custom_command(TARGET ${STPLUGIN_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${STPLUGIN_PACKAGE_BIN_DIR}" COMMAND ${CMAKE_COMMAND} -E copy "$" "${STPLUGIN_PACKAGE_BIN_DIR}/" COMMAND ${CMAKE_COMMAND} -E copy ${LIVEKIT_SDK_RUNTIME_LIBS} "${STPLUGIN_PACKAGE_BIN_DIR}/" COMMAND ${CMAKE_COMMAND} -E make_directory "${STPLUGIN_PACKAGE_DIR}/data/locale" COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/data/locale/en-US.ini" "${STPLUGIN_PACKAGE_DIR}/data/locale/" COMMENT "Staging plugin + LiveKit runtime libraries + locale data into ${STPLUGIN_PACKAGE_DIR}" VERBATIM ) endif() # Licence files: not something OBS's module loader looks for at all (unlike # the locale data above), so these always land in the same top-level spot # regardless of platform -- next to the bundle on macOS, next to bin/ on # Linux/Windows. Redistributing LiveKit's prebuilt binaries means shipping # their licence and notice with them; see third_party/livekit/README.md, # including what upstream does NOT ship, which is an open question, not a # solved one. add_custom_command(TARGET ${STPLUGIN_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${STPLUGIN_PACKAGE_DIR}/licenses/livekit" COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/third_party/livekit/LICENSE" "${CMAKE_SOURCE_DIR}/third_party/livekit/NOTICE" "${CMAKE_SOURCE_DIR}/third_party/livekit/README.md" "${STPLUGIN_PACKAGE_DIR}/licenses/livekit/" COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/LICENSE" "${STPLUGIN_PACKAGE_DIR}/licenses/" COMMENT "Staging licences into ${STPLUGIN_PACKAGE_DIR}" VERBATIM )