From d3a73d47c93e06b9e907a8c22d3c85fef1d8101b Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 4 Jul 2025 20:16:38 -0400 Subject: [PATCH] build: add freebsd support --- .github/workflows/ci-freebsd.yml | 256 ++++++++++++++++++ .github/workflows/ci.yml | 36 ++- CMakeLists.txt | 4 + cmake/compile_definitions/linux.cmake | 9 +- cmake/dependencies/common.cmake | 3 + cmake/packaging/linux.cmake | 24 ++ docs/app_examples.md | 27 ++ docs/building.md | 38 +++ docs/configuration.md | 25 +- docs/getting_started.md | 28 +- src/platform/linux/misc.cpp | 33 ++- src/system_tray.cpp | 2 +- src/video.cpp | 4 +- src/video.h | 2 +- .../common/assets/web/PlatformLayout.vue | 4 + src_assets/common/assets/web/apps.html | 6 +- src_assets/common/assets/web/config.html | 2 +- .../assets/web/configs/tabs/Advanced.vue | 7 + .../assets/web/configs/tabs/AudioVideo.vue | 4 + .../common/assets/web/configs/tabs/Inputs.vue | 8 +- .../tabs/audiovideo/AdapterNameSelector.vue | 10 + .../tabs/audiovideo/DisplayDeviceOptions.vue | 2 + .../tabs/audiovideo/DisplayOutputSelector.vue | 10 + tests/tests_common.h | 6 + tests/unit/test_mouse.cpp | 4 +- tests/unit/test_video.cpp | 2 +- 26 files changed, 527 insertions(+), 29 deletions(-) create mode 100644 .github/workflows/ci-freebsd.yml diff --git a/.github/workflows/ci-freebsd.yml b/.github/workflows/ci-freebsd.yml new file mode 100644 index 00000000..158fae39 --- /dev/null +++ b/.github/workflows/ci-freebsd.yml @@ -0,0 +1,256 @@ +--- +name: CI-FreeBSD +permissions: + contents: read + +on: + workflow_call: + inputs: + release_commit: + required: true + type: string + release_version: + required: true + type: string + +env: + FREEBSD_CLANG_VERSION: 19 + +jobs: + setup-matrix: + name: Setup Build Matrix + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.generate-matrix.outputs.matrix }} + steps: + - name: Generate Matrix + id: generate-matrix + shell: bash + run: | + # Base matrix with amd64 build + matrix='{ + "include": [ + { + "bsd_release": "14.3", + "arch": "x86_64", + "cmake_processor": "amd64", + "runner": "ubuntu-latest" + } + ] + }' + + # Add aarch64 build only if not a pull request event + if [[ "${{ github.event_name }}" != "pull_request" ]]; then + matrix=$(echo "$matrix" | jq '.include += [{ + "bsd_release": "14.3", + "arch": "aarch64", + "cmake_processor": "aarch64", + "runner": "ubuntu-latest" + }]') + fi + + # Use heredoc for multiline JSON output + { + echo "matrix<> "${GITHUB_OUTPUT}" + + echo "Generated matrix:" + echo "$matrix" | jq . + + build_freebsd: + name: ${{ matrix.cmake_processor }}-${{ matrix.bsd_release }} + runs-on: ubuntu-latest + needs: setup-matrix + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.setup-matrix.outputs.matrix) }} + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + submodules: recursive + + - name: Get Processor Count + id: processor_count + shell: bash + run: | + PROCESSOR_COUNT=$(nproc) + echo "PROCESSOR_COUNT=${PROCESSOR_COUNT}" >> "${GITHUB_OUTPUT}" + echo "PROCESSOR_COUNT: $PROCESSOR_COUNT" + + - name: Setup FreeBSD + uses: vmactions/freebsd-vm@v1.2.3 + with: + arch: ${{ matrix.arch }} + cpu: ${{ steps.processor_count.outputs.PROCESSOR_COUNT }} + # TODO: there is no libcap for freebsd... we need graphics/libdrm if we find a way to use libcap + # TODO: docs are off because doxygen is too old: https://www.freshports.org/devel/doxygen/ must be >= 1.10 + prepare: | + set -e + + pkg update + pkg upgrade -y + pkg install -y \ + audio/opus \ + audio/pulseaudio \ + devel/cmake-core \ + devel/evdev-proto \ + devel/git \ + devel/libayatana-appindicator \ + devel/libevdev \ + devel/libnotify \ + devel/llvm${{ env.FREEBSD_CLANG_VERSION }} \ + devel/ninja \ + devel/pkgconf \ + ftp/curl \ + graphics/libdrm \ + graphics/wayland \ + lang/python312 \ + multimedia/libva \ + net/miniupnpc \ + ports-mgmt/pkg \ + security/openssl \ + shells/bash \ + www/npm \ + x11/libX11 \ + x11/libxcb \ + x11/libXfixes \ + x11/libXrandr \ + x11/libXtst \ + x11-servers/xorg-server + + # create symlink for shebang bash compatibility + ln -s /usr/local/bin/bash /bin/bash + + # setup python + ln -s /usr/local/bin/python3.12 /usr/local/bin/python + python -m ensurepip + release: ${{ matrix.bsd_release }} + run: | + set -e + # install gcvor + python -m pip install gcovr + + # fix git safe.directory issues + git config --global --add safe.directory "*" + sync: nfs + + - name: Configure + env: + BRANCH: ${{ github.head_ref || github.ref_name }} + BUILD_VERSION: ${{ inputs.release_version }} + COMMIT: ${{ inputs.release_commit }} + shell: freebsd {0} + run: | + set -e + cd "${GITHUB_WORKSPACE}" + + export BRANCH="${BRANCH}" + export BUILD_VERSION="${BUILD_VERSION}" + export COMMIT="${COMMIT}" + + cc_path="$(which clang${{ env.FREEBSD_CLANG_VERSION }})" + cxx_path="$(which clang++${{ env.FREEBSD_CLANG_VERSION }})" + + export CC="${cc_path}" + export CXX="${cxx_path}" + + mkdir -p build + cmake \ + -B build \ + -G Ninja \ + -S . \ + -DBUILD_DOCS=OFF \ + -DBUILD_WERROR=OFF \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr/local \ + -DSUNSHINE_ASSETS_DIR=share/assets \ + -DSUNSHINE_EXECUTABLE_PATH=/usr/local/bin/sunshine \ + -DSUNSHINE_ENABLE_CUDA=OFF \ + -DSUNSHINE_ENABLE_DRM=OFF \ + -DSUNSHINE_ENABLE_WAYLAND=ON \ + -DSUNSHINE_ENABLE_X11=ON \ + -DSUNSHINE_PUBLISHER_NAME='${{ github.repository_owner }}' \ + -DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' \ + -DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support' + + - name: Build + shell: freebsd {0} + run: | + set -e + cd "${GITHUB_WORKSPACE}" + ninja -C build + + - name: Package + shell: freebsd {0} + run: | + set -e + cd "${GITHUB_WORKSPACE}" + + mkdir -p artifacts + + cd build + cpack -G FREEBSD + + # move compiled files to artifacts + mv ./cpack_artifacts/Sunshine.pkg \ + ../artifacts/Sunshine-FreeBSD-${{ matrix.bsd_release }}-${{ matrix.cmake_processor }}.pkg + + - name: Debug +MANIFEST + if: always() + shell: bash + working-directory: build/cpack_artifacts + run: cat ./_CPack_Packages/FreeBSD/FREEBSD/Sunshine/+MANIFEST + + - name: Test + id: test + shell: freebsd {0} + run: | + set -e + cd "${GITHUB_WORKSPACE}/build/tests" + + export DISPLAY=:1 + Xvfb ${DISPLAY} -screen 0 1024x768x24 & + XVFB_PID=$! + + ./test_sunshine --gtest_color=yes --gtest_output=xml:test_results.xml + + kill ${XVFB_PID} + + - name: Generate gcov report + id: test_report + # any except canceled or skipped + if: >- + always() && + (steps.test.outcome == 'success' || steps.test.outcome == 'failure') + shell: freebsd {0} + run: | + cd "${GITHUB_WORKSPACE}/build" + python -m gcovr . -r ../src \ + --exclude-noncode-lines \ + --exclude-throw-branches \ + --exclude-unreachable-branches \ + --verbose \ + --xml-pretty \ + -o coverage.xml + + - name: Upload coverage artifact + if: >- + always() && + (steps.test_report.outcome == 'success') + uses: actions/upload-artifact@v4 + with: + name: coverage-FreeBSD-${{ matrix.bsd_release }}-${{ matrix.cmake_processor }} + path: | + build/coverage.xml + build/tests/test_results.xml + if-no-files-found: error + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: build-FreeBSD-${{ matrix.bsd_release }}-${{ matrix.cmake_processor }} + path: artifacts/ + if-no-files-found: error diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cad98f64..b6b74daf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,6 +69,14 @@ jobs: GH_BOT_TOKEN: ${{ secrets.GH_BOT_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + build-freebsd: + name: FreeBSD + needs: release-setup + uses: ./.github/workflows/ci-freebsd.yml + with: + release_commit: ${{ needs.release-setup.outputs.release_commit }} + release_version: ${{ needs.release-setup.outputs.release_version }} + build-homebrew: name: Homebrew needs: release-setup @@ -128,6 +136,7 @@ jobs: !cancelled() && startsWith(github.repository, 'LizardByte/') needs: + - build-freebsd - build-linux - build-linux-flatpak - build-homebrew @@ -137,29 +146,53 @@ jobs: fail-fast: false matrix: include: + - name: FreeBSD-14.3-amd64 + coverage: true + pr: true + - name: FreeBSD-14.3-aarch64 + coverage: true + pr: false - name: Linux-AppImage coverage: true + pr: true - name: Homebrew-macos-14 coverage: false + pr: true - name: Homebrew-macos-15 coverage: false + pr: true - name: Homebrew-macos-26 coverage: false + pr: true - name: Homebrew-ubuntu-latest coverage: false + pr: true - name: Windows-AMD64 coverage: true + pr: true steps: + - name: Should run + id: should_run + run: | + if [ ${{ github.event_name }} != 'pull_request' ] || [ ${{ matrix.pr }} == 'true' ]; then + echo "SHOULD_RUN=true" >> "${GITHUB_OUTPUT}" + else + echo "SHOULD_RUN=false" >> "${GITHUB_OUTPUT}" + fi + - name: Checkout + if: steps.should_run.outputs.SHOULD_RUN == 'true' uses: actions/checkout@v5 - name: Download coverage artifact + if: steps.should_run.outputs.SHOULD_RUN == 'true' uses: actions/download-artifact@v5 with: name: coverage-${{ matrix.name }} path: _coverage - name: Upload test results + if: steps.should_run.outputs.SHOULD_RUN == 'true' uses: codecov/test-results-action@v1 with: disable_search: true @@ -170,8 +203,8 @@ jobs: verbose: true - name: Upload coverage + if: steps.should_run.outputs.SHOULD_RUN == 'true' && matrix.coverage != false uses: codecov/codecov-action@v5 - if: matrix.coverage != false with: disable_search: true fail_ci_if_error: true @@ -188,6 +221,7 @@ jobs: needs: - release-setup - build-docker + - build-freebsd - build-linux - build-linux-flatpak - build-homebrew diff --git a/CMakeLists.txt b/CMakeLists.txt index 5cedee55..08c0b1ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,10 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE) endif() +if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + set(FREEBSD ON) +endif() + # set the module path, used for includes set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") diff --git a/cmake/compile_definitions/linux.cmake b/cmake/compile_definitions/linux.cmake index e4ed683f..6f98c355 100644 --- a/cmake/compile_definitions/linux.cmake +++ b/cmake/compile_definitions/linux.cmake @@ -1,6 +1,10 @@ # linux specific compile definitions -add_compile_definitions(SUNSHINE_PLATFORM="linux") +if(FREEBSD) + add_compile_definitions(SUNSHINE_PLATFORM="freebsd") +else() + add_compile_definitions(SUNSHINE_PLATFORM="linux") +endif() # AppImage if(${SUNSHINE_BUILD_APPIMAGE}) @@ -211,6 +215,9 @@ endif() # These need to be set before adding the inputtino subdirectory in order for them to be picked up set(LIBEVDEV_CUSTOM_INCLUDE_DIR "${EVDEV_INCLUDE_DIR}") set(LIBEVDEV_CUSTOM_LIBRARY "${EVDEV_LIBRARY}") +if(FREEBSD) + set(USE_UHID OFF) +endif() add_subdirectory("${CMAKE_SOURCE_DIR}/third-party/inputtino") list(APPEND SUNSHINE_EXTERNAL_LIBRARIES inputtino::libinputtino) diff --git a/cmake/dependencies/common.cmake b/cmake/dependencies/common.cmake index 97319be6..24a80883 100644 --- a/cmake/dependencies/common.cmake +++ b/cmake/dependencies/common.cmake @@ -30,6 +30,9 @@ include_directories(SYSTEM ${MINIUPNP_INCLUDE_DIRS}) if(NOT DEFINED FFMPEG_PREPARED_BINARIES) if(WIN32) set(FFMPEG_PLATFORM_LIBRARIES mfplat ole32 strmiids mfuuid vpl) + elseif(FREEBSD) + # numa is not available on FreeBSD + set(FFMPEG_PLATFORM_LIBRARIES va va-drm va-x11 X11) elseif(UNIX AND NOT APPLE) set(FFMPEG_PLATFORM_LIBRARIES numa va va-drm va-x11 X11) endif() diff --git a/cmake/packaging/linux.cmake b/cmake/packaging/linux.cmake index cd8e706e..e5db9625 100644 --- a/cmake/packaging/linux.cmake +++ b/cmake/packaging/linux.cmake @@ -34,6 +34,14 @@ else() endif() endif() +# RPM specific +set(CPACK_RPM_PACKAGE_LICENSE "GPLv3") + +# FreeBSD specific +set(CPACK_FREEBSD_PACKAGE_MAINTAINER "${CPACK_PACKAGE_VENDOR}") +set(CPACK_FREEBSD_PACKAGE_ORIGIN "misc/${CPACK_PACKAGE_NAME}") +set(CPACK_FREEBSD_PACKAGE_LICENSE "GPLv3") + # Post install set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/postinst") set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/postinst") @@ -77,6 +85,15 @@ set(CPACK_RPM_PACKAGE_REQUIRES "\ openssl >= 3.0.2, \ pulseaudio-libs >= 10.0, \ which >= 2.21") +list(APPEND CPACK_FREEBSD_PACKAGE_DEPS + audio/opus + ftp/curl + devel/libevdev + net/avahi + x11/libX11 + net/miniupnpc + security/openssl +) if(NOT BOOST_USE_STATIC) set(CPACK_DEBIAN_PACKAGE_DEPENDS "\ @@ -91,6 +108,9 @@ if(NOT BOOST_USE_STATIC) boost-locale >= ${Boost_VERSION}, \ boost-log >= ${Boost_VERSION}, \ boost-program-options >= ${Boost_VERSION}") + list(APPEND CPACK_FREEBSD_PACKAGE_DEPS + devel/boost-libs + ) endif() # This should automatically figure out dependencies, doesn't work with the current config @@ -141,6 +161,10 @@ if(${SUNSHINE_TRAY} STREQUAL 1) set(CPACK_RPM_PACKAGE_REQUIRES "\ ${CPACK_RPM_PACKAGE_REQUIRES}, \ libappindicator-gtk3 >= 12.10.0") + list(APPEND CPACK_FREEBSD_PACKAGE_DEPS + devel/libayatana-appindicator + devel/libnotify + ) endif() # desktop file diff --git a/docs/app_examples.md b/docs/app_examples.md index 85f70337..e6e251b6 100644 --- a/docs/app_examples.md +++ b/docs/app_examples.md @@ -26,6 +26,14 @@ and applications to Sunshine. > process is killed. @tabs{ + @tab{FreeBSD | + \| Field \| Value \| + \|------------------------------\|------------------------------------------------------\| + \| Application Name \| @code{}Steam Big Picture@endcode \| + \| Command Preporations -> Undo \| @code{}setsid steam steam://close/bigpicture@endcode \| + \| Detached Commands \| @code{}setsid steam steam://open/bigpicture@endcode \| + \| Image \| @code{}steam.png@endcode \| + } @tab{Linux | \| Field \| Value \| \|------------------------------\|------------------------------------------------------\| @@ -97,6 +105,12 @@ and applications to Sunshine. #### URI @tabs{ + @tab{FreeBSD | + \| Field \| Value \| + \|-------------------\|------------------------------------------------------\| + \| Application Name \| @code{}Surviving Mars@endcode \| + \| Detached Commands \| @code{}setsid steam steam://rungameid/464920@endcode \| + } @tab{Linux | \| Field \| Value \| \|-------------------\|------------------------------------------------------\| @@ -119,6 +133,13 @@ and applications to Sunshine. #### Binary (w/ working directory @tabs{ + @tab{FreeBSD | + \| Field \| Value \| + \|-------------------\|--------------------------------------------------------------\| + \| Application Name \| @code{}Surviving Mars@endcode \| + \| Command \| @code{}MarsSteam@endcode \| + \| Working Directory \| @code{}~/.steam/steam/SteamApps/common/Survivng Mars@endcode \| + } @tab{Linux | \| Field \| Value \| \|-------------------\|--------------------------------------------------------------\| @@ -144,6 +165,12 @@ and applications to Sunshine. #### Binary (w/o working directory) @tabs{ + @tab{FreeBSD | + \| Field \| Value \| + \|-------------------\|------------------------------------------------------------------------\| + \| Application Name \| @code{}Surviving Mars@endcode \| + \| Command \| @code{}~/.steam/steam/SteamApps/common/Survivng Mars/MarsSteam@endcode \| + } @tab{Linux | \| Field \| Value \| \|-------------------\|------------------------------------------------------------------------\| diff --git a/docs/building.md b/docs/building.md index 5a176622..56febbce 100644 --- a/docs/building.md +++ b/docs/building.md @@ -14,6 +14,39 @@ It is recommended to use one of the following compilers: ### Dependencies +#### FreeBSD +> [!CAUTION] +> Sunshine support for FreeBSD is experimental and may be incomplete or not work as expected + +##### Install dependencies +```sh +pkg install -y \ + audio/opus \ + audio/pulseaudio \ + devel/cmake \ + devel/evdev-proto \ + devel/git \ + devel/libayatana-appindicator \ + devel/libevdev \ + devel/libnotify \ + devel/ninja \ + devel/pkgconf \ + ftp/curl \ + graphics/libdrm \ + graphics/wayland \ + multimedia/libva \ + net/miniupnpc \ + ports-mgmt/pkg \ + security/openssl \ + shells/bash \ + www/npm \ + x11/libX11 \ + x11/libxcb \ + x11/libXfixes \ + x11/libXrandr \ + x11/libXtst +``` + #### Linux Dependencies vary depending on the distribution. You can reference our [linux_build.sh](https://github.com/LizardByte/Sunshine/blob/master/scripts/linux_build.sh) script for a list of @@ -135,6 +168,11 @@ ninja -C build ### Package @tabs{ + @tab{FreeBSD | @tabs{ + @tab{pkg | ```bash + cpack -G FREEBSD --config ./build/CPackConfig.cmake + ```} + }} @tab{Linux | @tabs{ @tab{deb | ```bash cpack -G DEB --config ./build/CPackConfig.cmake diff --git a/docs/configuration.md b/docs/configuration.md index 2264aa8d..d060c4e0 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -26,6 +26,7 @@ location by modifying the configuration file. | OS | Location | |---------|-------------------------------------------------| | Docker | @code{}/config@endcode | +| FreeBSD | @code{}~/.config/sunshine@endcode | | Linux | @code{}~/.config/sunshine@endcode | | macOS | @code{}~/.config/sunshine@endcode | | Windows | @code{}%ProgramFiles%\\Sunshine\\config@endcode | @@ -339,12 +340,12 @@ editing the `conf` file in a text editor. Use the examples as reference. ds5 DualShock 5 controller (PS5) - @note{This option applies to Linux only.} + @note{This option applies to FreeBSD and Linux only.} switch Switch Pro controller - @note{This option applies to Linux only.} + @note{This option applies to FreeBSD and Linux only.} x360 @@ -354,7 +355,7 @@ editing the `conf` file in a text editor. Use the examples as reference. xone Xbox One controller - @note{This option applies to Linux only.} + @note{This option applies to FreeBSD and Linux only.} @@ -735,14 +736,14 @@ editing the `conf` file in a text editor. Use the examples as reference. @tip{To find the name of the audio sink follow these instructions.

