diff --git a/.clang-format b/.clang-format index 6944ec3eb08..9f868d756b0 100644 --- a/.clang-format +++ b/.clang-format @@ -1,3 +1,4 @@ +--- # This file is centrally managed in https://github.com//.github/ # Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in # the above-mentioned repo. @@ -6,7 +7,7 @@ BasedOnStyle: LLVM AccessModifierOffset: -2 AlignAfterOpenBracket: DontAlign -AlignConsecutiveAssignments: true +AlignConsecutiveAssignments: Consecutive AlignOperands: Align AllowAllArgumentsOnNextLine: false AllowAllConstructorInitializersOnNextLine: false @@ -14,7 +15,7 @@ AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: Always AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Always +AllowShortIfStatementsOnASingleLine: WithoutElse AllowShortLambdasOnASingleLine: All AllowShortLoopsOnASingleLine: true AlwaysBreakAfterReturnType: None @@ -62,7 +63,7 @@ SpaceBeforeParens: Never SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 -SpacesInAngles: false +SpacesInAngles: Never SpacesInCStyleCastParentheses: false SpacesInContainerLiterals: false SpacesInParentheses: false diff --git a/.docker_platforms b/.docker_platforms new file mode 100644 index 00000000000..11a8121d9e8 --- /dev/null +++ b/.docker_platforms @@ -0,0 +1 @@ +linux/amd64 \ No newline at end of file diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000000..fb14701dd6a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +# ignore git files +.git* + +# ignore hidden files +.* + +# ignore repo directories and files +docs/ +packaging/ +scripts/ +tools/ +crowdin.yml + +# ignore dev directories +build/ +venv/ diff --git a/.flake8 b/.flake8 index 2ea739519c1..2d028b2dbc1 100644 --- a/.flake8 +++ b/.flake8 @@ -1,6 +1,7 @@ [flake8] filename = - *.py + *.py, + *.pys max-line-length = 120 extend-exclude = venv/ diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index bd21df2945f..9e685501a11 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -6,7 +6,22 @@ body: attributes: value: > **THIS IS NOT THE PLACE TO ASK FOR SUPPORT!** - Please use [Discord](https://docs.lizardbyte.dev/en/latest/about/support.html#discord) for support issues. + Please use our [Support Center](https://app.lizardbyte.dev/support) for support issues. + Non actionable bug reports will be locked and closed! + - type: checkboxes + attributes: + label: Is there an existing issue for this? + description: Please search to see if an issue already exists for the bug you encountered. + options: + - label: I have searched the existing issues + required: true + - type: checkboxes + attributes: + label: Is your issue described in the documentation? + description: Please read our [documentation](https://docs.lizardbyte.dev/projects/sunshine) + options: + - label: I have read the documentation + required: true - type: textarea id: description attributes: @@ -30,10 +45,11 @@ body: label: Host Operating System description: What version operating system are you running the software on? options: + - Docker - Linux - macOS - Windows - - other + - other, n/a - type: input id: os-version attributes: @@ -41,28 +57,50 @@ body: description: Provide the version of the operating system. Additionally a build number would be helpful. validations: required: true - - type: input + - type: dropdown id: os-architecture attributes: label: Architecture - placeholder: e.g. 32 bit, 64 bit, arm - validations: - required: true + options: + - 32 bit + - 64 bit + - arm + - other, n/a - type: input id: version attributes: - label: Sunshine Version + label: Sunshine commit or version placeholder: eg. 0.14.0 validations: required: true - - type: input + - type: dropdown + id: package_type + attributes: + label: Package + description: The package you installed + options: + - Linux - AppImage + - Linux - deb + - Linux - flatpak + - Linux - rpm + - macOS - dmg + - macOS - Portfile + - macOS - pkg + - Windows - installer + - Windows - portable + - other (not listed) + - other (self built) + - other (fork of this repo) + - type: dropdown id: graphics_type attributes: label: GPU Type description: The type of the installed graphics card. - placeholder: e.g. Intel, AMD, Nvidia - validations: - required: true + options: + - AMD + - Intel + - Nvidia + - none (software encoding) - type: input id: graphics_model attributes: @@ -83,8 +121,8 @@ body: id: capture_method attributes: label: Capture Method (Linux Only) - description: The driver/mesa version of the installed graphics card. - placeholder: e.g. PipeWire/KVM/X11 + description: If on Linux, the capture method being used. + placeholder: e.g. PipeWire/KVM/X11/KMS validations: required: false - type: textarea diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index ba507895ebf..3371de065fa 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -5,15 +5,9 @@ blank_issues_enabled: false contact_links: - - name: Discord support - url: https://docs.lizardbyte.dev/about/support.html#discord - about: Ask questions in Discord - - name: Reddit support - url: https://www.reddit.com/r/LizardByte - about: Get community support on Reddit - - name: Facebook support - url: https://www.facebook.com/groups/lizardbyte - about: Get community support on Facebook + - name: Support Center + url: https://app.lizardbyte.dev/support + about: Official LizardByte support - name: Feature request - url: https://feedback.lizardbyte.dev + url: https://app.lizardbyte.dev/feedback about: Share your suggestions or ideas to help us improve diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e3b47ad73aa..b67ea63872a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,6 +5,14 @@ version: 2 updates: + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "daily" + time: "00:00" + target-branch: "nightly" + open-pull-requests-limit: 10 + - package-ecosystem: "github-actions" directory: "/" schedule: diff --git a/.github/label-actions.yml b/.github/label-actions.yml index 6d0a74a2a32..2949601885e 100644 --- a/.github/label-actions.yml +++ b/.github/label-actions.yml @@ -25,8 +25,8 @@ invalid:duplicate: invalid:support: comment: > :wave: @{issue-author}, we use the issue tracker exclusively for bug reports. - However, this issue appears to be a support request. Please use - [Discord](https://docs.lizardbyte.dev/about/support.html#discord) for support issues. Thanks. + However, this issue appears to be a support request. Please use our + [Support Center](https://app.lizardbyte.dev/support) for support issues. Thanks. close: true lock: true lock-reason: 'off-topic' diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 6c3bab87f25..00000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,22 +0,0 @@ -## Description - - -### Screenshot - - -### Issues Fixed or Closed - -- Fixes #(issue) - -## Type of Change - -- [ ] Bug fix (non-breaking change which fixes an issue) -- [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - -## Checklist - -- [ ] My code follows the style guidelines of this project -- [ ] I have performed a self-review of my own code -- [ ] I have commented my code, particularly in hard-to-understand areas -- [ ] I have added or updated the docstring/documentation-blocks for new or existing methods/components diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c9e6b0df0e6..653641d4a9c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -6,7 +6,7 @@ on: branches: [master, nightly] types: [opened, synchronize, reopened] push: - branches: [master] + branches: [master, nightly] workflow_dispatch: jobs: @@ -26,6 +26,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout + if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }} uses: actions/checkout@v3 - name: Verify Changelog @@ -66,14 +67,84 @@ jobs: "project(Sunshine [VERSION ${{ needs.check_changelog.outputs.next_version_bare }}]" exit 1 + setup_release: + name: Setup Release + needs: check_changelog + runs-on: ubuntu-latest + steps: + - name: Set release details + id: release_details + run: | + # determine to create a release or not + if [[ $GITHUB_EVENT_NAME == "push" ]]; then + RELEASE=true + else + RELEASE=false + fi + + # set the release tag + COMMIT=${{ github.sha }} + if [[ $GITHUB_REF == refs/heads/master ]]; then + TAG="${{ needs.check_changelog.outputs.next_version }}" + RELEASE_NAME="${{ needs.check_changelog.outputs.next_version }}" + RELEASE_BODY="${{ needs.check_changelog.outputs.release_body }}" + PRE_RELEASE="false" + elif [[ $GITHUB_REF == refs/heads/nightly ]]; then + TAG="nightly-dev" + RELEASE_NAME="nightly" + RELEASE_BODY="automated nightly release - $(date -u +'%Y-%m-%dT%H:%M:%SZ') - ${COMMIT}" + PRE_RELEASE="true" + fi + + echo "create_release=${RELEASE}" >> $GITHUB_OUTPUT + echo "release_tag=${TAG}" >> $GITHUB_OUTPUT + echo "release_commit=${COMMIT}" >> $GITHUB_OUTPUT + echo "release_name=${RELEASE_NAME}" >> $GITHUB_OUTPUT + echo "release_body=${RELEASE_BODY}" >> $GITHUB_OUTPUT + echo "pre_release=${PRE_RELEASE}" >> $GITHUB_OUTPUT + + outputs: + create_release: ${{ steps.release_details.outputs.create_release }} + release_tag: ${{ steps.release_details.outputs.release_tag }} + release_commit: ${{ steps.release_details.outputs.release_commit }} + release_name: ${{ steps.release_details.outputs.release_name }} + release_body: ${{ steps.release_details.outputs.release_body }} + pre_release: ${{ steps.release_details.outputs.pre_release }} + + setup_flatpak_matrix: + name: Setup Flatpak Matrix + runs-on: ubuntu-latest + steps: + - name: Set release details + id: flatpak_matrix + # https://www.cynkra.com/blog/2020-12-23-dynamic-gha + run: | + # determine which architectures to build + if [[ $GITHUB_EVENT_NAME == "push" ]]; then + matrix=$(( + echo '{ "arch" : ["x86_64", "aarch64"] }' + ) | jq -c .) + else + matrix=$(( + echo '{ "arch" : ["x86_64"] }' + ) | jq -c .) + fi + + echo $matrix + echo $matrix | jq . + echo "matrix=$matrix" >> $GITHUB_OUTPUT + + outputs: + matrix: ${{ steps.flatpak_matrix.outputs.matrix }} + build_linux_aur: name: Linux AUR runs-on: ubuntu-latest - needs: check_changelog + needs: setup_release steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup Dependencies Linux AUR run: | @@ -106,7 +177,6 @@ jobs: echo "aur_publish=true" >> $GITHUB_ENV elif [[ ${{ github.ref == 'refs/heads/nightly' }} ]]; then - aur_pkg=sunshine-git sub_version=".r${commit}" echo "aur_publish=true" >> $GITHUB_ENV @@ -158,7 +228,7 @@ jobs: - name: Publish AUR package if: ${{ env.aur_publish == 'true' }} - uses: KSXGitHub/github-actions-deploy-aur@v2.4.1 + uses: KSXGitHub/github-actions-deploy-aur@v2.5.0 with: pkgname: ${{ env.aur_pkg }} pkgbuild: ./artifacts/PKGBUILD @@ -172,8 +242,11 @@ jobs: build_linux_flatpak: name: Linux Flatpak - runs-on: ubuntu-latest - needs: check_changelog + runs-on: ubuntu-22.04 + needs: [setup_release, setup_flatpak_matrix] + strategy: + fail-fast: false # false to test all, true to fail entire job if any fail + matrix: ${{fromJson(needs.setup_flatpak_matrix.outputs.matrix)}} steps: - name: Checkout @@ -184,11 +257,22 @@ jobs: sudo apt-get update -y sudo apt-get install -y \ cmake \ + qemu-user-static \ flatpak - sudo su $(whoami) -c 'flatpak remote-add --user --if-not-exists flathub \ + sudo su $(whoami) -c 'flatpak --user remote-add --if-not-exists flathub \ https://flathub.org/repo/flathub.flatpakrepo' - sudo su $(whoami) -c 'flatpak install --user flathub \ - org.flatpak.Builder org.freedesktop.Platform//21.08 org.freedesktop.Sdk//21.08 -y' + sudo su $(whoami) -c 'flatpak --user install -y flathub \ + org.flatpak.Builder \ + org.freedesktop.Platform/${{ matrix.arch }}/21.08 \ + org.freedesktop.Sdk/${{ matrix.arch }}/21.08' + + - name: Cache Flatpak build + uses: actions/cache@v3 + with: + path: ./build/.flatpak-builder + key: flatpak-${{ matrix.arch }}-${{ github.sha }} + restore-keys: | + flatpak-${{ matrix.arch }}- - name: Configure Flatpak Manifest run: | @@ -218,49 +302,56 @@ jobs: cmake -DGITHUB_CLONE_URL=${clone_url} \ -DGITHUB_BRANCH=${branch} \ -DGITHUB_COMMIT=${commit} \ - -DSUNSHINE_CONFIGURE_FLATPAK=ON \ + -DSUNSHINE_CONFIGURE_FLATPAK_MAN=ON \ -DSUNSHINE_CONFIGURE_ONLY=ON \ .. - name: Build Linux Flatpak working-directory: build run: | - sudo su $(whoami) -c 'flatpak run org.flatpak.Builder --repo=repo --force-clean build-sunshine \ - dev.lizardbyte.sunshine.yml' - sudo su $(whoami) -c 'flatpak build-bundle ./repo ../artifacts/sunshine.flatpak dev.lizardbyte.sunshine' + sudo su $(whoami) -c 'flatpak run org.flatpak.Builder --arch=${{ matrix.arch }} --repo=repo --force-clean \ + --stop-at=cuda build-sunshine dev.lizardbyte.sunshine.yml' + cp -r .flatpak-builder copy-of-flatpak-builder + sudo su $(whoami) -c 'flatpak run org.flatpak.Builder --arch=${{ matrix.arch }} --repo=repo --force-clean \ + build-sunshine dev.lizardbyte.sunshine.yml' + rm -rf .flatpak-builder + mv copy-of-flatpak-builder .flatpak-builder + sudo su $(whoami) -c 'flatpak build-bundle --arch=${{ matrix.arch }} ./repo \ + ../artifacts/sunshine_${{ matrix.arch }}.flatpak dev.lizardbyte.sunshine' + sudo su $(whoami) -c 'flatpak build-bundle --runtime --arch=${{ matrix.arch }} ./repo \ + ../artifacts/sunshine_debug_${{ matrix.arch }}.flatpak dev.lizardbyte.sunshine.Debug' - name: Upload Artifacts uses: actions/upload-artifact@v3 with: - name: sunshine-linux-flatpak + name: sunshine-linux-flatpak-${{ matrix.arch }} path: artifacts/ - - name: Create Release - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} - uses: LizardByte/.github/actions/create_release@master + - name: Create/Update GitHub Release + if: ${{ needs.setup_release.outputs.create_release == 'true' }} + uses: ncipollo/release-action@v1 with: + name: ${{ needs.setup_release.outputs.release_name }} + tag: ${{ needs.setup_release.outputs.release_tag }} + commit: ${{ needs.setup_release.outputs.release_commit }} + artifacts: "*artifacts/*" token: ${{ secrets.GH_BOT_TOKEN }} - next_version: ${{ needs.check_changelog.outputs.next_version }} - last_version: ${{ needs.check_changelog.outputs.last_version }} - release_body: ${{ needs.check_changelog.outputs.release_body }} + allowUpdates: true + body: ${{ needs.setup_release.outputs.release_body }} + discussionCategory: announcements + prerelease: ${{ needs.setup_release.outputs.pre_release }} build_linux: name: Linux runs-on: ubuntu-20.04 - needs: check_changelog + needs: [check_changelog, setup_release] strategy: fail-fast: false # false to test all, true to fail entire job if any fail matrix: include: # package these differently - type: cpack - CMAKE_INSTALL_PREFIX: '/usr' - SUNSHINE_ASSETS_DIR: 'local/sunshine/assets' - SUNSHINE_CONFIG_DIR: 'local/sunshine/config' EXTRA_ARGS: '' - type: appimage - CMAKE_INSTALL_PREFIX: '/usr' - SUNSHINE_ASSETS_DIR: 'sunshine.AppImage.config' - SUNSHINE_CONFIG_DIR: 'sunshine.AppImage.home' EXTRA_ARGS: '-DSUNSHINE_CONFIGURE_APPIMAGE=ON' steps: @@ -280,7 +371,6 @@ jobs: build-essential \ cmake \ gcc-10 \ - git \ g++-10 \ libavdevice-dev \ libboost-filesystem-dev \ @@ -343,9 +433,8 @@ jobs: cd build cmake -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=${{ matrix.CMAKE_INSTALL_PREFIX }} \ - -DSUNSHINE_ASSETS_DIR=${{ matrix.SUNSHINE_ASSETS_DIR }} \ - -DSUNSHINE_CONFIG_DIR=${{ matrix.SUNSHINE_CONFIG_DIR }} \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DSUNSHINE_ASSETS_DIR=share/sunshine \ -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine \ -DSUNSHINE_ENABLE_WAYLAND=ON \ -DSUNSHINE_ENABLE_X11=ON \ @@ -368,7 +457,7 @@ jobs: mv ./cpack_artifacts/Sunshine.rpm ../artifacts/sunshine.rpm - name: Set AppImage Version - if: ${{ matrix.type == 'appimage' && ( needs.check_changelog.outputs.next_version_bare != needs.check_changelog.outputs.latest_version ) }} # yamllint disable-line rule:line-length + if: ${{ matrix.type == 'appimage' && ( needs.check_changelog.outputs.next_version_bare != needs.check_changelog.outputs.last_version ) }} # yamllint disable-line rule:line-length run: | version=${{ needs.check_changelog.outputs.next_version_bare }} echo "VERSION=${version}" >> $GITHUB_ENV @@ -380,12 +469,9 @@ jobs: # install sunshine to the DESTDIR make install DESTDIR=AppDir - # portable home and config - # todo - this is ugly... we should use a custom AppRun script to take care of this - mv ./AppDir${{ matrix.CMAKE_INSTALL_PREFIX }}/sunshine.AppImage.* ../artifacts/ - mkdir -p ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/.config/sunshine/${{ matrix.SUNSHINE_CONFIG_DIR }} - cp ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/apps.json \ - ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/.config/sunshine/${{ matrix.SUNSHINE_CONFIG_DIR }}/ + # custom AppRun file + cp -f ../packaging/linux/AppImage/AppRun ./AppDir/ + chmod +x ./AppDir/AppRun # variables DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" @@ -396,12 +482,6 @@ jobs: wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage chmod +x linuxdeploy-x86_64.AppImage - # # https://github.com/linuxdeploy/linuxdeploy-plugin-gtk - # sudo apt-get install libgtk-3-dev librsvg2-dev -y - # wget https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh - # chmod +x linuxdeploy-plugin-gtk.sh - # export DEPLOY_GTK_VERSION=3 - ./linuxdeploy-x86_64.AppImage \ --appdir ./AppDir \ --executable ./sunshine \ @@ -411,8 +491,6 @@ jobs: --library /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 \ --library /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 \ --output appimage - # # add this argument back if using gtk plugin - # --plugin gtk \ # move mv Sunshine*.AppImage ../artifacts/sunshine.AppImage @@ -430,33 +508,30 @@ jobs: ./appimagelint-x86_64.AppImage ./artifacts/sunshine.AppImage - - name: Archive AppImage - if: ${{ matrix.type == 'appimage' }} - working-directory: artifacts - run: | - chmod +x ./sunshine.AppImage - - zip --recurse-paths --move --test ./sunshine-appimage.zip ./* - - name: Upload Artifacts uses: actions/upload-artifact@v3 with: name: sunshine-linux-${{ matrix.type }} path: artifacts/ - - name: Create Release - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} - uses: LizardByte/.github/actions/create_release@master + - name: Create/Update GitHub Release + if: ${{ needs.setup_release.outputs.create_release == 'true' }} + uses: ncipollo/release-action@v1 with: + name: ${{ needs.setup_release.outputs.release_name }} + tag: ${{ needs.setup_release.outputs.release_tag }} + commit: ${{ needs.setup_release.outputs.release_commit }} + artifacts: "*artifacts/*" token: ${{ secrets.GH_BOT_TOKEN }} - next_version: ${{ needs.check_changelog.outputs.next_version }} - last_version: ${{ needs.check_changelog.outputs.last_version }} - release_body: ${{ needs.check_changelog.outputs.release_body }} + allowUpdates: true + body: ${{ needs.setup_release.outputs.release_body }} + discussionCategory: announcements + prerelease: ${{ needs.setup_release.outputs.pre_release }} build_mac: name: MacOS runs-on: macos-11 - needs: check_changelog + needs: setup_release steps: - name: Checkout @@ -479,7 +554,7 @@ jobs: cmake -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr \ -DSUNSHINE_ASSETS_DIR=local/sunshine/assets \ - -DSUNSHINE_CONFIG_DIR=local/sunshine/config \ + -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine \ .. make -j ${nproc} @@ -513,19 +588,24 @@ jobs: rm -f ./sunshine-macos-experimental-bundle.dmg rm -f ./sunshine-macos-experimental-archive.zip - ## no artifacts to release currently - # - name: Create Release - # if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} - # uses: LizardByte/.github/actions/create_release@master - # with: - # token: ${{ secrets.GH_BOT_TOKEN }} - # next_version: ${{ needs.check_changelog.outputs.next_version }} - # last_version: ${{ needs.check_changelog.outputs.last_version }} - # release_body: ${{ needs.check_changelog.outputs.release_body }} +# # no artifacts to release currently +# - name: Create/Update GitHub Release +# if: ${{ needs.setup_release.outputs.create_release == 'true' }} +# uses: ncipollo/release-action@v1 +# with: +# name: ${{ needs.setup_release.outputs.release_name }} +# tag: ${{ needs.setup_release.outputs.release_tag }} +# commit: ${{ needs.setup_release.outputs.release_commit }} +# artifacts: "*artifacts/*" +# token: ${{ secrets.GH_BOT_TOKEN }} +# allowUpdates: true +# body: ${{ needs.setup_release.outputs.release_body }} +# discussionCategory: announcements +# prerelease: ${{ needs.setup_release.outputs.pre_release }} build_mac_port: name: Macports - needs: check_changelog + needs: setup_release runs-on: macos-11 steps: @@ -619,7 +699,7 @@ jobs: echo "$subport" subportlist="$subportlist $subport" done - echo "::set-output name=subportlist::${subportlist}" + echo "subportlist=${subportlist}" >> $GITHUB_OUTPUT - name: Run port lint for all subports run: | @@ -723,19 +803,24 @@ jobs: name: sunshine-macports path: artifacts/ - - name: Create Release - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} - uses: LizardByte/.github/actions/create_release@master + - name: Create/Update GitHub Release + if: ${{ needs.setup_release.outputs.create_release == 'true' }} + uses: ncipollo/release-action@v1 with: + name: ${{ needs.setup_release.outputs.release_name }} + tag: ${{ needs.setup_release.outputs.release_tag }} + commit: ${{ needs.setup_release.outputs.release_commit }} + artifacts: "*artifacts/*" token: ${{ secrets.GH_BOT_TOKEN }} - next_version: ${{ needs.check_changelog.outputs.next_version }} - last_version: ${{ needs.check_changelog.outputs.last_version }} - release_body: ${{ needs.check_changelog.outputs.release_body }} + allowUpdates: true + body: ${{ needs.setup_release.outputs.release_body }} + discussionCategory: announcements + prerelease: ${{ needs.setup_release.outputs.pre_release }} build_win: name: Windows runs-on: windows-2019 - needs: check_changelog + needs: setup_release steps: - name: Checkout @@ -770,7 +855,6 @@ jobs: cd build cmake -DCMAKE_BUILD_TYPE=Release \ -DSUNSHINE_ASSETS_DIR=assets \ - -DSUNSHINE_CONFIG_DIR=config \ -G "MinGW Makefiles" \ .. mingw32-make -j2 @@ -795,11 +879,30 @@ jobs: name: sunshine-windows path: artifacts/ - - name: Create Release - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} - uses: LizardByte/.github/actions/create_release@master + - name: Create/Update GitHub Release + if: ${{ needs.setup_release.outputs.create_release == 'true' }} + uses: ncipollo/release-action@v1 + with: + name: ${{ needs.setup_release.outputs.release_name }} + tag: ${{ needs.setup_release.outputs.release_tag }} + commit: ${{ needs.setup_release.outputs.release_commit }} + artifacts: "*artifacts/*" + token: ${{ secrets.GH_BOT_TOKEN }} + allowUpdates: true + body: ${{ needs.setup_release.outputs.release_body }} + discussionCategory: announcements + prerelease: ${{ needs.setup_release.outputs.pre_release }} + + release-winget: + name: Release to WinGet + needs: build_win + if: ${{ needs.setup_release.outputs.create_release == 'true' && github.ref == 'refs/heads/master' }} + runs-on: windows-latest # the required action can only be run on Windows + steps: + - name: Release to WinGet + uses: vedantmgoyal2009/winget-releaser@v1 with: + identifier: LizardByte.Sunshine + release-tag: ${{ needs.setup_release.outputs.release_tag }} + installers-regex: '\.exe$' # only .exe files token: ${{ secrets.GH_BOT_TOKEN }} - next_version: ${{ needs.check_changelog.outputs.next_version }} - last_version: ${{ needs.check_changelog.outputs.last_version }} - release_body: ${{ needs.check_changelog.outputs.release_body }} diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index 7ff83e0a846..0ac82a7afb7 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Autoapproving - uses: hmarr/auto-approve-action@v2 + uses: hmarr/auto-approve-action@v3 with: github-token: "${{ secrets.GITHUB_TOKEN }}" @@ -44,7 +44,7 @@ jobs: steps: - name: Automerging - uses: pascalgn/automerge-action@v0.15.3 + uses: pascalgn/automerge-action@v0.15.5 env: BASE_BRANCHES: nightly GITHUB_TOKEN: ${{ secrets.GH_BOT_TOKEN }} diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml new file mode 100644 index 00000000000..962bb74cb81 --- /dev/null +++ b/.github/workflows/ci-docker.yml @@ -0,0 +1,203 @@ +--- +# This action is centrally managed in https://github.com//.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in +# the above-mentioned repo. + +name: CI Docker + +on: + pull_request: + branches: [master, nightly] + types: [opened, synchronize, reopened] + push: + branches: [master, nightly] + workflow_dispatch: + +jobs: + check_dockerfile: + name: Check Dockerfile + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Check + id: check + run: | + if [ -f "./Dockerfile" ] + then + FOUND=true + else + FOUND=false + fi + + echo "dockerfile=${FOUND}" >> $GITHUB_OUTPUT + + outputs: + dockerfile: ${{ steps.check.outputs.dockerfile }} + + lint_dockerfile: + name: Lint Dockerfile + needs: [check_dockerfile] + if: ${{ needs.check_dockerfile.outputs.dockerfile == 'true' }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Hadolint + id: hadolint + uses: hadolint/hadolint-action@v2.1.0 + with: + dockerfile: ./Dockerfile + ignore: DL3008,DL3013,DL3016,DL3018,DL3028,DL3059 + output-file: ./hadolint.log + verbose: true + + - name: Log + if: failure() + run: | + echo "Hadolint outcome: ${{ steps.hadolint.outcome }}" >> $GITHUB_STEP_SUMMARY + cat "./hadolint.log" >> $GITHUB_STEP_SUMMARY + + check_changelog: + name: Check Changelog + needs: [check_dockerfile] + if: ${{ needs.check_dockerfile.outputs.dockerfile == 'true' }} + runs-on: ubuntu-latest + steps: + - name: Checkout + if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }} + uses: actions/checkout@v3 + + - name: Verify Changelog + id: verify_changelog + if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }} + # base_ref for pull request check, ref for push + uses: LizardByte/.github/actions/verify_changelog@master + with: + token: ${{ secrets.GITHUB_TOKEN }} + outputs: + next_version: ${{ steps.verify_changelog.outputs.changelog_parser_version }} + + docker: + name: Docker + needs: [check_dockerfile, check_changelog] + if: ${{ needs.check_dockerfile.outputs.dockerfile == 'true' }} + runs-on: ubuntu-latest + permissions: + packages: write + contents: write + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Prepare + id: prepare + env: + NEXT_VERSION: ${{ needs.check_changelog.outputs.next_version }} + run: | + # get branch name + BRANCH=${GITHUB_HEAD_REF} + + if [ -z "$BRANCH" ] + then + echo "This is a PUSH event" + BRANCH=${{ github.ref_name }} + fi + + # determine to push image to dockerhub and ghcr or not + if [[ $GITHUB_EVENT_NAME == "push" ]]; then + PUSH=true + else + PUSH=false + fi + + # setup the tags + REPOSITORY=${{ github.repository }} + BASE_TAG=$(echo $REPOSITORY | tr '[:upper:]' '[:lower:]') + COMMIT=${{ github.sha }} + + TAGS="${BASE_TAG}:${COMMIT:0:7},ghcr.io/${BASE_TAG}:${COMMIT:0:7}" + + if [[ $GITHUB_REF == refs/heads/master ]]; then + TAGS="${TAGS},${BASE_TAG}:latest,ghcr.io/${BASE_TAG}:latest" + TAGS="${TAGS},${BASE_TAG}:master,ghcr.io/${BASE_TAG}:master" + elif [[ $GITHUB_REF == refs/heads/nightly ]]; then + TAGS="${TAGS},${BASE_TAG}:nightly,ghcr.io/${BASE_TAG}:nightly" + else + TAGS="${TAGS},${BASE_TAG}:test,ghcr.io/${BASE_TAG}:test" + fi + + if [[ ${NEXT_VERSION} != "" ]]; then + TAGS="${TAGS},${BASE_TAG}:${NEXT_VERSION},ghcr.io/${BASE_TAG}:${NEXT_VERSION}" + fi + + # read the platforms from `.docker_platforms` + PLATFORMS=$(<.docker_platforms) + + echo "branch=${BRANCH}" >> $GITHUB_OUTPUT + echo "build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT + echo "commit=${COMMIT}" >> $GITHUB_OUTPUT + echo "platforms=${PLATFORMS}" >> $GITHUB_OUTPUT + echo "push=${PUSH}" >> $GITHUB_OUTPUT + echo "tags=${TAGS}" >> $GITHUB_OUTPUT + + - name: Set Up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + id: buildx + + - name: Cache Docker Layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Log in to Docker Hub + if: ${{ steps.prepare.outputs.push == 'true' }} # PRs do not have access to secrets + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + + - name: Log in to the Container registry + if: ${{ steps.prepare.outputs.push == 'true' }} # PRs do not have access to secrets + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ secrets.GH_BOT_NAME }} + password: ${{ secrets.GH_BOT_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v3 + with: + context: ./ + file: ./Dockerfile + push: ${{ steps.prepare.outputs.push }} + platforms: ${{ steps.prepare.outputs.platforms }} + build-args: | + BRANCH=${{ steps.prepare.outputs.branch }} + BUILD_DATE=${{ steps.prepare.outputs.build_date }} + BUILD_VERSION=${{ needs.check_changelog.outputs.next_version }} + COMMIT=${{ steps.prepare.outputs.commit }} + tags: ${{ steps.prepare.outputs.tags }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache + + - name: Update Docker Hub Description + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + uses: peter-evans/dockerhub-description@v3 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_PASSWORD }} # token is not currently supported + repository: ${{ env.BASE_TAG }} + short-description: ${{ github.event.repository.description }} + readme-filepath: ./DOCKER_README.md diff --git a/.github/workflows/cpp-clang-format-lint.yml b/.github/workflows/cpp-clang-format-lint.yml index 4717f70a5e3..cc42ea10b04 100644 --- a/.github/workflows/cpp-clang-format-lint.yml +++ b/.github/workflows/cpp-clang-format-lint.yml @@ -28,7 +28,7 @@ jobs: FOUND=false fi - echo "::set-output name=src::${FOUND}" + echo "src=${FOUND}" >> $GITHUB_OUTPUT outputs: src: ${{ steps.check.outputs.src }} diff --git a/.github/workflows/issues-stale.yml b/.github/workflows/issues-stale.yml index 225b07de39d..7baf4b9a223 100644 --- a/.github/workflows/issues-stale.yml +++ b/.github/workflows/issues-stale.yml @@ -15,10 +15,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Stale - uses: actions/stale@v5 + uses: actions/stale@v6 with: close-issue-message: > - This issue was closed because it has been stalled for 5 days with no activity. + This issue was closed because it has been stalled for 10 days with no activity. close-pr-message: > This PR was closed because it has been stalled for 10 days with no activity. days-before-stale: 90 @@ -28,15 +28,16 @@ jobs: exempt-pr-labels: 'dependencies,l10n' stale-issue-label: 'stale' stale-issue-message: > - This issue is stale because it has been open for 30 days with no activity. - Comment or remove the stale label, otherwise this will be closed in 5 days. + This issue is stale because it has been open for 90 days with no activity. + Comment or remove the stale label, otherwise this will be closed in 10 days. stale-pr-label: 'stale' stale-pr-message: > This PR is stale because it has been open for 90 days with no activity. Comment or remove the stale label, otherwise this will be closed in 10 days. + repo-token: ${{ secrets.GH_BOT_TOKEN }} - name: Invalid Template - uses: actions/stale@v5 + uses: actions/stale@v6 with: close-issue-message: > This issue was closed because the the template was not completed after 5 days. @@ -52,3 +53,4 @@ jobs: stale-pr-label: 'invalid:template-incomplete' stale-pr-message: > Invalid PR template. + repo-token: ${{ secrets.GH_BOT_TOKEN }} diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml index f89975f9986..6ba44446373 100644 --- a/.github/workflows/issues.yml +++ b/.github/workflows/issues.yml @@ -19,4 +19,4 @@ jobs: - name: Label Actions uses: dessant/label-actions@v2 with: - github-token: ${{ github.token }} + github-token: ${{ secrets.GH_BOT_TOKEN }} diff --git a/.github/workflows/localize.yml b/.github/workflows/localize.yml index 79674aa427a..2c57c114e76 100644 --- a/.github/workflows/localize.yml +++ b/.github/workflows/localize.yml @@ -62,17 +62,20 @@ jobs: # print the git diff git diff locale/sunshine.po - # set the variable with minimal output - OUTPUT=$(git diff --numstat locale/sunshine.po) + # set the variable with minimal output, replacing `\t` with ` ` + OUTPUT=$(git diff --numstat locale/sunshine.po | sed -e "s#\t# #g") echo "git_diff=${OUTPUT}" >> $GITHUB_ENV - name: git reset # only run if a single line changed (date/time) and file already existed - # \t in next line is a tab character - if: ${{ env.git_diff == '1\t1\tlocale/sunshine.po' && env.new_file == 'false' }} + if: ${{ env.git_diff == '1 1 locale/sunshine.po' && env.new_file == 'false' }} run: | git reset --hard + - name: Get current date + id: date + run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + - name: Create/Update Pull Request uses: peter-evans/create-pull-request@v4 with: @@ -86,7 +89,7 @@ jobs: title: New Babel Updates body: | Update report - - Updated with *today's* date + - Updated ${{ steps.date.outputs.date }} - Auto-generated by [create-pull-request][1] [1]: https://github.com/peter-evans/create-pull-request diff --git a/.github/workflows/release-notifier-moonlight.yml b/.github/workflows/release-notifier-moonlight.yml new file mode 100644 index 00000000000..9ac896f376a --- /dev/null +++ b/.github/workflows/release-notifier-moonlight.yml @@ -0,0 +1,22 @@ +--- +name: Release Notifications (Moonlight) + +on: + release: + types: [published] + +jobs: + discord: + runs-on: ubuntu-latest + steps: + - name: discord + uses: sarisia/actions-status-discord@v1 # https://github.com/sarisia/actions-status-discord + with: + webhook: ${{ secrets.DISCORD_RELEASE_WEBHOOK_MOONLIGHT }} + nodetail: true + nofail: false + username: ${{ secrets.DISCORD_USERNAME }} + avatar_url: ${{ secrets.ORG_LOGO_URL }} + title: ${{ github.event.repository.name }} ${{ github.ref_name }} Released + description: ${{ github.event.release.body }} + color: 0xFF4500 diff --git a/.github/workflows/winget.yml b/.github/workflows/winget.yml deleted file mode 100644 index 0cf5b371277..00000000000 --- a/.github/workflows/winget.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: Publish to WinGet - -on: - release: - types: [released] - -jobs: - winget-releaser: - name: winget releaser - runs-on: windows-latest - steps: - - name: winget releaser - uses: vedantmgoyal2009/winget-releaser@latest - with: - identifier: LizardByte.Sunshine - token: ${{ secrets.GH_BOT_TOKEN }} diff --git a/.github/workflows/yaml-lint.yml b/.github/workflows/yaml-lint.yml index 83de6c2356c..5623c2dc6c2 100644 --- a/.github/workflows/yaml-lint.yml +++ b/.github/workflows/yaml-lint.yml @@ -15,7 +15,25 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 + + - name: Find additional files + id: find-files + run: | + # space separated list of files + FILES=.clang-format + + # empty placeholder + FOUND="" + + for FILE in ${FILES}; do + if [ -f "$FILE" ] + then + FOUND="$FOUND $FILE" + fi + done + + echo "found=${FOUND}" >> $GITHUB_OUTPUT - name: yaml lint id: yaml-lint @@ -30,17 +48,14 @@ jobs: line-length: max: 120 truthy: - allowed-values: ['true', 'false', 'on'] # GitHub uses "on" for workflow event triggers + # GitHub uses "on" for workflow event triggers + # .clang-format file has options of "Yes" "No" that will be caught by this, so changed to "warning" + allowed-values: ['true', 'false', 'on'] check-keys: true - level: error + level: warning + file_or_dir: . ${{ steps.find-files.outputs.found }} - name: Log - run: | - echo ${{ steps.yaml-lint.outputs.logfile }} - - - name: Upload logs - uses: actions/upload-artifact@v2 if: failure() - with: - name: yamllint-logfile - path: ${{ steps.yaml-lint.outputs.logfile }} + run: | + cat "${{ steps.yaml-lint.outputs.logfile }}" >> $GITHUB_STEP_SUMMARY diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 156e5624620..586666c22fc 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -10,7 +10,7 @@ version: 2 build: os: ubuntu-20.04 tools: - python: "3.9" + python: "3.10" ## apt packages required packages to run cmake on sunshine, note that additional packages are required # apt_packages: @@ -41,5 +41,5 @@ formats: all python: install: - - requirements: ./scripts/requirements.txt + - requirements: ./docs/requirements.txt system_packages: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 272709ee1ff..eb3955ccd46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [0.15.0] - 2022-10-30 +### Added +- (Windows) Add firewall rules scripts +- (Windows) Automatically add and remove firewall rules at install/uninstall +- (Windows) Automatically add and remove service at install/uninstall +- (Docker) Official image added +- (Linux) Add aarch64 flatpak package +### Changed +- (Windows/Linux/MacOS) - Move default config and apps file to assets directory +- (MacOS) Bump boost to 1.80 for macport builds +- (Linux) Remove backup and restore of config files +### Fixed +- (Linux) - Create sunshine config directory if it doesn't exist +- (Linux) Remove portable home and config directories for AppImage +- (Windows) Include service install and uninstall scripts again +- (Windows) Automatically delete start menu entry upon uninstall +- (Windows) Automatically delete program install directory upon uninstall, with user prompt +- (Linux) Handle the case of no default audio sink +- (Windows/Linux/MacOS) Fix default image paths +- (Linux) Fix CUDA RGBA to NV12 conversion + ## [0.14.1] - 2022-08-09 ### Added - (Linux) Flatpak package added diff --git a/CMakeLists.txt b/CMakeLists.txt index d3e36294fc0..840087b8d6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.0) -project(Sunshine VERSION 0.14.1 +project(Sunshine VERSION 0.15.0 DESCRIPTION "Sunshine is a Gamestream host for Moonlight." HOMEPAGE_URL "https://app.lizardbyte.dev" ) @@ -9,9 +9,10 @@ set(PROJECT_LONG_DESCRIPTION "Sunshine is a self hosted, low latency, cloud gami Intel, and Nvidia GPUs. It is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield. \ Connect to Sunshine from any Moonlight client, available for nearly any device imaginable.") -option(SUNSHINE_CONFIGURE_APPIMAGE "Configure files required for AppImage." OFF) +option(SUNSHINE_CONFIGURE_APPIMAGE "Configuration specific for AppImage." OFF) option(SUNSHINE_CONFIGURE_AUR "Configure files required for AUR." OFF) -option(SUNSHINE_CONFIGURE_FLATPAK "Configure files required for Flatpak." OFF) +option(SUNSHINE_CONFIGURE_FLATPAK_MAN "Configure manifest file required for Flatpak build." OFF) +option(SUNSHINE_CONFIGURE_FLATPAK "Configuration specific for Flatpak." OFF) option(SUNSHINE_CONFIGURE_PORTFILE "Configure macOS Portfile." OFF) option(SUNSHINE_CONFIGURE_ONLY "Configure special files only, then exit." OFF) @@ -19,7 +20,7 @@ if(${SUNSHINE_CONFIGURE_APPIMAGE}) configure_file(packaging/linux/sunshine.desktop sunshine.desktop @ONLY) elseif(${SUNSHINE_CONFIGURE_AUR}) configure_file(packaging/linux/aur/PKGBUILD PKGBUILD @ONLY) -elseif(${SUNSHINE_CONFIGURE_FLATPAK}) +elseif(${SUNSHINE_CONFIGURE_FLATPAK_MAN}) configure_file(packaging/linux/flatpak/dev.lizardbyte.sunshine.yml dev.lizardbyte.sunshine.yml @ONLY) elseif(${SUNSHINE_CONFIGURE_PORTFILE}) configure_file(packaging/macos/Portfile Portfile @ONLY) @@ -93,7 +94,7 @@ if(WIN32) endif() add_compile_definitions(SUNSHINE_PLATFORM="windows") - add_subdirectory(tools) #This is temporary, only tools for Windows are needed, for now + add_subdirectory(tools) # This is temporary, only tools for Windows are needed, for now include_directories(third-party/ViGEmClient/include) @@ -421,18 +422,22 @@ else() list(APPEND SUNSHINE_COMPILE_OPTIONS -O3) endif() +# setup assets directory if(NOT SUNSHINE_ASSETS_DIR) - set(SUNSHINE_ASSETS_DIR "${CMAKE_CURRENT_BINARY_DIR}/assets") + set(SUNSHINE_ASSETS_DIR "assets") endif() - -if(NOT SUNSHINE_CONFIG_DIR) - set(SUNSHINE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}/config") +if(UNIX) + set(SUNSHINE_ASSETS_DIR "${CMAKE_INSTALL_PREFIX}/${SUNSHINE_ASSETS_DIR}") endif() -if(UNIX AND CMAKE_INSTALL_PREFIX AND NOT ${SUNSHINE_CONFIGURE_APPIMAGE}) - set(SUNSHINE_ASSETS_DIR "${CMAKE_INSTALL_PREFIX}/${SUNSHINE_ASSETS_DIR}") - set(SUNSHINE_CONFIG_DIR "${CMAKE_INSTALL_PREFIX}/${SUNSHINE_CONFIG_DIR}") +# use relative assets path for AppImage... maybe for all unix +if(${SUNSHINE_CONFIGURE_APPIMAGE}) + string(REPLACE "${CMAKE_INSTALL_PREFIX}" ".${CMAKE_INSTALL_PREFIX}" SUNSHINE_ASSETS_DIR_DEF ${SUNSHINE_ASSETS_DIR}) +else() + set(SUNSHINE_ASSETS_DIR_DEF "${SUNSHINE_ASSETS_DIR}") endif() +list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_ASSETS_DIR="${SUNSHINE_ASSETS_DIR_DEF}") + list(APPEND CBS_EXTERNAL_LIBRARIES cbs) @@ -452,8 +457,6 @@ if(NOT WIN32) list(APPEND SUNSHINE_EXTERNAL_LIBRARIES Boost::log) endif() -list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_ASSETS_DIR="${SUNSHINE_ASSETS_DIR}") -list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_CONFIG_DIR="${SUNSHINE_CONFIG_DIR}") add_executable(sunshine ${SUNSHINE_TARGET_FILES}) target_link_libraries(sunshine ${SUNSHINE_EXTERNAL_LIBRARIES} ${EXTRA_LIBS}) target_compile_definitions(sunshine PUBLIC ${SUNSHINE_DEFINITIONS}) @@ -501,70 +504,101 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h install(TARGETS audio-info RUNTIME DESTINATION "tools" COMPONENT audio) install(TARGETS sunshinesvc RUNTIME DESTINATION "tools" COMPONENT sunshinesvc) + # scripts + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/misc/firewall/" DESTINATION "scripts" COMPONENT firewall) + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/misc/service/" DESTINATION "scripts" COMPONENT service) + + # Sunshine assets install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}" COMPONENT assets) install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}" COMPONENT assets) - install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/common/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT config) - install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT config) - - # set(CPACK_NSIS_MUI_HEADERIMAGE "") # TODO: image should be 150x57 bmp - set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\sunshine.ico") set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\\\${PROJECT_EXE}") - set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}") # The name of the directory that will be created in C:/Program files/ - string(APPEND CPACK_NSIS_DEFINES "\n RequestExecutionLevel admin") # TODO: Not sure if this is needed but it took me a while to figure out where to put this option so I'm leaving it here + set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}") # The name of the directory that will be created in C:/Program files/ + string(APPEND CPACK_NSIS_DEFINES "\n RequestExecutionLevel admin") # TODO: Not sure if this is needed but it took me a while to figure out where to put this option so I'm leaving it here + # Extra install commands # Sets permissions on the installed folder so that we can write in it + # Install service SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS - "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS} - ExecWait 'icacls \\\"$INSTDIR\\\" /grant:r Users:\\\(OI\\\)\\\(CI\\\)\\\(F\\\)' - ") + "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS} + ExecWait 'icacls \\\"$INSTDIR\\\" /grant:r Users:\\\(OI\\\)\\\(CI\\\)\\\(F\\\)' + ExecWait '\\\"$INSTDIR\\\\scripts\\\\add-firewall-rule.bat\\\"' + ExecWait '\\\"$INSTDIR\\\\scripts\\\\install-service.bat\\\"' + ") + + # Extra uninstall commands + # Uninstall service + set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS + "${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} + ExecWait '\\\"$INSTDIR\\\\scripts\\\\delete-firewall-rule.bat\\\"' + ExecWait '\\\"$INSTDIR\\\\scripts\\\\uninstall-service.bat\\\"' + MessageBox MB_YESNO|MB_ICONQUESTION 'Do you want to completely remove the directory $INSTDIR and all of its contents?' IDNO NoDelete + RMDir /r \\\"$INSTDIR\\\" ; skipped if no + NoDelete: + ") # Adding an option for the start menu and PATH set(CPACK_NSIS_MODIFY_PATH "OFF") # TODO: it asks to add it to the PATH but is not working https://gitlab.kitware.com/cmake/cmake/-/issues/15635 set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") set(CPACK_NSIS_MUI_FINISHPAGE_RUN "${CMAKE_PROJECT_NAME}.exe") - set(CPACK_NSIS_INSTALLED_ICON_NAME "${CMAKE_PROJECT_NAME}.exe") # This will be shown on the installed apps Windows settings - set(CPACK_NSIS_CREATE_ICONS "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${CMAKE_PROJECT_NAME}.lnk' '\$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe'") + set(CPACK_NSIS_INSTALLED_ICON_NAME "${CMAKE_PROJECT_NAME}.exe") # This will be shown on the installed apps Windows settings + set(CPACK_NSIS_CREATE_ICONS_EXTRA + "${CPACK_NSIS_CREATE_ICONS_EXTRA} + CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${CMAKE_PROJECT_NAME}.lnk' '\$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe' + ") + set(CPACK_NSIS_DELETE_ICONS_EXTRA + "${CPACK_NSIS_DELETE_ICONS_EXTRA} + Delete '\$SMPROGRAMS\\\\$MUI_TEMP\\\\${CMAKE_PROJECT_NAME}.lnk' + ") # Checking for previous installed versions - # set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL "ON") # TODO: doesn't work on my machine when Sunshine is already installed + # set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL "ON") # TODO: doesn't work on my machine when Sunshine is already installed + + set(CPACK_NSIS_HELP_LINK "https://docs.lizardbyte.dev/projects/sunshine/en/latest/about/installation.html") + set(CPACK_NSIS_URL_INFO_ABOUT "${CMAKE_PROJECT_HOMEPAGE_URL}") + set(CPACK_NSIS_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}/support") # Setting components groups and dependencies # sunshine binary set(CPACK_COMPONENT_APPLICATION_DISPLAY_NAME "${CMAKE_PROJECT_NAME}") - set(CPACK_COMPONENT_APPLICATION_DESCRIPTION "The main application.") - set(CPACK_COMPONENT_APPLICATION_GROUP "${CMAKE_PROJECT_NAME}") + set(CPACK_COMPONENT_APPLICATION_DESCRIPTION "${CMAKE_PROJECT_NAME} main application.") + set(CPACK_COMPONENT_APPLICATION_GROUP "core") set(CPACK_COMPONENT_APPLICATION_REQUIRED true) set(CPACK_COMPONENT_APPLICATION_DEPENDS assets) # assets - set(CPACK_COMPONENT_ASSETS_DISPLAY_NAME "Assets") + set(CPACK_COMPONENT_ASSETS_DISPLAY_NAME "assets") set(CPACK_COMPONENT_ASSETS_DESCRIPTION "Shaders, default box art, and web ui.") - set(CPACK_COMPONENT_ASSETS_GROUP "${CMAKE_PROJECT_NAME}") + set(CPACK_COMPONENT_ASSETS_GROUP "core") set(CPACK_COMPONENT_ASSETS_REQUIRED true) - # config - set(CPACK_COMPONENT_CONFIG_DISPLAY_NAME "Config") - set(CPACK_COMPONENT_CONFIG_DESCRIPTION "Default config and apps.json files.") - set(CPACK_COMPONENT_CONFIG_GROUP "${CMAKE_PROJECT_NAME}") - set(CPACK_COMPONENT_CONFIG_REQUIRED true) - # audio tool - set(CPACK_COMPONENT_AUDIO_DISPLAY_NAME "audio-info.exe") - set(CPACK_COMPONENT_AUDIO_DESCRIPTION "CLI tool that allows you to get information about sound devices.") - set(CPACK_COMPONENT_AUDIO_GROUP "Tools") + set(CPACK_COMPONENT_AUDIO_DISPLAY_NAME "audio-info") + set(CPACK_COMPONENT_AUDIO_DESCRIPTION "CLI tool providing information about sound devices.") + set(CPACK_COMPONENT_AUDIO_GROUP "tools") # display tool - set(CPACK_COMPONENT_DXGI_DISPLAY_NAME "dxgi-info.exe") - set(CPACK_COMPONENT_DXGI_DESCRIPTION "CLI tool that allows you to get information about graphics cards and displays.") - set(CPACK_COMPONENT_DXGI_GROUP "Tools") - - # service tool - set(CPACK_COMPONENT_SUNSHINESVC_DISPLAY_NAME "sunshinesvc.exe") - set(CPACK_COMPONENT_SUNSHINESVC_DESCRIPTION "CLI tool that allows you to enable/disable the Sunshine service.") - set(CPACK_COMPONENT_SUNSHINESVC_GROUP "Tools") + set(CPACK_COMPONENT_DXGI_DISPLAY_NAME "dxgi-info") + set(CPACK_COMPONENT_DXGI_DESCRIPTION "CLI tool providing information about graphics cards and displays.") + set(CPACK_COMPONENT_DXGI_GROUP "tools") + + # service + set(CPACK_COMPONENT_SUNSHINESVC_DISPLAY_NAME "sunshinesvc") + set(CPACK_COMPONENT_SUNSHINESVC_DESCRIPTION "CLI tool providing ability to enable/disable the Sunshine service.") + set(CPACK_COMPONENT_SUNSHINESVC_GROUP "tools") + + # service scripts + set(CPACK_COMPONENT_SERVICE_DISPLAY_NAME "service-scripts") + set(CPACK_COMPONENT_SERVICE_DESCRIPTION "Scripts to enable/disable the service.") + set(CPACK_COMPONENT_SERVICE_GROUP "scripts") + set(CPACK_COMPONENT_SERVICE_DEPENDS sunshinesvc) + + # firewall scripts + set(CPACK_COMPONENT_FIREWALL_DISPLAY_NAME "firewall-scripts") + set(CPACK_COMPONENT_FIREWALL_DESCRIPTION "Scripts to enable or disable firewall rules.") + set(CPACK_COMPONENT_FIREWALL_GROUP "scripts") endif() if(APPLE) # TODO: bundle doesn't produce a valid .app use cpack -G DragNDrop @@ -573,15 +607,12 @@ if(APPLE) set(CPACK_BUNDLE_ICON "${PROJECT_SOURCE_DIR}/sunshine.icns") # set(CPACK_BUNDLE_STARTUP_COMMAND "${INSTALL_RUNTIME_DIR}/sunshine") endif() -if(APPLE AND SUNSHINE_MACOS_PACKAGE) # TODO +if(APPLE AND SUNSHINE_MACOS_PACKAGE) # TODO set(prefix "${CMAKE_PROJECT_NAME}.app/Contents") set(INSTALL_RUNTIME_DIR "${prefix}/MacOS") install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}") - install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/common/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}") - install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}") - install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}") install(TARGETS sunshine BUNDLE DESTINATION . COMPONENT Runtime @@ -590,39 +621,35 @@ elseif(UNIX) # Installation destination dir set(CPACK_SET_DESTDIR true) if(NOT CMAKE_INSTALL_PREFIX) - set(CMAKE_INSTALL_PREFIX "/usr/local/sunshine") + set(CMAKE_INSTALL_PREFIX "/usr/share/sunshine") endif() install(TARGETS sunshine RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}") - install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/common/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}") if(APPLE) install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}") - install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}") - install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/misc/uninstall_pkg.sh" DESTINATION "${SUNSHINE_ASSETS_DIR}") else() install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}") - install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}") - - install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/85-sunshine.rules" DESTINATION "${CMAKE_INSTALL_LIBDIR}/udev/rules.d") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" DESTINATION "${CMAKE_INSTALL_LIBDIR}/systemd/user") + if(${SUNSHINE_CONFIGURE_APPIMAGE} OR ${SUNSHINE_CONFIGURE_FLATPAK}) + install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/85-sunshine.rules" DESTINATION "${SUNSHINE_ASSETS_DIR}/udev/rules.d") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" DESTINATION "${SUNSHINE_ASSETS_DIR}/systemd/user") + else() + install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/85-sunshine.rules" DESTINATION "${CMAKE_INSTALL_LIBDIR}/udev/rules.d") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" DESTINATION "${CMAKE_INSTALL_LIBDIR}/systemd/user") + endif() - # Pre and post install - set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA - "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/preinst" - "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/postinst" - "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/conffiles") - set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/preinst") + # 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") # Dependencies set(CPACK_DEB_COMPONENT_INSTALL ON) set(CPACK_DEBIAN_PACKAGE_DEPENDS "openssl, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2") set(CPACK_RPM_PACKAGE_REQUIRES "openssl >= 1.1, libavdevice >= 4.3, boost-thread >= 1.67.0, boost-filesystem >= 1.67.0, boost-log >= 1.67.0, pulseaudio-libs >= 10.0, libopusenc >= 0.2.1, libxcb >= 1.13, libXtst >= 1.2.3, libevdev >= 1.5.6, libdrm >= 2.4.97, libcap >= 2.22") - set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF) # This should automatically figure out dependencies, doesn't work with the current config + set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF) # This should automatically figure out dependencies, doesn't work with the current config endif() endif() diff --git a/DOCKER_README.md b/DOCKER_README.md index a2647e00d75..87dbc67284d 100644 --- a/DOCKER_README.md +++ b/DOCKER_README.md @@ -1,44 +1,50 @@ # Docker -## Using docker run +## Build your own containers +This image provides a method for you to easily use the latest Sunshine release in your own docker projects. It is not +intended to use as a standalone container at this point, and should be considered experimental. + +```dockerfile +FROM lizardbyte/sunshine + +# install Steam, Wayland, etc. + +ENTRYPOINT steam && sunshine +``` + +## Where used +This is a list of docker projects using Sunshine. Something missing? Let us know about it! + +- [Games on Whales](https://games-on-whales.github.io) + +## Port and Volume mappings +Examples are below of the required mappings. The configuration file will be saved to `/config` in the container. + +### Using docker run Create and run the container (substitute your ``): ```bash docker run -d \ - --name=sunshine \ + --name= \ --restart=unless-stopped - -v :/config \ -e PUID= \ -e PGID= \ -e TZ= \ + -v :/config \ -p 47984-47990:47984-47990/tcp \ -p 48010:48010 \ -p 47998-48000:47998-48000/udp \ - lizardbyte/sunshine + ``` -To update the container it must be removed and recreated: - -```bash -# Stop the container -docker stop sunshine -# Remove the container -docker rm sunshine -# Pull the latest update -docker pull lizardbyte/sunshine -# Run the container with the same parameters as before -docker run -d ... -``` - -## Using docker-compose - +### Using docker-compose Create a `docker-compose.yml` file with the following contents (substitute your ``): ```yaml version: '3' services: - sunshine: - image: lizardbyte/sunshine + : + image: container_name: sunshine restart: unless-stopped volumes: @@ -48,26 +54,12 @@ services: - PGID= - TZ= ports: - - 47984-47990:47984-47990/tcp - - 48010:48010 - - 47998-48000:47998-48000/udp + - "47984-47990:47984-47990/tcp" + - "48010:48010" + - "47998-48000:47998-48000/udp" ``` -Create and start the container (run the command from the same folder as your `docker-compose.yml` file): - -```bash -docker-compose up -d -``` - -To update the container: -```bash -# Pull the latest update -docker-compose pull -# Update and restart the container -docker-compose up -d -``` - -## Parameters +### Parameters You must substitute the `` with your own settings. Parameters are split into two halves separated by a colon. The left side represents the host and the right side the @@ -79,16 +71,17 @@ port `47990` (e.g. `http://:47990`). The internal port must be `47990`, (e.g. `-p 8080:47990`). All the ports listed in the `docker run` and `docker-compose` examples are required. -| Parameter | Function | Example Value | Required | -| --------------------------- | -------------------- | ------------------- | -------- | -| `-p :47990` | Web UI Port | `47990` | True | -| `-v :/config` | Volume mapping | `/home/sunshine` | True | -| `-e PUID=` | User ID | `1001` | False | -| `-e PGID=` | Group ID | `1001` | False | -| `-e TZ=` | Lookup TZ value [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) | `America/New_York` | True | +| Parameter | Function | Example Value | Required | +|-----------------------------|---------------------------|--------------------|----------| +| `-p :47990` | Web UI Port | `47990` | True | +| `-v :/config` | Volume mapping | `/home/sunshine` | True | +| `-e PUID=` | User ID | `1001` | False | +| `-e PGID=` | Group ID | `1001` | False | +| `-e TZ=` | Lookup TZ value [here][1] | `America/New_York` | False | -### User / Group Identifiers: +[1]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones +#### User / Group Identifiers: When using data volumes (-v flags) permissions issues can arise between the host OS and the container. To avoid this issue you can specify the user PUID and group PGID. Ensure the data volume directory on the host is owned by the same user you specify. @@ -99,3 +92,5 @@ In this instance `PUID=1001` and `PGID=1001`. To find yours use id user as below $ id dockeruser uid=1001(dockeruser) gid=1001(dockergroup) groups=1001(dockergroup) ``` + +If you want to change the PUID or PGID after the image has been built, it will require rebuilding the image. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000000..b493b0d4621 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,92 @@ +FROM ubuntu:22.04 AS sunshine-base + +ARG DEBIAN_FRONTEND=noninteractive + +FROM sunshine-base as sunshine-build + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN apt-get update -y \ + && apt-get install -y --no-install-recommends \ + build-essential=12.9* \ + cmake=3.22.1* \ + libavdevice-dev=7:4.4.* \ + libboost-filesystem-dev=1.74.0* \ + libboost-log-dev=1.74.0* \ + libboost-thread-dev=1.74.0* \ + libcap-dev=1:2.44* \ + libdrm-dev=2.4.110* \ + libevdev-dev=1.12.1* \ + libpulse-dev=1:15.99.1* \ + libopus-dev=1.3.1* \ + libssl-dev=3.0.2* \ + libwayland-dev=1.20.0* \ + libx11-dev=2:1.7.5* \ + libxcb-shm0-dev=1.14* \ + libxcb-xfixes0-dev=1.14* \ + libxcb1-dev=1.14* \ + libxfixes-dev=1:6.0.0* \ + libxrandr-dev=2:1.5.2* \ + libxtst-dev=2:1.2.3* \ + nvidia-cuda-dev=11.5.1* \ + nvidia-cuda-toolkit=11.5.1* \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# copy repository +WORKDIR /root/sunshine-build/ +COPY . . + +# setup build directory +WORKDIR /root/sunshine-build/build + +# cmake and cpack +RUN cmake -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DSUNSHINE_ASSETS_DIR=share/sunshine \ + -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine \ + -DSUNSHINE_ENABLE_WAYLAND=ON \ + -DSUNSHINE_ENABLE_X11=ON \ + -DSUNSHINE_ENABLE_DRM=ON \ + -DSUNSHINE_ENABLE_CUDA=ON \ + /root/sunshine-build \ + && make -j "$(nproc)" \ + && cpack -G DEB + +FROM sunshine-base as sunshine + +# copy deb from builder +COPY --from=sunshine-build /root/sunshine-build/build/cpack_artifacts/Sunshine.deb /sunshine.deb + +# install sunshine +RUN apt-get update -y \ + && apt-get install -y --no-install-recommends /sunshine.deb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# network setup +EXPOSE 47984-47990/tcp +EXPOSE 48010 +EXPOSE 47998-48000/udp + +# setup user +ARG PGID=1000 +ENV PGID=${PGID} +ARG PUID=1000 +ENV PUID=${PUID} +ENV TZ="UTC" +ARG UNAME=lizard +ENV UNAME=${UNAME} + +ENV HOME=/home/$UNAME + +RUN groupadd -f -g "${PGID}" "${UNAME}" && \ + useradd -lm -d ${HOME} -s /bin/bash -g "${PGID}" -G input -u "${PUID}" "${UNAME}" && \ + mkdir -p ${HOME}/.config/sunshine && \ + ln -s ${HOME}/.config/sunshine /config && \ + chown -R ${UNAME} ${HOME} + +USER ${UNAME} +WORKDIR ${HOME} + +# entrypoint +ENTRYPOINT ["/usr/bin/sunshine"] diff --git a/README.rst b/README.rst index 8d51ff0969e..f7853dee23a 100644 --- a/README.rst +++ b/README.rst @@ -1,8 +1,6 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/README.rst - Overview ======== -LizardByte has the full documentation hosted on `Read the Docs `_. +LizardByte has the full documentation hosted on `Read the Docs `_. About ----- @@ -13,18 +11,18 @@ Connect to Sunshine from any Moonlight client, available for nearly any device i These are the advantages of Sunshine over GeForce Experience. - - FOSS (Free and Open Source Software) - - Multi-platform +- FOSS (Free and Open Source Software) +- Multi-platform - - Linux - - macOS - - Windows + - Linux + - macOS + - Windows - - Pair over web ui - - Supports AMD, Intel, and Nvidia GPUs for encoding - - Supports software encoding - - Supports streaming to multiple clients - - Web UI for configuration +- Pair over web ui +- Supports AMD, Intel, and Nvidia GPUs for encoding +- Supports software encoding +- Supports streaming to multiple clients +- Web UI for configuration Integrations ------------ @@ -48,7 +46,8 @@ Integrations Support --------- -Our support methods are listed in our `LizardByte Docs `_. +Our support methods are listed in our +`LizardByte Docs `_. Downloads --------- @@ -57,11 +56,16 @@ Downloads :alt: GitHub Releases :target: https://github.com/LizardByte/Sunshine/releases/latest +.. image:: https://img.shields.io/docker/pulls/lizardbyte/sunshine?style=for-the-badge&logo=docker + :alt: Docker + :target: https://hub.docker.com/r/lizardbyte/sunshine + +Stats +------ +.. image:: https://img.shields.io/github/stars/lizardbyte/sunshine?logo=github&style=for-the-badge + :alt: GitHub stars + :target: https://github.com/LizardByte/Sunshine + .. image:: https://img.shields.io/badge/dynamic/json?color=blue&label=AUR&style=for-the-badge&query=$.results.0.NumVotes&url=https%3A%2F%2Fapp.lizardbyte.dev%2Funo%2Faur%2Fsunshine.json&logo=archlinux :alt: AUR votes :target: https://aur.archlinux.org/packages/sunshine - -.. comment - image:: https://img.shields.io/docker/pulls/lizardbyte/sunshine?style=for-the-badge&logo=docker - :alt: Docker - :target: https://hub.docker.com/r/lizardbyte/sunshine diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000000..fc950e037ce --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,4 @@ +furo==2022.9.29 +m2r2==0.3.3 +Sphinx==5.3.0 +sphinx-copybutton==0.5.0 diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index 0d65175e4c2..2ab43a856c6 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -1,5 +1,3 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/about/advanced_usage.rst - Advanced Usage ============== Sunshine will work with the default settings for most users. In some cases you may want to configure Sunshine further. @@ -21,14 +19,12 @@ location by modifying the configuration file. Value Description ========= =========== Docker /config/ - Linux-aur /usr/share/sunshine/config/ - Linux-deb /usr/local/sunshine/config/ - Linux-rpm /usr/local/sunshine/config/ - macOS /usr/local/sunshine/config/ + Linux ~/.config/sunshine/ + macOS ~/.config/sunshine/ Windows ./config/ ========= =========== -Example +**Example** .. code-block:: bash sunshine ~/sunshine_config.conf @@ -43,13 +39,13 @@ General sunshine_name ^^^^^^^^^^^^^ -Description +**Description** The name displayed by Moonlight -Default +**Default** PC hostname -Example +**Example** .. code-block:: text sunshine_name = Sunshine @@ -57,7 +53,7 @@ Example min_log_level ^^^^^^^^^^^^^ -Description +**Description** The minimum log level printed to standard out. **Choices** @@ -77,10 +73,10 @@ Description none no logging ======= =========== -Default +**Default** ``info`` -Example +**Example** .. code-block:: text min_log_level = info @@ -91,7 +87,7 @@ Controls gamepad ^^^^^^^ -Description +**Description** The type of gamepad to emulate on the host. .. Caution:: Applies to Windows only. @@ -108,10 +104,10 @@ Description ds4 dualshock controller (PS4) ===== =========== -Default +**Default** ``x360`` -Example +**Example** .. code-block:: text gamepad = x360 @@ -119,17 +115,17 @@ Example back_button_timeout ^^^^^^^^^^^^^^^^^^^ -Description +**Description** If, after the timeout, the back/select button is still pressed down, Home/Guide button press is emulated. On Nvidia Shield, the home and power button are not passed to Moonlight. .. Tip:: If back_button_timeout < 0, then the Home/Guide button will not be emulated. -Default +**Default** ``2000`` -Example +**Example** .. code-block:: text back_button_timeout = 2000 @@ -137,13 +133,13 @@ Example key_repeat_delay ^^^^^^^^^^^^^^^^ -Description +**Description** The initial delay in milliseconds before repeating keys. Controls how fast keys will repeat themselves. -Default +**Default** ``500`` -Example +**Example** .. code-block:: text key_repeat_delay = 500 @@ -151,15 +147,15 @@ Example key_repeat_frequency ^^^^^^^^^^^^^^^^^^^^ -Description +**Description** How often keys repeat every second. .. Tip:: This configurable option supports decimals. -Default +**Default** .. Todo:: Unknown -Example +**Example** .. code-block:: text key_repeat_frequency = 24.9 @@ -167,17 +163,17 @@ Example keybindings ^^^^^^^^^^^ -Description +**Description** Sometimes it may be useful to map keybindings. Wayland won't allow clients to capture the Win Key for example. .. Tip:: See `virtual key codes `_ .. Hint:: keybindings needs to have a multiple of two elements. -Default +**Default** None -Example +**Example** .. code-block:: text keybindings = [ @@ -190,14 +186,14 @@ Example key_rightalt_to_key_win ^^^^^^^^^^^^^^^^^^^^^^^ -Description +**Description** It may be possible that you cannot send the Windows Key from Moonlight directly. In those cases it may be useful to make Sunshine think the Right Alt key is the Windows key. -Default +**Default** None -Example +**Example** .. code-block:: text key_rightalt_to_key_win = enabled @@ -208,12 +204,12 @@ Display adapter_name ^^^^^^^^^^^^ -Description +**Description** Select the video card you want to stream. .. Tip:: To find the name of the appropriate values follow these instructions. - Linux + VA-API + **Linux + VA-API** Unlike with `amdvce` and `nvenc`, it doesn't matter if video encoding is done on a different GPU. .. code-block:: bash @@ -229,23 +225,23 @@ Description .. Todo:: macOS - Windows + **Windows** .. code-block:: batch tools\dxgi-info.exe -Default +**Default** Sunshine will select the default video card. -Examples - Linux +**Examples** + **Linux** .. code-block:: text adapter_name = /dev/dri/renderD128 .. Todo:: macOS - Windows + **Windows** .. code-block:: text adapter_name = Radeon RX 580 Series @@ -253,12 +249,12 @@ Examples output_name ^^^^^^^^^^^ -Description +**Description** Select the display number you want to stream. .. Tip:: To find the name of the appropriate values follow these instructions. - Linux + **Linux** .. code-block:: bash xrandr --listmonitors @@ -269,23 +265,23 @@ Description .. Todo:: macOS - Windows + **Windows** .. code-block:: batch tools\dxgi-info.exe -Default +**Default** Sunshine will select the default display. -Examples - Linux +**Examples** + **Linux** .. code-block:: text output_name = 0 .. Todo:: macOS - Windows + **Windows** .. code-block:: text output_name = \\.\DISPLAY1 @@ -293,16 +289,16 @@ Examples fps ^^^ -Description +**Description** The fps modes advertised by Sunshine. .. Note:: Some versions of Moonlight, such as Moonlight-nx (Switch), rely on this list to ensure that the requested fps is supported. -Default +**Default** .. Todo:: Unknown -Example +**Example** .. code-block:: text fps = [10, 30, 60, 90, 120] @@ -310,16 +306,16 @@ Example resolutions ^^^^^^^^^^^ -Description +**Description** The resolutions advertised by Sunshine. .. Note:: Some versions of Moonlight, such as Moonlight-nx (Switch), rely on this list to ensure that the requested resolution is supported. -Default +**Default** .. Todo:: Unknown -Example +**Example** .. code-block:: text resolutions = [ @@ -338,22 +334,20 @@ Example dwmflush ^^^^^^^^ -Description +**Description** Invoke DwmFlush() to sync screen capture to the Windows presentation interval. .. Caution:: Applies to Windows only. Alleviates visual stuttering during mouse movement. If enabled, this feature will automatically deactivate if the client framerate exceeds the host monitor's current refresh rate. -Default +**Default** ``enabled`` -Examples - - Windows - .. code-block:: text +**Example** + .. code-block:: text - dwmflush = enabled + dwmflush = enabled Audio ----- @@ -361,48 +355,48 @@ Audio audio_sink ^^^^^^^^^^ -Description +**Description** The name of the audio sink used for audio loopback. .. Tip:: To find the name of the audio sink follow these instructions. - Linux + pulseaudio + **Linux + pulseaudio** .. code-block:: bash pacmd list-sinks | grep "name:" - Linux + pipewire + **Linux + pipewire** .. code-block:: bash pactl info | grep Source # in some causes you'd need to use the `Sink` device, if `Source` doesn't work, so try: pactl info | grep Sink - macOS + **macOS** Sunshine can only access microphones on macOS due to system limitations. To stream system audio use `Soundflower `_ or `BlackHole `_. - Windows + **Windows** .. code-block:: batch tools\audio-info.exe -Default +**Default** Sunshine will select the default audio device. -Examples - Linux +**Examples** + **Linux** .. code-block:: text audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo - macOS + **macOS** .. code-block:: text audio_sink = BlackHole 2ch - Windows + **Windows** .. code-block:: text audio_sink = {0.0.0.00000000}.{FD47D9CC-4218-4135-9CE2-0C195C87405B} @@ -410,16 +404,16 @@ Examples virtual_sink ^^^^^^^^^^^^ -Description +**Description** The audio device that's virtual, like Steam Streaming Speakers. This allows Sunshine to stream audio, while muting the speakers. .. Tip:: See `audio_sink`_! -Default +**Default** .. Todo:: Unknown -Example +**Example** .. code-block:: text virtual_sink = {0.0.0.00000000}.{8edba70c-1125-467c-b89c-15da389bc1d4} @@ -430,13 +424,13 @@ Network external_ip ^^^^^^^^^^^ -Description +**Description** If no external IP address is given, Sunshine will attempt to automatically detect external ip-address. -Default +**Default** Automatic -Example +**Example** .. code-block:: text external_ip = 123.456.789.12 @@ -444,13 +438,31 @@ Example port ^^^^ -Description - Set the family of ports used by Sunshine. +**Description** + Set the family of ports used by Sunshine. Changing this value will offset other ports per the table below. + +.. table:: + :widths: auto -Default + ================ ============ =========================== + Port Description Default Port Difference from config port + ================ ============ =========================== + HTTPS 47984 TCP -5 + HTTP 47989 TCP 0 + Web 47990 TCP +1 + RTSP 48010 TCP +21 + Video 47998 UDP +9 + Control 47999 UDP +10 + Audio 48000 UDP +11 + Mic (unused) 48002 UDP +13 + ================ ============ =========================== + +.. Attention:: Custom ports are only allowed on select Moonlight clients. + +**Default** ``47989`` -Example +**Example** .. code-block:: text port = 47989 @@ -458,13 +470,13 @@ Example pkey ^^^^ -Description +**Description** The private key. This must be 2048 bits. -Default +**Default** .. Todo:: Unknown -Example +**Example** .. code-block:: text pkey = /dir/pkey.pem @@ -472,13 +484,13 @@ Example cert ^^^^ -Description +**Description** The certificate. Must be signed with a 2048 bit key. -Default +**Default** .. Todo:: Unknown -Example +**Example** .. code-block:: text cert = /dir/cert.pem @@ -486,7 +498,7 @@ Example origin_pin_allowed ^^^^^^^^^^^^^^^^^^ -Description +**Description** The origin of the remote endpoint address that is not denied for HTTP method /pin. **Choices** @@ -502,10 +514,10 @@ Description wan Anyone may access /pin ===== =========== -Default +**Default** ``pc`` -Example +**Example** .. code-block:: text origin_pin_allowed = pc @@ -513,7 +525,7 @@ Example origin_web_ui_allowed ^^^^^^^^^^^^^^^^^^^^^ -Description +**Description** The origin of the remote endpoint address that is not denied for HTTPS Web UI. **Choices** @@ -529,10 +541,10 @@ Description wan Anyone may access the web ui ===== =========== -Default +**Default** ``lan`` -Example +**Example** .. code-block:: text origin_web_ui_allowed = lan @@ -540,7 +552,7 @@ Example upnp ^^^^ -Description +**Description** Sunshine will attempt to open ports for streaming over the internet. **Choices** @@ -555,10 +567,10 @@ Description off disable UPnP ===== =========== -Default +**Default** ``off`` -Example +**Example** .. code-block:: text upnp = on @@ -566,13 +578,13 @@ Example ping_timeout ^^^^^^^^^^^^ -Description +**Description** How long to wait in milliseconds for data from Moonlight before shutting down the stream. -Default +**Default** ``10000`` -Example +**Example** .. code-block:: text ping_timeout = 10000 @@ -583,22 +595,22 @@ Encoding channels ^^^^^^^^ -Description +**Description** This will generate distinct video streams, unlike simply broadcasting to multiple Clients. When multicasting, it could be useful to have different configurations for each connected Client. For instance: - - Clients connected through WAN and LAN have different bitrate constraints. - - Decoders may require different settings for color. + - Clients connected through WAN and LAN have different bitrate constraints. + - Decoders may require different settings for color. .. Warning:: CPU usage increases for each distinct video stream generated. -Default +**Default** ``1`` -Example +**Example** .. code-block:: text channels = 1 @@ -606,18 +618,18 @@ Example fec_percentage ^^^^^^^^^^^^^^ -Description +**Description** Percentage of error correcting packets per data packet in each video frame. .. Warning:: Higher values can correct for more network packet loss, but at the cost of increasing bandwidth usage. -Default +**Default** ``20`` -Range +**Range** ``1-255`` -Example +**Example** .. code-block:: text fec_percentage = 20 @@ -625,15 +637,15 @@ Example qp ^^ -Description +**Description** Quantitization Parameter. Some devices don't support Constant Bit Rate. For those devices, QP is used instead. .. Warning:: Higher value means more compression, but less quality. -Default +**Default** ``28`` -Example +**Example** .. code-block:: text qp = 28 @@ -641,17 +653,17 @@ Example min_threads ^^^^^^^^^^^ -Description +**Description** Minimum number of threads used by ffmpeg to encode the video. .. Note:: Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually worth it to gain the use of more CPU cores for encoding. The ideal value is the lowest value that can reliably encode at your desired streaming settings on your hardware. -Default +**Default** ``1`` -Example +**Example** .. code-block:: text min_threads = 1 @@ -659,7 +671,7 @@ Example hevc_mode ^^^^^^^^^ -Description +**Description** Allows the client to request HEVC Main or HEVC Main10 video streams. .. Warning:: HEVC is more CPU-intensive to encode, so enabling this may reduce performance when using software @@ -679,10 +691,10 @@ Description 3 advertise support for HEVC Main and Main10 (HDR) profiles ===== =========== -Default +**Default** ``0`` -Example +**Example** .. code-block:: text hevc_mode = 2 @@ -690,7 +702,7 @@ Example encoder ^^^^^^^ -Description +**Description** Force a specific encoder. **Choices** @@ -706,10 +718,10 @@ Description software Encoding occurs on the CPU ======== =========== -Default +**Default** Sunshine will use the first encoder that is available. -Example +**Example** .. code-block:: text encoder = nvenc @@ -717,7 +729,7 @@ Example sw_preset ^^^^^^^^^ -Description +**Description** The encoder preset to use. .. Note:: This option only applies when using software `encoder`_. @@ -752,10 +764,10 @@ Description veryslow slowest ========= =========== -Default +**Default** ``superfast`` -Example +**Example** .. code-block:: text sw_preset = superfast @@ -763,7 +775,7 @@ Example sw_tune ^^^^^^^ -Description +**Description** The tuning preset to use. .. Note:: This option only applies when using software `encoder`_. @@ -788,10 +800,10 @@ Description zerolatency good for fast encoding and low-latency streaming =========== =========== -Default +**Default** ``zerolatency`` -Example +**Example** .. code-block:: text sw_tune = zerolatency @@ -799,7 +811,7 @@ Example nv_preset ^^^^^^^^^ -Description +**Description** The encoder preset to use. .. Note:: This option only applies when using nvenc `encoder`_. @@ -826,10 +838,10 @@ Description losslesshp lossless, high performance ========== =========== -Default +**Default** ``llhq`` -Example +**Example** .. code-block:: text nv_preset = llhq @@ -837,7 +849,7 @@ Example nv_rc ^^^^^ -Description +**Description** The encoder rate control. .. Note:: This option only applies when using nvenc `encoder`_. @@ -861,10 +873,10 @@ Description vbr_hq variable bitrate, high quality ========== =========== -Default +**Default** ``auto`` -Example +**Example** .. code-block:: text nv_rc = auto @@ -872,7 +884,7 @@ Example nv_coder ^^^^^^^^ -Description +**Description** The entropy encoding to use. .. Note:: This option only applies when using nvenc `encoder`_. @@ -890,10 +902,10 @@ Description cavlc ========== =========== -Default +**Default** ``auto`` -Example +**Example** .. code-block:: text nv_coder = auto @@ -901,7 +913,7 @@ Example amd_quality ^^^^^^^^^^^ -Description +**Description** The encoder preset to use. .. Note:: This option only applies when using amdvce `encoder`_. @@ -919,10 +931,10 @@ Description balanced balance performance and speed ========== =========== -Default +**Default** ``balanced`` -Example +**Example** .. code-block:: text amd_quality = balanced @@ -930,7 +942,7 @@ Example amd_rc ^^^^^^ -Description +**Description** The encoder rate control. .. Note:: This option only applies when using amdvce `encoder`_. @@ -952,10 +964,10 @@ Description vbr_peak variable bitrate, peak constrained =========== =========== -Default +**Default** ``auto`` -Example +**Example** .. code-block:: text amd_rc = auto @@ -963,7 +975,7 @@ Example amd_coder ^^^^^^^^^ -Description +**Description** The entropy encoding to use. .. Note:: This option only applies when using nvenc `encoder`_. @@ -981,10 +993,10 @@ Description cavlc ========== =========== -Default +**Default** ``auto`` -Example +**Example** .. code-block:: text amd_coder = auto @@ -992,7 +1004,7 @@ Example vt_software ^^^^^^^^^^^ -Description +**Description** Force Video Toolbox to use software encoding. .. Note:: This option only applies when using macOS. @@ -1011,10 +1023,10 @@ Description forced force software encoding ========== =========== -Default +**Default** ``auto`` -Example +**Example** .. code-block:: text vt_software = auto @@ -1022,17 +1034,17 @@ Example vt_realtime ^^^^^^^^^^^ -Description +**Description** Realtime encoding. .. Note:: This option only applies when using macOS. .. Warning:: Disabling realtime encoding might result in a delayed frame encoding or frame drop. -Default +**Default** ``enabled`` -Example +**Example** .. code-block:: text vt_realtime = enabled @@ -1040,7 +1052,7 @@ Example vt_coder ^^^^^^^^ -Description +**Description** The entropy encoding to use. .. Note:: This option only applies when using macOS. @@ -1058,10 +1070,10 @@ Description cavlc ========== =========== -Default +**Default** ``auto`` -Example +**Example** .. code-block:: text vt_coder = auto @@ -1072,14 +1084,14 @@ Advanced file_apps ^^^^^^^^^ -Description +**Description** The application configuration file path. The file contains a json formatted list of applications that can be started by Moonlight. -Default +**Default** OS and package dependent -Example +**Example** .. code-block:: text file_apps = apps.json @@ -1087,13 +1099,13 @@ Example file_state ^^^^^^^^^^ -Description +**Description** The file where current state of Sunshine is stored. -Default +**Default** ``sunshine_state.json`` -Example +**Example** .. code-block:: text file_state = sunshine_state.json @@ -1101,13 +1113,13 @@ Example credentials_file ^^^^^^^^^^^^^^^^ -Description +**Description** The file where user credentials for the UI are stored. -Default +**Default** ``sunshine_state.json`` -Example +**Example** .. code-block:: text credentials_file = sunshine_state.json diff --git a/docs/source/about/docker.rst b/docs/source/about/docker.rst index 8a597e261fa..77e4e20833d 100644 --- a/docs/source/about/docker.rst +++ b/docs/source/about/docker.rst @@ -1,5 +1,3 @@ :github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/DOCKER_README.md -.. Todo:: This is a planned feature. Currently no Dockerfile or image exists for Sunshine. - .. mdinclude:: ../../../DOCKER_README.md diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index f1687b3d1c0..9f65ba59d3a 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -1,12 +1,13 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/about/installation.rst - Installation ============ The recommended method for running Sunshine is to use the `binaries`_ bundled with the `latest release`_. +.. Attention:: Additional setup is required after installation. See + :ref:`Setup `. + Binaries -------- -Binaries of Sunshine are created for each release. They are available for Linux, and Windows. +Binaries of Sunshine are created for each release. They are available for Linux, macOS, and Windows. Binaries can be found in the `latest release`_. .. Tip:: Some third party packages also exist. See @@ -14,33 +15,55 @@ Binaries can be found in the `latest release`_. Docker ------ -.. Todo:: Docker images of Sunshine are planned to be included in the future. - They will be available on `Dockerhub.io`_ and `ghcr.io`_. +Docker images are available on `Dockerhub.io`_ and `ghcr.io`_. + +See :ref:`Docker ` for additional information. Linux ----- -Follow the instructions for your preferred package type below. +First, follow the instructions for your preferred package type below. + +Then start sunshine with the following command, unless a start command is listed in the specified package. + +.. code-block:: bash + + sunshine AppImage ^^^^^^^^ .. image:: https://img.shields.io/github/issues/lizardbyte/sunshine/pkg:appimage?logo=github&style=for-the-badge :alt: GitHub issues by-label -According to AppImageLint the AppImage can run on the following distros. +According to AppImageLint the supported distro matrix of the AppImage is below. - - [✖] Debian oldstable (buster) - - [✔] Debian stable (bullseye) - - [✔] Debian testing (bookworm) - - [✔] Debian unstable (sid) - - [✔] Ubuntu jammy - - [✔] Ubuntu impish - - [✔] Ubuntu focal - - [✖] Ubuntu bionic - - [✖] Ubuntu xenial - - [✖] Ubuntu trusty - - [✖] CentOS 7 +- [✖] Debian oldstable (buster) +- [✔] Debian stable (bullseye) +- [✔] Debian testing (bookworm) +- [✔] Debian unstable (sid) +- [✔] Ubuntu jammy +- [✔] Ubuntu impish +- [✔] Ubuntu focal +- [✖] Ubuntu bionic +- [✖] Ubuntu xenial +- [✖] Ubuntu trusty +- [✖] CentOS 7 #. Download ``sunshine-appimage.zip`` and extract the contents to your home directory. +#. Open terminal and run the following code. + + .. code-block:: bash + + ./sunshine.AppImage --install + +Start: + .. code-block:: bash + + ./sunshine.AppImage --install && ./sunshine.AppImage + +Uninstall: + .. code-block:: bash + + ./sunshine.AppImage --remove AUR Package ^^^^^^^^^^^ @@ -48,10 +71,15 @@ AUR Package .. code-block:: bash - git clone https://aur.archlinux.org/sunshine-git.git - cd sunshine-git + git clone https://aur.archlinux.org/sunshine.git + cd sunshine makepkg -fi +Uninstall: + .. code-block:: bash + + pacman -R sunshine + Debian Package ^^^^^^^^^^^^^^ .. image:: https://img.shields.io/github/issues/lizardbyte/sunshine/pkg:deb?logo=github&style=for-the-badge @@ -65,13 +93,16 @@ Debian Package .. Tip:: You can double click the deb file to see details about the package and begin installation. +Uninstall: + .. code-block:: bash + + sudo apt remove sunshine + Flatpak Package ^^^^^^^^^^^^^^^ .. image:: https://img.shields.io/github/issues/lizardbyte/sunshine/pkg:flatpak?logo=github&style=for-the-badge :alt: GitHub issues by-label -.. Todo:: This package needs to have CUDA added. - #. Install `Flatpak `_ as required. #. Download ``sunshine.flatpak`` and run the following code. @@ -85,6 +116,22 @@ Flatpak Package flatpak install --user sunshine.flatpak +Start: + X11 and NVFBC capture (X11 Only) + .. code-block:: bash + + flatpak run dev.lizardbyte.sunshine + + KMS capture (Wayland & X11) + .. code-block:: bash + + sudo -i PULSE_SERVER=unix:$(pactl info | awk '/Server String/{print$3}') flatpak run dev.lizardbyte.sunshine + +Uninstall: + .. code-block:: bash + + flatpak uninstall --delete-data sunshine.flatpak + RPM Package ^^^^^^^^^^^ .. image:: https://img.shields.io/github/issues/lizardbyte/sunshine/pkg:rpm?logo=github&style=for-the-badge @@ -105,41 +152,58 @@ RPM Package .. Tip:: You can double click the rpm file to see details about the package and begin installation. +Uninstall: + .. code-block:: bash + + sudo dnf remove sunshine + macOS ----- .. image:: https://img.shields.io/github/issues/lizardbyte/sunshine/os:macos?logo=github&style=for-the-badge :alt: GitHub issues by-label pkg - .. Warning:: The `pkg` does not include runtime dependencies and should be considered experimental. +^^^ +.. Warning:: The `pkg` does not include runtime dependencies and should be considered experimental. - #. Download the ``sunshine.pkg`` file and install it as normal. +#. Download the ``sunshine.pkg`` file and install it as normal. + +Uninstall: + .. code-block:: bash + + cd /etc/sunshine/assets + uninstall_pkg.sh Portfile - #. Install `MacPorts `_ - #. Update the Macports sources. +^^^^^^^^ +#. Install `MacPorts `_ +#. Update the Macports sources. - .. code-block:: bash + .. code-block:: bash - sudo nano /opt/local/etc/macports/sources.conf + sudo nano /opt/local/etc/macports/sources.conf - Add this line, replacing your username, below the line that starts with ``rsync``. + Add this line, replacing your username, below the line that starts with ``rsync``. + ``file:///Users//ports`` - file://Users//ports + ``Ctrl+x``, then ``Y`` to exit and save changes. - ``Ctrl+x``, then ``Y`` to exit and save changes. +#. Download the ``Portfile`` to ``~/Downloads`` and run the following code. - #. Download the ``Portfile`` to ``~/Downloads`` and run the following code. + .. code-block:: bash - .. code-block:: bash + mkdir -p ~/ports/multimedia/sunshine + mv ~/Downloads/Portfile ~/ports/multimedia/sunshine/ + cd ~/ports + portindex + sudo port install sunshine + +#. The first time you start Sunshine, you will be asked to grant access to screen recording and your microphone. - mkdir -p ~/ports/multimedia/sunshine - mv ~/Downlaods/Portfile ~/ports/multimedia/sunshine - cd ~/ports - portindex - sudo port install sunshine +Uninstall: + .. code-block:: bash - #. The first time you start Sunshine, you will be asked to grant access to screen recording and your microphone. + sudo port uninstall sunshine Windows ------- @@ -149,11 +213,18 @@ Windows .. image:: https://img.shields.io/github/issues/lizardbyte/sunshine/os:windows:11?logo=github&style=for-the-badge :alt: GitHub issues by-label -Installed option: - #. Download and install ``sunshine-windows.exe`` +Installer +^^^^^^^^^ +#. Download and install ``sunshine-windows.exe`` + +To uninstall, find Sunshine in the list `here `_ and select "Uninstall" from the overflow +menu. Different versions of Windows may provide slightly different steps for uninstall. + +Standalone +^^^^^^^^^^ +#. Download and extract ``sunshine-windows.zip`` -Standalone option: - #. Download and extract ``sunshine-windows.zip`` +To uninstall, delete the extracted directory which contains the ``sunshine.exe`` file. .. _latest release: https://github.com/LizardByte/Sunshine/releases/latest .. _Dockerhub.io: https://hub.docker.com/repository/docker/lizardbyte/sunshine diff --git a/docs/source/about/third_party_packages.rst b/docs/source/about/third_party_packages.rst index 5ae51e8bc9e..ad8979dc246 100644 --- a/docs/source/about/third_party_packages.rst +++ b/docs/source/about/third_party_packages.rst @@ -1,5 +1,3 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/about/third_party_packages.rst - Third Party Packages ==================== @@ -15,6 +13,12 @@ Chocolatey .. image:: https://img.shields.io/chocolatey/dt/sunshine?style=for-the-badge&logo=chocolatey :alt: Chocolatey +nixpkgs +------- +.. image:: https://img.shields.io/badge/dynamic/xml?color=orange&label=nixpkgs&style=for-the-badge&prefix=v&query=%2F%2Ftr%5B%40id%3D%27nix_unstable%27%5D%2Ftd%5B3%5D%2Fspan%2Fa&url=https%3A%2F%2Frepology.org%2Fproject%2Fsunshine%2Fversions&logo=nixos + :alt: nixpgs Version + :target: https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/sunshine/default.nix + Scoop ----- @@ -22,6 +26,12 @@ Scoop :alt: Scoop Version (extras bucket) :target: https://scoop.sh/#/apps?s=0&d=1&o=true&q=sunshine +Solus +----- +.. image:: https://img.shields.io/badge/dynamic/xml?color=orange&label=Solus&style=for-the-badge&prefix=v&query=%2F%2Ftr%5B%40id%3D%27solus%27%5D%2Ftd%5B3%5D%2Fspan%2Fa&url=https%3A%2F%2Frepology.org%2Fproject%2Fsunshine%2Fversions&logo=solus + :alt: Solus Version + :target: https://dev.getsol.us/source/sunshine + Winget ------ .. image:: https://img.shields.io/badge/dynamic/xml?color=orange&label=Winget&style=for-the-badge&prefix=v&query=%2F%2Ftr%5B%40id%3D%27winget%27%5D%2Ftd%5B3%5D%2Fspan%2Fa&url=https%3A%2F%2Frepology.org%2Fproject%2Fsunshine%2Fversions&logo=microsoft diff --git a/docs/source/about/usage.rst b/docs/source/about/usage.rst index 009585ed031..81cfcdcda8e 100644 --- a/docs/source/about/usage.rst +++ b/docs/source/about/usage.rst @@ -1,5 +1,3 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/about/usage.rst - Usage ===== #. See the `setup`_ section for your specific OS. @@ -12,6 +10,7 @@ Usage .. Tip:: If using the Linux AppImage, replace ``sunshine`` with ``./sunshine.AppImage`` #. Configure Sunshine in the web ui + The web ui is available on `https://localhost:47990 `_ by default. You may replace `localhost` with your internal ip address. @@ -20,14 +19,14 @@ Usage .. Caution:: If running for the first time, make sure to note the username and password Sunshine showed to you, since you cannot get back later! - Add games and applications. - This can be configured in the web ui. + **Add games and applications.** + This can be configured in the web ui. - .. Note:: Additionally, apps can be configured manually. `src_assets//config/apps.json` is an example of a - list of applications that are started just before running a stream. This is the directory within the GitHub - repo. + .. Note:: Additionally, apps can be configured manually. `src_assets//config/apps.json` is an example of a + list of applications that are started just before running a stream. This is the directory within the GitHub + repo. - .. Attention:: Application list is not fully supported on macOS + .. Attention:: Application list is not fully supported on macOS #. In Moonlight, you may need to add the PC manually. #. When Moonlight request you insert the correct pin on sunshine: @@ -39,14 +38,13 @@ Usage Network ------- -Sunshine will be available on port 47990 by default. +The Sunshine user interface will be available on port 47990 by default. -.. Danger:: Do not expose port 47990, or the web ui, to the internet! +.. Warning:: Exposing ports to the internet can be dangerous. Do this at your own risk. Arguments --------- To get a list of available arguments run the following: - .. code-block:: bash sunshine --help @@ -56,7 +54,8 @@ Setup Linux ^^^^^ -The deb and rpm packages handle these steps automatically. The AppImage does not, third party packages may not as well. +The `deb`, `rpm`, and `AppImage` packages handle these steps automatically. The flatpak does not, third party packages +also may not. Sunshine needs access to `uinput` to create mouse and gamepad events. @@ -66,25 +65,15 @@ Sunshine needs access to `uinput` to create mouse and gamepad events. sudo usermod -a -G input $USER #. Create `udev` rules. - .. code-block:: bash - - sudo nano /etc/udev/rules.d/85-sunshine.rules - - Input the following contents. - .. code-block:: - KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput" - - Save the file and exit: - - #. ``CTRL+X`` to start exit. - #. ``Y`` to save modifications. + echo 'KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput"' | \ + sudo tee /etc/udev/rules.d/85-sunshine-input.rules #. Optionally, configure autostart service - - filename: ``~/.config/systemd/user/sunshine.service`` - - contents: + - filename: ``~/.config/systemd/user/sunshine.service`` + - contents: .. code-block:: [Unit] @@ -105,16 +94,16 @@ Sunshine needs access to `uinput` to create mouse and gamepad events. aur /usr/bin/sunshine ✔ deb /usr/bin/sunshine ✔ rpm /usr/bin/sunshine ✔ - AppImage ~/sunshine.AppImage ✖ + AppImage ~/sunshine.AppImage ✔ Flatpak flatpak run dev.lizardbyte.sunshine ✖ ======== ============================================== =============== - Start once + **Start once** .. code-block:: bash systemctl --user start sunshine - Start on boot + **Start on boot** .. code-block:: bash systemctl --user enable sunshine @@ -123,12 +112,12 @@ Sunshine needs access to `uinput` to create mouse and gamepad events. .. Note:: ``cap_sys_admin`` may as well be root, except you don't need to be root to run it. It is necessary to allow Sunshine to use KMS. - Enable + **Enable** .. code-block:: bash sudo setcap cap_sys_admin+p $(readlink -f $(which sunshine)) - Disable + **Disable** .. code-block:: bash sudo setcap -r $(readlink -f $(which sunshine)) @@ -150,8 +139,7 @@ select their sink as audio device in `sunshine.conf`. .. Caution:: Gamepads are not currently supported. Configure autostart service - - MacPorts + **MacPorts** .. code-block:: bash sudo port load Sunshine @@ -162,36 +150,37 @@ For gamepad support, install `ViGEmBus `_. Cross compilation is not @@ -11,7 +9,6 @@ Building Locally Clone ^^^^^ Ensure `git `_ is installed and run the following: - .. code-block:: bash git clone https://github.com/lizardbyte/sunshine.git --recurse-submodules diff --git a/docs/source/building/linux.rst b/docs/source/building/linux.rst index c841ad61cfb..009ef882fec 100644 --- a/docs/source/building/linux.rst +++ b/docs/source/building/linux.rst @@ -1,12 +1,8 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/building/linux.rst - Linux ===== Requirements ------------ -.. Danger:: Installing these dependencies may break your distribution. It is recommended to build in a virtual machine - or to use the `Dockerfile builds`_ located in the `./scripts` directory. Debian Bullseye ^^^^^^^^^^^^^^^ @@ -18,7 +14,6 @@ Install Requirements sudo apt update && sudo apt install \ build-essential \ cmake \ - git \ libavdevice-dev \ libboost-filesystem-dev \ libboost-log-dev \ @@ -97,7 +92,6 @@ Install Requirements build-essential \ cmake \ gcc-10 \ - git \ g++-10 \ libavdevice-dev \ libboost-filesystem1.71-dev \ @@ -150,7 +144,6 @@ Install Requirements sudo apt update && sudo apt install \ build-essential \ cmake \ - git \ g++-10 \ libavdevice-dev \ libboost-filesystem-dev \ @@ -183,9 +176,9 @@ Install CuDA wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O ./cuda.run && chmod a+x ./cuda.run ./cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && rm ./cuda.run -Ubuntu 21.10 +Ubuntu 22.04 ^^^^^^^^^^^^ -End of Life: July 2022 +End of Life: April 2027 Install Requirements .. code-block:: bash @@ -193,7 +186,6 @@ Install Requirements sudo apt update && sudo apt install \ build-essential \ cmake \ - git \ libavdevice-dev \ libboost-filesystem-dev \ libboost-log-dev \ @@ -215,12 +207,6 @@ Install Requirements nvidia-cuda-dev \ # Cuda, NvFBC nvidia-cuda-toolkit \ # Cuda, NvFBC -Ubuntu 22.04 -^^^^^^^^^^^^ -End of Life: April 2027 - -.. Todo:: Create Ubuntu 22.04 Dockerfile and complete this documentation. - Build ----- .. Attention:: Ensure you are in the build directory created during the clone step earlier before continuing. @@ -230,7 +216,7 @@ Debian based OSes cmake -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 .. -Red Hat based Oses +Red Hat based OSes .. code-block:: bash cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ .. @@ -241,62 +227,3 @@ Finally make -j ${nproc} cpack -G DEB # optionally, create a deb package cpack -G RPM # optionally, create a rpm package - -Dockerfile Builds ------------------ -You may wish to simply build sunshine from source, without bloating your OS with development files. -There are scripts located in the ``./scripts`` directory that will create docker images that have the necessary -packages. As a result, removing the development files after you're done is a single command away. -These scripts use docker under the hood, as such, they can only be used to compile the Linux version - -.. Todo:: Publish the Dockerfiles to Dockerhub and ghcr. - -Requirements - Install `Docker `_ - -Instructions - #. :ref:`Clone `. Sunshine. - #. Select the desired Dockerfile from the ``./scripts`` directory. - - Available Files: - .. code-block:: text - - Dockerfile-debian - Dockerfile-fedora_33 # end of life - Dockerfile-fedora_35 - Dockerfile-ubuntu_18_04 - Dockerfile-ubuntu_20_04 - Dockerfile-ubuntu_21_04 # end of life - Dockerfile-ubuntu_21_10 - - #. Execute - - .. code-block:: bash - - cd scripts # move to the scripts directory - ./build-container.sh -f Dockerfile- # create the container (replace the "") - ./build-sunshine.sh -p -s .. # compile and build sunshine - - #. Updating - - .. code-block:: bash - - git pull # pull the latest changes from github - ./build-sunshine.sh -p -s .. # compile and build sunshine - - #. Optionally, delete the container - .. code-block:: bash - - ./build-container.sh -c delete - - #. Install the resulting package - - Debian - .. code-block:: bash - - sudo apt install -f sunshine-build/sunshine.deb - - Red Hat - .. code-block:: bash - - sudo dnf install sunshine-build/sunshine.rpm diff --git a/docs/source/building/macos.rst b/docs/source/building/macos.rst index b719c6ee80b..074eaf4e68c 100644 --- a/docs/source/building/macos.rst +++ b/docs/source/building/macos.rst @@ -1,5 +1,3 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/building/macos.rst - macOS ===== @@ -30,14 +28,13 @@ Build ----- .. Attention:: Ensure you are in the build directory created during the clone step earlier before continuing. - .. code-block:: bash +.. code-block:: bash - cmake .. - make -j ${nproc} + cmake .. + make -j ${nproc} - cpack -G DragNDrop # optionally, create a macOS dmg package + cpack -G DragNDrop # optionally, create a macOS dmg package If cmake fails complaining to find Boost, try to set the path explicitly. - ``cmake -DBOOST_ROOT=[boost path] ..``, e.g., ``cmake -DBOOST_ROOT=/opt/local/libexec/boost/1.76 ..`` diff --git a/docs/source/building/windows.rst b/docs/source/building/windows.rst index 0c6dde572c1..43f84a22541 100644 --- a/docs/source/building/windows.rst +++ b/docs/source/building/windows.rst @@ -1,5 +1,3 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/building/windows.rst - Windows ======= @@ -10,18 +8,20 @@ following packages using: .. code-block:: bash - pacman -S mingw-w64-x86_64-binutils mingw-w64-x86_64-openssl mingw-w64-x86_64-cmake mingw-w64-x86_64-toolchain mingw-w64-x86_64-opus mingw-w64-x86_64-x265 mingw-w64-x86_64-boost git mingw-w64-x86_64-make cmake make gcc + pacman -S mingw-w64-x86_64-binutils mingw-w64-x86_64-openssl mingw-w64-x86_64-cmake \ + mingw-w64-x86_64-toolchain mingw-w64-x86_64-opus mingw-w64-x86_64-x265 mingw-w64-x86_64-boost \ + git mingw-w64-x86_64-make cmake make gcc Build ----- .. Attention:: Ensure you are in the build directory created during the clone step earlier before continuing. - .. code-block:: bash +.. code-block:: bash - cmake -G"Unix Makefiles" .. - cmake -G"MinGW Makefiles" .. # alternatively + cmake -G"Unix Makefiles" .. + cmake -G"MinGW Makefiles" .. # alternatively - mingw32-make + mingw32-make - cpack -G NSIS # optionally, create a windows installer - cpack -G ZIP # optionally, create a windows standalone package + cpack -G NSIS # optionally, create a windows installer + cpack -G ZIP # optionally, create a windows standalone package diff --git a/docs/source/conf.py b/docs/source/conf.py index 5ef4356c70e..65afdc61dbe 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -73,23 +73,11 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'sphinx_rtd_theme' +html_theme = 'furo' html_theme_options = { - # 'analytics_id': 'G-XXXXXXXXXX', # Provided by Google in your dashboard - # 'analytics_anonymize_ip': False, - 'logo_only': False, - 'display_version': False, - 'prev_next_buttons_location': 'bottom', - 'style_external_links': True, - 'vcs_pageview_mode': 'blob', - 'style_nav_header_background': '#151515', - # Toc options - 'collapse_navigation': True, - 'sticky_navigation': True, - 'navigation_depth': 4, - 'includehidden': True, - 'titles_only': False, + "top_of_page_button": "edit", + "source_edit_link": "https://github.com/lizardbyte/sunshine/tree/nightly/docs/source/{filename}", } # extension config options diff --git a/docs/source/contributing/contributing.rst b/docs/source/contributing/contributing.rst index e79fd4eab7e..217bda130bd 100644 --- a/docs/source/contributing/contributing.rst +++ b/docs/source/contributing/contributing.rst @@ -1,39 +1,5 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/contributing/contributing.rst - Contributing ============ -.. Tip:: If this is your first time contributing to an open source project, it is a good idea to read - MDN's `Basic etiquette for open source projects`_ first. There are a few best practices to adopt that will help - ensure that you and the other project contributors feel valued and safe, and stay productive. - -#. Fork the repo on GitHub -#. Create a new branch for the feature you are adding or the issue you are fixing - - .. Tip:: Base the new branch off the `nightly` branch. It will make your life easier when you submit the PR! - -#. Make changes, push commits, etc. -#. Files should contain an empty line at the end. -#. Document your code! -#. Test your code! -#. When ready create a PR to this repo on the `nightly` branch. - - .. Hint:: If you accidentally make your PR against a different branch, a bot will comment letting you know it's on - the wrong branch. Don't worry. You can edit the PR to change the target branch. There is no reason to close the - PR! - - .. Note:: Draft PRs are also welcome as you work through issues. The benefit of creating a draft PR is that an - automated build can run in a github runner. - - .. Attention:: Do not expect partially complete PRs to be merged. These topics will be considered before merging. - - - Does the code follows the style guidelines of this project? - - .. Tip:: Look at examples of existing code in the project! - - - Is the code well commented? - - Were documentation blocks updated for new or modified components? - - .. Note:: Developers and maintainers will attempt to assist with challenging issues. - -.. _Basic etiquette for open source projects: https://developer.mozilla.org/en-US/docs/MDN/Contribute/Open_source_etiquette +Read our contribution guide in our organization level +`docs `_. diff --git a/docs/source/contributing/localization.rst b/docs/source/contributing/localization.rst index 8b04867f16d..dc3e26da877 100644 --- a/docs/source/contributing/localization.rst +++ b/docs/source/contributing/localization.rst @@ -1,5 +1,3 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/contributing/localization.rst - Localization ============ Sunshine is being localized into various languages. The default language is `en` (English) and is highlighted green. @@ -24,15 +22,15 @@ Only elements of the API are planned to be translated. .. Attention:: The rest API has not yet been implemented. -Translations Basics +**Translations Basics** - The brand names `LizardByte` and `Sunshine` should never be translated. - Other brand names should never be translated. Examples: - - AMD - - Nvidia + - AMD + - Nvidia -CrowdIn Integration +**CrowdIn Integration** How does it work? When a change is made to sunshine source code, a workflow generates new translation templates @@ -47,15 +45,14 @@ Extraction There should be minimal cases where strings need to be extracted from source code; however it may be necessary in some situations. For example if a system tray icon is added it should be localized as it is user interfacing. - - Wrap the string to be extracted in a function as shown. - - .. code-block:: cpp +- Wrap the string to be extracted in a function as shown. + .. code-block:: cpp - #include - boost::locale::translate("Hello world!") + #include + boost::locale::translate("Hello world!") - .. Tip:: More examples can be found in the documentation for - `boost locale `_. +.. Tip:: More examples can be found in the documentation for + `boost locale `_. .. Warning:: This is for information only. Contributors should never include manually updated template files, or manually compiled language files in Pull Requests. @@ -65,20 +62,20 @@ used by CrowdIn to generate language specific template files. The file is genera `.github/workflows/localize.yml` workflow and is run on any push event into the `nightly` branch. Jobs are only run if any of the following paths are modified. - .. code-block:: yaml +.. code-block:: yaml - - 'src/**' + - 'src/**' When testing locally it may be desirable to manually extract, initialize, update, and compile strings. Python is required for this, along with the python dependencies in the `./scripts/requirements.txt` file. Additionally, `xgettext `_ must be installed. - Extract, initialize, and update - .. code-block:: bash +**Extract, initialize, and update** + .. code-block:: bash - python ./scripts/_locale.py --extract --init --update + python ./scripts/_locale.py --extract --init --update - Compile - .. code-block:: bash +**Compile** + .. code-block:: bash - python ./scripts/_locale.py --compile + python ./scripts/_locale.py --compile diff --git a/docs/source/contributing/testing.rst b/docs/source/contributing/testing.rst index a08c6f9c819..512aed1ceed 100644 --- a/docs/source/contributing/testing.rst +++ b/docs/source/contributing/testing.rst @@ -1,12 +1,10 @@ -:github_url: https://github.com/RetroArcher/RetroArcher/tree/nightly/docs/source/contributing/testing.rst - Testing ======= Clang Format ------------ Source code is tested against the `.clang-format` file for linting errors. The workflow file responsible for clang -format testing is `.github/workflows/clang.yml`. +format testing is `.github/workflows/cpp-clang-format-lint.yml`. Test clang-format locally. .. Todo:: This documentation needs to be improved. @@ -17,9 +15,9 @@ Test clang-format locally. Sphinx ------ -Sunshine uses `Sphinx `_ for documentation building. Sphinx is included -in the `./scripts/requirements.txt` file. Python is required to build sphinx docs. Installation and setup of python -will not be covered here. +Sunshine uses `Sphinx `_ for documentation building. Sphinx, along with other +required documentation depencies are included in the `./docs/requirements.txt` file. Python is required to build +sphinx docs. Installation and setup of python will not be covered here. The config file for Sphinx is `docs/source/conf.py`. This is already included in the repo and should not be modified. diff --git a/docs/source/troubleshooting/general.rst b/docs/source/troubleshooting/general.rst index 865214dbc63..010a52c825a 100644 --- a/docs/source/troubleshooting/general.rst +++ b/docs/source/troubleshooting/general.rst @@ -1,13 +1,17 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/troubleshooting/general.rst - General ======= If you forgot your credentials to the web UI, try this. - .. code-block:: bash sunshine -creds Can't access the web UI? - #. Check firefall rules. + +NvFBC, NvENC, or general issues with Nvidia graphics card. + - Consumer grade Nvidia cards are software limited to a specific number of encodes. See + `Video Encode and Decode GPU Support Matrix `_ + for more info. + - You can usually bypass the restriction with a driver patch. See Keylase's + `Linux `_ + or `Windows `_ patches for more guidance. diff --git a/docs/source/troubleshooting/linux.rst b/docs/source/troubleshooting/linux.rst index 5bac8c08319..0c8e3f979ba 100644 --- a/docs/source/troubleshooting/linux.rst +++ b/docs/source/troubleshooting/linux.rst @@ -1,9 +1,6 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/troubleshooting/linux.rst - Linux ===== -If screencasting fails with Wayland, you may need to run the following to force screencasting with X11. - +If screencasting fails with KMS, you may need to run the following to force unprivileged screencasting. .. code-block:: bash sudo setcap -r $(readlink -f $(which sunshine)) diff --git a/docs/source/troubleshooting/macos.rst b/docs/source/troubleshooting/macos.rst index f6014eb738a..70a0d60c22f 100644 --- a/docs/source/troubleshooting/macos.rst +++ b/docs/source/troubleshooting/macos.rst @@ -1,29 +1,10 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/troubleshooting/macos.rst - macOS ===== If you get this error: - - ``Dynamic session lookup supported but failed: launchd did not provide a socket path, verify that - org.freedesktop.dbus-session.plist is loaded!`` + `Dynamic session lookup supported but failed: launchd did not provide a socket path, verify that + org.freedesktop.dbus-session.plist is loaded!` Try this. - .. code-block:: bash launchctl load -w /Library/LaunchAgents/org.freedesktop.dbus-session.plist - -Uninstall: - - - pkg - - .. code-block:: bash - - sudo chmod +x /opt/local/etc/sunshine/assets/uninstall_pkg.sh - sudo /opt/local/etc/sunshine/assets/uninstall_pkg.sh - - - Portfile - - .. code-block:: bash - - sudo port uninstall Sunshine diff --git a/docs/source/troubleshooting/windows.rst b/docs/source/troubleshooting/windows.rst index bb21589c153..15053519cb1 100644 --- a/docs/source/troubleshooting/windows.rst +++ b/docs/source/troubleshooting/windows.rst @@ -1,7 +1,4 @@ -:github_url: https://github.com/LizardByte/Sunshine/tree/nightly/docs/source/troubleshooting/windows.rst - Windows ======= No gamepad is detected. - #. Verify that you've installed `ViGEmBus `_. diff --git a/packaging/linux/AppImage/AppRun b/packaging/linux/AppImage/AppRun new file mode 100644 index 00000000000..e9f9f3f733c --- /dev/null +++ b/packaging/linux/AppImage/AppRun @@ -0,0 +1,110 @@ +#!/bin/bash + +# custom AppRun for Sunshine AppImage + +# path of the extracted AppRun +HERE="$(dirname "$(readlink -f "${0}")")" +SUNSHINE_PATH=/usr/bin/sunshine +SUNSHINE_BIN_HERE=$HERE/usr/bin/sunshine +SUNSHINE_SHARE_HERE=$HERE/usr/share/sunshine + +# Set APPDIR when running directly from the AppDir: +if [ -z "$APPDIR" ]; then + ARGV0="AppRun" +fi + +cd "$HERE" || exit 1 + +function help() { +echo " + ------------------------------ + Sunshine AppImage package. + ------------------------------ + + sunshine.AppImage options + ------------------------ + + Usage: $ARGV0 --help, -h + ------ # This message + + $ARGV0 --install, -i + # Install input rules sunshine.service files. Restart required. + + $ARGV0 --remove, -r + # Remove input rules sunshine.service files. + + $ARGV0 --appimage-help + # Show available AppImage options + + sunshine options + ---------------- +" +# print sunshine binary help, replacing the sunshine command in usage statement +"$SUNSHINE_BIN_HERE" --help | sed -e "s#$SUNSHINE_BIN_HERE#$ARGV0#g" +} + +function install() { + # user input rules + sudo usermod -a -G input $USER + # shellcheck disable=SC2002 + cat "$SUNSHINE_SHARE_HERE/udev/rules.d/85-sunshine.rules" | sudo tee /etc/udev/85-sunshine.rules + + # sunshine service + mkdir -p ~/.config/systemd/user + cp -r "$SUNSHINE_SHARE_HERE/systemd/user/" ~/.config/systemd/ + # patch service executable path + sed -i -e "s#$SUNSHINE_PATH#$(readlink -f $ARGV0)#g" ~/.config/systemd/user/sunshine.service + + # setcap + sudo setcap cap_sys_admin+p "$(readlink -f "$SUNSHINE_BIN_HERE")" + + while true + do + read -r -p "This installation requires a reboot. Do you want to reboot NOW? [y/n] " input + + case $input in + [yY][eE][sS]|[yY]) + echo "Yes" + sudo reboot now + ;; + [nN][oO]|[nN]) + echo "No" + break + ;; + *) + echo "Invalid input..." + ;; + esac + done +} + +function remove() { + # remove input rules + sudo rm -f /etc/udev/rules.d/85-sunshine.rules + + # remove service + sudo rm -f ~/.config/systemd/user/sunshine.service +} + +# process arguments +if [ "x$1" == "xhelp" ] || [ "x$1" == "x--help" ] || [ "x$1" == "x-h" ] ; then + help + exit $? +fi + +if [ "x$1" == "xinstall" ] || [ "x$1" == "x--install" ] || [ "x$1" == "x-i" ] ; then + install + exit $? +fi + +if [ "x$1" == "xremove" ] || [ "x$1" == "x--remove" ] || [ "x$1" == "x-r" ] ; then + remove + exit $? +fi + +# create config directory if it doesn't exist +# https://github.com/LizardByte/Sunshine/issues/324 +mkdir -p ~/.config/sunshine + +# run sunshine +"$SUNSHINE_BIN_HERE" $@ diff --git a/packaging/linux/aur/PKGBUILD b/packaging/linux/aur/PKGBUILD index ede1af256eb..1ef6d54b6c5 100644 --- a/packaging/linux/aur/PKGBUILD +++ b/packaging/linux/aur/PKGBUILD @@ -32,10 +32,9 @@ build() { -S "$pkgname" \ -B build \ -Wno-dev \ + -D CMAKE_INSTALL_PREFIX=/usr \ -D SUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine \ - -D CMAKE_INSTALL_PREFIX="/usr" \ - -D SUNSHINE_ASSETS_DIR="share/sunshine/assets" \ - -D SUNSHINE_CONFIG_DIR="share/sunshine/config" \ + -D SUNSHINE_ASSETS_DIR="share/sunshine" \ -D LIBAVCODEC_INCLUDE_DIR=/usr/include/ffmpeg4.4 \ -D LIBAVCODEC_LIBRARIES=/usr/lib/ffmpeg4.4/libavcodec.so \ -D LIBAVDEVICE_INCLUDE_DIR=/usr/include/ffmpeg4.4 \ diff --git a/packaging/linux/flatpak/dev.lizardbyte.sunshine.yml b/packaging/linux/flatpak/dev.lizardbyte.sunshine.yml index 04d3df5a6a9..7bb4cd1b7c5 100644 --- a/packaging/linux/flatpak/dev.lizardbyte.sunshine.yml +++ b/packaging/linux/flatpak/dev.lizardbyte.sunshine.yml @@ -6,16 +6,16 @@ sdk: org.freedesktop.Sdk command: sunshine separate-locales: false finish-args: - - --device=all - - --env=PULSE_PROP_media.category=Manager - - --persist=.config/sunshine - - --share=ipc - - --share=network - - --socket=pulseaudio - - --socket=wayland - - --socket=x11 - - --system-talk-name=org.freedesktop.Avahi - - --talk-name=org.freedesktop.Flatpak + - --device=all # access all devices + - --env=PULSE_PROP_media.category=Manager # allow sunshine to manage audio sinks + - --filesystem=home # need to save files in user's home directory + - --share=ipc # required for X11 shared memory extension + - --share=network # access network + - --socket=pulseaudio # play sounds using pulseaudio + - --socket=wayland # show windows using Wayland + - --socket=x11 # show windows using X11 + - --system-talk-name=org.freedesktop.Avahi # talk to avahi on the system bus + - --talk-name=org.freedesktop.Flatpak # talk to flatpak on the session bus cleanup: - /include @@ -23,47 +23,24 @@ cleanup: - /lib/pkgconfig - /lib/*.la - /lib/*.a - - /share + - /share/man modules: - - name: cuda - disabled: false - buildsystem: simple - only-arches: - - x86_64 - - aarch64 - cleanup: - - '*' - build-commands: - - chmod u+x ./cuda.run - - ./cuda.run --silent --toolkit --toolkitpath=$FLATPAK_DEST/cuda --no-opengl-libs --no-man-page --no-drm --tmpdir=$FLATPAK_BUILDER_BUILDDIR # yamllint disable-line rule:line-length - - rm -r $FLATPAK_DEST/cuda/nsight-systems-2021.3.2 - - rm ./cuda.run - sources: - - type: file - only-arches: - - x86_64 - url: https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run - sha256: bbd87ca0e913f837454a796367473513cddef555082e4d86ed9a38659cc81f0a - dest-filename: cuda.run - - type: file - only-arches: - - aarch64 - url: https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux_sbsa.run # yamllint disable-line rule:line-length - sha256: f2c4a52e06329606c8dfb7c5ea3f4cb4c0b28f9d3fdffeeb734fcc98daf580d8 - dest-filename: cuda.run - - name: boost + disabled: false buildsystem: simple build-commands: - - ./bootstrap.sh --prefix=$FLATPAK_DEST --with-libraries=system,thread,log - - ./b2 install variant=release link=static,shared runtime-link=shared cxxflags="$CXXFLAGS" linkflags="$LDFLAGS" -j $FLATPAK_BUILDER_N_JOBS # yamllint disable-line rule:line-length + - cd tools/build && bison -y -d -o src/engine/jamgram.cpp src/engine/jamgram.y + - ./bootstrap.sh --prefix=$FLATPAK_DEST --with-libraries=system,thread,log || cat bootstrap.log + - ./b2 install variant=release link=static,shared runtime-link=shared cxxflags="$CXXFLAGS" linkflags="$LDFLAGS" + -j $FLATPAK_BUILDER_N_JOBS sources: - type: archive - url: https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2 - sha256: 475d589d51a7f8b3ba2ba4eda022b170e562ca3b760ee922c146b6c65856ef39 + url: http://archive.ubuntu.com/ubuntu/pool/main/b/boost1.74/boost1.74_1.74.0.orig.tar.xz + sha256: 2467be4af625b5ae4b3c93fc7af196a09eba39c11a7338cd9e8b356fa44d2f45 - name: ffmpeg + disabled: false config-opts: - --enable-gpl - --disable-static @@ -71,47 +48,38 @@ modules: - --disable-doc - --disable-programs - --disable-decoders - - --enable-libfontconfig - - --enable-libfreetype - - --enable-libopus - - --enable-libvorbis - - --enable-libvpx + - --disable-vdpau + - --disable-audiotoolbox + - --disable-videotoolbox + - --disable-vulkan + - --disable-sdl2 + - --disable-filters + - --disable-avfilter + - --disable-postproc + - --disable-autodetect + - --enable-nvenc + - --enable-ffnvcodec + - --enable-vaapi - --enable-libx264 - --enable-libx265 - - --enable-nvenc - - --enable-encoder=h264_v4l2m2m - - --enable-encoder=hevc_v4l2m2m - # - --enable-nonfree - # - --enable-cuda-nvcc - # - --enable-libnpp - # - --extra-cflags=-I${FLATPAK_DEST}/cuda/include - # - --extra-ldflags=-L${FLATPAK_DEST}/cuda/lib64 - # - --nvccflags="-gencode arch=compute_52,code=sm_52 -O2" cleanup: - - /share/ffmpeg/examples + - /share sources: - type: archive - url: http://archive.ubuntu.com/ubuntu/pool/universe/f/ffmpeg/ffmpeg_4.4.2.orig.tar.xz - sha256: af419a7f88adbc56c758ab19b4c708afbcae15ef09606b82b855291f6a6faa93 + url: http://archive.ubuntu.com/ubuntu/pool/universe/f/ffmpeg/ffmpeg_5.1.1.orig.tar.xz + sha256: 95bf3ff8c496511e71e958fb249e663c8c9c3de583c5bebc0f5a9745abbc0435 modules: - - name: vmaf - buildsystem: meson - subdir: libvmaf - cleanup: - - /bin - sources: - - type: archive - url: https://github.com/Netflix/vmaf/archive/refs/tags/v2.3.1.tar.gz - sha256: 8d60b1ddab043ada25ff11ced821da6e0c37fd7730dd81c24f1fc12be7293ef2 - name: x264 config-opts: - --disable-cli - --enable-shared sources: - type: archive - url: https://code.videolan.org/videolan/x264/-/archive/stable/x264-stable.tar.bz2 - sha256: 8fedb184045722d8cc39353099373a5b7350171d0964d01fff8eced21b959b29 + url: http://archive.ubuntu.com/ubuntu/pool/universe/x/x264/x264_0.164.3095+gitbaee400.orig.tar.gz + sha256: 8b237e94b08c196a1da22f2f25875f10be4cff3648df4eeff21e00da8f683fc2 + - name: x265 + disabled: false buildsystem: cmake-ninja builddir: true subdir: source @@ -120,9 +88,10 @@ modules: - -DENABLE_CLI=OFF sources: - type: archive - url: https://bitbucket.org/multicoreware/x265_git/downloads/x265_3.5.tar.gz + url: http://archive.ubuntu.com/ubuntu/pool/universe/x/x265/x265_3.5.orig.tar.gz sha256: e70a3335cacacbba0b3a20ec6fecd6783932288ebc8163ad74bcc9606477cae8 - - name: ffnvcodec + + - name: nv-codec-headers no-autogen: true make-install-args: - PREFIX=${FLATPAK_DEST} @@ -130,15 +99,15 @@ modules: - '*' sources: - type: archive - url: https://github.com/FFmpeg/nv-codec-headers/archive/refs/tags/n11.1.5.1.tar.gz + url: http://archive.ubuntu.com/ubuntu/pool/universe/n/nv-codec-headers/nv-codec-headers_11.1.5.1.orig.tar.gz sha256: d095fbd56aa93772471a323be0ebe65504a0f43f06c76a30b6d25da77b06ae9c - name: avahi + disabled: false cleanup: - /bin - /lib/avahi - - /share/applications/*.desktop - - /share/avahi + - /share config-opts: - --with-distro=none - --disable-gobject @@ -161,38 +130,55 @@ modules: - --disable-doxygen-html - --disable-manpages - --disable-xmltoman + - --disable-libevent sources: - type: archive - url: https://avahi.org/download/avahi-0.8.tar.gz + url: http://archive.ubuntu.com/ubuntu/pool/main/a/avahi/avahi_0.8.orig.tar.gz sha256: 060309d7a333d38d951bc27598c677af1796934dbd98e1024e7ad8de798fedda - modules: - - name: libevent - cleanup: - - /bin - sources: - - type: archive - url: https://github.com/libevent/libevent/releases/download/release-2.1.12-stable/libevent-2.1.12-stable.tar.gz # yamllint disable-line rule:line-length - sha256: 92e6de1be9ec176428fd2367677e61ceffc2ee1cb119035037a27d346b0403bb - name: libevdev + disabled: false buildsystem: meson + config-opts: + - -Ddocumentation=disabled + - -Dtests=disabled cleanup: - /bin sources: - type: archive - url: https://www.freedesktop.org/software/libevdev/libevdev-1.12.1.tar.xz - sha256: 1dbba41bc516d3ca7abc0da5b862efe3ea8a7018fa6e9b97ce9d39401b22426c - modules: - - name: libcheck - buildsystem: cmake - cleanup: - - /bin - sources: - - type: archive - url: https://github.com/libcheck/check/archive/refs/tags/0.15.2.tar.gz - sha256: 998d355294bb94072f40584272cf4424571c396c631620ce463f6ea97aa67d2e + url: http://archive.ubuntu.com/ubuntu/pool/main/libe/libevdev/libevdev_1.13.0+dfsg.orig.tar.xz + sha256: a882e13ef1dd6bd227318080cabf60fe5af3c06471259d3acfc9dbfb202351a7 + + - name: cuda + disabled: false + buildsystem: simple + only-arches: + - x86_64 + - aarch64 + cleanup: + - '*' + build-commands: + - chmod u+x ./cuda.run + - ./cuda.run --silent --toolkit --toolkitpath=$FLATPAK_DEST/cuda --no-opengl-libs --no-man-page --no-drm + --tmpdir=$FLATPAK_BUILDER_BUILDDIR + - rm -r $FLATPAK_DEST/cuda/nsight-systems-2021.3.2 + - rm ./cuda.run + sources: + - type: file + only-arches: + - x86_64 + url: https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run + sha256: bbd87ca0e913f837454a796367473513cddef555082e4d86ed9a38659cc81f0a + dest-filename: cuda.run + - type: file + only-arches: + - aarch64 + url: https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux_sbsa.run # yamllint disable-line rule:line-length + sha256: f2c4a52e06329606c8dfb7c5ea3f4cb4c0b28f9d3fdffeeb734fcc98daf580d8 + dest-filename: cuda.run - name: sunshine + disabled: false buildsystem: cmake no-make-install: false builddir: true @@ -202,15 +188,23 @@ modules: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/app - -DCMAKE_CUDA_COMPILER=/app/cuda/bin/nvcc - - -DSUNSHINE_ASSETS_DIR=assets - - -DSUNSHINE_CONFIG_DIR=config + - -DSUNSHINE_ASSETS_DIR=share/sunshine - -DSUNSHINE_EXECUTABLE_PATH=/app/bin/sunshine - -DSUNSHINE_ENABLE_WAYLAND=ON - -DSUNSHINE_ENABLE_X11=ON - -DSUNSHINE_ENABLE_DRM=ON - -DSUNSHINE_ENABLE_CUDA=ON + - -DSUNSHINE_CONFIGURE_FLATPAK=ON sources: - type: git url: '@GITHUB_CLONE_URL@' branch: '@GITHUB_BRANCH@' commit: '@GITHUB_COMMIT@' + post-install: + # use `sed` to update apps.json with prefixes required for flatpak + # -r (regex) + # -z (handle new lines) https://linuxhint.com/sed-replace-newline-with-space + # `/gm` global and multiline + - sed -r -z -i -e + 's/("((do)|(undo)|(cmd)|(detached))"\s*:\s*\[?\n*\s*")(.*")/\1flatpak-spawn --host \7/gm' + /app/share/sunshine/apps.json diff --git a/packaging/macos/Portfile b/packaging/macos/Portfile index 8707cedca13..d440fad3e16 100644 --- a/packaging/macos/Portfile +++ b/packaging/macos/Portfile @@ -35,11 +35,10 @@ depends_lib port:avahi \ port:ffmpeg \ port:libopus -boost.version 1.76 +boost.version 1.80 configure.args -DCMAKE_INSTALL_PREFIX=${prefix} \ - -DSUNSHINE_ASSETS_DIR=etc/sunshine/assets \ - -DSUNSHINE_CONFIG_DIR=etc/sunshine/config + -DSUNSHINE_ASSETS_DIR=etc/sunshine/assets startupitem.create yes startupitem.executable "${prefix}/bin/{$name}" @@ -54,30 +53,6 @@ platform darwin { } } -# destroot not required as cmake install directive handles moving files - -# # Rename files in `destroot` -# post-destroot { -# file rename ${destroot}${prefix}/etc/${name}/config/sunshine.conf ${destroot}${prefix}/etc/${name}/config/sunshine.conf.sample -# file rename ${destroot}${prefix}/etc/${name}/config/apps.json ${destroot}${prefix}/etc/${name}/config/apps.json.sample -# } - -# # Don't overwrite existing preference files -# post-activate { -# if {![file exists ${prefix}/etc/${name}/config/sunshine.conf]} { -# file copy ${destroot}${prefix}/etc/${name}/config/sunshine.conf.sample \ -# ${prefix}/etc/${name}/config/sunshine.conf -# } -# if {![file exists ${prefix}/etc/${name}/config/apps.json]} { -# file copy ${destroot}${prefix}/etc/${name}/config/apps.json.sample \ -# ${prefix}/etc/${name}/config/apps.json -# } -# } - -# disabled not overwriting config files... these are the default config files required by Sunshine -# this did not work with pkg created by macports -# we should always install the default files and user should start sunshine like "sunshine " -# if the file doesn't exist sunshine will copy the default config to that location notes-append "Run @PROJECT_NAME@ by executing 'sunshine ', e.g. 'sunshine ~/sunshine.conf' " notes-append "The config file will be created if it doesn't exist." notes-append "It is recommended to set a location for the apps file in the config." diff --git a/scripts/Dockerfile-debian b/scripts/Dockerfile-debian deleted file mode 100644 index fc77eb8e989..00000000000 --- a/scripts/Dockerfile-debian +++ /dev/null @@ -1,40 +0,0 @@ -FROM debian:bullseye AS sunshine-debian - -# Debian Bullseye end of life is TBD - -ARG DEBIAN_FRONTEND=noninteractive -ARG TZ="Europe/London" - -SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN echo deb http://deb.debian.org/debian/ bullseye main contrib non-free | tee /etc/apt/sources.list.d/non-free.list -RUN apt-get update -y && \ - apt-get install -y \ - build-essential \ - cmake \ - git \ - libavdevice-dev \ - libboost-filesystem-dev \ - libboost-log-dev \ - libboost-thread-dev \ - libcap-dev \ - libdrm-dev \ - libevdev-dev \ - libpulse-dev \ - libopus-dev \ - libssl-dev \ - libwayland-dev \ - libx11-dev \ - libxcb-shm0-dev \ - libxcb-xfixes0-dev \ - libxcb1-dev \ - libxfixes-dev \ - libxrandr-dev \ - libxtst-dev \ - nvidia-cuda-dev \ - nvidia-cuda-toolkit \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* - -# Entrypoint -COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh", "-deb"] diff --git a/scripts/Dockerfile-fedora_33 b/scripts/Dockerfile-fedora_33 deleted file mode 100644 index 320c6a6748c..00000000000 --- a/scripts/Dockerfile-fedora_33 +++ /dev/null @@ -1,32 +0,0 @@ -FROM fedora:33 AS sunshine-fedora_33 - -# Fedora 33 end of life is November 2021 -# This file remains for reference only - -SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN dnf -y update && \ - dnf -y group install "Development Tools" && \ - dnf -y install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm && \ - dnf -y install \ - boost-devel \ - boost-static.x86_64 \ - cmake \ - ffmpeg-devel \ - libevdev-devel \ - libxcb-devel \ - libX11-devel \ - libXfixes-devel \ - libXrandr-devel \ - libXtst-devel \ - openssl-devel \ - opus-devel \ - pulseaudio-libs-devel \ - libcap-devel \ - libdrm-devel \ - rpm-build \ - && dnf clean all \ - && rm -rf /var/cache/yum - -# Entrypoint -COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh", "-rpm"] diff --git a/scripts/Dockerfile-fedora_35 b/scripts/Dockerfile-fedora_35 deleted file mode 100644 index 18f5bf53a56..00000000000 --- a/scripts/Dockerfile-fedora_35 +++ /dev/null @@ -1,36 +0,0 @@ -FROM fedora:35 AS sunshine-fedora_35 - -# Fedora 35 end of life is TBD - -SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN dnf -y update && \ - dnf -y group install "Development Tools" && \ - dnf -y install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm && \ - dnf -y install \ - boost-devel \ - boost-static.x86_64 \ - cmake \ - ffmpeg-devel \ - gcc-c++ \ - libevdev-devel \ - libX11-devel \ - libxcb-devel \ - libXcursor-devel \ - libXfixes-devel \ - libXinerama-devel \ - libXi-devel \ - libXrandr-devel \ - libXtst-devel \ - mesa-libGL-devel \ - openssl-devel \ - opus-devel \ - pulseaudio-libs-devel \ - libcap-devel \ - libdrm-devel \ - rpm-build \ - && dnf clean all \ - && rm -rf /var/cache/yum - -# Entrypoint -COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh", "-rpm"] diff --git a/scripts/Dockerfile-ubuntu_18_04 b/scripts/Dockerfile-ubuntu_18_04 deleted file mode 100644 index 6ad3e8c02ad..00000000000 --- a/scripts/Dockerfile-ubuntu_18_04 +++ /dev/null @@ -1,63 +0,0 @@ -FROM ubuntu:18.04 AS sunshine-ubuntu_18_04 - -# Ubuntu 18.04 end of life is April 2028 - -ARG DEBIAN_FRONTEND=noninteractive -ARG TZ="Europe/London" - -SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN apt-get update -y && \ - apt-get install -y \ - software-properties-common \ - && add-apt-repository ppa:savoury1/graphics && \ - add-apt-repository ppa:savoury1/multimedia && \ - add-apt-repository ppa:savoury1/ffmpeg4 && \ - add-apt-repository ppa:savoury1/boost-defaults-1.71 && \ - add-apt-repository ppa:ubuntu-toolchain-r/test && \ - apt-get update -y && \ - apt-get install -y \ - build-essential \ - cmake \ - gcc-10 \ - git \ - g++-10 \ - libavdevice-dev \ - libboost-filesystem1.71-dev \ - libboost-log1.71-dev \ - libboost-regex1.71-dev \ - libboost-thread1.71-dev \ - libcap-dev \ - libdrm-dev \ - libevdev-dev \ - libpulse-dev \ - libopus-dev \ - libssl-dev \ - libwayland-dev \ - libx11-dev \ - libxcb-shm0-dev \ - libxcb-xfixes0-dev \ - libxcb1-dev \ - libxfixes-dev \ - libxrandr-dev \ - libxtst-dev \ - wget \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* - -# Update gcc alias -RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 - -# Install CuDA -RUN wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run && chmod a+x /root/cuda.run -RUN /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && rm /root/cuda.run - -# Install cmake -ADD https://cmake.org/files/v3.22/cmake-3.22.2-linux-x86_64.sh /cmake-3.22.2-linux-x86_64.sh -RUN mkdir /opt/cmake -RUN sh /cmake-3.22.2-linux-x86_64.sh --prefix=/opt/cmake --skip-license -RUN ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake -RUN cmake --version - -# Entrypoint -COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh", "-deb"] diff --git a/scripts/Dockerfile-ubuntu_20_04 b/scripts/Dockerfile-ubuntu_20_04 deleted file mode 100644 index 44e897a7586..00000000000 --- a/scripts/Dockerfile-ubuntu_20_04 +++ /dev/null @@ -1,46 +0,0 @@ -FROM ubuntu:20.04 AS sunshine-ubuntu_20_04 - -# Ubuntu 20.04 end of life is April 2030 - -ARG DEBIAN_FRONTEND=noninteractive -ARG TZ="Europe/London" - -SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN apt-get update -y && \ - apt-get install -y \ - build-essential \ - cmake \ - git \ - g++-10 \ - libavdevice-dev \ - libboost-filesystem-dev \ - libboost-log-dev \ - libboost-thread-dev \ - libcap-dev \ - libdrm-dev \ - libevdev-dev \ - libpulse-dev \ - libopus-dev \ - libssl-dev \ - libwayland-dev \ - libx11-dev \ - libxcb-shm0-dev \ - libxcb-xfixes0-dev \ - libxcb1-dev \ - libxfixes-dev \ - libxrandr-dev \ - libxtst-dev \ - wget \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* - -# Update gcc alias -RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 - -# Install CuDA -RUN wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run && chmod a+x /root/cuda.run -RUN /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && rm /root/cuda.run - -# Entrypoint -COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh", "-deb"] diff --git a/scripts/Dockerfile-ubuntu_21_04 b/scripts/Dockerfile-ubuntu_21_04 deleted file mode 100644 index 012845a5b69..00000000000 --- a/scripts/Dockerfile-ubuntu_21_04 +++ /dev/null @@ -1,40 +0,0 @@ -FROM ubuntu:21.04 AS sunshine-ubuntu_21_04 - -# Ubuntu 21.04 end of life is January 2022 -# This file remains for reference only - -ARG DEBIAN_FRONTEND=noninteractive -ARG TZ="Europe/London" - -SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN apt-get update -y && \ - apt-get install -y \ - build-essential \ - cmake \ - git \ - libavdevice-dev \ - libboost-thread-dev \ - libboost-filesystem-dev \ - libboost-log-dev \ - libcap-dev \ - libdrm-dev \ - libevdev-dev \ - libpulse-dev \ - libopus-dev \ - libssl-dev \ - libwayland-dev \ - libx11-dev \ - libxcb-shm0-dev \ - libxcb-xfixes0-dev \ - libxcb1-dev \ - libxfixes-dev \ - libxrandr-dev \ - libxtst-dev \ - nvidia-cuda-dev \ - nvidia-cuda-toolkit \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* - -# Entrypoint -COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh", "-deb"] diff --git a/scripts/Dockerfile-ubuntu_21_10 b/scripts/Dockerfile-ubuntu_21_10 deleted file mode 100644 index 6be49dbe0cb..00000000000 --- a/scripts/Dockerfile-ubuntu_21_10 +++ /dev/null @@ -1,39 +0,0 @@ -FROM ubuntu:21.10 AS sunshine-ubuntu_21_10 - -# Ubuntu 21.10 end of life is July 2022 - -ARG DEBIAN_FRONTEND=noninteractive -ARG TZ="Europe/London" - -SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN apt-get update -y && \ - apt-get install -y \ - build-essential \ - cmake \ - git \ - libavdevice-dev \ - libboost-filesystem-dev \ - libboost-log-dev \ - libboost-thread-dev \ - libcap-dev \ - libdrm-dev \ - libevdev-dev \ - libpulse-dev \ - libopus-dev \ - libssl-dev \ - libwayland-dev \ - libx11-dev \ - libxcb-shm0-dev \ - libxcb-xfixes0-dev \ - libxcb1-dev \ - libxfixes-dev \ - libxrandr-dev \ - libxtst-dev \ - nvidia-cuda-dev \ - nvidia-cuda-toolkit \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* - -# Entrypoint -COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh", "-deb"] diff --git a/scripts/build-container.sh b/scripts/build-container.sh deleted file mode 100755 index 5da4784aef2..00000000000 --- a/scripts/build-container.sh +++ /dev/null @@ -1,179 +0,0 @@ -#!/bin/bash -e -set -e - -usage() { - echo "Usage: $0 [OPTIONS]" - echo " -c: command --> default [build]" - echo " | delete --> Delete the container, Dockerfile isn't mandatory" - echo " | build --> Build the container, Dockerfile is mandatory" - echo " | compile --> Builds the container, then compiles it. Dockerfile is mandatory" - echo "" - echo " -s: path: The path to the source for compilation" - echo " -n: name: Docker container name --> default [sunshine]" - echo " --> all: Build/Compile/Delete all available docker containers" - echo " -f: Dockerfile: The name of the docker file" -} - -# Attempt to turn relative paths into absolute paths -absolute_path() { - RELATIVE_PATH=$1 - if which realpath >/dev/null 2>/dev/null - then - RELATIVE_PATH=$(realpath $RELATIVE_PATH) - else - echo "Warning: realpath is not installed on your system, ensure [$1] is absolute" - fi - - RETURN=$RELATIVE_PATH -} - -CONTAINER_NAME=sunshine -COMMAND=BUILD - -build_container() { - CONTAINER_NAME=$1 - DOCKER_FILE=$2 - - if [ ! -f "$DOCKER_FILE" ] - then - echo "Error: $DOCKER_FILE doesn't exist" - exit 7 - fi - - echo "docker build . -t $CONTAINER_NAME -f $DOCKER_FILE" - docker build . -t "$CONTAINER_NAME" -f "$DOCKER_FILE" -} - -delete() { - CONTAINER_NAME_UPPER=$(echo "$CONTAINER_NAME" | tr '[:lower:]' '[:upper:]') - if [ "$CONTAINER_NAME_UPPER" = "ALL" ] - then - shopt -s nullglob - for file in $(find . -maxdepth 1 -iname "Dockerfile-*" -type f) - do - CURRENT_CONTAINER="sunshine-$(echo $file | cut -c 14-)" - - if docker inspect "$CURRENT_CONTAINER" > /dev/null 2> /dev/null - then - echo "docker rmi $CURRENT_CONTAINER" - docker rmi "$CURRENT_CONTAINER" - fi - done - shopt -u nullglob #revert nullglob back to it's normal default state - else - if docker inspect "$CONTAINER_NAME" > /dev/null 2> /dev/null - then - echo "docker rmi $CONTAINER_NAME" - docker rmi $CONTAINER_NAME - fi - fi -} - -build() { - CONTAINER_NAME_UPPER=$(echo "$CONTAINER_NAME" | tr '[:lower:]' '[:upper:]') - if [ "$CONTAINER_NAME_UPPER" = "ALL" ] - then - shopt -s nullglob - for file in $(find . -maxdepth 1 -iname "Dockerfile-*" -type f) - do - CURRENT_CONTAINER="sunshine-$(echo $file | cut -c 14-)" - build_container "$CURRENT_CONTAINER" "$file" - done - shopt -u nullglob #revert nullglob back to it's normal default state - else - if [[ -z "$DOCKER_FILE" ]] - then - echo "Error: if container name isn't equal to 'all', you need to specify the Dockerfile" - exit 6 - fi - - build_container "$CONTAINER_NAME" "$DOCKER_FILE" - fi -} - -abort() { - echo "$1" - exit 10 -} - -compile() { - CONTAINER_NAME_UPPER=$(echo "$CONTAINER_NAME" | tr '[:lower:]' '[:upper:]') - if [ "$CONTAINER_NAME_UPPER" = "ALL" ] - then - shopt -s nullglob - - # If any docker container doesn't exist, we cannot compile all of them - for file in $(find . -maxdepth 1 -iname "Dockerfile-*" -type f) - do - CURRENT_CONTAINER="sunshine-$(echo $file | cut -c 14-)" - - # If container doesn't exist --> abort. - docker inspect "$CURRENT_CONTAINER" > /dev/null 2> /dev/null || abort "Error: container image [$CURRENT_CONTAINER] doesn't exist" - done - - for file in $(find . -maxdepth 1 -iname "Dockerfile-*" -type f) - do - CURRENT_CONTAINER="sunshine-$(echo $file | cut -c 14-)" - - echo "$PWD/build-sunshine.sh -p -n $CURRENT_CONTAINER $SUNSHINE_SOURCES" - "$PWD/build-sunshine.sh" -p -n "$CURRENT_CONTAINER" $SUNSHINE_SOURCES - done - shopt -u nullglob #revert nullglob back to it's normal default state - else - # If container exists - if docker inspect "$CONTAINER_NAME" > /dev/null 2> /dev/null - then - echo "$PWD/build-sunshine.sh -p -n $CONTAINER_NAME $SUNSHINE_SOURCES" - "$PWD/build-sunshine.sh" -p -n "$CONTAINER_NAME" $SUNSHINE_SOURCES - else - echo "Error: container image [$CONTAINER_NAME] doesn't exist" - exit 9 - fi - fi -} - -while getopts ":c:hn:f:s:" arg; do - case ${arg} in - s) - SUNSHINE_SOURCES="-s $OPTARG" - ;; - c) - COMMAND=$(echo $OPTARG | tr '[:lower:]' '[:upper:]') - ;; - n) - echo "Container name: $OPTARG" - CONTAINER_NAME="$OPTARG" - ;; - f) - echo "Using Dockerfile [$OPTARG]" - DOCKER_FILE="$OPTARG" - ;; - h) - usage - exit 0 - ;; - esac -done - -echo "$0 set to $(echo $COMMAND | tr '[:upper:]' '[:lower:]')" - -if [ "$COMMAND" = "BUILD" ] -then - echo "Start building..." - delete - build - echo "Done." -elif [ "$COMMAND" = "COMPILE" ] -then - echo "Start compiling..." - compile - echo "Done." -elif [ "$COMMAND" = "DELETE" ] -then - echo "Start deleting..." - delete - echo "Done." -else - echo "Unknown command [$(echo $COMMAND | tr '[:upper:]' '[:lower:]')]" - exit 4 -fi diff --git a/scripts/build-private.sh b/scripts/build-private.sh deleted file mode 100755 index 80c7d6bcb49..00000000000 --- a/scripts/build-private.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash -e -set -e - -CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" -SUNSHINE_EXECUTABLE_PATH="${SUNSHINE_EXECUTABLE_PATH:-/usr/bin/sunshine}" -SUNSHINE_ASSETS_DIR="${SUNSHINE_ASSETS_DIR:-/etc/sunshine}" - - -SUNSHINE_ROOT="${SUNSHINE_ROOT:-/root/sunshine}" -SUNSHINE_TAG="${SUNSHINE_TAG:-master}" -SUNSHINE_GIT_URL="${SUNSHINE_GIT_URL:-https://github.com/lizardbyte/sunshine.git}" - - -SUNSHINE_ENABLE_WAYLAND=${SUNSHINE_ENABLE_WAYLAND:-ON} -SUNSHINE_ENABLE_X11=${SUNSHINE_ENABLE_X11:-ON} -SUNSHINE_ENABLE_DRM=${SUNSHINE_ENABLE_DRM:-ON} -SUNSHINE_ENABLE_CUDA=${SUNSHINE_ENABLE_CUDA:-ON} - -# For debugging, it would be usefull to have the sources on the host. -if [[ ! -d "$SUNSHINE_ROOT" ]] -then - git clone --depth 1 --branch "$SUNSHINE_TAG" "$SUNSHINE_GIT_URL" --recurse-submodules "$SUNSHINE_ROOT" -fi - -if [[ ! -d /root/sunshine-build ]] -then - mkdir -p /root/sunshine-build -fi -cd /root/sunshine-build - -cmake "-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE" "-DSUNSHINE_EXECUTABLE_PATH=$SUNSHINE_EXECUTABLE_PATH" "-DSUNSHINE_ASSETS_DIR=$SUNSHINE_ASSETS_DIR" "-DSUNSHINE_ENABLE_WAYLAND=$SUNSHINE_ENABLE_WAYLAND" "-DSUNSHINE_ENABLE_X11=$SUNSHINE_ENABLE_X11" "-DSUNSHINE_ENABLE_DRM=$SUNSHINE_ENABLE_DRM" "-DSUNSHINE_ENABLE_CUDA=$SUNSHINE_ENABLE_CUDA" "$SUNSHINE_ROOT" - -make -j ${nproc} - -# Get preferred package format -if [ "$1" == "-rpm" ] -then - echo "Packaging in .rpm format." - ./gen-rpm -d -elif [ "$1" == "-deb" ] -then - echo "Packaging in .deb format." - ./gen-deb -else - echo "Preferred packaging not specified." - echo "Use -deb or -rpm to specify preferred package format." - exit 1 -fi diff --git a/scripts/build-sunshine.sh b/scripts/build-sunshine.sh deleted file mode 100755 index 4284375290b..00000000000 --- a/scripts/build-sunshine.sh +++ /dev/null @@ -1,132 +0,0 @@ -#!/bin/bash -e -set -e - -usage() { - echo "Usage: $0" - echo " -d: Generate a debug build" - echo " -p: Generate a linux package" - echo " -e: Extension of package... i.e. 'deb', 'rpm' --> default [deb]" - echo " -u: The input device is not a TTY" - echo " -n name: Docker container name --> default [sunshine]" - echo " -s path/to/sources/sunshine: Use local sources instead of a git repository" - echo " -c path/to/cmake/binary/dir: Store cmake output on host OS" -} - -# Attempt to turn relative paths into absolute paths -absolute_path() { - RELATIVE_PATH=$1 - if which realpath >/dev/null 2>/dev/null - then - RELATIVE_PATH=$(realpath $RELATIVE_PATH) - else - echo "Warning: realpath is not installed on your system, ensure [$1] is absolute" - fi - - RETURN=$RELATIVE_PATH -} - -CMAKE_BUILD_TYPE="-e CMAKE_BUILD_TYPE=Release" -SUNSHINE_PACKAGE_BUILD=OFF -SUNSHINE_PACKAGE_EXTENSION=deb -SUNSHINE_GIT_URL=https://github.com/lizardbyte/sunshine.git -CONTAINER_NAME=sunshine - -# Docker will fail if ctrl+c is passed through and the input is not a tty -DOCKER_INTERACTIVE=-ti - -while getopts ":dpuhc:e:s:n:" arg; do - case ${arg} in - u) - echo "Input device is not a TTY" - USERNAME="$USER" - unset DOCKER_INTERACTIVE - ;; - d) - echo "Creating debug build" - CMAKE_BUILD_TYPE="-e CMAKE_BUILD_TYPE=Debug" - ;; - p) - echo "Creating package build" - SUNSHINE_PACKAGE_BUILD=ON - SUNSHINE_ASSETS_DIR="-e SUNSHINE_ASSETS_DIR=/etc/sunshine" - SUNSHINE_EXECUTABLE_PATH="-e SUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine" - ;; - e) - echo "Defining package extension: $OPTARG" - if [ "$OPTARG" == "deb" ] - then - SUNSHINE_PACKAGE_EXTENSION=$OPTARG - echo "Package extension: deb" - elif [ "$OPTARG" == "rpm" ] - then - SUNSHINE_PACKAGE_EXTENSION=$OPTARG - echo "Package extension: rpm" - else - echo "Package extension not supported: $OPTARG" - echo "Falling back to default package extension: $SUNSHINE_PACKAGE_EXTENSION" - fi - ;; - s) - absolute_path "$OPTARG" - OPTARG="$RETURN" - echo "Using sources from $OPTARG" - SUNSHINE_ROOT="-v $OPTARG:/root/sunshine" - ;; - c) - [ "$USERNAME" == "" ] && USERNAME=$(logname) - - absolute_path "$OPTARG" - OPTARG="$RETURN" - - echo "Using $OPTARG as cmake binary dir" - if [[ ! -d $OPTARG ]] - then - echo "cmake binary dir doesn't exist, a new one will be created." - mkdir -p "$OPTARG" - [ "$USERNAME" == "$USER"] || chown $USERNAME:$USERNAME "$OPTARG" - fi - - CMAKE_ROOT="-v $OPTARG:/root/sunshine-build" - ;; - n) - echo "Container name: $OPTARG" - CONTAINER_NAME=$OPTARG - ;; - h) - usage - exit 0 - ;; - esac -done - -[ "$USERNAME" = "" ] && USERNAME=$(logname) - -BUILD_DIR="$PWD/$CONTAINER_NAME-build" -[ "$SUNSHINE_ASSETS_DIR" = "" ] && SUNSHINE_ASSETS_DIR="-e SUNSHINE_ASSETS_DIR=$BUILD_DIR/assets" -[ "$SUNSHINE_EXECUTABLE_PATH" = "" ] && SUNSHINE_EXECUTABLE_PATH="-e SUNSHINE_EXECUTABLE_PATH=$BUILD_DIR/sunshine" - -echo "docker run $DOCKER_INTERACTIVE --privileged $SUNSHINE_ROOT $CMAKE_ROOT $SUNSHINE_ASSETS_DIR $SUNSHINE_EXECUTABLE_PATH $CMAKE_BUILD_TYPE --name $CONTAINER_NAME $CONTAINER_NAME" -docker run $DOCKER_INTERACTIVE --privileged $SUNSHINE_ROOT $CMAKE_ROOT $SUNSHINE_ASSETS_DIR $SUNSHINE_EXECUTABLE_PATH $CMAKE_BUILD_TYPE --name $CONTAINER_NAME $CONTAINER_NAME - -exit_code=$? - -if [ $exit_code -eq 0 ] -then - mkdir -p $BUILD_DIR - case $SUNSHINE_PACKAGE_BUILD in - ON) - echo "Downloading package to: $BUILD_DIR/$CONTAINER_NAME.$SUNSHINE_PACKAGE_EXTENSION" - docker cp $CONTAINER_NAME:/root/sunshine-build/package-$SUNSHINE_PACKAGE_EXTENSION/sunshine.$SUNSHINE_PACKAGE_EXTENSION "$BUILD_DIR/$CONTAINER_NAME.$SUNSHINE_PACKAGE_EXTENSION" - ;; - *) - echo "Downloading binary and assets to: $BUILD_DIR" - docker cp $CONTAINER_NAME:/root/sunshine/assets "$BUILD_DIR" - docker cp $CONTAINER_NAME:/root/sunshine-build/sunshine "$BUILD_DIR" - ;; - esac - echo "chown --recursive $USERNAME:$USERNAME $BUILD_DIR" - chown --recursive $USERNAME:$USERNAME "$BUILD_DIR" -fi - -echo "Removing docker container $CONTAINER_NAME" -docker rm $CONTAINER_NAME diff --git a/scripts/requirements.txt b/scripts/requirements.txt index a572e2493ab..ab35a359f59 100644 --- a/scripts/requirements.txt +++ b/scripts/requirements.txt @@ -1,5 +1 @@ Babel==2.10.3 -m2r2==0.3.2 -Sphinx==5.1.1 -sphinx-copybutton==0.5.0 -sphinx-rtd-theme==1.0.0 diff --git a/src/audio.cpp b/src/audio.cpp index 2894d12884d..c5b6a976de1 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -75,7 +75,7 @@ auto control_shared = safe::make_shared(start_audio_control, stop_a void encodeThread(sample_queue_t samples, config_t config, void *channel_data) { auto packets = mail::man->queue(mail::audio_packets); - //FIXME: Pick correct opus_stream_config_t based on config.channels + // FIXME: Pick correct opus_stream_config_t based on config.channels auto stream = &stream_configs[map_stream(config.channels, config.flags[config_t::HIGH_QUALITY])]; opus_t opus { opus_multistream_encoder_create( @@ -120,7 +120,7 @@ void encodeThread(sample_queue_t samples, config_t config, void *channel_data) { void capture(safe::mail_t mail, config_t config, void *channel_data) { auto shutdown_event = mail->event(mail::shutdown); - //FIXME: Pick correct opus_stream_config_t based on config.channels + // FIXME: Pick correct opus_stream_config_t based on config.channels auto stream = &stream_configs[map_stream(config.channels, config.flags[config_t::HIGH_QUALITY])]; auto ref = control_shared.ref(); @@ -135,7 +135,7 @@ void capture(safe::mail_t mail, config_t config, void *channel_data) { return; } - // Order of priorty: + // Order of priority: // 1. Config // 2. Virtual if available // 3. Host @@ -162,8 +162,14 @@ void capture(safe::mail_t mail, config_t config, void *channel_data) { if(!ref->sink_flag->exchange(true, std::memory_order_acquire)) { ref->restore_sink = !config.flags[config_t::HOST_AUDIO]; + // If the sink is empty (Host has no sink!), definately switch to the virtual. + if(ref->sink.host.empty()) { + if(control->set_sink(*sink)) { + return; + } + } // If the client requests audio on the host, don't change the default sink - if(!config.flags[config_t::HOST_AUDIO] && control->set_sink(*sink)) { + else if(!config.flags[config_t::HOST_AUDIO] && control->set_sink(*sink)) { return; } } diff --git a/src/cbs.cpp b/src/cbs.cpp index e4e24571363..d50bd1951fb 100644 --- a/src/cbs.cpp +++ b/src/cbs.cpp @@ -124,9 +124,9 @@ util::buffer_t make_sps_h264(const AVCodecContext *ctx) { sps.seq_parameter_set_id = 0; sps.chroma_format_idc = 1; - sps.log2_max_frame_num_minus4 = 3; //4; + sps.log2_max_frame_num_minus4 = 3; // 4; sps.pic_order_cnt_type = 0; - sps.log2_max_pic_order_cnt_lsb_minus4 = 0; //4; + sps.log2_max_pic_order_cnt_lsb_minus4 = 0; // 4; sps.max_num_ref_frames = dpb_frame; @@ -297,4 +297,4 @@ bool validate_sps(const AVPacket *packet, int codec_id) { return ((CodedBitstreamH265Context *)ctx->priv_data)->active_sps->vui_parameters_present_flag; } -} // namespace cbs \ No newline at end of file +} // namespace cbs diff --git a/src/cbs.h b/src/cbs.h index dc772dd94b4..cd989b4a172 100644 --- a/src/cbs.h +++ b/src/cbs.h @@ -31,4 +31,4 @@ h264_t make_sps_h264(const AVCodecContext *ctx, const AVPacket *packet); bool validate_sps(const AVPacket *packet, int codec_id); } // namespace cbs -#endif \ No newline at end of file +#endif diff --git a/src/config.cpp b/src/config.cpp index fd887605019..b7f483ac6f3 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -6,6 +6,7 @@ #include #include +#include #include "config.h" #include "main.h" @@ -104,14 +105,14 @@ enum quality_e : int { enum class rc_hevc_e : int { constqp, /**< Constant QP mode */ vbr_latency, /**< Latency Constrained Variable Bitrate */ - vbr_peak, /**< Peak Contrained Variable Bitrate */ + vbr_peak, /**< Peak Constrained Variable Bitrate */ cbr, /**< Constant bitrate mode */ }; enum class rc_h264_e : int { constqp, /**< Constant QP mode */ cbr, /**< Constant bitrate mode */ - vbr_peak, /**< Peak Contrained Variable Bitrate */ + vbr_peak, /**< Peak Constrained Variable Bitrate */ vbr_latency, /**< Latency Constrained Variable Bitrate */ }; @@ -702,7 +703,7 @@ int apply_flags(const char *line) { void apply_config(std::unordered_map &&vars) { if(!fs::exists(stream.file_apps.c_str())) { - fs::copy_file(SUNSHINE_CONFIG_DIR "/apps.json", stream.file_apps); + fs::copy_file(SUNSHINE_ASSETS_DIR "/apps.json", stream.file_apps); } for(auto &[name, val] : vars) { @@ -910,8 +911,14 @@ int parse(int argc, char *argv[]) { } } + // create appdata folder if it does not exist + if(!boost::filesystem::exists(platf::appdata().string())) { + boost::filesystem::create_directory(platf::appdata().string()); + } + + // create config file if it does not exist if(!fs::exists(sunshine.config_file)) { - fs::copy_file(SUNSHINE_CONFIG_DIR "/sunshine.conf", sunshine.config_file); + std::ofstream { sunshine.config_file }; // create empty config file } auto vars = parse_config(read_file(sunshine.config_file.c_str())); diff --git a/src/confighttp.cpp b/src/confighttp.cpp index c21089de21f..f5f2ce090b9 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -1,4 +1,3 @@ -// // Created by TheElixZammuto on 2021-05-09. // TODO: Authentication, better handling of routes common to nvhttp, cleanup @@ -92,7 +91,7 @@ bool authenticate(resp_https_t response, req_https_t request) { return false; } - //If credentials are shown, redirect the user to a /welcome page + // If credentials are shown, redirect the user to a /welcome page if(config::sunshine.username.empty()) { send_redirect(response, request, "/welcome"); return false; @@ -314,7 +313,7 @@ void saveApp(resp_https_t response, req_https_t request) { BOOST_LOG(fatal) << config::stream.file_apps; try { - //TODO: Input Validation + // TODO: Input Validation pt::read_json(ss, inputTree); pt::read_json(config::stream.file_apps, fileTree); @@ -335,7 +334,7 @@ void saveApp(resp_https_t response, req_https_t request) { apps_node.push_back(std::make_pair("", inputTree)); } else { - //Unfortuantely Boost PT does not allow to directly edit the array, copy should do the trick + // Unfortunately Boost PT does not allow to directly edit the array, copy should do the trick pt::ptree newApps; int i = 0; for(const auto &kv : apps_node) { @@ -388,7 +387,7 @@ void deleteApp(resp_https_t response, req_https_t request) { return; } else { - //Unfortuantely Boost PT does not allow to directly edit the array, copy should do the trick + // Unfortunately Boost PT does not allow to directly edit the array, copy should do the trick pt::ptree newApps; int i = 0; for(const auto &kv : apps_node) { @@ -452,7 +451,7 @@ void saveConfig(resp_https_t response, req_https_t request) { }); pt::ptree inputTree; try { - //TODO: Input Validation + // TODO: Input Validation pt::read_json(ss, inputTree); for(const auto &kv : inputTree) { std::string value = inputTree.get(kv.first); @@ -488,7 +487,7 @@ void savePassword(resp_https_t response, req_https_t request) { }); try { - //TODO: Input Validation + // TODO: Input Validation pt::read_json(ss, inputTree); auto username = inputTree.count("currentUsername") > 0 ? inputTree.get("currentUsername") : ""; auto newUsername = inputTree.get("newUsername"); @@ -544,7 +543,7 @@ void savePin(resp_https_t response, req_https_t request) { }); try { - //TODO: Input Validation + // TODO: Input Validation pt::read_json(ss, inputTree); std::string pin = inputTree.get("pin"); outputTree.put("status", nvhttp::pin(pin)); diff --git a/src/confighttp.h b/src/confighttp.h index 1e0c4a76d14..cae32aefdb5 100644 --- a/src/confighttp.h +++ b/src/confighttp.h @@ -1,6 +1,4 @@ -// // Created by loki on 6/3/19. -// #ifndef SUNSHINE_CONFIGHTTP_H #define SUNSHINE_CONFIGHTTP_H @@ -18,4 +16,4 @@ constexpr auto PORT_HTTPS = 1; void start(); } // namespace confighttp -#endif //SUNSHINE_CONFIGHTTP_H +#endif // SUNSHINE_CONFIGHTTP_H diff --git a/src/crypto.cpp b/src/crypto.cpp index 006cf7fb69e..45b65abcff7 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -1,13 +1,11 @@ -// // Created by loki on 5/31/19. -// #include "crypto.h" #include namespace crypto { using big_num_t = util::safe_ptr; -//using rsa_t = util::safe_ptr; +// using rsa_t = util::safe_ptr; using asn1_string_t = util::safe_ptr; cert_chain_t::cert_chain_t() : _certs {}, _cert_ctx { X509_STORE_CTX_new() } {} @@ -22,7 +20,7 @@ static int openssl_verify_cb(int ok, X509_STORE_CTX *ctx) { int err_code = X509_STORE_CTX_get_error(ctx); switch(err_code) { - //FIXME: Checking for X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY is a temporary workaround to get mmonlight-embedded to work on the raspberry pi + // FIXME: Checking for X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY is a temporary workaround to get mmonlight-embedded to work on the raspberry pi case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: return 1; @@ -274,7 +272,7 @@ int cbc_t::encrypt(const std::string_view &plaintext, std::uint8_t *cipher, aes_ int len; - int size = plaintext.size(); //round_to_pkcs7_padded(plaintext.size()); + int size = plaintext.size(); // round_to_pkcs7_padded(plaintext.size()); // Encrypt into the caller's buffer if(EVP_EncryptUpdate(encrypt_ctx.get(), cipher, &size, (const std::uint8_t *)plaintext.data(), plaintext.size()) != 1) { @@ -492,4 +490,4 @@ std::string rand_alphabet(std::size_t bytes, const std::string_view &alphabet) { return value; } -} // namespace crypto \ No newline at end of file +} // namespace crypto diff --git a/src/crypto.h b/src/crypto.h index 7f6483114a7..46259d1a7b7 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -1,6 +1,4 @@ -// // Created by loki on 6/1/19. -// #ifndef SUNSHINE_CRYPTO_H #define SUNSHINE_CRYPTO_H diff --git a/src/httpcommon.cpp b/src/httpcommon.cpp index 9107414495d..5f1955a6055 100644 --- a/src/httpcommon.cpp +++ b/src/httpcommon.cpp @@ -44,7 +44,7 @@ int init() { if(clean_slate) { unique_id = util::uuid_t::generate().string(); - auto dir = std::filesystem::temp_directory_path() / "Sushine"sv; + auto dir = std::filesystem::temp_directory_path() / "Sunshine"sv; config::nvhttp.cert = (dir / ("cert-"s + unique_id)).string(); config::nvhttp.pkey = (dir / ("pkey-"s + unique_id)).string(); } @@ -180,4 +180,4 @@ int create_creds(const std::string &pkey, const std::string &cert) { return 0; } -} // namespace http \ No newline at end of file +} // namespace http diff --git a/src/httpcommon.h b/src/httpcommon.h index 37d8451fab5..e1a1509ac67 100644 --- a/src/httpcommon.h +++ b/src/httpcommon.h @@ -16,4 +16,4 @@ extern std::string unique_id; extern net::net_e origin_pin_allowed; extern net::net_e origin_web_ui_allowed; -} // namespace http \ No newline at end of file +} // namespace http diff --git a/src/input.cpp b/src/input.cpp index 050a8687b86..c40cdef520b 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -1,6 +1,4 @@ -// // Created by loki on 6/20/19. -// // define uint32_t for #include @@ -89,7 +87,7 @@ struct gamepad_t { // When emulating the HOME button, we may need to artificially release the back button. // Afterwards, the gamepad state on sunshine won't match the state on Moonlight. - // To prevent Sunshine from sending erronious input data to the active application, + // To prevent Sunshine from sending erroneous input data to the active application, // Sunshine forces the button to be in a specific state until the gamepad state matches that of // Moonlight once more. button_state_e back_button_state; @@ -316,11 +314,11 @@ void passthrough(std::shared_ptr &input, PNV_MOUSE_BUTTON_PACKET packet /*/ * When Moonlight sends mouse input through absolute coordinates, * it's possible that BUTTON_RIGHT is pressed down immediately after releasing BUTTON_LEFT. - * As a result, Sunshine will left click on hyperlinks in the browser before right clicking + * As a result, Sunshine will left-click on hyperlinks in the browser before right-clicking * * This can be solved by delaying BUTTON_LEFT, however, any delay on input is undesirable during gaming * As a compromise, Sunshine will only put delays on BUTTON_LEFT when - * absolute mouse coordinates have been send. + * absolute mouse coordinates have been sent. * * Try to make sure BUTTON_RIGHT gets called before BUTTON_LEFT is released. * @@ -428,7 +426,7 @@ void passthrough(std::shared_ptr &input, PNV_KEYBOARD_PACKET packet) { if(!pressed) { if(!release) { // A new key has been pressed down, we need to check for key combo's - // If a keycombo has been pressed down, don't pass it through + // If a key-combo has been pressed down, don't pass it through if(input->shortcutFlags == input_t::SHORTCUT && apply_shortcut(keyCode) > 0) { return; } diff --git a/src/input.h b/src/input.h index c9c0590e43b..ce291623adb 100644 --- a/src/input.h +++ b/src/input.h @@ -1,6 +1,4 @@ -// // Created by loki on 6/20/19. -// #ifndef SUNSHINE_INPUT_H #define SUNSHINE_INPUT_H @@ -32,4 +30,4 @@ struct touch_port_t : public platf::touch_port_t { }; } // namespace input -#endif //SUNSHINE_INPUT_H +#endif // SUNSHINE_INPUT_H diff --git a/src/main.cpp b/src/main.cpp index 0f5581d6f03..58271f83d02 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,4 @@ -// // Created by loki on 5/30/19. -// #include "process.h" @@ -289,7 +287,7 @@ int main(int argc, char *argv[]) { upnp_unmap = upnp::start(); }); - //FIXME: Temporary workaround: Simple-Web_server needs to be updated or replaced + // FIXME: Temporary workaround: Simple-Web_server needs to be updated or replaced if(shutdown_event->peek()) { return 0; } diff --git a/src/main.h b/src/main.h index aa9558b3c32..89c4dbdc6f4 100644 --- a/src/main.h +++ b/src/main.h @@ -1,6 +1,4 @@ -// // Created by loki on 12/22/19. -// #ifndef SUNSHINE_MAIN_H #define SUNSHINE_MAIN_H @@ -54,4 +52,4 @@ MAIL(rumble); } // namespace mail -#endif //SUNSHINE_MAIN_H +#endif // SUNSHINE_MAIN_H diff --git a/src/network.cpp b/src/network.cpp index ccf9e32f959..90254899fcb 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -1,6 +1,4 @@ -// // Created by loki on 12/27/19. -// #include "network.h" #include "utility.h" @@ -112,4 +110,4 @@ void free_host(ENetHost *host) { enet_host_destroy(host); } -} // namespace net \ No newline at end of file +} // namespace net diff --git a/src/network.h b/src/network.h index 88f18a40e6b..bd371841550 100644 --- a/src/network.h +++ b/src/network.h @@ -1,6 +1,4 @@ -// // Created by loki on 12/27/19. -// #ifndef SUNSHINE_NETWORK_H #define SUNSHINE_NETWORK_H @@ -32,4 +30,4 @@ net_e from_address(const std::string_view &view); host_t host_create(ENetAddress &addr, std::size_t peers, std::uint16_t port); } // namespace net -#endif //SUNSHINE_NETWORK_H +#endif // SUNSHINE_NETWORK_H diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 67f8878c20b..47067d2654d 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -1,6 +1,4 @@ -// // Created by loki on 6/3/19. -// #define BOOST_BIND_GLOBAL_PLACEHOLDERS @@ -297,7 +295,7 @@ void clientpairingsecret(std::shared_ptr> &add_cer // if hash not correct, probably MITM if(std::memcmp(hash.data(), sess.clienthash.data(), hash.size())) { - //TODO: log + // TODO: log map_id_sess.erase(client.uniqueID); tree.put("root.paired", 0); diff --git a/src/nvhttp.h b/src/nvhttp.h index af077a5651f..ae96c6dbc70 100644 --- a/src/nvhttp.h +++ b/src/nvhttp.h @@ -1,6 +1,4 @@ -// // Created by loki on 6/3/19. -// #ifndef SUNSHINE_NVHTTP_H #define SUNSHINE_NVHTTP_H @@ -17,4 +15,4 @@ bool pin(std::string pin); void erase_all_clients(); } // namespace nvhttp -#endif //SUNSHINE_NVHTTP_H +#endif // SUNSHINE_NVHTTP_H diff --git a/src/platform/linux/audio.cpp b/src/platform/linux/audio.cpp index d3ac03f97b5..531e348ae42 100644 --- a/src/platform/linux/audio.cpp +++ b/src/platform/linux/audio.cpp @@ -343,12 +343,7 @@ class server_t : public audio_control_t { } auto sink_name = get_default_sink_name(); - if(sink_name.empty()) { - BOOST_LOG(warning) << "Couldn't find an active sink"sv; - } - else { - sink.host = sink_name; - } + sink.host = sink_name; if(index.stereo == PA_INVALID_INDEX) { index.stereo = load_null(stereo, speaker::map_stereo, sizeof(speaker::map_stereo)); @@ -380,6 +375,10 @@ class server_t : public audio_control_t { } } + if(sink_name.empty()) { + BOOST_LOG(warning) << "Couldn't find an active default sink. Continuing with virtual audio only."sv; + } + if(nullcount == 3) { sink.null = std::make_optional(sink_t::null_t { stereo, surround51, surround71 }); } @@ -388,8 +387,8 @@ class server_t : public audio_control_t { } std::string get_default_sink_name() { - std::string sink_name = "@DEFAULT_SINK@"s; - auto alarm = safe::make_alarm(); + std::string sink_name; + auto alarm = safe::make_alarm(); cb_simple_t server_f = [&](ctx_t::pointer ctx, const pa_server_info *server_info) { if(!server_info) { @@ -397,7 +396,9 @@ class server_t : public audio_control_t { alarm->ring(-1); } - sink_name = server_info->default_sink_name; + if(server_info->default_sink_name) { + sink_name = server_info->default_sink_name; + } alarm->ring(0); }; @@ -408,8 +409,12 @@ class server_t : public audio_control_t { } std::string get_monitor_name(const std::string &sink_name) { - std::string monitor_name = "@DEFAULT_MONITOR@"s; - auto alarm = safe::make_alarm(); + std::string monitor_name; + auto alarm = safe::make_alarm(); + + if(sink_name.empty()) { + return monitor_name; + } cb_t sink_f = [&](ctx_t::pointer ctx, const pa_sink_info *sink_info, int eol) { if(!sink_info) { diff --git a/src/platform/linux/cuda.cu b/src/platform/linux/cuda.cu index f69be7308a8..1c6169b38ae 100644 --- a/src/platform/linux/cuda.cu +++ b/src/platform/linux/cuda.cu @@ -160,7 +160,7 @@ __global__ void RGBA_to_NV12( float scale, const viewport_t viewport, const video::color_t *const color_matrix) { int idX = (threadIdx.x + blockDim.x * blockIdx.x) * 2; - int idY = (threadIdx.y + blockDim.y * blockIdx.y); + int idY = (threadIdx.y + blockDim.y * blockIdx.y) * 2; if(idX >= viewport.width) return; if(idY >= viewport.height) return; @@ -171,18 +171,28 @@ __global__ void RGBA_to_NV12( idX += viewport.offsetX; idY += viewport.offsetY; - dstY = dstY + idX + idY * dstPitchY; + uint8_t *dstY0 = dstY + idX + idY * dstPitchY; + uint8_t *dstY1 = dstY + idX + (idY + 1) * dstPitchY; dstUV = dstUV + idX + (idY / 2 * dstPitchUV); - float3 rgb_l = bgra_to_rgb(tex2D(srcImage, x, y)); - float3 rgb_r = bgra_to_rgb(tex2D(srcImage, x + scale, y)); + float3 rgb_lt = bgra_to_rgb(tex2D(srcImage, x, y)); + float3 rgb_rt = bgra_to_rgb(tex2D(srcImage, x + scale, y)); + float3 rgb_lb = bgra_to_rgb(tex2D(srcImage, x, y + scale)); + float3 rgb_rb = bgra_to_rgb(tex2D(srcImage, x + scale, y + scale)); - float2 uv = calcUV((rgb_l + rgb_r) * 0.5f, color_matrix) * 256.0f; + float2 uv_lt = calcUV(rgb_lt, color_matrix) * 256.0f; + float2 uv_rt = calcUV(rgb_rt, color_matrix) * 256.0f; + float2 uv_lb = calcUV(rgb_lb, color_matrix) * 256.0f; + float2 uv_rb = calcUV(rgb_rb, color_matrix) * 256.0f; + + float2 uv = (uv_lt + uv_lb + uv_rt + uv_rb) * 0.25f; dstUV[0] = uv.x; dstUV[1] = uv.y; - dstY[0] = calcY(rgb_l, color_matrix) * 245.0f; // 245.0f is a magic number to ensure slight changes in luminosity are more visisble - dstY[1] = calcY(rgb_r, color_matrix) * 245.0f; // 245.0f is a magic number to ensure slight changes in luminosity are more visisble + dstY0[0] = calcY(rgb_lt, color_matrix) * 245.0f; // 245.0f is a magic number to ensure slight changes in luminosity are more visisble + dstY0[1] = calcY(rgb_rt, color_matrix) * 245.0f; // 245.0f is a magic number to ensure slight changes in luminosity are more visisble + dstY1[0] = calcY(rgb_lb, color_matrix) * 245.0f; // 245.0f is a magic number to ensure slight changes in luminosity are more visisble + dstY1[1] = calcY(rgb_rb, color_matrix) * 245.0f; // 245.0f is a magic number to ensure slight changes in luminosity are more visisble } int tex_t::copy(std::uint8_t *src, int height, int pitch) { @@ -292,7 +302,7 @@ int sws_t::convert(std::uint8_t *Y, std::uint8_t *UV, std::uint32_t pitchY, std: int sws_t::convert(std::uint8_t *Y, std::uint8_t *UV, std::uint32_t pitchY, std::uint32_t pitchUV, cudaTextureObject_t texture, stream_t::pointer stream, const viewport_t &viewport) { int threadsX = viewport.width / 2; - int threadsY = viewport.height; + int threadsY = viewport.height / 2; dim3 block(threadsPerBlock); dim3 grid(div_align(threadsX, threadsPerBlock), threadsY); @@ -328,4 +338,4 @@ int sws_t::load_ram(platf::img_t &img, cudaArray_t array) { return CU_CHECK_IGNORE(cudaMemcpy2DToArray(array, 0, 0, img.data, img.row_pitch, img.width * img.pixel_pitch, img.height, cudaMemcpyHostToDevice), "Couldn't copy to cuda array"); } -} // namespace cuda \ No newline at end of file +} // namespace cuda diff --git a/src/platform/linux/graphics.cpp b/src/platform/linux/graphics.cpp index 3c0adbda389..59b855221a3 100644 --- a/src/platform/linux/graphics.cpp +++ b/src/platform/linux/graphics.cpp @@ -365,6 +365,7 @@ display_t make_display(std::variant &proc_t::get_apps() { return _apps; } -/// Gets application image from application list. -/// Returns default image if image configuration is not set. -/// returns http content-type header compatible image type +// Gets application image from application list. +// Returns image from assets directory if found there. +// Returns default image if image configuration is not set. +// Returns http content-type header compatible image type. std::string proc_t::get_app_image(int app_id) { auto app_index = app_id - 1; if(app_index < 0 || app_index >= _apps.size()) { @@ -203,20 +202,41 @@ std::string proc_t::get_app_image(int app_id) { return SUNSHINE_ASSETS_DIR "/box.png"; } + auto default_image = SUNSHINE_ASSETS_DIR "/box.png"; auto app_image_path = _apps[app_index].image_path; if(app_image_path.empty()) { - return SUNSHINE_ASSETS_DIR "/box.png"; + // image is empty, return default box image + return default_image; } + // get the image extension and convert it to lowercase auto image_extension = std::filesystem::path(app_image_path).extension().string(); boost::to_lower(image_extension); + // return the default box image if extension is not "png" + if(image_extension != ".png") { + return default_image; + } + + // check if image is in assets directory + auto full_image_path = std::filesystem::path(SUNSHINE_ASSETS_DIR) / app_image_path; + if(std::filesystem::exists(full_image_path)) { + return full_image_path.string(); + } + else if(app_image_path == "./assets/steam.png") { + // handle old default steam image definition + return SUNSHINE_ASSETS_DIR "/steam.png"; + } + + // check if specified image exists std::error_code code; - if(!std::filesystem::exists(app_image_path, code) || image_extension != ".png") { - return SUNSHINE_ASSETS_DIR "/box.png"; + if(!std::filesystem::exists(app_image_path, code)) { + // return default box image if image does not exist + return default_image; } - // return only "content-type" http header compatible image type. + // image is a png, and not in assets directory + // return only "content-type" http header compatible image type return app_image_path; } diff --git a/src/process.h b/src/process.h index 2b3fdad8df1..eab324a7887 100644 --- a/src/process.h +++ b/src/process.h @@ -1,6 +1,4 @@ -// // Created by loki on 12/14/19. -// #ifndef SUNSHINE_PROCESS_H #define SUNSHINE_PROCESS_H @@ -105,4 +103,4 @@ std::optional parse(const std::string &file_name); extern proc_t proc; } // namespace proc -#endif //SUNSHINE_PROCESS_H +#endif // SUNSHINE_PROCESS_H diff --git a/src/rtsp.cpp b/src/rtsp.cpp index 983aff963d9..a2ffa143629 100644 --- a/src/rtsp.cpp +++ b/src/rtsp.cpp @@ -1,6 +1,4 @@ -// // Created by loki on 2/2/20. -// #define BOOST_BIND_GLOBAL_PLACEHOLDERS @@ -123,7 +121,7 @@ class socket_t : public std::enable_shared_from_this { socket->read_payload(); }); - auto content_lenght = 0; + auto content_length = 0; for(auto option = req->options; option != nullptr; option = option->next) { if("Content-length"sv == option->option) { BOOST_LOG(debug) << "Found Content-Length: "sv << option->content << " bytes"sv; @@ -133,14 +131,14 @@ class socket_t : public std::enable_shared_from_this { std::string_view content { option->content }; auto begin = std::find_if(std::begin(content), std::end(content), [](auto ch) { return (bool)std::isdigit(ch); }); - content_lenght = util::from_chars(begin, std::end(content)); + content_length = util::from_chars(begin, std::end(content)); break; } } - if(end - socket->crlf >= content_lenght) { - if(end - socket->crlf > content_lenght) { - BOOST_LOG(warning) << "(end - socket->crlf) > content_lenght -- "sv << (std::size_t)(end - socket->crlf) << " > "sv << content_lenght; + if(end - socket->crlf >= content_length) { + if(end - socket->crlf > content_length) { + BOOST_LOG(warning) << "(end - socket->crlf) > content_length -- "sv << (std::size_t)(end - socket->crlf) << " > "sv << content_length; } fg.disable(); @@ -271,7 +269,7 @@ class rtsp_server_t { if(ec) { BOOST_LOG(error) << "Couldn't accept incoming connections: "sv << ec.message(); - //Stop server + // Stop server clear(); return; } @@ -380,7 +378,7 @@ void launch_session_raise(launch_session_t launch_session) { } int session_count() { - // Ensure session_count is up to date + // Ensure session_count is up-to-date server.clear(false); return server.session_count(); diff --git a/src/rtsp.h b/src/rtsp.h index f038a5cfa1f..f295e615a40 100644 --- a/src/rtsp.h +++ b/src/rtsp.h @@ -1,6 +1,4 @@ -// // Created by loki on 2/2/20. -// #ifndef SUNSHINE_RTSP_H #define SUNSHINE_RTSP_H @@ -27,4 +25,4 @@ void rtpThread(); } // namespace stream -#endif //SUNSHINE_RTSP_H +#endif // SUNSHINE_RTSP_H diff --git a/src/stream.cpp b/src/stream.cpp index 27fbe85ab0b..7a357c129cc 100644 --- a/src/stream.cpp +++ b/src/stream.cpp @@ -1,6 +1,4 @@ -// // Created by loki on 6/5/19. -// #include "process.h" @@ -240,11 +238,10 @@ struct broadcast_ctx_t { udp::socket video_sock { io }; udp::socket audio_sock { io }; - // This is purely for adminitrative purposes. - // - // It's possible two instances of Moonlight are behind a NAT. - // From Sunshine's point of view, the ip addresses are identical - // We need some way to know what ports are already used for different streams + // This is purely for administrative purposes. + // It's possible two instances of Moonlight are behind a NAT. + // From Sunshine's point of view, the ip addresses are identical + // We need some way to know what ports are already used for different streams util::sync_t>> audio_video_connections; control_server_t control_server; @@ -767,7 +764,7 @@ void controlBroadcastThread(control_server_t *server) { } // Let all remaining connections know the server is shutting down - // reason: gracefull termination + // reason: graceful termination std::uint32_t reason = 0x80030023; control_terminate_t plaintext; @@ -932,7 +929,7 @@ void videoBroadcastThread(udp::socket &sock) { // With a fecpercentage of 255, if payload_new is broken up into more than a 100 data_shards // it will generate greater than DATA_SHARDS_MAX shards. - // Therefore, we start breaking the data up into three seperate fec blocks. + // Therefore, we start breaking the data up into three separate fec blocks. auto multi_fec_threshold = 90 * blocksize; // We can go up to 4 fec blocks, but 3 is plenty @@ -1331,7 +1328,7 @@ void join(session_t &session) { session.audioThread.join(); BOOST_LOG(debug) << "Waiting for control to end..."sv; session.controlEnd.view(); - //Reset input on session stop to avoid stuck repeated keys + // Reset input on session stop to avoid stuck repeated keys BOOST_LOG(debug) << "Resetting Input..."sv; input::reset(session.input); diff --git a/src/stream.h b/src/stream.h index b1e17b0f1be..8e054aa93ce 100644 --- a/src/stream.h +++ b/src/stream.h @@ -1,6 +1,4 @@ -// // Created by loki on 6/5/19. -// #ifndef SUNSHINE_STREAM_H #define SUNSHINE_STREAM_H @@ -45,4 +43,4 @@ state_e state(session_t &session); } // namespace session } // namespace stream -#endif //SUNSHINE_STREAM_H +#endif // SUNSHINE_STREAM_H diff --git a/src/sync.h b/src/sync.h index 8d67de2a19f..019adc9eb75 100644 --- a/src/sync.h +++ b/src/sync.h @@ -1,6 +1,4 @@ -// // Created by loki on 16-4-19. -// #ifndef SUNSHINE_SYNC_H #define SUNSHINE_SYNC_H @@ -92,4 +90,4 @@ class sync_t { } // namespace util -#endif //T_MAN_SYNC_H +#endif // SUNSHINE_SYNC_H diff --git a/src/task_pool.h b/src/task_pool.h index fc07e8abf3f..8352289c6f5 100644 --- a/src/task_pool.h +++ b/src/task_pool.h @@ -17,7 +17,7 @@ namespace util { class _ImplBase { public: - //_unique_base_type _this_ptr; + // _unique_base_type _this_ptr; inline virtual ~_ImplBase() = default; diff --git a/src/thread_pool.h b/src/thread_pool.h index 8048e6d099a..b26c8e347de 100644 --- a/src/thread_pool.h +++ b/src/thread_pool.h @@ -7,7 +7,7 @@ namespace util { /* * Allow threads to execute unhindered - * while keeping full controll over the threads. + * while keeping full control over the threads. */ class ThreadPool : public TaskPool { public: diff --git a/src/thread_safe.h b/src/thread_safe.h index d1541ee9a48..b14b3234245 100644 --- a/src/thread_safe.h +++ b/src/thread_safe.h @@ -1,6 +1,4 @@ -// // Created by loki on 6/10/19. -// #ifndef SUNSHINE_THREAD_SAFE_H #define SUNSHINE_THREAD_SAFE_H @@ -37,7 +35,7 @@ class event_t { _cv.notify_all(); } - // pop and view shoud not be used interchangebly + // pop and view shoud not be used interchangeably status_t pop() { std::unique_lock ul { _lock }; @@ -58,7 +56,7 @@ class event_t { return val; } - // pop and view shoud not be used interchangebly + // pop and view shoud not be used interchangeably template status_t pop(std::chrono::duration delay) { std::unique_lock ul { _lock }; @@ -78,7 +76,7 @@ class event_t { return val; } - // pop and view shoud not be used interchangebly + // pop and view shoud not be used interchangeably const status_t &view() { std::unique_lock ul { _lock }; @@ -508,4 +506,4 @@ inline void cleanup(mail_raw_t *mail) { } } // namespace safe -#endif //SUNSHINE_THREAD_SAFE_H +#endif // SUNSHINE_THREAD_SAFE_H diff --git a/src/upnp.cpp b/src/upnp.cpp index a8fc6f4bdaa..a5a99e86fe1 100644 --- a/src/upnp.cpp +++ b/src/upnp.cpp @@ -181,4 +181,4 @@ std::unique_ptr start() { return std::make_unique(std::move(urls), data, std::move(mappings)); } -} // namespace upnp \ No newline at end of file +} // namespace upnp diff --git a/src/upnp.h b/src/upnp.h index 478d69b1f20..2ab57df6b9a 100644 --- a/src/upnp.h +++ b/src/upnp.h @@ -7,4 +7,4 @@ namespace upnp { [[nodiscard]] std::unique_ptr start(); } -#endif \ No newline at end of file +#endif diff --git a/src/uuid.h b/src/uuid.h index 6d8abe80c32..c3a026c059b 100644 --- a/src/uuid.h +++ b/src/uuid.h @@ -1,6 +1,4 @@ -// // Created by loki on 8-2-19. -// #ifndef T_MAN_UUID_H #define T_MAN_UUID_H @@ -76,4 +74,4 @@ union uuid_t { } }; } // namespace util -#endif //T_MAN_UUID_H +#endif // T_MAN_UUID_H diff --git a/src/video.cpp b/src/video.cpp index f49cac95f99..bec77c81b9d 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -1,6 +1,4 @@ -// // Created by loki on 6/6/19. -// #include #include @@ -225,7 +223,7 @@ class swdevice_t : public platf::hwdevice_t { ~swdevice_t() override {} - // Store ownsership when frame is hw_frame + // Store ownership when frame is hw_frame frame_t hw_frame; frame_t sw_frame; @@ -239,7 +237,7 @@ class swdevice_t : public platf::hwdevice_t { enum flag_e { DEFAULT = 0x00, PARALLEL_ENCODING = 0x01, - H264_ONLY = 0x02, // When HEVC is to heavy + H264_ONLY = 0x02, // When HEVC is too heavy LIMITED_GOP_SIZE = 0x04, // Some encoders don't like it when you have an infinite GOP_SIZE. *cough* VAAPI *cough* SINGLE_SLICE_ONLY = 0x08, // Never use multiple slices <-- Older intel iGPU's ruin it for everyone else :P }; @@ -1622,12 +1620,7 @@ bool validate_encoder(encoder_t &encoder) { } int init() { - BOOST_LOG(info) << "//////////////////////////////////////////////////////////////////"sv; - BOOST_LOG(info) << "// //"sv; - BOOST_LOG(info) << "// Testing for available encoders, this may generate errors. //"sv; - BOOST_LOG(info) << "// You can safely ignore those errors. //"sv; - BOOST_LOG(info) << "// //"sv; - BOOST_LOG(info) << "//////////////////////////////////////////////////////////////////"sv; + BOOST_LOG(info) << "// Testing for available encoders, this may generate errors. You can safely ignore those errors. //"sv; KITTY_WHILE_LOOP(auto pos = std::begin(encoders), pos != std::end(encoders), { if( @@ -1643,11 +1636,7 @@ int init() { }) BOOST_LOG(info); - BOOST_LOG(info) << "//////////////////////////////////////////////////////////////"sv; - BOOST_LOG(info) << "// //"sv; - BOOST_LOG(info) << "// Ignore any errors mentioned above, they are not relevant //"sv; - BOOST_LOG(info) << "// //"sv; - BOOST_LOG(info) << "//////////////////////////////////////////////////////////////"sv; + BOOST_LOG(info) << "// Ignore any errors mentioned above, they are not relevant. //"sv; BOOST_LOG(info); if(encoders.empty()) { diff --git a/src/video.h b/src/video.h index 05df4463d2b..6b8d6e57077 100644 --- a/src/video.h +++ b/src/video.h @@ -1,6 +1,4 @@ -// // Created by loki on 6/9/19. -// #ifndef SUNSHINE_VIDEO_H #define SUNSHINE_VIDEO_H @@ -84,4 +82,4 @@ void capture( int init(); } // namespace video -#endif //SUNSHINE_VIDEO_H +#endif // SUNSHINE_VIDEO_H diff --git a/src_assets/common/config/sunshine.conf b/src_assets/common/config/sunshine.conf deleted file mode 100644 index 58dd670b003..00000000000 --- a/src_assets/common/config/sunshine.conf +++ /dev/null @@ -1 +0,0 @@ -# See our documentation at https://docs.lizardbyte.dev/projects/sunshine diff --git a/src_assets/linux/assets/apps.json b/src_assets/linux/assets/apps.json new file mode 100644 index 00000000000..927c70285e3 --- /dev/null +++ b/src_assets/linux/assets/apps.json @@ -0,0 +1,24 @@ +{ + "env": { + "PATH": "$(PATH):$(HOME)/.local/bin" + }, + "apps": [ + { + "name": "Low Res Desktop", + "prep-cmd": [ + { + "do": "xrandr --output HDMI-1 --mode 1920x1080", + "undo": "xrandr --output HDMI-1 --mode 1920x1200" + } + ] + }, + { + "name": "Steam BigPicture", + "output": "steam.txt", + "detached": [ + "setsid steam steam://open/bigpicture" + ], + "image-path": "steam.png" + } + ] +} diff --git a/src_assets/linux/config/apps.json b/src_assets/linux/config/apps.json deleted file mode 100644 index 552dabe23cf..00000000000 --- a/src_assets/linux/config/apps.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "env":{ - "PATH":"$(PATH):$(HOME)/.local/bin" - }, - "apps":[ - { - "name":"Low Res Desktop", - "prep-cmd":[ - { "do":"xrandr --output HDMI-1 --mode 1920x1080", "undo":"xrandr --output HDMI-1 --mode 1920x1200" } - ] - }, - { - "name":"Steam BigPicture", - - "output":"steam.txt", - "detached":["setsid steam steam://open/bigpicture"], - "image-path":"./assets/steam.png" - } - ] -} diff --git a/src_assets/linux/misc/conffiles b/src_assets/linux/misc/conffiles deleted file mode 100644 index 4a35822bf61..00000000000 --- a/src_assets/linux/misc/conffiles +++ /dev/null @@ -1,2 +0,0 @@ -/usr/local/sunshine/config/sunshine.conf -/usr/local/sunshine/config/apps.json diff --git a/src_assets/linux/misc/postinst b/src_assets/linux/misc/postinst index a42d3ca50c0..da617605ae4 100644 --- a/src_assets/linux/misc/postinst +++ b/src_assets/linux/misc/postinst @@ -12,27 +12,6 @@ else echo "Warning: /etc/group not found" fi -if [ -f /usr/local/sunshine/config/sunshine.conf.old ]; then - echo "Restoring old sunshine.conf" - mv /usr/local/sunshine/config/sunshine.conf.old /usr/local/sunshine/config/sunshine.conf -fi - -if [ -f /usr/local/sunshine/config/apps.json.old ]; then - echo "Restoring old apps.json" - mv /usr/local/sunshine/config/apps.json.old /usr/local/sunshine/config/apps.json -fi - -# Update permissions on config files for Web Manager -if [ -f /usr/local/sunshine/config/apps.json ]; then - echo "chmod 666 /etc/sunshine/apps.json" - chmod 666 /usr/local/sunshine/config/apps.json -fi - -if [ -f /usr/local/sunshine/config/sunshine.conf ]; then - echo "chmod 666 /etc/sunshine/sunshine.conf" - chmod 666 /usr/local/sunshine/config/sunshine.conf -fi - # Ensure Sunshine can grab images from KMS path_to_setcap=$(which setcap) if [ -x "$path_to_setcap" ] ; then diff --git a/src_assets/linux/misc/preinst b/src_assets/linux/misc/preinst deleted file mode 100644 index 0522b5d6f84..00000000000 --- a/src_assets/linux/misc/preinst +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -#Store backup for old config files to prevent it from being overwritten -if [ -f /usr/local/sunshine/config/sunshine.conf ]; then - cp /usr/local/sunshine/config/sunshine.conf /usr/local/sunshine/config/sunshine.conf.old -fi - -if [ -f /usr/local/sunshine/config/apps.json ]; then - cp /usr/local/sunshine/config/apps.json /usr/local/sunshine/config/apps.json.old -fi diff --git a/src_assets/macos/assets/apps.json b/src_assets/macos/assets/apps.json new file mode 100644 index 00000000000..cb1c548a5e9 --- /dev/null +++ b/src_assets/macos/assets/apps.json @@ -0,0 +1,6 @@ +{ + "env": { + "PATH": "$(PATH):$(HOME)/.local/bin" + }, + "apps": [] +} diff --git a/src_assets/macos/config/apps.json b/src_assets/macos/config/apps.json deleted file mode 100644 index 746c69b3b5a..00000000000 --- a/src_assets/macos/config/apps.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "env":{ - "PATH":"$(PATH):$(HOME)/.local/bin" - }, - "apps":[ ] -} diff --git a/src_assets/macos/misc/uninstall_pkg.sh b/src_assets/macos/misc/uninstall_pkg.sh index 7e136109f64..869f33d2fe6 100644 --- a/src_assets/macos/misc/uninstall_pkg.sh +++ b/src_assets/macos/misc/uninstall_pkg.sh @@ -6,41 +6,10 @@ package_name=org.macports.Sunshine echo "Removing files now..." FILES=$(pkgutil --files $package_name --only-files) -remove_config=True -remove_apps=True - for file in ${FILES}; do file="/$file" - remove_current=True - if [[ $file == *sunshine.conf ]]; then - if [[ $remove_config == True ]]; then - while true; do - read -p -r "Do you wish to remove 'sunshine.conf'?" yn - case $yn in - [Yy]* ) echo "removing: $file"; rm -f "$file"; break;; - [Nn]* ) remove_config=False; remove_current=False; break;; - * ) echo "Please answer yes or no.";; - esac - done - fi - fi - if [[ $file == *apps.json ]]; then - if [[ $remove_apps == True ]]; then - while true; do - read -p -r "Do you wish to remove 'apps.conf'?" yn - case $yn in - [Yy]* ) echo "removing: $file"; rm -f "$file"; break;; - [Nn]* ) remove_apps=False; remove_current=False; break;; - * ) echo "Please answer yes or no.";; - esac - done - fi - fi - - if [[ $remove_current == True ]]; then - echo "removing: $file" - rm -f "$file" - fi + echo "removing: $file" + rm -f "$file" done echo "Removing directories now..." diff --git a/src_assets/windows/assets/apps.json b/src_assets/windows/assets/apps.json new file mode 100644 index 00000000000..de4847c344f --- /dev/null +++ b/src_assets/windows/assets/apps.json @@ -0,0 +1,15 @@ +{ + "env": { + "PATH": "$(PATH);C:\\Program Files (x86)\\Steam" + }, + "apps": [ + { + "name": "Steam BigPicture", + "output": "steam.txt", + "detached": [ + "steam steam://open/bigpicture" + ], + "image-path": "steam.png" + } + ] +} diff --git a/src_assets/windows/config/apps.json b/src_assets/windows/config/apps.json deleted file mode 100644 index 419f2be486d..00000000000 --- a/src_assets/windows/config/apps.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "env":{ - "PATH":"$(PATH);C:\\Program Files (x86)\\Steam" - }, - "apps":[ - { - "name":"Steam BigPicture", - - "output":"steam.txt", - "detached":["steam steam://open/bigpicture"], - "image-path":"./assets/steam.png" - } - ] -} diff --git a/src_assets/windows/misc/firewall/add-firewall-rule.bat b/src_assets/windows/misc/firewall/add-firewall-rule.bat new file mode 100644 index 00000000000..81d5dd92db0 --- /dev/null +++ b/src_assets/windows/misc/firewall/add-firewall-rule.bat @@ -0,0 +1,11 @@ +@echo off + +rem Get sunshine root directory +for %%I in ("%~dp0\..") do set "ROOT_DIR=%%~fI" + +set RULE_NAME=Sunshine +set PROGRAM_BIN="%ROOT_DIR%\sunshine.exe" + +rem Add the rule +netsh advfirewall firewall add rule name=%RULE_NAME% dir=in action=allow protocol=tcp program=%PROGRAM_BIN% enable=yes +netsh advfirewall firewall add rule name=%RULE_NAME% dir=in action=allow protocol=udp program=%PROGRAM_BIN% enable=yes diff --git a/src_assets/windows/misc/firewall/delete-firewall-rule.bat b/src_assets/windows/misc/firewall/delete-firewall-rule.bat new file mode 100644 index 00000000000..3ab0d4e97cf --- /dev/null +++ b/src_assets/windows/misc/firewall/delete-firewall-rule.bat @@ -0,0 +1,6 @@ +@echo off + +set RULE_NAME=Sunshine + +rem Delete the rule +netsh advfirewall firewall delete rule name=%RULE_NAME% diff --git a/tools/install-service.bat b/src_assets/windows/misc/service/install-service.bat similarity index 80% rename from tools/install-service.bat rename to src_assets/windows/misc/service/install-service.bat index 5e6fbc220e3..af27fec15d1 100644 --- a/tools/install-service.bat +++ b/src_assets/windows/misc/service/install-service.bat @@ -1,7 +1,10 @@ @echo off +rem Get sunshine root directory +for %%I in ("%~dp0\..") do set "ROOT_DIR=%%~fI" + set SERVICE_NAME=sunshinesvc -set SERVICE_BIN="%~dp0\tools\sunshinesvc.exe" +set SERVICE_BIN="%ROOT_DIR%\tools\sunshinesvc.exe" set SERVICE_START_TYPE=auto rem Check if sunshinesvc already exists diff --git a/tools/uninstall-service.bat b/src_assets/windows/misc/service/uninstall-service.bat similarity index 100% rename from tools/uninstall-service.bat rename to src_assets/windows/misc/service/uninstall-service.bat