- **Linux + pulseaudio:** + **FreeBSD/Linux + pulseaudio:**
@code{} pacmd list-sinks | grep "name:" @endcode

- **Linux + pipewire:** + **FreeBSD/Linux + pipewire:**
@code{} pactl info | grep Source @@ -776,7 +777,7 @@ editing the `conf` file in a text editor. Use the examples as reference. Sunshine will select the default audio device. - Example (Linux) + Example (FreeBSD/Linux) @code{} audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo @endcode @@ -883,7 +884,7 @@ editing the `conf` file in a text editor. Use the examples as reference. @tip{To find the appropriate values follow these instructions.

- **Linux + VA-API:** + **FreeBSD/Linux + VA-API:**
Unlike with *amdvce* and *nvenc*, it doesn't matter if video encoding is done on a different GPU. @code{} @@ -913,7 +914,7 @@ editing the `conf` file in a text editor. Use the examples as reference. Sunshine will select the default video card. - Example (Linux) + Example (FreeBSD/Linux) @code{} adapter_name = /dev/dri/renderD128 @endcode @@ -936,7 +937,7 @@ editing the `conf` file in a text editor. Use the examples as reference. @tip{To find the appropriate values follow these instructions.

- **Linux:** + **FreeBSD/Linux:**
During Sunshine startup, you should see the list of detected displays: @code{} @@ -1021,7 +1022,7 @@ editing the `conf` file in a text editor. Use the examples as reference. Sunshine will select the default display. - Example (Linux) + Example (FreeBSD/Linux) @code{} output_name = 0 @endcode @@ -2034,7 +2035,7 @@ editing the `conf` file in a text editor. Use the examples as reference. x11 Uses XCB. This is the slowest and most CPU intensive so should be avoided if possible. - @note{Applies to Linux only.} + @note{Applies to FreeBSD and Linux only.} ddx @@ -2083,7 +2084,7 @@ editing the `conf` file in a text editor. Use the examples as reference. vaapi - Use Linux VA-API (AMD, Intel) + Use VA-API (AMD, Intel) software diff --git a/docs/getting_started.md b/docs/getting_started.md index 1aba10b0..6abf8cd8 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -8,7 +8,7 @@ and release artifacts may be missing when merging changes on a faster cadence. ## Binaries -Binaries of Sunshine are created for each release. They are available for Linux, macOS, and Windows. +Binaries of Sunshine are created for each release. They are available for FreeBSD, Linux, macOS, and Windows. Binaries can be found in the [latest release][latest-release]. > [!NOTE] @@ -28,7 +28,27 @@ and [ghcr.io](https://github.com/orgs/LizardByte/packages?repo_name=sunshine). See [Docker](../DOCKER_README.md) for more information. +### FreeBSD + +#### Install +1. Download the appropriate package for your architecture + + | Architecture | Package | + |---------------|----------------------------------------------------------------------------------------------------------------------------------------| + | amd64/x86_64 | [Sunshine-FreeBSD-14.3-amd64.pkg](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-FreeBSD-14.3-amd64.pkg) | + | arm64/aarch64 | [Sunshine-FreeBSD-14.3-aarch64.pkg](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-FreeBSD-14.3-aarch64.pkg) | + +2. Open terminal and run the following command. + ```sh + sudo pkg install ./Sunshine-FreeBSD-14.3-{arch}.pkg + ``` +##### Uninstall +```sh +sudo pkg delete Sunshine +``` + ### Linux + **CUDA Compatibility** CUDA is used for NVFBC capture. @@ -522,6 +542,12 @@ All shortcuts start with `Ctrl+Alt+Shift`, just like Moonlight. * The "Desktop" app works the same as any other application except it has no commands. It does not start an application, instead it simply starts a stream. If you removed it and would like to get it back, just add a new application with the name "Desktop" and "desktop.png" as the image path. +* The FreeBSD version of Sunshine is missing some features that are present on Linux. + The following are known limitations. + + * Only X11 and Wayland capture are supported + * DualSense5 emulation is limited due to missing uhid features + * For the Linux flatpak you must prepend commands with `flatpak-spawn --host`. * If inputs (mouse, keyboard, gamepads...) aren't working after connecting, add the user running sunshine to the `input` group. diff --git a/src/platform/linux/misc.cpp b/src/platform/linux/misc.cpp index 9da87337..891fad42 100644 --- a/src/platform/linux/misc.cpp +++ b/src/platform/linux/misc.cpp @@ -35,6 +35,30 @@ #include "src/platform/common.h" #include "vaapi.h" +#ifdef __FreeBSD__ + #include + #include + // Define constants that are missing in FreeBSD + #ifndef IP_PKTINFO // packet info for IPv4 + #define IP_PKTINFO IP_RECVDSTADDR + #endif + #ifndef SOL_IP // socket level for IPv4 + #define SOL_IP IPPROTO_IP + #endif + #ifndef SOL_IPV6 // socket level for IPv6 + #define SOL_IPV6 IPPROTO_IPV6 + #endif + #ifndef SO_PRIORITY // socket option for priority, disabled for FreeBSD + #define SO_PRIORITY -1 + #endif +// Define in_pktinfo structure for IPv4 packet info +struct in_pktinfo { + struct in_addr ipi_addr; + struct in_addr ipi_spec_dst; + int ipi_ifindex; +}; +#endif + #ifdef __GNUC__ #define SUNSHINE_GNUC_EXTENSION __extension__ #else @@ -507,8 +531,8 @@ namespace platf { { // If GSO is not supported, use sendmmsg() instead. - struct mmsghdr msgs[send_info.block_count]; - struct iovec iovs[send_info.block_count * (send_info.headers ? 2 : 1)]; + std::vector msgs(send_info.block_count); + std::vector iovs(send_info.block_count * (send_info.headers ? 2 : 1)); int iov_idx = 0; for (size_t i = 0; i < send_info.block_count; i++) { msgs[i].msg_len = 0; @@ -753,6 +777,10 @@ namespace platf { // reset SO_PRIORITY back to 0. // // 6 is the highest priority that can be used without SYS_CAP_ADMIN. +#ifdef __FreeBSD__ + // FreeBSD doesn't support SO_PRIORITY, so we skip this + BOOST_LOG(debug) << "SO_PRIORITY not supported on FreeBSD, skipping traffic priority setting"; +#else int priority = data_type == qos_data_type_e::audio ? 6 : 5; if (setsockopt(sockfd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) == 0) { // Reset SO_PRIORITY to 0 when QoS is disabled @@ -760,6 +788,7 @@ namespace platf { } else { BOOST_LOG(error) << "Failed to set SO_PRIORITY: "sv << errno; } +#endif return std::make_unique(sockfd, reset_options); } diff --git a/src/system_tray.cpp b/src/system_tray.cpp index 81248356..e2bfa239 100644 --- a/src/system_tray.cpp +++ b/src/system_tray.cpp @@ -13,7 +13,7 @@ #define TRAY_ICON_PLAYING WEB_DIR "images/sunshine-playing.ico" #define TRAY_ICON_PAUSING WEB_DIR "images/sunshine-pausing.ico" #define TRAY_ICON_LOCKED WEB_DIR "images/sunshine-locked.ico" - #elif defined(__linux__) || defined(linux) || defined(__linux) + #elif defined(__linux__) || defined(linux) || defined(__linux) || defined(__FreeBSD__) #define TRAY_ICON SUNSHINE_TRAY_PREFIX "-tray" #define TRAY_ICON_PLAYING SUNSHINE_TRAY_PREFIX "-playing" #define TRAY_ICON_PAUSING SUNSHINE_TRAY_PREFIX "-pausing" diff --git a/src/video.cpp b/src/video.cpp index 8f6b69c4..8030c7f8 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -897,7 +897,7 @@ namespace video { H264_ONLY | PARALLEL_ENCODING | ALWAYS_REPROBE | YUV444_SUPPORT }; -#ifdef __linux__ +#if defined(__linux__) || defined(linux) || defined(__linux) || defined(__FreeBSD__) encoder_t vaapi { "vaapi"sv, std::make_unique( @@ -1032,7 +1032,7 @@ namespace video { &quicksync, &amdvce, #endif -#ifdef __linux__ +#if defined(__linux__) || defined(linux) || defined(__linux) || defined(__FreeBSD__) &vaapi, #endif #ifdef __APPLE__ diff --git a/src/video.h b/src/video.h index a966c53e..43119fc9 100644 --- a/src/video.h +++ b/src/video.h @@ -221,7 +221,7 @@ namespace video { extern encoder_t quicksync; #endif -#ifdef __linux__ +#if defined(__linux__) || defined(linux) || defined(__linux) || defined(__FreeBSD__) extern encoder_t vaapi; #endif diff --git a/src_assets/common/assets/web/PlatformLayout.vue b/src_assets/common/assets/web/PlatformLayout.vue index 31064fec..49cbacc0 100644 --- a/src_assets/common/assets/web/PlatformLayout.vue +++ b/src_assets/common/assets/web/PlatformLayout.vue @@ -12,6 +12,10 @@ const props = defineProps({ + + diff --git a/src_assets/common/assets/web/apps.html b/src_assets/common/assets/web/apps.html index 8b0cb517..e1f7c83d 100644 --- a/src_assets/common/assets/web/apps.html +++ b/src_assets/common/assets/web/apps.html @@ -331,7 +331,7 @@
{{ $t('apps.env_qres_example') }}
cmd /C <{{ $t('apps.env_qres_path') }}>\QRes.exe /X:%SUNSHINE_CLIENT_WIDTH% /Y:%SUNSHINE_CLIENT_HEIGHT% /R:%SUNSHINE_CLIENT_FPS%
-
{{ $t('apps.env_xrandr_example') }} +
{{ $t('apps.env_xrandr_example') }}
sh -c "xrandr --output HDMI-1 --mode \"${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}\" --rate ${SUNSHINE_CLIENT_FPS}"
{{ $t('apps.env_displayplacer_example') }} @@ -442,8 +442,8 @@ if (resp) { fetch("./api/apps/" + id, { method: "DELETE", - headers: { - "Content-Type": "application/json" + headers: { + "Content-Type": "application/json" }, }).then((r) => { if (r.status === 200) document.location.reload(); diff --git a/src_assets/common/assets/web/config.html b/src_assets/common/assets/web/config.html index 62a37906..887062d6 100644 --- a/src_assets/common/assets/web/config.html +++ b/src_assets/common/assets/web/config.html @@ -305,7 +305,7 @@ return el.id !== "vt" && el.id !== "vaapi"; }); } - if (this.platform === "linux") { + if (this.platform === "freebsd" || this.platform === "linux") { this.tabs = this.tabs.filter((el) => { return el.id !== "amd" && el.id !== "qsv" && el.id !== "vt"; }); diff --git a/src_assets/common/assets/web/configs/tabs/Advanced.vue b/src_assets/common/assets/web/configs/tabs/Advanced.vue index bd11adf2..37191c7e 100644 --- a/src_assets/common/assets/web/configs/tabs/Advanced.vue +++ b/src_assets/common/assets/web/configs/tabs/Advanced.vue @@ -64,6 +64,10 @@ const config = ref(props.config)