Merge remote-tracking branch 'sunshine/master'
This commit is contained in:
@@ -1,11 +0,0 @@
|
|||||||
# install dependencies for C++ analysis
|
|
||||||
set -e
|
|
||||||
|
|
||||||
chmod +x ./scripts/linux_build.sh
|
|
||||||
./scripts/linux_build.sh --skip-package --ubuntu-test-repo
|
|
||||||
|
|
||||||
# Delete CUDA
|
|
||||||
rm -rf ./build/cuda
|
|
||||||
|
|
||||||
# skip autobuild
|
|
||||||
echo "skip_autobuild=true" >> "$GITHUB_OUTPUT"
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
# install dependencies for C++ analysis
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# update pacman
|
|
||||||
pacman --noconfirm -Syu
|
|
||||||
|
|
||||||
gcc_version="14.2.0-3"
|
|
||||||
|
|
||||||
broken_deps=(
|
|
||||||
"mingw-w64-ucrt-x86_64-gcc"
|
|
||||||
"mingw-w64-ucrt-x86_64-gcc-libs"
|
|
||||||
)
|
|
||||||
|
|
||||||
tarballs=""
|
|
||||||
for dep in "${broken_deps[@]}"; do
|
|
||||||
tarball="${dep}-${gcc_version}-any.pkg.tar.zst"
|
|
||||||
|
|
||||||
# download and install working version
|
|
||||||
wget https://repo.msys2.org/mingw/ucrt64/${tarball}
|
|
||||||
|
|
||||||
tarballs="${tarballs} ${tarball}"
|
|
||||||
done
|
|
||||||
|
|
||||||
# install broken dependencies
|
|
||||||
if [ -n "$tarballs" ]; then
|
|
||||||
pacman -U --noconfirm ${tarballs}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# install dependencies
|
|
||||||
dependencies=(
|
|
||||||
"git"
|
|
||||||
"mingw-w64-ucrt-x86_64-cmake"
|
|
||||||
"mingw-w64-ucrt-x86_64-cppwinrt"
|
|
||||||
"mingw-w64-ucrt-x86_64-curl-winssl"
|
|
||||||
"mingw-w64-ucrt-x86_64-MinHook"
|
|
||||||
"mingw-w64-ucrt-x86_64-miniupnpc"
|
|
||||||
"mingw-w64-ucrt-x86_64-nlohmann-json"
|
|
||||||
"mingw-w64-ucrt-x86_64-nodejs"
|
|
||||||
"mingw-w64-ucrt-x86_64-nsis"
|
|
||||||
"mingw-w64-ucrt-x86_64-onevpl"
|
|
||||||
"mingw-w64-ucrt-x86_64-openssl"
|
|
||||||
"mingw-w64-ucrt-x86_64-opus"
|
|
||||||
"mingw-w64-ucrt-x86_64-toolchain"
|
|
||||||
)
|
|
||||||
|
|
||||||
pacman -Syu --noconfirm --ignore="$(IFS=,; echo "${broken_deps[*]}")" "${dependencies[@]}"
|
|
||||||
|
|
||||||
# build
|
|
||||||
mkdir -p build
|
|
||||||
cmake \
|
|
||||||
-B build \
|
|
||||||
-G Ninja \
|
|
||||||
-S . \
|
|
||||||
-DBUILD_DOCS=OFF \
|
|
||||||
-DBUILD_WERROR=ON
|
|
||||||
ninja -C build
|
|
||||||
|
|
||||||
# skip autobuild
|
|
||||||
echo "skip_autobuild=true" >> "$GITHUB_OUTPUT"
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# install dependencies for C++ analysis
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# setup homebrew for x86_64
|
|
||||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
||||||
eval "$(/usr/local/bin/brew shellenv)"
|
|
||||||
|
|
||||||
# install dependencies
|
|
||||||
dependencies=(
|
|
||||||
"cmake"
|
|
||||||
"miniupnpc"
|
|
||||||
"ninja"
|
|
||||||
"node"
|
|
||||||
"openssl@3"
|
|
||||||
"opus"
|
|
||||||
"pkg-config"
|
|
||||||
)
|
|
||||||
brew install "${dependencies[@]}"
|
|
||||||
|
|
||||||
# build
|
|
||||||
mkdir -p build
|
|
||||||
cmake \
|
|
||||||
-B build \
|
|
||||||
-G Ninja \
|
|
||||||
-S . \
|
|
||||||
-DBOOST_USE_STATIC=OFF \
|
|
||||||
-DBUILD_DOCS=OFF \
|
|
||||||
-DBUILD_WERROR=ON
|
|
||||||
ninja -C build
|
|
||||||
|
|
||||||
# skip autobuild
|
|
||||||
echo "skip_autobuild=true" >> "$GITHUB_OUTPUT"
|
|
||||||
1
.flake8
1
.flake8
@@ -3,4 +3,5 @@ filename =
|
|||||||
*.py
|
*.py
|
||||||
max-line-length = 120
|
max-line-length = 120
|
||||||
extend-exclude =
|
extend-exclude =
|
||||||
|
.venv/
|
||||||
venv/
|
venv/
|
||||||
|
|||||||
1
.github/semantic.yml
vendored
1
.github/semantic.yml
vendored
@@ -12,3 +12,4 @@ titleAndCommits: false
|
|||||||
anyCommit: false
|
anyCommit: false
|
||||||
allowMergeCommits: false
|
allowMergeCommits: false
|
||||||
allowRevertCommits: false
|
allowRevertCommits: false
|
||||||
|
targetUrl: https://docs.lizardbyte.dev/latest/developers/contributing.html#creating-a-pull-request
|
||||||
|
|||||||
30
.github/workflows/_codeql.yml
vendored
Normal file
30
.github/workflows/_codeql.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
# This workflow is centrally managed in https://github.com/LizardByte/.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: CodeQL
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
schedule:
|
||||||
|
- cron: '00 12 * * 0' # every Sunday at 12:00 UTC
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "${{ github.workflow }}-${{ github.ref }}"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
call-codeql:
|
||||||
|
name: CodeQL
|
||||||
|
uses: LizardByte/.github/.github/workflows/__call-codeql.yml@master
|
||||||
|
if: ${{ github.repository != 'LizardByte/.github' }}
|
||||||
27
.github/workflows/_common-lint.yml
vendored
Normal file
27
.github/workflows/_common-lint.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
# This workflow is centrally managed in https://github.com/LizardByte/.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: common lint
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
- reopened
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "${{ github.workflow }}-${{ github.ref }}"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
name: Common Lint
|
||||||
|
uses: LizardByte/.github/.github/workflows/__call-common-lint.yml@master
|
||||||
|
if: ${{ github.repository != 'LizardByte/.github' }}
|
||||||
23
.github/workflows/_release-notifier.yml
vendored
Normal file
23
.github/workflows/_release-notifier.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
# This workflow is centrally managed in https://github.com/LizardByte/.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.
|
||||||
|
|
||||||
|
# Create a blog post for a new release and open a PR to the blog repo
|
||||||
|
|
||||||
|
name: Release Notifications
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- released # this triggers when a release is published, but does not include pre-releases or drafts
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-blog:
|
||||||
|
name: Update blog
|
||||||
|
uses: LizardByte/.github/.github/workflows/__call-release-notifier.yml@master
|
||||||
|
if: github.repository_owner == 'LizardByte'
|
||||||
|
secrets:
|
||||||
|
GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
|
||||||
34
.github/workflows/_update-docs.yml
vendored
Normal file
34
.github/workflows/_update-docs.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
# This workflow is centrally managed in https://github.com/LizardByte/.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.
|
||||||
|
|
||||||
|
# To use, add the `rtd` repository label to identify repositories that should trigger this workflow.
|
||||||
|
# If the project slug is not the repository name, add a repository variable named `READTHEDOCS_SLUG` with the value of
|
||||||
|
# the ReadTheDocs project slug.
|
||||||
|
|
||||||
|
# Update readthedocs on release events.
|
||||||
|
|
||||||
|
name: Update docs
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- created
|
||||||
|
- edited
|
||||||
|
- deleted
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "${{ github.workflow }}-${{ github.event.release.tag_name }}"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-docs:
|
||||||
|
name: Update docs
|
||||||
|
uses: LizardByte/.github/.github/workflows/__call-update-docs.yml@master
|
||||||
|
if: github.repository_owner == 'LizardByte'
|
||||||
|
with:
|
||||||
|
readthedocs_slug: ${{ vars.READTHEDOCS_SLUG }}
|
||||||
|
secrets:
|
||||||
|
READTHEDOCS_TOKEN: ${{ secrets.READTHEDOCS_TOKEN }}
|
||||||
29
.github/workflows/_update-flathub-repo.yml
vendored
Normal file
29
.github/workflows/_update-flathub-repo.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
# This workflow is centrally managed in https://github.com/LizardByte/.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.
|
||||||
|
|
||||||
|
# To use, add the `flathub-pkg` repository label to identify repositories that should trigger this workflow.
|
||||||
|
|
||||||
|
# Update Flathub on release events.
|
||||||
|
|
||||||
|
name: Update Flathub repo
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- released
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "${{ github.workflow }}-${{ github.event.release.tag_name }}"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-flathub-repo:
|
||||||
|
name: Update Flathub Repo
|
||||||
|
uses: LizardByte/.github/.github/workflows/__call-update-flathub-repo.yml@master
|
||||||
|
if: github.repository_owner == 'LizardByte'
|
||||||
|
secrets:
|
||||||
|
GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
|
||||||
31
.github/workflows/_update-homebrew-repo.yml
vendored
Normal file
31
.github/workflows/_update-homebrew-repo.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
# This workflow is centrally managed in https://github.com/LizardByte/.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.
|
||||||
|
|
||||||
|
# To use, add the `homebrew-pkg` repository label to identify repositories that should trigger this workflow.
|
||||||
|
|
||||||
|
# Update Homebrew on release events.
|
||||||
|
|
||||||
|
name: Update Homebrew repo
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- released
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "${{ github.workflow }}-${{ github.event.release.tag_name }}"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-homebrew-repo:
|
||||||
|
name: Update Homebrew repo
|
||||||
|
uses: LizardByte/.github/.github/workflows/__call-update-homebrew-repo.yml@master
|
||||||
|
if: github.repository_owner == 'LizardByte'
|
||||||
|
secrets:
|
||||||
|
GH_EMAIL: ${{ secrets.GH_BOT_EMAIL }}
|
||||||
|
GH_USERNAME: ${{ secrets.GH_BOT_NAME }}
|
||||||
|
GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
|
||||||
29
.github/workflows/_update-pacman-repo.yml
vendored
Normal file
29
.github/workflows/_update-pacman-repo.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
# This workflow is centrally managed in https://github.com/LizardByte/.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.
|
||||||
|
|
||||||
|
# To use, add the `pacman-pkg` repository label to identify repositories that should trigger this workflow.
|
||||||
|
|
||||||
|
# Update pacman repo on release events.
|
||||||
|
|
||||||
|
name: Update pacman repo
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- released
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "${{ github.workflow }}-${{ github.event.release.tag_name }}"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-homebrew-release:
|
||||||
|
name: Update pacman repo
|
||||||
|
uses: LizardByte/.github/.github/workflows/__call-update-pacman-repo.yml@master
|
||||||
|
if: github.repository_owner == 'LizardByte'
|
||||||
|
secrets:
|
||||||
|
GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
|
||||||
29
.github/workflows/_update-winget-repo.yml
vendored
Normal file
29
.github/workflows/_update-winget-repo.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
# This workflow is centrally managed in https://github.com/LizardByte/.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.
|
||||||
|
|
||||||
|
# To use, add the `winget-pkg` repository label to identify repositories that should trigger this workflow.
|
||||||
|
|
||||||
|
# Update Winget on release events.
|
||||||
|
|
||||||
|
name: Update Winget repo
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- released
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "${{ github.workflow }}-${{ github.event.release.tag_name }}"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-winget-repo:
|
||||||
|
name: Update Winget repo
|
||||||
|
uses: LizardByte/.github/.github/workflows/__call-update-winget-repo.yml@master
|
||||||
|
if: github.repository_owner == 'LizardByte'
|
||||||
|
secrets:
|
||||||
|
GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
|
||||||
213
.github/workflows/ci-flatpak.yml
vendored
Normal file
213
.github/workflows/ci-flatpak.yml
vendored
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
---
|
||||||
|
name: CI-Flatpak
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
release_commit:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
release_version:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_linux_flatpak:
|
||||||
|
name: ${{ matrix.arch }}
|
||||||
|
env:
|
||||||
|
APP_ID: dev.lizardbyte.app.Sunshine
|
||||||
|
NODE_VERSION: "20"
|
||||||
|
PLATFORM_VERSION: "23.08"
|
||||||
|
runs-on: ${{ matrix.runner }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- arch: x86_64
|
||||||
|
runner: ubuntu-22.04
|
||||||
|
- arch: aarch64
|
||||||
|
runner: ubuntu-22.04-arm
|
||||||
|
steps:
|
||||||
|
- name: Maximize build space
|
||||||
|
if: matrix.arch == 'x86_64'
|
||||||
|
uses: easimon/maximize-build-space@v10
|
||||||
|
with:
|
||||||
|
root-reserve-mb: 10240
|
||||||
|
remove-dotnet: 'true'
|
||||||
|
remove-android: 'true'
|
||||||
|
remove-haskell: 'true'
|
||||||
|
remove-codeql: 'true'
|
||||||
|
remove-docker-images: 'true'
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Setup node
|
||||||
|
id: node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
|
||||||
|
- name: Install npm dependencies
|
||||||
|
run: npm install --package-lock-only
|
||||||
|
|
||||||
|
- name: Debug package-lock.json
|
||||||
|
run: cat package-lock.json
|
||||||
|
|
||||||
|
- name: Setup python
|
||||||
|
id: python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.12'
|
||||||
|
|
||||||
|
- name: Setup Dependencies Linux Flatpak
|
||||||
|
run: |
|
||||||
|
python -m pip install ./packaging/linux/flatpak/deps/flatpak-builder-tools/node
|
||||||
|
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y \
|
||||||
|
cmake \
|
||||||
|
flatpak
|
||||||
|
|
||||||
|
sudo su $(whoami) -c "flatpak --user remote-add --if-not-exists flathub \
|
||||||
|
https://flathub.org/repo/flathub.flatpakrepo"
|
||||||
|
|
||||||
|
sudo su $(whoami) -c "flatpak --user install -y flathub \
|
||||||
|
org.flatpak.Builder \
|
||||||
|
org.freedesktop.Platform/${{ matrix.arch }}/${PLATFORM_VERSION} \
|
||||||
|
org.freedesktop.Sdk/${{ matrix.arch }}/${PLATFORM_VERSION} \
|
||||||
|
org.freedesktop.Sdk.Extension.node${NODE_VERSION}/${{ matrix.arch }}/${PLATFORM_VERSION} \
|
||||||
|
"
|
||||||
|
|
||||||
|
flatpak run org.flatpak.Builder --version
|
||||||
|
|
||||||
|
- name: flatpak node generator
|
||||||
|
# https://github.com/flatpak/flatpak-builder-tools/blob/master/node/README.md
|
||||||
|
run: flatpak-node-generator npm package-lock.json
|
||||||
|
|
||||||
|
- name: Debug generated-sources.json
|
||||||
|
run: cat generated-sources.json
|
||||||
|
|
||||||
|
- name: Cache Flatpak build
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ./build/.flatpak-builder
|
||||||
|
key: flatpak-${{ matrix.arch }}-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
flatpak-${{ matrix.arch }}-
|
||||||
|
|
||||||
|
- name: Configure Flatpak Manifest
|
||||||
|
run: |
|
||||||
|
# variables for manifest
|
||||||
|
branch="${{ github.head_ref }}"
|
||||||
|
build_version=${{ inputs.release_version }}
|
||||||
|
commit=${{ inputs.release_commit }}
|
||||||
|
|
||||||
|
# check the branch variable
|
||||||
|
if [ -z "$branch" ]
|
||||||
|
then
|
||||||
|
echo "This is a PUSH event"
|
||||||
|
branch=${{ github.ref_name }}
|
||||||
|
clone_url=${{ github.event.repository.clone_url }}
|
||||||
|
else
|
||||||
|
echo "This is a PR event"
|
||||||
|
clone_url=${{ github.event.pull_request.head.repo.clone_url }}
|
||||||
|
fi
|
||||||
|
echo "Branch: ${branch}"
|
||||||
|
echo "Commit: ${commit}"
|
||||||
|
echo "Clone URL: ${clone_url}"
|
||||||
|
|
||||||
|
export BRANCH=${branch}
|
||||||
|
export BUILD_VERSION=${build_version}
|
||||||
|
export CLONE_URL=${clone_url}
|
||||||
|
export COMMIT=${commit}
|
||||||
|
|
||||||
|
mkdir -p build
|
||||||
|
mkdir -p artifacts
|
||||||
|
|
||||||
|
cmake -DGITHUB_CLONE_URL=${clone_url} \
|
||||||
|
-B build \
|
||||||
|
-S . \
|
||||||
|
-DSUNSHINE_CONFIGURE_FLATPAK_MAN=ON \
|
||||||
|
-DSUNSHINE_CONFIGURE_ONLY=ON
|
||||||
|
|
||||||
|
- name: Debug Manifest
|
||||||
|
working-directory: build
|
||||||
|
run: cat ${APP_ID}.yml
|
||||||
|
|
||||||
|
- name: Build Linux Flatpak
|
||||||
|
working-directory: build
|
||||||
|
run: |
|
||||||
|
sudo su $(whoami) -c "flatpak run org.flatpak.Builder \
|
||||||
|
--arch=${{ matrix.arch }} \
|
||||||
|
--force-clean \
|
||||||
|
--repo=repo \
|
||||||
|
--sandbox \
|
||||||
|
--stop-at=cuda build-sunshine ${APP_ID}.yml"
|
||||||
|
cp -r .flatpak-builder copy-of-flatpak-builder
|
||||||
|
sudo su $(whoami) -c "flatpak run org.flatpak.Builder \
|
||||||
|
--arch=${{ matrix.arch }} \
|
||||||
|
--force-clean \
|
||||||
|
--repo=repo \
|
||||||
|
--sandbox \
|
||||||
|
build-sunshine ${APP_ID}.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 ${APP_ID}"
|
||||||
|
sudo su $(whoami) -c "flatpak build-bundle \
|
||||||
|
--runtime \
|
||||||
|
--arch=${{ matrix.arch }} \
|
||||||
|
./repo \
|
||||||
|
../artifacts/sunshine_debug_${{ matrix.arch }}.flatpak ${APP_ID}.Debug"
|
||||||
|
|
||||||
|
- name: Lint Flatpak
|
||||||
|
working-directory: build
|
||||||
|
run: |
|
||||||
|
exceptions_file="${{ github.workspace }}/packaging/linux/flatpak/exceptions.json"
|
||||||
|
|
||||||
|
echo "Linting flatpak manifest"
|
||||||
|
flatpak run --command=flatpak-builder-lint org.flatpak.Builder \
|
||||||
|
--exceptions \
|
||||||
|
--user-exceptions "${exceptions_file}" \
|
||||||
|
manifest \
|
||||||
|
${APP_ID}.yml
|
||||||
|
|
||||||
|
echo "Linting flatpak repo"
|
||||||
|
# TODO: add arg
|
||||||
|
# --mirror-screenshots-url=https://dl.flathub.org/media \
|
||||||
|
flatpak run --command=flatpak-builder-lint org.flatpak.Builder \
|
||||||
|
--exceptions \
|
||||||
|
--user-exceptions "${exceptions_file}" \
|
||||||
|
repo \
|
||||||
|
repo
|
||||||
|
|
||||||
|
- name: Package Flathub repo archive
|
||||||
|
# copy files required to generate the Flathub repo
|
||||||
|
if: matrix.arch == 'x86_64'
|
||||||
|
run: |
|
||||||
|
mkdir -p flathub/modules
|
||||||
|
cp ./build/generated-sources.json ./flathub/
|
||||||
|
cp ./build/package-lock.json ./flathub/
|
||||||
|
cp ./build/${APP_ID}.yml ./flathub/
|
||||||
|
cp ./build/${APP_ID}.metainfo.xml ./flathub/
|
||||||
|
cp ./packaging/linux/flatpak/README.md ./flathub/
|
||||||
|
cp ./packaging/linux/flatpak/flathub.json ./flathub/
|
||||||
|
cp -r ./packaging/linux/flatpak/modules/. ./flathub/modules/
|
||||||
|
# submodules will need to be handled in the workflow that creates the PR
|
||||||
|
|
||||||
|
# create the archive
|
||||||
|
tar -czf ./artifacts/flathub.tar.gz -C ./flathub .
|
||||||
|
|
||||||
|
- name: Upload Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-Linux-Flatpak-${{ matrix.arch }}
|
||||||
|
path: artifacts/
|
||||||
|
if-no-files-found: error
|
||||||
235
.github/workflows/ci-homebrew.yml
vendored
Normal file
235
.github/workflows/ci-homebrew.yml
vendored
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
---
|
||||||
|
name: CI-Homebrew
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
publish_release:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
release_commit:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
release_tag:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
release_version:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
secrets:
|
||||||
|
GH_TOKEN:
|
||||||
|
required: true
|
||||||
|
GIT_EMAIL:
|
||||||
|
required: true
|
||||||
|
GIT_USERNAME:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_homebrew:
|
||||||
|
name: ${{ matrix.os_name }}-${{ matrix.os_version }}${{ matrix.release == true && ' (Release)' || '' }}
|
||||||
|
runs-on: ${{ matrix.os_name }}-${{ matrix.os_version }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories
|
||||||
|
# while GitHub has larger macOS runners, they are not available for our repos :(
|
||||||
|
- os_version: "13"
|
||||||
|
os_name: "macos"
|
||||||
|
- os_version: "14"
|
||||||
|
os_name: "macos"
|
||||||
|
- os_version: "15"
|
||||||
|
os_name: "macos"
|
||||||
|
- os_version: "latest"
|
||||||
|
os_name: "ubuntu"
|
||||||
|
- os_version: "latest" # this job will only configure the formula for release, no validation
|
||||||
|
os_name: "ubuntu"
|
||||||
|
release: true
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Fix homebrew python
|
||||||
|
if: matrix.os_name == 'macos' && matrix.os_version == '13'
|
||||||
|
run: |
|
||||||
|
rm '/usr/local/bin/2to3'
|
||||||
|
rm '/usr/local/bin/2to3-3.12'
|
||||||
|
rm '/usr/local/bin/idle3'
|
||||||
|
rm '/usr/local/bin/idle3.12'
|
||||||
|
rm '/usr/local/bin/idle3.13'
|
||||||
|
rm '/usr/local/bin/pip3.12'
|
||||||
|
rm '/usr/local/bin/pip3.13'
|
||||||
|
rm '/usr/local/bin/pydoc3'
|
||||||
|
rm '/usr/local/bin/pydoc3.12'
|
||||||
|
rm '/usr/local/bin/pydoc3.13'
|
||||||
|
rm '/usr/local/bin/python3'
|
||||||
|
rm '/usr/local/bin/python3.12'
|
||||||
|
rm '/usr/local/bin/python3.13'
|
||||||
|
rm '/usr/local/bin/python3-config'
|
||||||
|
rm '/usr/local/bin/python3.12-config'
|
||||||
|
rm '/usr/local/bin/python3.13-config'
|
||||||
|
brew install python3
|
||||||
|
|
||||||
|
- name: Configure formula
|
||||||
|
run: |
|
||||||
|
# variables for formula
|
||||||
|
branch="${{ github.head_ref }}"
|
||||||
|
build_version=${{ inputs.release_version }}
|
||||||
|
commit=${{ inputs.release_commit }}
|
||||||
|
|
||||||
|
# check the branch variable
|
||||||
|
if [ -z "$branch" ]
|
||||||
|
then
|
||||||
|
echo "This is a PUSH event"
|
||||||
|
clone_url=${{ github.event.repository.clone_url }}
|
||||||
|
branch="${{ github.ref_name }}"
|
||||||
|
default_branch="${{ github.event.repository.default_branch }}"
|
||||||
|
|
||||||
|
if [ "${{ matrix.release }}" == "true" ]; then
|
||||||
|
# we will publish the formula with the release tag
|
||||||
|
tag="${{ inputs.release_tag }}"
|
||||||
|
else
|
||||||
|
tag="${{ github.ref_name }}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "This is a PR event"
|
||||||
|
clone_url=${{ github.event.pull_request.head.repo.clone_url }}
|
||||||
|
branch="${{ github.event.pull_request.head.ref }}"
|
||||||
|
default_branch="${{ github.event.pull_request.head.repo.default_branch }}"
|
||||||
|
tag="${{ github.event.pull_request.head.ref }}"
|
||||||
|
fi
|
||||||
|
echo "Branch: ${branch}"
|
||||||
|
echo "Clone URL: ${clone_url}"
|
||||||
|
echo "Tag: ${tag}"
|
||||||
|
|
||||||
|
export BRANCH=${branch}
|
||||||
|
export BUILD_VERSION=${build_version}
|
||||||
|
export CLONE_URL=${clone_url}
|
||||||
|
export COMMIT=${commit}
|
||||||
|
export TAG=${tag}
|
||||||
|
|
||||||
|
mkdir -p build
|
||||||
|
cmake \
|
||||||
|
-B build \
|
||||||
|
-S . \
|
||||||
|
-DGITHUB_DEFAULT_BRANCH="${default_branch}" \
|
||||||
|
-DSUNSHINE_CONFIGURE_HOMEBREW=ON \
|
||||||
|
-DSUNSHINE_CONFIGURE_ONLY=ON
|
||||||
|
|
||||||
|
# copy formula to artifacts
|
||||||
|
mkdir -p homebrew
|
||||||
|
cp -f ./build/sunshine.rb ./homebrew/sunshine.rb
|
||||||
|
|
||||||
|
# testing
|
||||||
|
cat ./homebrew/sunshine.rb
|
||||||
|
|
||||||
|
- name: Upload Artifacts
|
||||||
|
if: matrix.release
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-Homebrew
|
||||||
|
path: homebrew/
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Setup Xvfb
|
||||||
|
if: matrix.release != true && runner.os == 'Linux'
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y \
|
||||||
|
xvfb
|
||||||
|
|
||||||
|
export DISPLAY=:1
|
||||||
|
Xvfb ${DISPLAY} -screen 0 1024x768x24 &
|
||||||
|
|
||||||
|
echo "DISPLAY=${DISPLAY}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Validate Homebrew Formula
|
||||||
|
id: test
|
||||||
|
if: matrix.release != true
|
||||||
|
uses: LizardByte/actions/actions/release_homebrew@v2025.711.172650
|
||||||
|
with:
|
||||||
|
formula_file: ${{ github.workspace }}/homebrew/sunshine.rb
|
||||||
|
git_email: ${{ secrets.GIT_EMAIL }}
|
||||||
|
git_username: ${{ secrets.GIT_USERNAME }}
|
||||||
|
publish: false
|
||||||
|
token: ${{ secrets.GH_TOKEN }}
|
||||||
|
validate: true
|
||||||
|
|
||||||
|
- name: Setup python
|
||||||
|
id: python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
|
||||||
|
- name: Generate gcov report
|
||||||
|
id: test_report
|
||||||
|
# any except canceled or skipped
|
||||||
|
# TODO: fix coverage, no .gcno files are being created
|
||||||
|
# TODO: .gcno files are supposed to be created next to .o files
|
||||||
|
if: false
|
||||||
|
# if: >-
|
||||||
|
# always() &&
|
||||||
|
# matrix.release != true &&
|
||||||
|
# (steps.test.outcome == 'success' || steps.test.outcome == 'failure')
|
||||||
|
run: |
|
||||||
|
cp -rf ${{ steps.test.outputs.buildpath }}/build/ ./build/
|
||||||
|
cd build
|
||||||
|
ls -Ra
|
||||||
|
|
||||||
|
${{ steps.python.outputs.python-path }} -m pip install gcovr
|
||||||
|
${{ steps.python.outputs.python-path }} -m gcovr . -r ../src \
|
||||||
|
--exclude-noncode-lines \
|
||||||
|
--exclude-throw-branches \
|
||||||
|
--exclude-unreachable-branches \
|
||||||
|
--verbose \
|
||||||
|
--xml-pretty \
|
||||||
|
-o coverage.xml
|
||||||
|
|
||||||
|
- name: Upload coverage artifact
|
||||||
|
if: >-
|
||||||
|
always() &&
|
||||||
|
matrix.release != true &&
|
||||||
|
(steps.test.outcome == 'success' || steps.test.outcome == 'failure') &&
|
||||||
|
startsWith(github.repository, 'LizardByte/')
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-Homebrew-${{ matrix.os_name }}-${{ matrix.os_version }}
|
||||||
|
path: |
|
||||||
|
build/coverage.xml
|
||||||
|
${{ steps.test.outputs.testpath }}/test_results.xml
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Patch homebrew formula
|
||||||
|
# create beta version of the formula
|
||||||
|
# don't run this on macOS, as the sed command fails
|
||||||
|
if: matrix.release
|
||||||
|
run: |
|
||||||
|
# variables
|
||||||
|
formula_file="homebrew/sunshine-beta.rb"
|
||||||
|
|
||||||
|
# rename the file
|
||||||
|
mv homebrew/sunshine.rb $formula_file
|
||||||
|
|
||||||
|
# update the formula
|
||||||
|
sed -i 's/class Sunshine < Formula/class SunshineBeta < Formula/' $formula_file
|
||||||
|
sed -i 's/# conflicts_with/conflicts_with/' $formula_file
|
||||||
|
|
||||||
|
# print new file
|
||||||
|
echo "New formula:"
|
||||||
|
cat $formula_file
|
||||||
|
|
||||||
|
- name: Upload Homebrew Beta Formula
|
||||||
|
if: >-
|
||||||
|
github.repository_owner == 'LizardByte' &&
|
||||||
|
matrix.release &&
|
||||||
|
inputs.publish_release == 'true'
|
||||||
|
uses: LizardByte/actions/actions/release_homebrew@v2025.711.172650
|
||||||
|
with:
|
||||||
|
formula_file: ${{ github.workspace }}/homebrew/sunshine-beta.rb
|
||||||
|
git_email: ${{ secrets.GIT_EMAIL }}
|
||||||
|
git_username: ${{ secrets.GIT_USERNAME }}
|
||||||
|
publish: true
|
||||||
|
token: ${{ secrets.GH_TOKEN }}
|
||||||
|
validate: false
|
||||||
216
.github/workflows/ci-linux.yml
vendored
Normal file
216
.github/workflows/ci-linux.yml
vendored
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
---
|
||||||
|
name: CI-Linux
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
release_commit:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
release_version:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_linux:
|
||||||
|
name: ${{ matrix.name }}
|
||||||
|
env:
|
||||||
|
APP_ID: dev.lizardbyte.app.Sunshine
|
||||||
|
runs-on: ubuntu-${{ matrix.dist }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- name: AppImage
|
||||||
|
EXTRA_ARGS: '--appimage-build'
|
||||||
|
dist: 22.04
|
||||||
|
steps:
|
||||||
|
- name: Maximize build space
|
||||||
|
uses: easimon/maximize-build-space@v10
|
||||||
|
with:
|
||||||
|
root-reserve-mb: 30720
|
||||||
|
remove-dotnet: 'true'
|
||||||
|
remove-android: 'true'
|
||||||
|
remove-haskell: 'true'
|
||||||
|
remove-codeql: 'true'
|
||||||
|
remove-docker-images: 'true'
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Setup Dependencies Linux
|
||||||
|
timeout-minutes: 5
|
||||||
|
run: |
|
||||||
|
# create the artifacts directory
|
||||||
|
mkdir -p artifacts
|
||||||
|
|
||||||
|
# allow libfuse2 for appimage on 22.04+
|
||||||
|
sudo add-apt-repository universe
|
||||||
|
|
||||||
|
sudo apt-get install -y \
|
||||||
|
libdrm-dev \
|
||||||
|
libfuse2 \
|
||||||
|
libgl-dev \
|
||||||
|
libwayland-dev \
|
||||||
|
libx11-xcb-dev \
|
||||||
|
libxcb-dri3-dev \
|
||||||
|
libxfixes-dev
|
||||||
|
|
||||||
|
- name: Setup python
|
||||||
|
id: python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
|
||||||
|
- name: Build latest libva
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
timeout-minutes: 5
|
||||||
|
run: |
|
||||||
|
gh release download --archive=tar.gz --repo=intel/libva
|
||||||
|
tar xzf libva-*.tar.gz && rm libva-*.tar.gz
|
||||||
|
cd libva-*
|
||||||
|
./autogen.sh --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu \
|
||||||
|
--enable-drm \
|
||||||
|
--enable-x11 \
|
||||||
|
--enable-glx \
|
||||||
|
--enable-wayland \
|
||||||
|
--without-legacy # emgd, nvctrl, fglrx
|
||||||
|
make -j $(nproc)
|
||||||
|
sudo make install
|
||||||
|
cd .. && rm -rf libva-*
|
||||||
|
|
||||||
|
- name: Build Linux
|
||||||
|
env:
|
||||||
|
BRANCH: ${{ github.head_ref || github.ref_name }}
|
||||||
|
BUILD_VERSION: ${{ inputs.release_version }}
|
||||||
|
COMMIT: ${{ inputs.release_commit }}
|
||||||
|
run: |
|
||||||
|
chmod +x ./scripts/linux_build.sh
|
||||||
|
./scripts/linux_build.sh \
|
||||||
|
--publisher-name='${{ github.repository_owner }}' \
|
||||||
|
--publisher-website='https://app.lizardbyte.dev' \
|
||||||
|
--publisher-issue-url='https://app.lizardbyte.dev/support' \
|
||||||
|
--skip-cleanup \
|
||||||
|
--skip-package \
|
||||||
|
--ubuntu-test-repo ${{ matrix.EXTRA_ARGS }}
|
||||||
|
|
||||||
|
- name: Set AppImage Version
|
||||||
|
if: matrix.name == 'AppImage'
|
||||||
|
run: |
|
||||||
|
version=${{ inputs.release_version }}
|
||||||
|
echo "VERSION=${version}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Package Linux - AppImage
|
||||||
|
if: matrix.name == 'AppImage'
|
||||||
|
working-directory: build
|
||||||
|
run: |
|
||||||
|
# install sunshine to the DESTDIR
|
||||||
|
DESTDIR=AppDir ninja install
|
||||||
|
|
||||||
|
# custom AppRun file
|
||||||
|
cp -f ../packaging/linux/AppImage/AppRun ./AppDir/
|
||||||
|
chmod +x ./AppDir/AppRun
|
||||||
|
|
||||||
|
# variables
|
||||||
|
DESKTOP_FILE="${DESKTOP_FILE:-${APP_ID}.desktop}"
|
||||||
|
ICON_FILE="${ICON_FILE:-sunshine.png}"
|
||||||
|
|
||||||
|
# AppImage
|
||||||
|
# https://docs.appimage.org/packaging-guide/index.html
|
||||||
|
wget -q 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 -q 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 \
|
||||||
|
--plugin gtk \
|
||||||
|
--executable ./sunshine \
|
||||||
|
--icon-file "../$ICON_FILE" \
|
||||||
|
--desktop-file "./$DESKTOP_FILE" \
|
||||||
|
--output appimage
|
||||||
|
|
||||||
|
# move
|
||||||
|
mv Sunshine*.AppImage ../artifacts/sunshine.AppImage
|
||||||
|
|
||||||
|
# permissions
|
||||||
|
chmod +x ../artifacts/sunshine.AppImage
|
||||||
|
|
||||||
|
- name: Delete CUDA
|
||||||
|
# free up space on the runner
|
||||||
|
run: |
|
||||||
|
rm -rf ./build/cuda
|
||||||
|
|
||||||
|
- name: Verify AppImage
|
||||||
|
if: matrix.name == 'AppImage'
|
||||||
|
run: |
|
||||||
|
wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage
|
||||||
|
chmod +x appimagelint-x86_64.AppImage
|
||||||
|
|
||||||
|
./appimagelint-x86_64.AppImage ./artifacts/sunshine.AppImage
|
||||||
|
|
||||||
|
- name: Install test deps
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y \
|
||||||
|
x11-xserver-utils \
|
||||||
|
xvfb
|
||||||
|
|
||||||
|
# clean apt cache
|
||||||
|
sudo apt-get clean
|
||||||
|
sudo rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
id: test
|
||||||
|
working-directory: build/tests
|
||||||
|
run: |
|
||||||
|
export DISPLAY=:1
|
||||||
|
Xvfb ${DISPLAY} -screen 0 1024x768x24 &
|
||||||
|
sleep 5 # give Xvfb time to start
|
||||||
|
|
||||||
|
./test_sunshine --gtest_color=yes --gtest_output=xml:test_results.xml
|
||||||
|
|
||||||
|
- name: Generate gcov report
|
||||||
|
id: test_report
|
||||||
|
# any except canceled or skipped
|
||||||
|
if: >-
|
||||||
|
always() &&
|
||||||
|
(steps.test.outcome == 'success' || steps.test.outcome == 'failure')
|
||||||
|
working-directory: build
|
||||||
|
run: |
|
||||||
|
${{ steps.python.outputs.python-path }} -m pip install gcovr
|
||||||
|
${{ steps.python.outputs.python-path }} -m gcovr . -r ../src \
|
||||||
|
--exclude-noncode-lines \
|
||||||
|
--exclude-throw-branches \
|
||||||
|
--exclude-unreachable-branches \
|
||||||
|
--verbose \
|
||||||
|
--xml-pretty \
|
||||||
|
-o coverage.xml
|
||||||
|
|
||||||
|
- name: Upload coverage artifact
|
||||||
|
if: >-
|
||||||
|
always() &&
|
||||||
|
(steps.test_report.outcome == 'success')
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-Linux-${{ matrix.name }}
|
||||||
|
path: |
|
||||||
|
build/coverage.xml
|
||||||
|
build/tests/test_results.xml
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Upload Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-Linux-${{ matrix.name }}
|
||||||
|
path: artifacts/
|
||||||
|
if-no-files-found: error
|
||||||
345
.github/workflows/ci-windows.yml
vendored
Normal file
345
.github/workflows/ci-windows.yml
vendored
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
---
|
||||||
|
name: CI-Windows
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
release_commit:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
release_version:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
secrets:
|
||||||
|
CODECOV_TOKEN:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_windows:
|
||||||
|
name: ${{ matrix.name }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: msys2 {0}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- name: Windows-AMD64
|
||||||
|
os: windows-2022
|
||||||
|
arch: x86_64
|
||||||
|
msystem: ucrt64
|
||||||
|
toolchain: ucrt-x86_64
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Prepare tests
|
||||||
|
id: prepare-tests
|
||||||
|
if: false # todo: DirectX11 is not available, so even software encoder fails
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
# function to download and extract a zip file
|
||||||
|
function DownloadAndExtract {
|
||||||
|
param (
|
||||||
|
[string]$Uri,
|
||||||
|
[string]$OutFile
|
||||||
|
)
|
||||||
|
|
||||||
|
$maxRetries = 5
|
||||||
|
$retryCount = 0
|
||||||
|
$success = $false
|
||||||
|
|
||||||
|
while (-not $success -and $retryCount -lt $maxRetries) {
|
||||||
|
$retryCount++
|
||||||
|
Write-Host "Downloading $Uri to $OutFile, attempt $retryCount of $maxRetries"
|
||||||
|
try {
|
||||||
|
Invoke-WebRequest -Uri $Uri -OutFile $OutFile
|
||||||
|
$success = $true
|
||||||
|
} catch {
|
||||||
|
Write-Host "Attempt $retryCount of $maxRetries failed with error: $($_.Exception.Message). Retrying..."
|
||||||
|
Start-Sleep -Seconds 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $success) {
|
||||||
|
Write-Host "Failed to download the file after $maxRetries attempts."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# use .NET to get the base name of the file
|
||||||
|
$baseName = (Get-Item $OutFile).BaseName
|
||||||
|
|
||||||
|
# Extract the zip file
|
||||||
|
Expand-Archive -Path $OutFile -DestinationPath $baseName
|
||||||
|
}
|
||||||
|
|
||||||
|
# virtual display driver
|
||||||
|
DownloadAndExtract `
|
||||||
|
-Uri "https://www.amyuni.com/downloads/usbmmidd_v2.zip" `
|
||||||
|
-OutFile "usbmmidd_v2.zip"
|
||||||
|
|
||||||
|
# install
|
||||||
|
Set-Location -Path usbmmidd_v2/usbmmidd_v2
|
||||||
|
./deviceinstaller64 install usbmmidd.inf usbmmidd
|
||||||
|
|
||||||
|
# create the virtual display
|
||||||
|
./deviceinstaller64 enableidd 1
|
||||||
|
|
||||||
|
# move up a directory
|
||||||
|
Set-Location -Path ../..
|
||||||
|
|
||||||
|
# install devcon
|
||||||
|
DownloadAndExtract `
|
||||||
|
-Uri "https://github.com/Drawbackz/DevCon-Installer/releases/download/1.4-rc/Devcon.Installer.zip" `
|
||||||
|
-OutFile "Devcon.Installer.zip"
|
||||||
|
Set-Location -Path Devcon.Installer
|
||||||
|
# hash needs to match OS version
|
||||||
|
# https://github.com/Drawbackz/DevCon-Installer/blob/master/devcon_sources.json
|
||||||
|
Start-Process -FilePath "./Devcon Installer.exe" -Wait -ArgumentList `
|
||||||
|
'install', `
|
||||||
|
'-hash', '54004C83EE34F6A55380528A8B29F4C400E61FBB947A19E0AB9E5A193D7D961E', `
|
||||||
|
'-addpath', `
|
||||||
|
'-update', `
|
||||||
|
'-dir', 'C:\Windows\System32'
|
||||||
|
|
||||||
|
# disable Hyper-V Video
|
||||||
|
# https://stackoverflow.com/a/59490940
|
||||||
|
C:\Windows\System32\devcon.exe disable "VMBUS\{da0a7802-e377-4aac-8e77-0558eb1073f8}"
|
||||||
|
|
||||||
|
# move up a directory
|
||||||
|
Set-Location -Path ..
|
||||||
|
|
||||||
|
# multi monitor tool
|
||||||
|
DownloadAndExtract `
|
||||||
|
-Uri "http://www.nirsoft.net/utils/multimonitortool-x64.zip" `
|
||||||
|
-OutFile "multimonitortool.zip"
|
||||||
|
|
||||||
|
# enable the virtual display
|
||||||
|
# http://www.nirsoft.net/utils/multi_monitor_tool.html
|
||||||
|
Set-Location -Path multimonitortool
|
||||||
|
|
||||||
|
# Original Hyper-V is \\.\DISPLAY1, it will recreate itself as \\.\DISPLAY6 (or something higher than 2)
|
||||||
|
# USB Mobile Monitor Virtual Display is \\.\DISPLAY2
|
||||||
|
|
||||||
|
# these don't seem to work if not using runAs
|
||||||
|
# todo: do they work if not using runAs?
|
||||||
|
Start-Process powershell -Verb runAs -ArgumentList '-Command ./MultiMonitorTool.exe /enable \\.\DISPLAY2'
|
||||||
|
Start-Process powershell -Verb runAs -ArgumentList '-Command ./MultiMonitorTool.exe /SetPrimary \\.\DISPLAY2'
|
||||||
|
|
||||||
|
# wait a few seconds
|
||||||
|
Start-Sleep -s 5
|
||||||
|
|
||||||
|
# list monitors
|
||||||
|
./MultiMonitorTool.exe /stext monitor_list.txt
|
||||||
|
|
||||||
|
# wait a few seconds
|
||||||
|
Start-Sleep -s 5
|
||||||
|
|
||||||
|
# print the monitor list
|
||||||
|
Get-Content -Path monitor_list.txt
|
||||||
|
|
||||||
|
- name: Setup Dependencies Windows
|
||||||
|
# if a dependency needs to be pinned, see https://github.com/LizardByte/build-deps/pull/186
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: ${{ matrix.msystem }}
|
||||||
|
update: true
|
||||||
|
install: >-
|
||||||
|
wget
|
||||||
|
|
||||||
|
- name: Update Windows dependencies
|
||||||
|
env:
|
||||||
|
MSYSTEM: ${{ matrix.msystem }}
|
||||||
|
TOOLCHAIN: ${{ matrix.toolchain }}
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
# variables
|
||||||
|
declare -A pinned_deps
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
dependencies=(
|
||||||
|
"git"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-cmake"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-cppwinrt"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-curl-winssl"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-gcc"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-graphviz"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-MinHook"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-miniupnpc"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-nlohmann-json"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-nodejs"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-nsis"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-onevpl"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-openssl"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-opus"
|
||||||
|
"mingw-w64-${TOOLCHAIN}-toolchain"
|
||||||
|
)
|
||||||
|
|
||||||
|
# do not modify below this line
|
||||||
|
|
||||||
|
ignore_packages=()
|
||||||
|
tarballs=""
|
||||||
|
for pkg in "${!pinned_deps[@]}"; do
|
||||||
|
ignore_packages+=("${pkg}")
|
||||||
|
version="${pinned_deps[$pkg]}"
|
||||||
|
tarball="${pkg}-${version}-any.pkg.tar.zst"
|
||||||
|
|
||||||
|
# download working version
|
||||||
|
wget "https://repo.msys2.org/mingw/${MSYSTEM}/${tarball}"
|
||||||
|
|
||||||
|
tarballs="${tarballs} ${tarball}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create the ignore string for pacman
|
||||||
|
ignore_list=$(IFS=,; echo "${ignore_packages[*]}")
|
||||||
|
|
||||||
|
# install pinned dependencies
|
||||||
|
if [ -n "$tarballs" ]; then
|
||||||
|
pacman -U --noconfirm ${tarballs}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Only add --ignore if we have packages to ignore
|
||||||
|
if [ -n "$ignore_list" ]; then
|
||||||
|
pacman -Syu --noconfirm --ignore="${ignore_list}" "${dependencies[@]}"
|
||||||
|
else
|
||||||
|
pacman -Syu --noconfirm "${dependencies[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Install Doxygen
|
||||||
|
# GCC compiled doxygen has issues when running graphviz
|
||||||
|
env:
|
||||||
|
DOXYGEN_VERSION: "1.11.0"
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
# Set version variables
|
||||||
|
$doxy_ver = $env:DOXYGEN_VERSION
|
||||||
|
$_doxy_ver = $doxy_ver.Replace(".", "_")
|
||||||
|
|
||||||
|
# Download the Doxygen installer
|
||||||
|
Invoke-WebRequest -Uri `
|
||||||
|
"https://github.com/doxygen/doxygen/releases/download/Release_${_doxy_ver}/doxygen-${doxy_ver}-setup.exe" `
|
||||||
|
-OutFile "doxygen-setup.exe"
|
||||||
|
|
||||||
|
# Run the installer
|
||||||
|
Start-Process `
|
||||||
|
-FilePath .\doxygen-setup.exe `
|
||||||
|
-ArgumentList `
|
||||||
|
'/VERYSILENT' `
|
||||||
|
-Wait `
|
||||||
|
-NoNewWindow
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
Remove-Item -Path doxygen-setup.exe
|
||||||
|
|
||||||
|
- name: Setup python
|
||||||
|
id: setup-python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
|
||||||
|
- name: Python Path
|
||||||
|
id: python-path
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
# replace backslashes with double backslashes
|
||||||
|
python_path=$(echo "${{ steps.setup-python.outputs.python-path }}" | sed 's/\\/\\\\/g')
|
||||||
|
|
||||||
|
# step output
|
||||||
|
echo "python-path=${python_path}"
|
||||||
|
echo "python-path=${python_path}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Build Windows
|
||||||
|
shell: msys2 {0}
|
||||||
|
env:
|
||||||
|
BRANCH: ${{ github.head_ref || github.ref_name }}
|
||||||
|
BUILD_VERSION: ${{ inputs.release_version }}
|
||||||
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
COMMIT: ${{ inputs.release_commit }}
|
||||||
|
run: |
|
||||||
|
mkdir -p build
|
||||||
|
cmake \
|
||||||
|
-B build \
|
||||||
|
-G Ninja \
|
||||||
|
-S . \
|
||||||
|
-DBUILD_WERROR=ON \
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
|
-DSUNSHINE_ASSETS_DIR=assets \
|
||||||
|
-DSUNSHINE_PUBLISHER_NAME='${{ github.repository_owner }}' \
|
||||||
|
-DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' \
|
||||||
|
-DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'
|
||||||
|
ninja -C build
|
||||||
|
|
||||||
|
- name: Package Windows
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
mkdir -p artifacts
|
||||||
|
cd build
|
||||||
|
|
||||||
|
# package
|
||||||
|
cpack -G NSIS
|
||||||
|
cpack -G ZIP
|
||||||
|
|
||||||
|
# move
|
||||||
|
mv ./cpack_artifacts/Sunshine.exe ../artifacts/Sunshine-${{ matrix.name }}-installer.exe
|
||||||
|
mv ./cpack_artifacts/Sunshine.zip ../artifacts/Sunshine-${{ matrix.name }}-portable.zip
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
id: test
|
||||||
|
shell: msys2 {0}
|
||||||
|
working-directory: build/tests
|
||||||
|
run: |
|
||||||
|
./test_sunshine.exe --gtest_color=yes --gtest_output=xml:test_results.xml
|
||||||
|
|
||||||
|
- name: Generate gcov report
|
||||||
|
id: test_report
|
||||||
|
# any except canceled or skipped
|
||||||
|
if: always() && (steps.test.outcome == 'success' || steps.test.outcome == 'failure')
|
||||||
|
shell: msys2 {0}
|
||||||
|
working-directory: build
|
||||||
|
run: |
|
||||||
|
${{ steps.python-path.outputs.python-path }} -m pip install gcovr
|
||||||
|
${{ steps.python-path.outputs.python-path }} -m gcovr . -r ../src \
|
||||||
|
--exclude-noncode-lines \
|
||||||
|
--exclude-throw-branches \
|
||||||
|
--exclude-unreachable-branches \
|
||||||
|
--verbose \
|
||||||
|
--xml-pretty \
|
||||||
|
-o coverage.xml
|
||||||
|
|
||||||
|
- name: Upload coverage artifact
|
||||||
|
if: >-
|
||||||
|
always() &&
|
||||||
|
(steps.test_report.outcome == 'success')
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-${{ matrix.name }}
|
||||||
|
path: |
|
||||||
|
build/coverage.xml
|
||||||
|
build/tests/test_results.xml
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Package Windows Debug Info
|
||||||
|
shell: pwsh
|
||||||
|
working-directory: build
|
||||||
|
run: |
|
||||||
|
# use .dbg file extension for binaries to avoid confusion with real packages
|
||||||
|
Get-ChildItem -File -Recurse | `
|
||||||
|
% { Rename-Item -Path $_.PSPath -NewName $_.Name.Replace(".exe",".dbg") }
|
||||||
|
|
||||||
|
# save the binaries with debug info
|
||||||
|
7z -r `
|
||||||
|
"-xr!CMakeFiles" `
|
||||||
|
"-xr!cpack_artifacts" `
|
||||||
|
a "../artifacts/Sunshine-${{ matrix.name }}-debuginfo.7z" "*.dbg"
|
||||||
|
|
||||||
|
- name: Upload Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-${{ matrix.name }}
|
||||||
|
path: artifacts/
|
||||||
|
if-no-files-found: error
|
||||||
214
.github/workflows/ci.yml
vendored
Normal file
214
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
---
|
||||||
|
name: CI
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
- reopened
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "${{ github.workflow }}-${{ github.ref }}"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
github-env:
|
||||||
|
name: GitHub Env Debug
|
||||||
|
uses: LizardByte/.github/.github/workflows/__call-github-env.yml@master
|
||||||
|
|
||||||
|
release-setup:
|
||||||
|
name: Release Setup
|
||||||
|
outputs:
|
||||||
|
publish_release: ${{ steps.release-setup.outputs.publish_release }}
|
||||||
|
release_body: ${{ steps.release-setup.outputs.release_body }}
|
||||||
|
release_commit: ${{ steps.release-setup.outputs.release_commit }}
|
||||||
|
release_generate_release_notes: ${{ steps.release-setup.outputs.release_generate_release_notes }}
|
||||||
|
release_tag: ${{ steps.release-setup.outputs.release_tag }}
|
||||||
|
release_version: ${{ steps.release-setup.outputs.release_version }}
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Release Setup
|
||||||
|
id: release-setup
|
||||||
|
uses: LizardByte/actions/actions/release_setup@v2025.711.172650
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
build-docker:
|
||||||
|
name: Docker
|
||||||
|
needs: release-setup
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
uses: LizardByte/.github/.github/workflows/__call-docker.yml@master
|
||||||
|
with:
|
||||||
|
maximize_build_space: true
|
||||||
|
publish_release: ${{ needs.release-setup.outputs.publish_release }}
|
||||||
|
release_commit: ${{ needs.release-setup.outputs.release_commit }}
|
||||||
|
release_tag: ${{ needs.release-setup.outputs.release_tag }}
|
||||||
|
release_version: ${{ needs.release-setup.outputs.release_version }}
|
||||||
|
secrets:
|
||||||
|
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
|
DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||||
|
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
|
GH_BOT_NAME: ${{ secrets.GH_BOT_NAME }}
|
||||||
|
GH_BOT_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
build-homebrew:
|
||||||
|
name: Homebrew
|
||||||
|
needs: release-setup
|
||||||
|
uses: ./.github/workflows/ci-homebrew.yml
|
||||||
|
with:
|
||||||
|
publish_release: ${{ needs.release-setup.outputs.publish_release }}
|
||||||
|
release_commit: ${{ needs.release-setup.outputs.release_commit }}
|
||||||
|
release_tag: ${{ needs.release-setup.outputs.release_tag }}
|
||||||
|
release_version: ${{ needs.release-setup.outputs.release_version }}
|
||||||
|
secrets:
|
||||||
|
GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
|
||||||
|
GIT_EMAIL: ${{ secrets.GH_BOT_EMAIL }}
|
||||||
|
GIT_USERNAME: ${{ secrets.GH_BOT_NAME }}
|
||||||
|
|
||||||
|
build-linux:
|
||||||
|
name: Linux
|
||||||
|
needs: release-setup
|
||||||
|
uses: ./.github/workflows/ci-linux.yml
|
||||||
|
with:
|
||||||
|
release_commit: ${{ needs.release-setup.outputs.release_commit }}
|
||||||
|
release_version: ${{ needs.release-setup.outputs.release_version }}
|
||||||
|
|
||||||
|
build-linux-copr:
|
||||||
|
name: Linux Copr
|
||||||
|
if: github.event_name != 'push' # releases are handled directly in ci-copr.yml
|
||||||
|
needs: release-setup
|
||||||
|
uses: ./.github/workflows/ci-copr.yml
|
||||||
|
secrets:
|
||||||
|
COPR_BETA_WEBHOOK_TOKEN: ${{ secrets.COPR_BETA_WEBHOOK_TOKEN }}
|
||||||
|
COPR_STABLE_WEBHOOK_TOKEN: ${{ secrets.COPR_STABLE_WEBHOOK_TOKEN }}
|
||||||
|
COPR_CLI_CONFIG: ${{ secrets.COPR_CLI_CONFIG }}
|
||||||
|
|
||||||
|
build-linux-flatpak:
|
||||||
|
name: Linux Flatpak
|
||||||
|
needs: release-setup
|
||||||
|
uses: ./.github/workflows/ci-flatpak.yml
|
||||||
|
with:
|
||||||
|
release_commit: ${{ needs.release-setup.outputs.release_commit }}
|
||||||
|
release_version: ${{ needs.release-setup.outputs.release_version }}
|
||||||
|
|
||||||
|
build-windows:
|
||||||
|
name: Windows
|
||||||
|
needs: release-setup
|
||||||
|
uses: ./.github/workflows/ci-windows.yml
|
||||||
|
with:
|
||||||
|
release_commit: ${{ needs.release-setup.outputs.release_commit }}
|
||||||
|
release_version: ${{ needs.release-setup.outputs.release_version }}
|
||||||
|
secrets:
|
||||||
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
name: Coverage-${{ matrix.name }}
|
||||||
|
if: >-
|
||||||
|
always() &&
|
||||||
|
!cancelled() &&
|
||||||
|
startsWith(github.repository, 'LizardByte/')
|
||||||
|
needs:
|
||||||
|
- build-linux
|
||||||
|
- build-linux-flatpak
|
||||||
|
- build-homebrew
|
||||||
|
- build-windows
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- name: Linux-AppImage
|
||||||
|
coverage: true
|
||||||
|
- name: Homebrew-macos-13
|
||||||
|
coverage: false
|
||||||
|
- name: Homebrew-macos-14
|
||||||
|
coverage: false
|
||||||
|
- name: Homebrew-macos-15
|
||||||
|
coverage: false
|
||||||
|
- name: Homebrew-ubuntu-latest
|
||||||
|
coverage: false
|
||||||
|
- name: Windows-AMD64
|
||||||
|
coverage: true
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Download coverage artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-${{ matrix.name }}
|
||||||
|
path: _coverage
|
||||||
|
|
||||||
|
- name: Upload test results
|
||||||
|
uses: codecov/test-results-action@v1
|
||||||
|
with:
|
||||||
|
disable_search: true
|
||||||
|
fail_ci_if_error: true
|
||||||
|
files: ./_coverage/tests/test_results.xml
|
||||||
|
flags: ${{ matrix.name }}
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
verbose: true
|
||||||
|
|
||||||
|
- name: Upload coverage
|
||||||
|
uses: codecov/codecov-action@v5
|
||||||
|
if: matrix.coverage != false
|
||||||
|
with:
|
||||||
|
disable_search: true
|
||||||
|
fail_ci_if_error: true
|
||||||
|
files: ./_coverage/coverage.xml
|
||||||
|
flags: ${{ matrix.name }}
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
verbose: true
|
||||||
|
|
||||||
|
release:
|
||||||
|
name: Release
|
||||||
|
if:
|
||||||
|
needs.release-setup.outputs.publish_release == 'true' &&
|
||||||
|
startsWith(github.repository, 'LizardByte/')
|
||||||
|
needs:
|
||||||
|
- release-setup
|
||||||
|
- build-docker
|
||||||
|
- build-linux
|
||||||
|
- build-linux-flatpak
|
||||||
|
- build-homebrew
|
||||||
|
- build-windows
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Download build artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: artifacts
|
||||||
|
pattern: build-*
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: Debug artifacts
|
||||||
|
run: ls -l artifacts
|
||||||
|
|
||||||
|
- name: Create/Update GitHub Release
|
||||||
|
uses: LizardByte/actions/actions/release_create@v2025.711.172650
|
||||||
|
with:
|
||||||
|
allowUpdates: false
|
||||||
|
body: ${{ needs.release-setup.outputs.release_body }}
|
||||||
|
generateReleaseNotes: ${{ needs.release-setup.outputs.release_generate_release_notes }}
|
||||||
|
name: ${{ needs.release-setup.outputs.release_tag }}
|
||||||
|
prerelease: true
|
||||||
|
tag: ${{ needs.release-setup.outputs.release_tag }}
|
||||||
|
token: ${{ secrets.GH_BOT_TOKEN }}
|
||||||
|
virustotal_api_key: ${{ secrets.VIRUSTOTAL_API_KEY }}
|
||||||
@@ -52,9 +52,6 @@ include_directories(BEFORE SYSTEM "${CMAKE_SOURCE_DIR}/third-party/nv-codec-head
|
|||||||
file(GLOB NVENC_SOURCES CONFIGURE_DEPENDS "src/nvenc/*.cpp" "src/nvenc/*.h")
|
file(GLOB NVENC_SOURCES CONFIGURE_DEPENDS "src/nvenc/*.cpp" "src/nvenc/*.h")
|
||||||
list(APPEND PLATFORM_TARGET_FILES ${NVENC_SOURCES})
|
list(APPEND PLATFORM_TARGET_FILES ${NVENC_SOURCES})
|
||||||
|
|
||||||
configure_file("${CMAKE_SOURCE_DIR}/src/version.h.in" version.h @ONLY)
|
|
||||||
include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}") # required for importing version.h
|
|
||||||
|
|
||||||
set(SUNSHINE_TARGET_FILES
|
set(SUNSHINE_TARGET_FILES
|
||||||
"${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/src/Input.h"
|
"${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/src/Input.h"
|
||||||
"${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/src/Rtsp.h"
|
"${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/src/Rtsp.h"
|
||||||
|
|||||||
@@ -85,18 +85,27 @@ if(CUDA_FOUND)
|
|||||||
add_compile_definitions(SUNSHINE_BUILD_CUDA)
|
add_compile_definitions(SUNSHINE_BUILD_CUDA)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# drm
|
# libdrm is required for both DRM (KMS) and Wayland
|
||||||
if(${SUNSHINE_ENABLE_DRM})
|
if(${SUNSHINE_ENABLE_DRM} OR ${SUNSHINE_ENABLE_WAYLAND})
|
||||||
find_package(LIBDRM REQUIRED)
|
find_package(LIBDRM REQUIRED)
|
||||||
find_package(LIBCAP REQUIRED)
|
|
||||||
else()
|
else()
|
||||||
set(LIBDRM_FOUND OFF)
|
set(LIBDRM_FOUND OFF)
|
||||||
|
endif()
|
||||||
|
if(LIBDRM_FOUND)
|
||||||
|
include_directories(SYSTEM ${LIBDRM_INCLUDE_DIRS})
|
||||||
|
list(APPEND PLATFORM_LIBRARIES ${LIBDRM_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# drm
|
||||||
|
if(${SUNSHINE_ENABLE_DRM})
|
||||||
|
find_package(LIBCAP REQUIRED)
|
||||||
|
else()
|
||||||
set(LIBCAP_FOUND OFF)
|
set(LIBCAP_FOUND OFF)
|
||||||
endif()
|
endif()
|
||||||
if(LIBDRM_FOUND AND LIBCAP_FOUND)
|
if(LIBDRM_FOUND AND LIBCAP_FOUND)
|
||||||
add_compile_definitions(SUNSHINE_BUILD_DRM)
|
add_compile_definitions(SUNSHINE_BUILD_DRM)
|
||||||
include_directories(SYSTEM ${LIBDRM_INCLUDE_DIRS} ${LIBCAP_INCLUDE_DIRS})
|
include_directories(SYSTEM ${LIBCAP_INCLUDE_DIRS})
|
||||||
list(APPEND PLATFORM_LIBRARIES ${LIBDRM_LIBRARIES} ${LIBCAP_LIBRARIES})
|
list(APPEND PLATFORM_LIBRARIES ${LIBCAP_LIBRARIES})
|
||||||
list(APPEND PLATFORM_TARGET_FILES
|
list(APPEND PLATFORM_TARGET_FILES
|
||||||
"${CMAKE_SOURCE_DIR}/src/platform/linux/kmsgrab.cpp")
|
"${CMAKE_SOURCE_DIR}/src/platform/linux/kmsgrab.cpp")
|
||||||
list(APPEND SUNSHINE_DEFINITIONS EGL_NO_X11=1)
|
list(APPEND SUNSHINE_DEFINITIONS EGL_NO_X11=1)
|
||||||
|
|||||||
@@ -38,10 +38,17 @@ if(NOT DEFINED SUNSHINE_ICON_PATH)
|
|||||||
set(SUNSHINE_ICON_PATH "${CMAKE_SOURCE_DIR}/apollo.ico")
|
set(SUNSHINE_ICON_PATH "${CMAKE_SOURCE_DIR}/apollo.ico")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
configure_file("${CMAKE_SOURCE_DIR}/src/platform/windows/windows.rc.in" windows.rc @ONLY)
|
# Create a separate object library for the RC file with minimal includes
|
||||||
|
add_library(sunshine_rc_object OBJECT "${CMAKE_SOURCE_DIR}/src/platform/windows/windows.rc")
|
||||||
|
|
||||||
|
# Set minimal properties for RC compilation - only what's needed for the resource file
|
||||||
|
# Otherwise compilation can fail due to "line too long" errors
|
||||||
|
set_target_properties(sunshine_rc_object PROPERTIES
|
||||||
|
COMPILE_DEFINITIONS "PROJECT_ICON_PATH=${SUNSHINE_ICON_PATH};PROJECT_NAME=${PROJECT_NAME};PROJECT_VENDOR=${SUNSHINE_PUBLISHER_NAME};PROJECT_VERSION=${PROJECT_VERSION};PROJECT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR};PROJECT_VERSION_MINOR=${PROJECT_VERSION_MINOR};PROJECT_VERSION_PATCH=${PROJECT_VERSION_PATCH}" # cmake-lint: disable=C0301
|
||||||
|
INCLUDE_DIRECTORIES ""
|
||||||
|
)
|
||||||
|
|
||||||
set(PLATFORM_TARGET_FILES
|
set(PLATFORM_TARGET_FILES
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/windows.rc"
|
|
||||||
"${CMAKE_SOURCE_DIR}/src/platform/windows/publish.cpp"
|
"${CMAKE_SOURCE_DIR}/src/platform/windows/publish.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/src/platform/windows/misc.h"
|
"${CMAKE_SOURCE_DIR}/src/platform/windows/misc.h"
|
||||||
"${CMAKE_SOURCE_DIR}/src/platform/windows/misc.cpp"
|
"${CMAKE_SOURCE_DIR}/src/platform/windows/misc.cpp"
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
# common cpack options
|
# common cpack options
|
||||||
set(CPACK_PACKAGE_NAME ${CMAKE_PROJECT_NAME})
|
set(CPACK_PACKAGE_NAME ${CMAKE_PROJECT_NAME})
|
||||||
set(CPACK_PACKAGE_VENDOR "SudoMaker")
|
set(CPACK_PACKAGE_VENDOR "SudoMaker")
|
||||||
string(REGEX REPLACE "^v" "" CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) # remove the v prefix if it exists
|
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
||||||
|
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
|
||||||
|
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
|
||||||
|
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
|
||||||
set(CPACK_PACKAGE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/cpack_artifacts)
|
set(CPACK_PACKAGE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/cpack_artifacts)
|
||||||
set(CPACK_PACKAGE_CONTACT "https://www.sudomaker.com")
|
set(CPACK_PACKAGE_CONTACT "https://www.sudomaker.com")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION ${CMAKE_PROJECT_DESCRIPTION})
|
set(CPACK_PACKAGE_DESCRIPTION ${CMAKE_PROJECT_DESCRIPTION})
|
||||||
|
|||||||
@@ -136,26 +136,13 @@ if(${SUNSHINE_TRAY} STREQUAL 1)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# desktop file
|
# desktop file
|
||||||
# todo - validate desktop files with `desktop-file-validate`
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_FQDN}.desktop"
|
||||||
if(NOT ${SUNSHINE_BUILD_FLATPAK})
|
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications")
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.desktop"
|
|
||||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications")
|
|
||||||
else()
|
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.desktop"
|
|
||||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications"
|
|
||||||
RENAME "${PROJECT_FQDN}.desktop")
|
|
||||||
endif()
|
|
||||||
if(NOT ${SUNSHINE_BUILD_APPIMAGE} AND NOT ${SUNSHINE_BUILD_FLATPAK})
|
if(NOT ${SUNSHINE_BUILD_APPIMAGE} AND NOT ${SUNSHINE_BUILD_FLATPAK})
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine_terminal.desktop"
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_FQDN}.terminal.desktop"
|
||||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications")
|
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# metadata file
|
# metadata file
|
||||||
# todo - validate file with `appstream-util validate-relax`
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_FQDN}.metainfo.xml"
|
||||||
if(NOT ${SUNSHINE_BUILD_FLATPAK})
|
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo")
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.appdata.xml"
|
|
||||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo")
|
|
||||||
else()
|
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_FQDN}.metainfo.xml"
|
|
||||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo")
|
|
||||||
endif()
|
|
||||||
|
|||||||
@@ -1,18 +1,34 @@
|
|||||||
|
# Set build variables if env variables are defined
|
||||||
|
# These are used in configured files such as manifests for different packages
|
||||||
|
if(DEFINED ENV{BRANCH}) # cmake-lint: disable=W0106
|
||||||
|
set(GITHUB_BRANCH $ENV{BRANCH})
|
||||||
|
endif()
|
||||||
|
if(DEFINED ENV{BUILD_VERSION}) # cmake-lint: disable=W0106
|
||||||
|
set(BUILD_VERSION $ENV{BUILD_VERSION})
|
||||||
|
endif()
|
||||||
|
if(DEFINED ENV{CLONE_URL}) # cmake-lint: disable=W0106
|
||||||
|
set(GITHUB_CLONE_URL $ENV{CLONE_URL})
|
||||||
|
endif()
|
||||||
|
if(DEFINED ENV{COMMIT}) # cmake-lint: disable=W0106
|
||||||
|
set(GITHUB_COMMIT $ENV{COMMIT})
|
||||||
|
endif()
|
||||||
|
if(DEFINED ENV{TAG}) # cmake-lint: disable=W0106
|
||||||
|
set(GITHUB_TAG $ENV{TAG})
|
||||||
|
endif()
|
||||||
|
|
||||||
# Check if env vars are defined before attempting to access them, variables will be defined even if blank
|
# Check if env vars are defined before attempting to access them, variables will be defined even if blank
|
||||||
if((DEFINED ENV{BRANCH}) AND (DEFINED ENV{BUILD_VERSION}) AND (DEFINED ENV{COMMIT})) # cmake-lint: disable=W0106
|
if((DEFINED ENV{BRANCH}) AND (DEFINED ENV{BUILD_VERSION})) # cmake-lint: disable=W0106
|
||||||
if(($ENV{BRANCH} STREQUAL "master") AND (NOT $ENV{BUILD_VERSION} STREQUAL ""))
|
if((DEFINED ENV{BRANCH}) AND (NOT $ENV{BUILD_VERSION} STREQUAL ""))
|
||||||
# If BRANCH is "master" and BUILD_VERSION is not empty, then we are building a master branch
|
# If BRANCH is defined and BUILD_VERSION is not empty, then we are building from CI
|
||||||
MESSAGE("Got from CI master branch and version $ENV{BUILD_VERSION}")
|
# If BRANCH is master we are building a push/release build
|
||||||
|
MESSAGE("Got from CI '$ENV{BRANCH}' branch and version '$ENV{BUILD_VERSION}'")
|
||||||
set(PROJECT_VERSION $ENV{BUILD_VERSION})
|
set(PROJECT_VERSION $ENV{BUILD_VERSION})
|
||||||
|
string(REGEX REPLACE "^v" "" PROJECT_VERSION ${PROJECT_VERSION}) # remove the v prefix if it exists
|
||||||
set(CMAKE_PROJECT_VERSION ${PROJECT_VERSION}) # cpack will use this to set the binary versions
|
set(CMAKE_PROJECT_VERSION ${PROJECT_VERSION}) # cpack will use this to set the binary versions
|
||||||
elseif((DEFINED ENV{BRANCH}) AND (DEFINED ENV{COMMIT}))
|
|
||||||
# If BRANCH is set but not BUILD_VERSION we are building a PR, we gather only the commit hash
|
|
||||||
MESSAGE("Got from CI $ENV{BRANCH} branch and commit $ENV{COMMIT}")
|
|
||||||
set(PROJECT_VERSION ${PROJECT_VERSION}.$ENV{COMMIT})
|
|
||||||
endif()
|
endif()
|
||||||
|
else()
|
||||||
# Generate Sunshine Version based of the git tag
|
# Generate Sunshine Version based of the git tag
|
||||||
# https://github.com/nocnokneo/cmake-git-versioning-example/blob/master/LICENSE
|
# https://github.com/nocnokneo/cmake-git-versioning-example/blob/master/LICENSE
|
||||||
else()
|
|
||||||
find_package(Git)
|
find_package(Git)
|
||||||
if(GIT_EXECUTABLE)
|
if(GIT_EXECUTABLE)
|
||||||
MESSAGE("${CMAKE_SOURCE_DIR}")
|
MESSAGE("${CMAKE_SOURCE_DIR}")
|
||||||
@@ -54,3 +70,72 @@ else()
|
|||||||
MESSAGE(WARNING ": Git not found, cannot find git version")
|
MESSAGE(WARNING ": Git not found, cannot find git version")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# set date variables
|
||||||
|
set(PROJECT_YEAR "1990")
|
||||||
|
set(PROJECT_MONTH "01")
|
||||||
|
set(PROJECT_DAY "01")
|
||||||
|
|
||||||
|
# Extract year, month, and day (do this AFTER version parsing)
|
||||||
|
# Note: Cmake doesn't support "{}" regex syntax
|
||||||
|
if(PROJECT_VERSION MATCHES "^([0-9][0-9][0-9][0-9])\\.([0-9][0-9][0-9][0-9]?)\\.([0-9]+)$")
|
||||||
|
message("Extracting year and month/day from PROJECT_VERSION: ${PROJECT_VERSION}")
|
||||||
|
# First capture group is the year
|
||||||
|
set(PROJECT_YEAR "${CMAKE_MATCH_1}")
|
||||||
|
|
||||||
|
# Second capture group contains month and day
|
||||||
|
set(MONTH_DAY "${CMAKE_MATCH_2}")
|
||||||
|
|
||||||
|
# Extract month (first 1-2 digits) and day (last 2 digits)
|
||||||
|
string(LENGTH "${MONTH_DAY}" MONTH_DAY_LENGTH)
|
||||||
|
if(MONTH_DAY_LENGTH EQUAL 3)
|
||||||
|
# Format: MDD (e.g., 703 = month 7, day 03)
|
||||||
|
string(SUBSTRING "${MONTH_DAY}" 0 1 PROJECT_MONTH)
|
||||||
|
string(SUBSTRING "${MONTH_DAY}" 1 2 PROJECT_DAY)
|
||||||
|
elseif(MONTH_DAY_LENGTH EQUAL 4)
|
||||||
|
# Format: MMDD (e.g., 1203 = month 12, day 03)
|
||||||
|
string(SUBSTRING "${MONTH_DAY}" 0 2 PROJECT_MONTH)
|
||||||
|
string(SUBSTRING "${MONTH_DAY}" 2 2 PROJECT_DAY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Ensure month is two digits
|
||||||
|
if(PROJECT_MONTH LESS 10 AND NOT PROJECT_MONTH MATCHES "^0")
|
||||||
|
set(PROJECT_MONTH "0${PROJECT_MONTH}")
|
||||||
|
endif()
|
||||||
|
# Ensure day is two digits
|
||||||
|
if(PROJECT_DAY LESS 10 AND NOT PROJECT_DAY MATCHES "^0")
|
||||||
|
set(PROJECT_DAY "0${PROJECT_DAY}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Parse PROJECT_VERSION to extract major, minor, and patch components
|
||||||
|
if(PROJECT_VERSION MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)")
|
||||||
|
set(PROJECT_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
||||||
|
set(CMAKE_PROJECT_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
||||||
|
|
||||||
|
set(PROJECT_VERSION_MINOR "${CMAKE_MATCH_2}")
|
||||||
|
set(CMAKE_PROJECT_VERSION_MINOR "${CMAKE_MATCH_2}")
|
||||||
|
|
||||||
|
set(PROJECT_VERSION_PATCH "${CMAKE_MATCH_3}")
|
||||||
|
set(CMAKE_PROJECT_VERSION_PATCH "${CMAKE_MATCH_3}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message("PROJECT_NAME: ${PROJECT_NAME}")
|
||||||
|
message("PROJECT_VERSION: ${PROJECT_VERSION}")
|
||||||
|
message("PROJECT_VERSION_MAJOR: ${PROJECT_VERSION_MAJOR}")
|
||||||
|
message("PROJECT_VERSION_MINOR: ${PROJECT_VERSION_MINOR}")
|
||||||
|
message("PROJECT_VERSION_PATCH: ${PROJECT_VERSION_PATCH}")
|
||||||
|
message("CMAKE_PROJECT_VERSION: ${CMAKE_PROJECT_VERSION}")
|
||||||
|
message("CMAKE_PROJECT_VERSION_MAJOR: ${CMAKE_PROJECT_VERSION_MAJOR}")
|
||||||
|
message("CMAKE_PROJECT_VERSION_MINOR: ${CMAKE_PROJECT_VERSION_MINOR}")
|
||||||
|
message("CMAKE_PROJECT_VERSION_PATCH: ${CMAKE_PROJECT_VERSION_PATCH}")
|
||||||
|
message("PROJECT_YEAR: ${PROJECT_YEAR}")
|
||||||
|
message("PROJECT_MONTH: ${PROJECT_MONTH}")
|
||||||
|
message("PROJECT_DAY: ${PROJECT_DAY}")
|
||||||
|
|
||||||
|
list(APPEND SUNSHINE_DEFINITIONS PROJECT_NAME="${PROJECT_NAME}")
|
||||||
|
list(APPEND SUNSHINE_DEFINITIONS PROJECT_VERSION="${PROJECT_VERSION}")
|
||||||
|
list(APPEND SUNSHINE_DEFINITIONS PROJECT_VERSION_MAJOR="${PROJECT_VERSION_MAJOR}")
|
||||||
|
list(APPEND SUNSHINE_DEFINITIONS PROJECT_VERSION_MINOR="${PROJECT_VERSION_MINOR}")
|
||||||
|
list(APPEND SUNSHINE_DEFINITIONS PROJECT_VERSION_PATCH="${PROJECT_VERSION_PATCH}")
|
||||||
|
list(APPEND SUNSHINE_DEFINITIONS PROJECT_VERSION_COMMIT="${GITHUB_COMMIT}")
|
||||||
|
|||||||
@@ -12,19 +12,17 @@ elseif(UNIX)
|
|||||||
# configure the .desktop file
|
# configure the .desktop file
|
||||||
set(SUNSHINE_DESKTOP_ICON "apollo.svg")
|
set(SUNSHINE_DESKTOP_ICON "apollo.svg")
|
||||||
if(${SUNSHINE_BUILD_APPIMAGE})
|
if(${SUNSHINE_BUILD_APPIMAGE})
|
||||||
configure_file(packaging/linux/AppImage/sunshine.desktop sunshine.desktop @ONLY)
|
configure_file(packaging/linux/AppImage/${PROJECT_FQDN}.desktop ${PROJECT_FQDN}.desktop @ONLY)
|
||||||
elseif(${SUNSHINE_BUILD_FLATPAK})
|
elseif(${SUNSHINE_BUILD_FLATPAK})
|
||||||
set(SUNSHINE_DESKTOP_ICON "${PROJECT_FQDN}")
|
set(SUNSHINE_DESKTOP_ICON "${PROJECT_FQDN}")
|
||||||
configure_file(packaging/linux/flatpak/sunshine.desktop sunshine.desktop @ONLY)
|
configure_file(packaging/linux/flatpak/${PROJECT_FQDN}.desktop ${PROJECT_FQDN}.desktop @ONLY)
|
||||||
configure_file(packaging/linux/flatpak/${PROJECT_FQDN}.metainfo.xml
|
|
||||||
${PROJECT_FQDN}.metainfo.xml @ONLY)
|
|
||||||
else()
|
else()
|
||||||
configure_file(packaging/linux/sunshine.desktop sunshine.desktop @ONLY)
|
configure_file(packaging/linux/${PROJECT_FQDN}.desktop ${PROJECT_FQDN}.desktop @ONLY)
|
||||||
configure_file(packaging/linux/sunshine_terminal.desktop sunshine_terminal.desktop @ONLY)
|
configure_file(packaging/linux/${PROJECT_FQDN}.terminal.desktop ${PROJECT_FQDN}.terminal.desktop @ONLY)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# configure metadata file
|
# configure metadata file
|
||||||
configure_file(packaging/linux/sunshine.appdata.xml sunshine.appdata.xml @ONLY)
|
configure_file(packaging/linux/${PROJECT_FQDN}.metainfo.xml ${PROJECT_FQDN}.metainfo.xml @ONLY)
|
||||||
|
|
||||||
# configure service
|
# configure service
|
||||||
configure_file(packaging/linux/sunshine.service.in sunshine.service @ONLY)
|
configure_file(packaging/linux/sunshine.service.in sunshine.service @ONLY)
|
||||||
@@ -38,8 +36,6 @@ elseif(UNIX)
|
|||||||
# configure the flatpak manifest
|
# configure the flatpak manifest
|
||||||
if(${SUNSHINE_CONFIGURE_FLATPAK_MAN})
|
if(${SUNSHINE_CONFIGURE_FLATPAK_MAN})
|
||||||
configure_file(packaging/linux/flatpak/${PROJECT_FQDN}.yml ${PROJECT_FQDN}.yml @ONLY)
|
configure_file(packaging/linux/flatpak/${PROJECT_FQDN}.yml ${PROJECT_FQDN}.yml @ONLY)
|
||||||
configure_file(packaging/linux/flatpak/${PROJECT_FQDN}.metainfo.xml
|
|
||||||
${PROJECT_FQDN}.metainfo.xml @ONLY)
|
|
||||||
file(COPY packaging/linux/flatpak/deps/ DESTINATION ${CMAKE_BINARY_DIR})
|
file(COPY packaging/linux/flatpak/deps/ DESTINATION ${CMAKE_BINARY_DIR})
|
||||||
file(COPY packaging/linux/flatpak/modules DESTINATION ${CMAKE_BINARY_DIR})
|
file(COPY packaging/linux/flatpak/modules DESTINATION ${CMAKE_BINARY_DIR})
|
||||||
file(COPY generated-sources.json DESTINATION ${CMAKE_BINARY_DIR})
|
file(COPY generated-sources.json DESTINATION ${CMAKE_BINARY_DIR})
|
||||||
|
|||||||
@@ -3,5 +3,6 @@ set_target_properties(sunshine PROPERTIES LINK_SEARCH_START_STATIC 1)
|
|||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll")
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll")
|
||||||
find_library(ZLIB ZLIB1)
|
find_library(ZLIB ZLIB1)
|
||||||
list(APPEND SUNSHINE_EXTERNAL_LIBRARIES
|
list(APPEND SUNSHINE_EXTERNAL_LIBRARIES
|
||||||
|
$<TARGET_OBJECTS:sunshine_rc_object>
|
||||||
Windowsapp.lib
|
Windowsapp.lib
|
||||||
Wtsapi32.lib)
|
Wtsapi32.lib)
|
||||||
|
|||||||
@@ -17,7 +17,9 @@
|
|||||||
"two_letters_code": {
|
"two_letters_code": {
|
||||||
# map non-two letter codes here, left side is crowdin designation, right side is babel designation
|
# map non-two letter codes here, left side is crowdin designation, right side is babel designation
|
||||||
"en-GB": "en_GB",
|
"en-GB": "en_GB",
|
||||||
"en-US": "en_US"
|
"en-US": "en_US",
|
||||||
|
"pt-BR": "pt_BR",
|
||||||
|
"zh-TW": "zh_TW"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"update_option": "update_as_unapproved"
|
"update_option": "update_as_unapproved"
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ ARG CLONE_URL
|
|||||||
ENV BRANCH=${BRANCH}
|
ENV BRANCH=${BRANCH}
|
||||||
ENV BUILD_VERSION=${BUILD_VERSION}
|
ENV BUILD_VERSION=${BUILD_VERSION}
|
||||||
ENV COMMIT=${COMMIT}
|
ENV COMMIT=${COMMIT}
|
||||||
|
ENV CLONE_URL=${CLONE_URL}
|
||||||
|
|
||||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
|
|
||||||
@@ -68,19 +69,16 @@ WORKDIR /build/sunshine/build
|
|||||||
RUN <<_MAKE
|
RUN <<_MAKE
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
if [[ "${BUILD_VERSION}" == '' ]]; then
|
|
||||||
|
sub_version=""
|
||||||
|
if [[ "${BRANCH}" != "master" ]]; then
|
||||||
sub_version=".r${COMMIT}"
|
sub_version=".r${COMMIT}"
|
||||||
else
|
|
||||||
sub_version=""
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cmake \
|
cmake \
|
||||||
|
-DSUNSHINE_CONFIGURE_ONLY=ON \
|
||||||
-DSUNSHINE_CONFIGURE_PKGBUILD=ON \
|
-DSUNSHINE_CONFIGURE_PKGBUILD=ON \
|
||||||
-DSUNSHINE_SUB_VERSION="${sub_version}" \
|
-DSUNSHINE_SUB_VERSION="${sub_version}" \
|
||||||
-DGITHUB_CLONE_URL="${CLONE_URL}" \
|
|
||||||
-DGITHUB_BRANCH=${BRANCH} \
|
|
||||||
-DGITHUB_BUILD_VERSION=${BUILD_VERSION} \
|
|
||||||
-DGITHUB_COMMIT="${COMMIT}" \
|
|
||||||
-DSUNSHINE_CONFIGURE_ONLY=ON \
|
|
||||||
/build/sunshine
|
/build/sunshine
|
||||||
_MAKE
|
_MAKE
|
||||||
|
|
||||||
@@ -114,14 +112,13 @@ rm -f /build/sunshine/pkg/sunshine-debug*.pkg.tar.zst
|
|||||||
ls -a
|
ls -a
|
||||||
_PKGBUILD
|
_PKGBUILD
|
||||||
|
|
||||||
FROM scratch AS artifacts
|
|
||||||
|
|
||||||
COPY --link --from=sunshine-build /build/sunshine/pkg/sunshine*.pkg.tar.zst /sunshine.pkg.tar.zst
|
|
||||||
COPY --link --from=sunshine-build /build/sunshine/sunshine.pkg.tar.gz /sunshine.pkg.tar.gz
|
|
||||||
|
|
||||||
FROM sunshine-base AS sunshine
|
FROM sunshine-base AS sunshine
|
||||||
|
|
||||||
COPY --link --from=artifacts /sunshine.pkg.tar.zst /
|
COPY --link --from=sunshine-build /build/sunshine/pkg/sunshine*.pkg.tar.zst /sunshine.pkg.tar.zst
|
||||||
|
|
||||||
|
# artifacts to be extracted in CI
|
||||||
|
COPY --link --from=sunshine-build /build/sunshine/pkg/sunshine*.pkg.tar.zst /artifacts/sunshine.pkg.tar.zst
|
||||||
|
COPY --link --from=sunshine-build /build/sunshine/sunshine.pkg.tar.gz /artifacts/sunshine.pkg.tar.gz
|
||||||
|
|
||||||
# install sunshine
|
# install sunshine
|
||||||
RUN <<_INSTALL_SUNSHINE
|
RUN <<_INSTALL_SUNSHINE
|
||||||
|
|||||||
@@ -51,16 +51,17 @@ Xvfb ${DISPLAY} -screen 0 1024x768x24 &
|
|||||||
./test_sunshine --gtest_color=yes
|
./test_sunshine --gtest_color=yes
|
||||||
_TEST
|
_TEST
|
||||||
|
|
||||||
FROM scratch AS artifacts
|
FROM sunshine-base AS sunshine
|
||||||
|
|
||||||
ARG BASE
|
ARG BASE
|
||||||
ARG TAG
|
ARG TAG
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /sunshine-${BASE}-${TAG}-${TARGETARCH}.deb
|
|
||||||
|
|
||||||
FROM sunshine-base AS sunshine
|
# artifacts to be extracted in CI
|
||||||
|
COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /artifacts/sunshine-${BASE}-${TAG}-${TARGETARCH}.deb
|
||||||
|
|
||||||
# copy deb from builder
|
# copy deb from builder
|
||||||
COPY --link --from=artifacts /sunshine*.deb /sunshine.deb
|
COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /sunshine.deb
|
||||||
|
|
||||||
# install sunshine
|
# install sunshine
|
||||||
RUN <<_INSTALL_SUNSHINE
|
RUN <<_INSTALL_SUNSHINE
|
||||||
|
|||||||
@@ -51,16 +51,17 @@ Xvfb ${DISPLAY} -screen 0 1024x768x24 &
|
|||||||
./test_sunshine --gtest_color=yes
|
./test_sunshine --gtest_color=yes
|
||||||
_TEST
|
_TEST
|
||||||
|
|
||||||
FROM scratch AS artifacts
|
FROM sunshine-base AS sunshine
|
||||||
|
|
||||||
ARG BASE
|
ARG BASE
|
||||||
ARG TAG
|
ARG TAG
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /sunshine-${BASE}-${TAG}-${TARGETARCH}.deb
|
|
||||||
|
|
||||||
FROM sunshine-base AS sunshine
|
# artifacts to be extracted in CI
|
||||||
|
COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /artifacts/sunshine-${BASE}-${TAG}-${TARGETARCH}.deb
|
||||||
|
|
||||||
# copy deb from builder
|
# copy deb from builder
|
||||||
COPY --link --from=artifacts /sunshine*.deb /sunshine.deb
|
COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /sunshine.deb
|
||||||
|
|
||||||
# install sunshine
|
# install sunshine
|
||||||
RUN <<_INSTALL_SUNSHINE
|
RUN <<_INSTALL_SUNSHINE
|
||||||
|
|||||||
@@ -51,16 +51,17 @@ Xvfb ${DISPLAY} -screen 0 1024x768x24 &
|
|||||||
./test_sunshine --gtest_color=yes
|
./test_sunshine --gtest_color=yes
|
||||||
_TEST
|
_TEST
|
||||||
|
|
||||||
FROM scratch AS artifacts
|
FROM sunshine-base AS sunshine
|
||||||
|
|
||||||
ARG BASE
|
ARG BASE
|
||||||
ARG TAG
|
ARG TAG
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /sunshine-${BASE}-${TAG}-${TARGETARCH}.deb
|
|
||||||
|
|
||||||
FROM sunshine-base AS sunshine
|
# artifacts to be extracted in CI
|
||||||
|
COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /artifacts/sunshine-${BASE}-${TAG}-${TARGETARCH}.deb
|
||||||
|
|
||||||
# copy deb from builder
|
# copy deb from builder
|
||||||
COPY --link --from=artifacts /sunshine*.deb /sunshine.deb
|
COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /sunshine.deb
|
||||||
|
|
||||||
# install sunshine
|
# install sunshine
|
||||||
RUN <<_INSTALL_SUNSHINE
|
RUN <<_INSTALL_SUNSHINE
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ function generateExamples(endpoint, method, body = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
cURL: `curl -u user:pass -X ${method.trim()} -k https://localhost:47990${endpoint.trim()}${curlBodyString}`,
|
cURL: `curl -u user:pass -H "Content-Type: application/json" -X ${method.trim()} -k https://localhost:47990${endpoint.trim()}${curlBodyString}`,
|
||||||
Python: `import json
|
Python: `import json
|
||||||
import requests
|
import requests
|
||||||
from requests.auth import HTTPBasicAuth
|
from requests.auth import HTTPBasicAuth
|
||||||
@@ -30,6 +30,7 @@ requests.${method.trim().toLowerCase()}(
|
|||||||
.then(data => console.log(data));`,
|
.then(data => console.log(data));`,
|
||||||
PowerShell: `Invoke-RestMethod \`
|
PowerShell: `Invoke-RestMethod \`
|
||||||
-SkipCertificateCheck \`
|
-SkipCertificateCheck \`
|
||||||
|
-ContentType 'application/json' \`
|
||||||
-Uri 'https://localhost:47990${endpoint.trim()}' \`
|
-Uri 'https://localhost:47990${endpoint.trim()}' \`
|
||||||
-Method ${method.trim()} \`
|
-Method ${method.trim()} \`
|
||||||
-Headers @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes('user:pass'))}
|
-Headers @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes('user:pass'))}
|
||||||
|
|||||||
@@ -57,10 +57,14 @@ editing the `conf` file in a text editor. Use the examples as reference.
|
|||||||
@endcode</td>
|
@endcode</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="18">Choices</td>
|
<td rowspan="20">Choices</td>
|
||||||
<td>bg</td>
|
<td>bg</td>
|
||||||
<td>Bulgarian</td>
|
<td>Bulgarian</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>cs</td>
|
||||||
|
<td>Czech</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>de</td>
|
<td>de</td>
|
||||||
<td>German</td>
|
<td>German</td>
|
||||||
@@ -129,6 +133,10 @@ editing the `conf` file in a text editor. Use the examples as reference.
|
|||||||
<td>zh</td>
|
<td>zh</td>
|
||||||
<td>Chinese (Simplified)</td>
|
<td>Chinese (Simplified)</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>zh_TW</td>
|
||||||
|
<td>Chinese (Traditional)</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
### sunshine_name
|
### sunshine_name
|
||||||
@@ -1384,35 +1392,6 @@ editing the `conf` file in a text editor. Use the examples as reference.
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
### min_fps_factor
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>Description</td>
|
|
||||||
<td colspan="2">
|
|
||||||
Sunshine will use this factor to calculate the minimum time between frames. Increasing this value may help
|
|
||||||
when streaming mostly static content.
|
|
||||||
@warning{Higher values will consume more bandwidth.}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Default</td>
|
|
||||||
<td colspan="2">@code{}
|
|
||||||
1
|
|
||||||
@endcode</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Range</td>
|
|
||||||
<td colspan="2">1-3</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Example</td>
|
|
||||||
<td colspan="2">@code{}
|
|
||||||
min_fps_factor = 1
|
|
||||||
@endcode</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
## Network
|
## Network
|
||||||
|
|
||||||
### upnp
|
### upnp
|
||||||
|
|||||||
@@ -56,27 +56,28 @@ need to install CUDA.}
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="1">12.0.0</td>
|
<td rowspan="1">12.0.0</td>
|
||||||
<td rowspan="2">525.60.13</td>
|
<td rowspan="1">525.60.13</td>
|
||||||
<td rowspan="5">50;52;60;61;62;70;72;75;80;86;87;89;90</td>
|
<td rowspan="5">50;52;60;61;62;70;72;75;80;86;87;89;90</td>
|
||||||
<td>sunshine-debian-bookworm-{arch}.deb</td>
|
<td>sunshine-debian-bookworm-{arch}.deb</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td rowspan="1">12.5.1</td>
|
|
||||||
<td>sunshine.pkg.tar.zst</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="2">12.6.2</td>
|
<td rowspan="2">12.6.2</td>
|
||||||
<td rowspan="2">560.35.03</td>
|
<td rowspan="2">560.35.03</td>
|
||||||
<td>sunshine_{arch}.flatpak</td>
|
<td>sunshine_{arch}.flatpak</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Sunshine (copr - Fedora 40/41)</td>
|
<td>Sunshine (copr - Fedora 41)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="1">12.8.1</td>
|
<td rowspan="1">12.8.1</td>
|
||||||
<td rowspan="1">570.124.06</td>
|
<td rowspan="1">570.124.06</td>
|
||||||
<td>Sunshine (copr - Fedora 42)</td>
|
<td>Sunshine (copr - Fedora 42)</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td rowspan="1">12.9.1</td>
|
||||||
|
<td rowspan="1">575.57.08</td>
|
||||||
|
<td>sunshine.pkg.tar.zst</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
#### AppImage
|
#### AppImage
|
||||||
@@ -283,7 +284,7 @@ brew uninstall sunshine
|
|||||||
#### Installer (recommended)
|
#### Installer (recommended)
|
||||||
|
|
||||||
1. Download and install
|
1. Download and install
|
||||||
[sunshine-windows-installer.exe](https://github.com/LizardByte/Sunshine/releases/latest/download/sunshine-windows-installer.exe)
|
[Sunshine-Windows-AMD64-installer.exe](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-AMD64-installer.exe)
|
||||||
|
|
||||||
@attention{You should carefully select or unselect the options you want to install. Do not blindly install or
|
@attention{You should carefully select or unselect the options you want to install. Do not blindly install or
|
||||||
enable features.}
|
enable features.}
|
||||||
@@ -297,7 +298,7 @@ overflow menu. Different versions of Windows may provide slightly different step
|
|||||||
recommended for most users. No support will be provided!}
|
recommended for most users. No support will be provided!}
|
||||||
|
|
||||||
1. Download and extract
|
1. Download and extract
|
||||||
[sunshine-windows-portable.zip](https://github.com/LizardByte/Sunshine/releases/latest/download/sunshine-windows-portable.zip)
|
[Sunshine-Windows-AMD64-portable.zip](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-AMD64-portable.zip)
|
||||||
2. Open command prompt as administrator
|
2. Open command prompt as administrator
|
||||||
3. Firewall rules
|
3. Firewall rules
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 133 KiB |
10
package.json
10
package.json
@@ -8,14 +8,14 @@
|
|||||||
"serve": "serve ./tests/fixtures/http --no-port-switching"
|
"serve": "serve ./tests/fixtures/http --no-port-switching"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lizardbyte/shared-web": "2025.326.11214",
|
"@lizardbyte/shared-web": "2025.626.181239",
|
||||||
"vue": "3.5.14",
|
"vue": "3.5.17",
|
||||||
"vue-i18n": "11.1.4"
|
"vue-i18n": "11.1.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@codecov/vite-plugin": "1.9.0",
|
"@codecov/vite-plugin": "1.9.1",
|
||||||
"@vitejs/plugin-vue": "4.6.2",
|
"@vitejs/plugin-vue": "4.6.2",
|
||||||
"serve": "14.2.3",
|
"serve": "14.2.4",
|
||||||
"vite": "4.5.14",
|
"vite": "4.5.14",
|
||||||
"vite-plugin-ejs": "1.6.4"
|
"vite-plugin-ejs": "1.6.4"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Type=Application
|
Categories=RemoteAccess;Network;
|
||||||
Name=@PROJECT_NAME@
|
|
||||||
Exec=sunshine
|
|
||||||
Version=1.0
|
|
||||||
Comment=@PROJECT_DESCRIPTION@
|
Comment=@PROJECT_DESCRIPTION@
|
||||||
|
Exec=sunshine
|
||||||
Icon=sunshine
|
Icon=sunshine
|
||||||
Keywords=gamestream;stream;moonlight;remote play;
|
Keywords=gamestream;stream;moonlight;remote play;
|
||||||
Categories=AudioVideo;Network;RemoteAccess;
|
Name=@PROJECT_NAME@
|
||||||
Terminal=true
|
Terminal=true
|
||||||
|
Type=Application
|
||||||
|
Version=1.0
|
||||||
|
X-AppImage-Arch=x86_64
|
||||||
X-AppImage-Name=sunshine
|
X-AppImage-Name=sunshine
|
||||||
X-AppImage-Version=@PROJECT_VERSION@
|
X-AppImage-Version=@PROJECT_VERSION@
|
||||||
X-AppImage-Arch=x86_64
|
|
||||||
@@ -10,7 +10,7 @@ url=@PROJECT_HOMEPAGE_URL@
|
|||||||
license=('GPL-3.0-only')
|
license=('GPL-3.0-only')
|
||||||
install=sunshine.install
|
install=sunshine.install
|
||||||
|
|
||||||
_gcc_version=13
|
_gcc_version=14
|
||||||
|
|
||||||
depends=(
|
depends=(
|
||||||
'avahi'
|
'avahi'
|
||||||
@@ -36,7 +36,10 @@ depends=(
|
|||||||
)
|
)
|
||||||
|
|
||||||
makedepends=(
|
makedepends=(
|
||||||
|
'appstream'
|
||||||
|
'appstream-glib'
|
||||||
'cmake'
|
'cmake'
|
||||||
|
'desktop-file-utils'
|
||||||
'cuda'
|
'cuda'
|
||||||
"gcc${_gcc_version}"
|
"gcc${_gcc_version}"
|
||||||
'git'
|
'git'
|
||||||
@@ -64,7 +67,7 @@ prepare() {
|
|||||||
|
|
||||||
build() {
|
build() {
|
||||||
export BRANCH="@GITHUB_BRANCH@"
|
export BRANCH="@GITHUB_BRANCH@"
|
||||||
export BUILD_VERSION="@GITHUB_BUILD_VERSION@"
|
export BUILD_VERSION="@BUILD_VERSION@"
|
||||||
export COMMIT="@GITHUB_COMMIT@"
|
export COMMIT="@GITHUB_COMMIT@"
|
||||||
|
|
||||||
export CC="gcc-${_gcc_version}"
|
export CC="gcc-${_gcc_version}"
|
||||||
@@ -86,6 +89,11 @@ build() {
|
|||||||
-D SUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' \
|
-D SUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' \
|
||||||
-D SUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'
|
-D SUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'
|
||||||
|
|
||||||
|
appstreamcli validate "build/dev.lizardbyte.app.Sunshine.metainfo.xml"
|
||||||
|
appstream-util validate "build/dev.lizardbyte.app.Sunshine.metainfo.xml"
|
||||||
|
desktop-file-validate "build/dev.lizardbyte.app.Sunshine.desktop"
|
||||||
|
desktop-file-validate "build/dev.lizardbyte.app.Sunshine.terminal.desktop"
|
||||||
|
|
||||||
make -C build
|
make -C build
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Type=Application
|
Actions=RunInTerminal;
|
||||||
Name=@PROJECT_NAME@
|
Categories=RemoteAccess;Network;
|
||||||
Exec=/usr/bin/env systemctl start --u sunshine
|
|
||||||
Version=1.0
|
|
||||||
Comment=@PROJECT_DESCRIPTION@
|
Comment=@PROJECT_DESCRIPTION@
|
||||||
|
Exec=/usr/bin/env systemctl start --u sunshine
|
||||||
Icon=@SUNSHINE_DESKTOP_ICON@
|
Icon=@SUNSHINE_DESKTOP_ICON@
|
||||||
Keywords=gamestream;stream;moonlight;remote play;
|
Keywords=gamestream;stream;moonlight;remote play;
|
||||||
Categories=AudioVideo;Network;RemoteAccess;
|
Name=@PROJECT_NAME@
|
||||||
Actions=RunInTerminal;
|
Type=Application
|
||||||
|
Version=1.0
|
||||||
|
|
||||||
[Desktop Action RunInTerminal]
|
[Desktop Action RunInTerminal]
|
||||||
Name=Run in Terminal
|
Exec=gio launch @CMAKE_INSTALL_FULL_DATAROOTDIR@/applications/@PROJECT_FQDN@.terminal.desktop
|
||||||
Icon=application-x-executable
|
Icon=application-x-executable
|
||||||
Exec=gio launch @CMAKE_INSTALL_FULL_DATAROOTDIR@/applications/sunshine_terminal.desktop
|
Name=Run in Terminal
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<component type="desktop-application">
|
<component type="desktop">
|
||||||
<id>@PROJECT_FQDN@</id>
|
<id>@PROJECT_FQDN@</id>
|
||||||
|
|
||||||
<name>@CMAKE_PROJECT_NAME@</name>
|
<name>@PROJECT_NAME@</name>
|
||||||
<summary>@PROJECT_BRIEF_DESCRIPTION@</summary>
|
<summary>@PROJECT_BRIEF_DESCRIPTION@</summary>
|
||||||
|
|
||||||
<metadata_license>CC0-1.0</metadata_license>
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
@@ -15,39 +15,49 @@
|
|||||||
<control>gamepad</control>
|
<control>gamepad</control>
|
||||||
</supports>
|
</supports>
|
||||||
|
|
||||||
<url type="bugtracker">https://github.com/LizardByte/Sunshine/issues</url>
|
|
||||||
<url type="homepage">@PROJECT_HOMEPAGE_URL@</url>
|
<url type="homepage">@PROJECT_HOMEPAGE_URL@</url>
|
||||||
|
<url type="bugtracker">https://github.com/LizardByte/Sunshine/issues</url>
|
||||||
|
<url type="faq">https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2troubleshooting.html</url>
|
||||||
|
<url type="help">https://docs.lizardbyte.dev/projects/sunshine</url>
|
||||||
<url type="donation">https://app.lizardbyte.dev/#Donate</url>
|
<url type="donation">https://app.lizardbyte.dev/#Donate</url>
|
||||||
<url type="contact">https://app.lizardbyte.dev/support</url>
|
|
||||||
<url type="translate">https://translate.lizardbyte.dev</url>
|
<url type="translate">https://translate.lizardbyte.dev</url>
|
||||||
<url type="contribute">https://docs.lizardbyte.dev</url>
|
<url type="contact">https://app.lizardbyte.dev/support</url>
|
||||||
<url type="vcs-browser">https://github.com/LizardByte/Sunshine</url>
|
|
||||||
|
|
||||||
<description>
|
<description>
|
||||||
<p>
|
<p>
|
||||||
@PROJECT_LONG_DESCRIPTION@
|
@PROJECT_LONG_DESCRIPTION@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>NOTE: Sunshine requires additional installation steps.</p>
|
<p>NOTE: Sunshine requires additional installation steps (Flatpak).</p>
|
||||||
<p>
|
<p>
|
||||||
<code>flatpak run --command=additional-install.sh @PROJECT_FQDN@</code>
|
<code>flatpak run --command=additional-install.sh @PROJECT_FQDN@</code>
|
||||||
</p>
|
</p>
|
||||||
<p>NOTE: Sunshine uses a self-signed certificate. The web browser will report it as not secure, but it is safe.</p>
|
<p>NOTE: Sunshine uses a self-signed certificate. The web browser will report it as not secure, but it is safe.</p>
|
||||||
<p>NOTE: KMS Grab (Optional)</p>
|
<p>NOTE: KMS Grab (Flatpak)</p>
|
||||||
<p>
|
<p>
|
||||||
<code>sudo -i PULSE_SERVER=unix:/run/user/$(id -u $whoami)/pulse/native flatpak run @PROJECT_FQDN@</code>
|
<code>sudo -i PULSE_SERVER=unix:/run/user/$(id -u $whoami)/pulse/native flatpak run @PROJECT_FQDN@</code>
|
||||||
</p>
|
</p>
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
<release version="@PROJECT_VERSION@" date="1990-01-01"></release>
|
<release version="@PROJECT_VERSION@" date="@PROJECT_YEAR@-@PROJECT_MONTH@-@PROJECT_DAY@">
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
See the full changelog on GitHub
|
||||||
|
|
||||||
|
<!-- changelog -->
|
||||||
|
</p>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
</releases>
|
</releases>
|
||||||
|
|
||||||
<developer_name>LizardByte</developer_name>
|
<developer id="dev.lizardbyte">
|
||||||
|
<name>LizardByte</name>
|
||||||
|
</developer>
|
||||||
<screenshots>
|
<screenshots>
|
||||||
<screenshot type="default">
|
<screenshot type="default">
|
||||||
<image>https://app.lizardbyte.dev/Sunshine/assets/img/banners/AdobeStock_305732536_1920x1280.jpg</image>
|
<image>https://app.lizardbyte.dev/Sunshine/assets/img/screenshots/01-sunshine-welcome-page.png</image>
|
||||||
<caption>Sunshine</caption>
|
<caption>Sunshine welcome page</caption>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
</screenshots>
|
</screenshots>
|
||||||
<content_rating type="oars-1.0">
|
<content_rating type="oars-1.0">
|
||||||
@@ -15,8 +15,11 @@ License: GPLv3-only
|
|||||||
URL: https://github.com/LizardByte/Sunshine
|
URL: https://github.com/LizardByte/Sunshine
|
||||||
Source0: tarball.tar.gz
|
Source0: tarball.tar.gz
|
||||||
|
|
||||||
|
BuildRequires: appstream
|
||||||
# BuildRequires: boost-devel >= 1.86.0
|
# BuildRequires: boost-devel >= 1.86.0
|
||||||
BuildRequires: cmake >= 3.25.0
|
BuildRequires: cmake >= 3.25.0
|
||||||
|
BuildRequires: desktop-file-utils
|
||||||
|
BuildRequires: libappstream-glib
|
||||||
BuildRequires: libayatana-appindicator3-devel
|
BuildRequires: libayatana-appindicator3-devel
|
||||||
BuildRequires: libcap-devel
|
BuildRequires: libcap-devel
|
||||||
BuildRequires: libcurl-devel
|
BuildRequires: libcurl-devel
|
||||||
@@ -197,6 +200,11 @@ cmake "${cmake_args[@]}"
|
|||||||
make -j$(nproc) -C "%{_builddir}/Sunshine/build"
|
make -j$(nproc) -C "%{_builddir}/Sunshine/build"
|
||||||
|
|
||||||
%check
|
%check
|
||||||
|
# validate the metainfo file
|
||||||
|
appstreamcli validate %{buildroot}%{_metainfodir}/*.metainfo.xml
|
||||||
|
appstream-util validate %{buildroot}%{_metainfodir}/*.metainfo.xml
|
||||||
|
desktop-file-validate %{buildroot}%{_datadir}/applications/*.desktop
|
||||||
|
|
||||||
# run tests
|
# run tests
|
||||||
cd %{_builddir}/Sunshine/build
|
cd %{_builddir}/Sunshine/build
|
||||||
xvfb-run ./tests/test_sunshine
|
xvfb-run ./tests/test_sunshine
|
||||||
@@ -252,14 +260,14 @@ rm -f /usr/lib/modules-load.d/uhid.conf
|
|||||||
%{_modulesloaddir}/uhid.conf
|
%{_modulesloaddir}/uhid.conf
|
||||||
|
|
||||||
# Desktop entries
|
# Desktop entries
|
||||||
%{_datadir}/applications/sunshine*.desktop
|
%{_datadir}/applications/*.desktop
|
||||||
|
|
||||||
# Icons
|
# Icons
|
||||||
%{_datadir}/icons/hicolor/scalable/apps/apollo.svg
|
%{_datadir}/icons/hicolor/scalable/apps/apollo.svg
|
||||||
%{_datadir}/icons/hicolor/scalable/status/apollo*.svg
|
%{_datadir}/icons/hicolor/scalable/status/apollo*.svg
|
||||||
|
|
||||||
# Metainfo
|
# Metainfo
|
||||||
%{_datadir}/metainfo/sunshine.appdata.xml
|
%{_datadir}/metainfo/*.metainfo.xml
|
||||||
|
|
||||||
# Assets
|
# Assets
|
||||||
%{_datadir}/sunshine/**
|
%{_datadir}/sunshine/**
|
||||||
|
|||||||
Submodule packaging/linux/flatpak/deps/flatpak-builder-tools updated: fe89c19b14...903919f82f
Submodule packaging/linux/flatpak/deps/shared-modules updated: 1f8e591b26...756091e3d5
@@ -1,5 +1,5 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Categories=AudioVideo;Network;RemoteAccess;
|
Categories=RemoteAccess;Network;
|
||||||
Comment=@PROJECT_DESCRIPTION@
|
Comment=@PROJECT_DESCRIPTION@
|
||||||
Exec=sunshine.sh
|
Exec=sunshine.sh
|
||||||
Icon=@SUNSHINE_DESKTOP_ICON@
|
Icon=@SUNSHINE_DESKTOP_ICON@
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
{
|
{
|
||||||
"dev.lizardbyte.app.Sunshine": [
|
"dev.lizardbyte.app.Sunshine": [
|
||||||
"appstream-missing-screenshots",
|
"appstream-external-screenshot-url",
|
||||||
"appstream-screenshots-not-mirrored-in-ostree",
|
"appstream-screenshots-not-mirrored-in-ostree",
|
||||||
"external-gitmodule-url-found",
|
"external-gitmodule-url-found",
|
||||||
"finish-args-flatpak-spawn-access"
|
"finish-args-flatpak-spawn-access",
|
||||||
|
"finish-args-home-filesystem-access"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,15 +32,12 @@
|
|||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://salsa.debian.org/utopia-team/avahi.git",
|
"url": "https://github.com/avahi/avahi.git",
|
||||||
"commit": "1412c015d348166d58ea9c192239b00769eae24e",
|
"commit": "f060abee2807c943821d88839c013ce15db17b58",
|
||||||
"tag": "debian/0.8-13",
|
"tag": "v0.8",
|
||||||
"x-checker-data": {
|
"x-checker-data": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"tag-pattern": "^debian\\/(\\d.+)$",
|
"tag-pattern": "^v([\\d.]+)$"
|
||||||
"versions": {
|
|
||||||
"<": "0.9"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,22 +5,24 @@
|
|||||||
"-Ddocumentation=disabled",
|
"-Ddocumentation=disabled",
|
||||||
"-Dtests=disabled"
|
"-Dtests=disabled"
|
||||||
],
|
],
|
||||||
"cleanup": [
|
|
||||||
"/bin"
|
|
||||||
],
|
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://salsa.debian.org/debian/libevdev.git",
|
"url": "https://github.com/LizardByte-infrastructure/libevdev.git",
|
||||||
"commit": "1aa7baa233d6df4cee6a66fbc61bb5ffc8b6e88d",
|
"commit": "ac0056961c3332a260db063ab4fccc7747638a1d",
|
||||||
"tag": "debian/1.13.0+dfsg-1",
|
"tag": "libevdev-1.13.4",
|
||||||
"x-checker-data": {
|
"x-checker-data": {
|
||||||
"type": "git",
|
"type": "anitya",
|
||||||
"tag-pattern": "^debian\\/(\\d.\\d+\\.\\d+)",
|
"project-id": 20540,
|
||||||
"versions": {
|
"stable-only": true,
|
||||||
"<": "1.13.1"
|
"tag-template": "libevdev-$version"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"cleanup": [
|
||||||
|
"/bin",
|
||||||
|
"/include",
|
||||||
|
"/lib/pkgconfig",
|
||||||
|
"/share"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,15 +11,12 @@
|
|||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://salsa.debian.org/gnome-team/libnotify.git",
|
"url": "https://github.com/LizardByte-infrastructure/libnotify.git",
|
||||||
"commit": "ccf2f62ef0a4b264dd4eff32cab70a3e213ceb1a",
|
"commit": "131aad01ff5f563b4863becbb6ed84dac6e75d5a",
|
||||||
"tag": "debian/0.8.1-1",
|
"tag": "0.8.6",
|
||||||
"x-checker-data": {
|
"x-checker-data": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"tag-pattern": "^debian\\/(\\d.+)$",
|
"tag-pattern": "^([\\d.]+)$"
|
||||||
"versions": {
|
|
||||||
"<": "0.8.2"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,25 +1,33 @@
|
|||||||
{
|
{
|
||||||
"name": "miniupnpc",
|
"name": "miniupnpc",
|
||||||
"buildsystem": "cmake-ninja",
|
"buildsystem": "cmake-ninja",
|
||||||
|
"builddir": true,
|
||||||
"config-opts": [
|
"config-opts": [
|
||||||
"-DCMAKE_BUILD_TYPE=Release",
|
"-DCMAKE_BUILD_TYPE=RelWithDebInfo",
|
||||||
"-DUPNPC_BUILD_SAMPLE=OFF",
|
"-DUPNPC_BUILD_STATIC=OFF",
|
||||||
"-DUPNPC_BUILD_SHARED=ON",
|
"-DUPNPC_BUILD_SHARED=ON",
|
||||||
"-DUPNPC_BUILD_TESTS=OFF"
|
"-DUPNPC_BUILD_TESTS=OFF",
|
||||||
|
"-DUPNPC_BUILD_SAMPLE=OFF"
|
||||||
],
|
],
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "git",
|
"url": "https://miniupnp.tuxfamily.org/files/miniupnpc-2.3.3.tar.gz",
|
||||||
"url": "https://salsa.debian.org/miniupnp-team/miniupnpc.git",
|
"sha256": "d52a0afa614ad6c088cc9ddff1ae7d29c8c595ac5fdd321170a05f41e634bd1a",
|
||||||
"commit": "c5fe3aa794e92a503cecec6a4071eb6d310b4e42",
|
|
||||||
"tag": "debian/2.2.4-1",
|
|
||||||
"x-checker-data": {
|
"x-checker-data": {
|
||||||
"type": "git",
|
"type": "anitya",
|
||||||
"tag-pattern": "^debian\\/(\\d.+)$",
|
"project-id": 1986,
|
||||||
"versions": {
|
"stable-only": true,
|
||||||
"<": "2.2.5"
|
"url-template": "https://miniupnp.tuxfamily.org/files/miniupnpc-$version.tar.gz"
|
||||||
}
|
},
|
||||||
}
|
"type": "archive"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"cleanup": [
|
||||||
|
"/share/man",
|
||||||
|
"/lib/pkgconfig",
|
||||||
|
"/lib/libminiupnpc.so",
|
||||||
|
"/lib/cmake",
|
||||||
|
"/include",
|
||||||
|
"/bin/external-ip.sh"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
{
|
{
|
||||||
"name": "numactl",
|
"name": "numactl",
|
||||||
"buildsystem": "autotools",
|
|
||||||
"cleanup": [
|
|
||||||
"/bin"
|
|
||||||
],
|
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://salsa.debian.org/debian/numactl.git",
|
"url": "https://github.com/numactl/numactl.git",
|
||||||
"commit": "640bb34497702f9aaeb8af1b491f32b91d03ec80",
|
"tag": "v2.0.19",
|
||||||
"tag": "debian/2.0.16-1",
|
"commit": "3bc85e37d5a30da6790cb7e8bb488bb8f679170f",
|
||||||
"x-checker-data": {
|
"x-checker-data": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"tag-pattern": "^debian\\/(\\d.+)$",
|
"tag-pattern": "^v([\\d.]+)$"
|
||||||
"versions": {
|
|
||||||
"<": "2.0.17"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"rm-configure": true,
|
||||||
|
"cleanup": [
|
||||||
|
"/include",
|
||||||
|
"/lib/pkgconfig",
|
||||||
|
"/lib/*.a",
|
||||||
|
"/lib/*.la",
|
||||||
|
"/lib/*.so",
|
||||||
|
"/share/man"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<component type="desktop">
|
|
||||||
<id>@PROJECT_NAME@.desktop</id>
|
|
||||||
<metadata_license>@PROJECT_LICENSE@</metadata_license>
|
|
||||||
<project_license>@PROJECT_LICENSE@</project_license>
|
|
||||||
<name>@PROJECT_NAME@</name>
|
|
||||||
<url type="homepage">@CMAKE_PROJECT_HOMEPAGE_URL@</url>
|
|
||||||
<summary>@PROJECT_BRIEF_DESCRIPTION@</summary>
|
|
||||||
<description>
|
|
||||||
<p>
|
|
||||||
@PROJECT_LONG_DESCRIPTION@
|
|
||||||
</p>
|
|
||||||
</description>
|
|
||||||
<screenshots>
|
|
||||||
<screenshot type="default">
|
|
||||||
<image>https://app.lizardbyte.dev/Sunshine/assets/images/AdobeStock_305732536_1920x1280.jpg</image>
|
|
||||||
<caption>Sunshine</caption>
|
|
||||||
</screenshot>
|
|
||||||
</screenshots>
|
|
||||||
</component>
|
|
||||||
@@ -6,7 +6,7 @@ class @PROJECT_NAME@ < Formula
|
|||||||
homepage "@PROJECT_HOMEPAGE_URL@"
|
homepage "@PROJECT_HOMEPAGE_URL@"
|
||||||
url "@GITHUB_CLONE_URL@",
|
url "@GITHUB_CLONE_URL@",
|
||||||
tag: "@GITHUB_TAG@"
|
tag: "@GITHUB_TAG@"
|
||||||
version "@FORMULA_VERSION@"
|
version "@BUILD_VERSION@"
|
||||||
license all_of: ["GPL-3.0-only"]
|
license all_of: ["GPL-3.0-only"]
|
||||||
head "@GITHUB_CLONE_URL@", branch: "@GITHUB_DEFAULT_BRANCH@"
|
head "@GITHUB_CLONE_URL@", branch: "@GITHUB_DEFAULT_BRANCH@"
|
||||||
|
|
||||||
@@ -319,31 +319,31 @@ index 5b3638d..aca9481 100644
|
|||||||
run [opt_bin/"sunshine", "~/.config/sunshine/sunshine.conf"]
|
run [opt_bin/"sunshine", "~/.config/sunshine/sunshine.conf"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def caveats
|
def post_install
|
||||||
caveats_message = <<~EOS
|
|
||||||
Thanks for installing @PROJECT_NAME@!
|
|
||||||
|
|
||||||
To get started, review the documentation at:
|
|
||||||
https://docs.lizardbyte.dev/projects/sunshine
|
|
||||||
EOS
|
|
||||||
|
|
||||||
if OS.linux?
|
if OS.linux?
|
||||||
caveats_message += <<~EOS
|
opoo <<~EOS
|
||||||
ATTENTION: To complete installation, you must run the following command:
|
ATTENTION: To complete installation, you must run the following command:
|
||||||
`sudo #{bin}/postinst`
|
`sudo #{bin}/postinst`
|
||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
|
|
||||||
if OS.mac?
|
if OS.mac?
|
||||||
caveats_message += <<~EOS
|
opoo <<~EOS
|
||||||
Sunshine can only access microphones on macOS due to system limitations.
|
Sunshine can only access microphones on macOS due to system limitations.
|
||||||
To stream system audio use "Soundflower" or "BlackHole".
|
To stream system audio use "Soundflower" or "BlackHole".
|
||||||
|
|
||||||
Gamepads are not currently supported on macOS.
|
Gamepads are not currently supported on macOS.
|
||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
caveats_message
|
def caveats
|
||||||
|
<<~EOS
|
||||||
|
Thanks for installing @PROJECT_NAME@!
|
||||||
|
|
||||||
|
To get started, review the documentation at:
|
||||||
|
https://docs.lizardbyte.dev/projects/sunshine
|
||||||
|
EOS
|
||||||
end
|
end
|
||||||
|
|
||||||
test do
|
test do
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ year = datetime.datetime.now().year
|
|||||||
# target locales
|
# target locales
|
||||||
target_locales = [
|
target_locales = [
|
||||||
'bg', # Bulgarian
|
'bg', # Bulgarian
|
||||||
|
'cs', # Czech
|
||||||
'de', # German
|
'de', # German
|
||||||
'en', # English
|
'en', # English
|
||||||
'en_GB', # English (United Kingdom)
|
'en_GB', # English (United Kingdom)
|
||||||
@@ -42,6 +43,7 @@ target_locales = [
|
|||||||
'tr', # Turkish
|
'tr', # Turkish
|
||||||
'uk', # Ukrainian
|
'uk', # Ukrainian
|
||||||
'zh', # Chinese
|
'zh', # Chinese
|
||||||
|
'zh_TW', # Chinese (Traditional)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -138,9 +138,12 @@ function add_arch_deps() {
|
|||||||
|
|
||||||
function add_debian_based_deps() {
|
function add_debian_based_deps() {
|
||||||
dependencies+=(
|
dependencies+=(
|
||||||
|
"appstream"
|
||||||
|
"appstream-util"
|
||||||
"bison" # required if we need to compile doxygen
|
"bison" # required if we need to compile doxygen
|
||||||
"build-essential"
|
"build-essential"
|
||||||
"cmake"
|
"cmake"
|
||||||
|
"desktop-file-utils"
|
||||||
"doxygen"
|
"doxygen"
|
||||||
"flex" # required if we need to compile doxygen
|
"flex" # required if we need to compile doxygen
|
||||||
"gcc-${gcc_version}"
|
"gcc-${gcc_version}"
|
||||||
@@ -201,13 +204,16 @@ function add_ubuntu_deps() {
|
|||||||
|
|
||||||
function add_fedora_deps() {
|
function add_fedora_deps() {
|
||||||
dependencies+=(
|
dependencies+=(
|
||||||
|
"appstream"
|
||||||
"cmake"
|
"cmake"
|
||||||
|
"desktop-file-utils"
|
||||||
"doxygen"
|
"doxygen"
|
||||||
"gcc${gcc_version}"
|
"gcc${gcc_version}"
|
||||||
"gcc${gcc_version}-c++"
|
"gcc${gcc_version}-c++"
|
||||||
"git"
|
"git"
|
||||||
"graphviz"
|
"graphviz"
|
||||||
"libappindicator-gtk3-devel"
|
"libappindicator-gtk3-devel"
|
||||||
|
"libappstream-glib"
|
||||||
"libcap-devel"
|
"libcap-devel"
|
||||||
"libcurl-devel"
|
"libcurl-devel"
|
||||||
"libdrm-devel"
|
"libdrm-devel"
|
||||||
@@ -392,7 +398,7 @@ function run_install() {
|
|||||||
"gcc-ranlib"
|
"gcc-ranlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
#set gcc version based on distros
|
#set gcc version based on distros
|
||||||
if [ "$distro" == "arch" ]; then
|
if [ "$distro" == "arch" ]; then
|
||||||
export CC=gcc-14
|
export CC=gcc-14
|
||||||
export CXX=g++-14
|
export CXX=g++-14
|
||||||
@@ -466,6 +472,8 @@ function run_install() {
|
|||||||
install_cuda
|
install_cuda
|
||||||
cmake_args+=("-DSUNSHINE_ENABLE_CUDA=ON")
|
cmake_args+=("-DSUNSHINE_ENABLE_CUDA=ON")
|
||||||
cmake_args+=("-DCMAKE_CUDA_COMPILER:PATH=$nvcc_path")
|
cmake_args+=("-DCMAKE_CUDA_COMPILER:PATH=$nvcc_path")
|
||||||
|
else
|
||||||
|
cmake_args+=("-DSUNSHINE_ENABLE_CUDA=OFF")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Cmake stuff here
|
# Cmake stuff here
|
||||||
@@ -473,6 +481,16 @@ function run_install() {
|
|||||||
echo "cmake args:"
|
echo "cmake args:"
|
||||||
echo "${cmake_args[@]}"
|
echo "${cmake_args[@]}"
|
||||||
cmake "${cmake_args[@]}"
|
cmake "${cmake_args[@]}"
|
||||||
|
|
||||||
|
# Run appstream validation, etc.
|
||||||
|
appstreamcli validate "build/dev.lizardbyte.app.Sunshine.metainfo.xml"
|
||||||
|
appstream-util validate "build/dev.lizardbyte.app.Sunshine.metainfo.xml"
|
||||||
|
desktop-file-validate "build/dev.lizardbyte.app.Sunshine.desktop"
|
||||||
|
if [ "$appimage_build" == 0 ]; then
|
||||||
|
desktop-file-validate "build/dev.lizardbyte.app.Sunshine.terminal.desktop"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the project
|
||||||
ninja -C "build"
|
ninja -C "build"
|
||||||
|
|
||||||
# Create the package
|
# Create the package
|
||||||
@@ -570,6 +588,15 @@ elif grep -q "Ubuntu 24.04" /etc/os-release; then
|
|||||||
cuda_build="520.61.05"
|
cuda_build="520.61.05"
|
||||||
gcc_version="11"
|
gcc_version="11"
|
||||||
nvm_node=0
|
nvm_node=0
|
||||||
|
elif grep -q "Ubuntu 25.04" /etc/os-release; then
|
||||||
|
distro="ubuntu"
|
||||||
|
version="25.04"
|
||||||
|
package_update_command="${sudo_cmd} apt-get update"
|
||||||
|
package_install_command="${sudo_cmd} apt-get install -y"
|
||||||
|
cuda_version="11.8.0"
|
||||||
|
cuda_build="520.61.05"
|
||||||
|
gcc_version="11"
|
||||||
|
nvm_node=0
|
||||||
else
|
else
|
||||||
echo "Unsupported Distro or Version"
|
echo "Unsupported Distro or Version"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -509,7 +509,6 @@ namespace config {
|
|||||||
{} // wa
|
{} // wa
|
||||||
}, // display_device
|
}, // display_device
|
||||||
|
|
||||||
1, // min_fps_factor
|
|
||||||
0, // max_bitrate
|
0, // max_bitrate
|
||||||
|
|
||||||
"1920x1080x60", // fallback_mode
|
"1920x1080x60", // fallback_mode
|
||||||
@@ -1195,7 +1194,6 @@ namespace config {
|
|||||||
video.dd.wa.hdr_toggle_delay = std::chrono::milliseconds {value};
|
video.dd.wa.hdr_toggle_delay = std::chrono::milliseconds {value};
|
||||||
}
|
}
|
||||||
|
|
||||||
int_between_f(vars, "min_fps_factor", video.min_fps_factor, {1, 3});
|
|
||||||
int_f(vars, "max_bitrate", video.max_bitrate);
|
int_f(vars, "max_bitrate", video.max_bitrate);
|
||||||
string_f(vars, "fallback_mode", video.fallback_mode);
|
string_f(vars, "fallback_mode", video.fallback_mode);
|
||||||
bool_f(vars, "isolated_virtual_display_option", video.isolated_virtual_display_option);
|
bool_f(vars, "isolated_virtual_display_option", video.isolated_virtual_display_option);
|
||||||
@@ -1304,6 +1302,7 @@ namespace config {
|
|||||||
|
|
||||||
string_restricted_f(vars, "locale", config::sunshine.locale, {
|
string_restricted_f(vars, "locale", config::sunshine.locale, {
|
||||||
"bg"sv, // Bulgarian
|
"bg"sv, // Bulgarian
|
||||||
|
"cs"sv, // Czech
|
||||||
"de"sv, // German
|
"de"sv, // German
|
||||||
"en"sv, // English
|
"en"sv, // English
|
||||||
"en_GB"sv, // English (UK)
|
"en_GB"sv, // English (UK)
|
||||||
@@ -1321,6 +1320,7 @@ namespace config {
|
|||||||
"tr"sv, // Turkish
|
"tr"sv, // Turkish
|
||||||
"uk"sv, // Ukrainian
|
"uk"sv, // Ukrainian
|
||||||
"zh"sv, // Chinese
|
"zh"sv, // Chinese
|
||||||
|
"zh_TW"sv, // Chinese (Traditional)
|
||||||
});
|
});
|
||||||
|
|
||||||
std::string log_level_string;
|
std::string log_level_string;
|
||||||
|
|||||||
@@ -143,7 +143,6 @@ namespace config {
|
|||||||
workarounds_t wa;
|
workarounds_t wa;
|
||||||
} dd;
|
} dd;
|
||||||
|
|
||||||
int min_fps_factor; // Minimum fps target, determines minimum frame time
|
|
||||||
int max_bitrate; // Maximum bitrate, sets ceiling in kbps for bitrate requested from client
|
int max_bitrate; // Maximum bitrate, sets ceiling in kbps for bitrate requested from client
|
||||||
|
|
||||||
std::string fallback_mode;
|
std::string fallback_mode;
|
||||||
|
|||||||
@@ -38,7 +38,6 @@
|
|||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "uuid.h"
|
#include "uuid.h"
|
||||||
#include "version.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "platform/windows/utils.h"
|
#include "platform/windows/utils.h"
|
||||||
@@ -89,6 +88,8 @@ namespace confighttp {
|
|||||||
void send_response(resp_https_t response, const nlohmann::json &output_tree) {
|
void send_response(resp_https_t response, const nlohmann::json &output_tree) {
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
headers.emplace("Content-Type", "application/json");
|
headers.emplace("Content-Type", "application/json");
|
||||||
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
response->write(output_tree.dump(), headers);
|
response->write(output_tree.dump(), headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +107,9 @@ namespace confighttp {
|
|||||||
tree["status"] = false;
|
tree["status"] = false;
|
||||||
tree["error"] = "Unauthorized";
|
tree["error"] = "Unauthorized";
|
||||||
const SimpleWeb::CaseInsensitiveMultimap headers {
|
const SimpleWeb::CaseInsensitiveMultimap headers {
|
||||||
{"Content-Type", "application/json"}
|
{"Content-Type", "application/json"},
|
||||||
|
{"X-Frame-Options", "DENY"},
|
||||||
|
{"Content-Security-Policy", "frame-ancestors 'none';"}
|
||||||
};
|
};
|
||||||
response->write(code, tree.dump(), headers);
|
response->write(code, tree.dump(), headers);
|
||||||
}
|
}
|
||||||
@@ -121,7 +124,9 @@ namespace confighttp {
|
|||||||
auto address = net::addr_to_normalized_string(request->remote_endpoint().address());
|
auto address = net::addr_to_normalized_string(request->remote_endpoint().address());
|
||||||
BOOST_LOG(info) << "Web UI: ["sv << address << "] -- redirecting"sv;
|
BOOST_LOG(info) << "Web UI: ["sv << address << "] -- redirecting"sv;
|
||||||
const SimpleWeb::CaseInsensitiveMultimap headers {
|
const SimpleWeb::CaseInsensitiveMultimap headers {
|
||||||
{"Location", path}
|
{"Location", path},
|
||||||
|
{"X-Frame-Options", "DENY"},
|
||||||
|
{"Content-Security-Policy", "frame-ancestors 'none';"}
|
||||||
};
|
};
|
||||||
response->write(SimpleWeb::StatusCode::redirection_temporary_redirect, headers);
|
response->write(SimpleWeb::StatusCode::redirection_temporary_redirect, headers);
|
||||||
}
|
}
|
||||||
@@ -218,6 +223,9 @@ namespace confighttp {
|
|||||||
tree["error"] = "Not Found";
|
tree["error"] = "Not Found";
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
headers.emplace("Content-Type", "application/json");
|
headers.emplace("Content-Type", "application/json");
|
||||||
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
|
|
||||||
response->write(code, tree.dump(), headers);
|
response->write(code, tree.dump(), headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,6 +243,9 @@ namespace confighttp {
|
|||||||
tree["error"] = error_message;
|
tree["error"] = error_message;
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
headers.emplace("Content-Type", "application/json");
|
headers.emplace("Content-Type", "application/json");
|
||||||
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
|
|
||||||
response->write(code, tree.dump(), headers);
|
response->write(code, tree.dump(), headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,10 +263,25 @@ namespace confighttp {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestContentType->second != contentType) {
|
// Extract the media type part before any parameters (e.g., charset)
|
||||||
|
std::string actualContentType = requestContentType->second;
|
||||||
|
size_t semicolonPos = actualContentType.find(';');
|
||||||
|
if (semicolonPos != std::string::npos) {
|
||||||
|
actualContentType = actualContentType.substr(0, semicolonPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim whitespace and convert to lowercase for case-insensitive comparison
|
||||||
|
boost::algorithm::trim(actualContentType);
|
||||||
|
boost::algorithm::to_lower(actualContentType);
|
||||||
|
|
||||||
|
std::string expectedContentType(contentType);
|
||||||
|
boost::algorithm::to_lower(expectedContentType);
|
||||||
|
|
||||||
|
if (actualContentType != expectedContentType) {
|
||||||
bad_request(response, request, "Content type mismatch");
|
bad_request(response, request, "Content type mismatch");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -273,9 +299,10 @@ namespace confighttp {
|
|||||||
print_req(request);
|
print_req(request);
|
||||||
|
|
||||||
std::string content = file_handler::read_file(WEB_DIR "index.html");
|
std::string content = file_handler::read_file(WEB_DIR "index.html");
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers {
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
{"Content-Type", "text/html; charset=utf-8"}
|
headers.emplace("Content-Type", "text/html; charset=utf-8");
|
||||||
};
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
response->write(content, headers);
|
response->write(content, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,9 +319,10 @@ namespace confighttp {
|
|||||||
print_req(request);
|
print_req(request);
|
||||||
|
|
||||||
std::string content = file_handler::read_file(WEB_DIR "pin.html");
|
std::string content = file_handler::read_file(WEB_DIR "pin.html");
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers {
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
{"Content-Type", "text/html; charset=utf-8"}
|
headers.emplace("Content-Type", "text/html; charset=utf-8");
|
||||||
};
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
response->write(content, headers);
|
response->write(content, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,10 +339,11 @@ namespace confighttp {
|
|||||||
print_req(request);
|
print_req(request);
|
||||||
|
|
||||||
std::string content = file_handler::read_file(WEB_DIR "apps.html");
|
std::string content = file_handler::read_file(WEB_DIR "apps.html");
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers {
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
{"Content-Type", "text/html; charset=utf-8"},
|
headers.emplace("Content-Type", "text/html; charset=utf-8");
|
||||||
{"Access-Control-Allow-Origin", "https://images.igdb.com/"}
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
};
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
|
headers.emplace("Access-Control-Allow-Origin", "https://images.igdb.com/");
|
||||||
response->write(content, headers);
|
response->write(content, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,9 +360,10 @@ namespace confighttp {
|
|||||||
print_req(request);
|
print_req(request);
|
||||||
|
|
||||||
std::string content = file_handler::read_file(WEB_DIR "clients.html");
|
std::string content = file_handler::read_file(WEB_DIR "clients.html");
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers {
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
{"Content-Type", "text/html; charset=utf-8"}
|
headers.emplace("Content-Type", "text/html; charset=utf-8");
|
||||||
};
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
response->write(content, headers);
|
response->write(content, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,9 +380,10 @@ namespace confighttp {
|
|||||||
print_req(request);
|
print_req(request);
|
||||||
|
|
||||||
std::string content = file_handler::read_file(WEB_DIR "config.html");
|
std::string content = file_handler::read_file(WEB_DIR "config.html");
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers {
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
{"Content-Type", "text/html; charset=utf-8"}
|
headers.emplace("Content-Type", "text/html; charset=utf-8");
|
||||||
};
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
response->write(content, headers);
|
response->write(content, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,9 +400,10 @@ namespace confighttp {
|
|||||||
print_req(request);
|
print_req(request);
|
||||||
|
|
||||||
std::string content = file_handler::read_file(WEB_DIR "password.html");
|
std::string content = file_handler::read_file(WEB_DIR "password.html");
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers {
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
{"Content-Type", "text/html; charset=utf-8"}
|
headers.emplace("Content-Type", "text/html; charset=utf-8");
|
||||||
};
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
response->write(content, headers);
|
response->write(content, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,9 +425,10 @@ namespace confighttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string content = file_handler::read_file(WEB_DIR "login.html");
|
std::string content = file_handler::read_file(WEB_DIR "login.html");
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers {
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
{"Content-Type", "text/html; charset=utf-8"}
|
headers.emplace("Content-Type", "text/html; charset=utf-8");
|
||||||
};
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
response->write(content, headers);
|
response->write(content, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,9 +446,10 @@ namespace confighttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string content = file_handler::read_file(WEB_DIR "welcome.html");
|
std::string content = file_handler::read_file(WEB_DIR "welcome.html");
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers {
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
{"Content-Type", "text/html; charset=utf-8"}
|
headers.emplace("Content-Type", "text/html; charset=utf-8");
|
||||||
};
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
response->write(content, headers);
|
response->write(content, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,9 +466,10 @@ namespace confighttp {
|
|||||||
print_req(request);
|
print_req(request);
|
||||||
|
|
||||||
std::string content = file_handler::read_file(WEB_DIR "troubleshooting.html");
|
std::string content = file_handler::read_file(WEB_DIR "troubleshooting.html");
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers {
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
{"Content-Type", "text/html; charset=utf-8"}
|
headers.emplace("Content-Type", "text/html; charset=utf-8");
|
||||||
};
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
response->write(content, headers);
|
response->write(content, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,9 +482,10 @@ namespace confighttp {
|
|||||||
print_req(request);
|
print_req(request);
|
||||||
|
|
||||||
std::ifstream in(WEB_DIR "images/apollo.ico", std::ios::binary);
|
std::ifstream in(WEB_DIR "images/apollo.ico", std::ios::binary);
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers {
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
{"Content-Type", "image/x-icon"}
|
headers.emplace("Content-Type", "image/x-icon");
|
||||||
};
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
response->write(SimpleWeb::StatusCode::success_ok, in, headers);
|
response->write(SimpleWeb::StatusCode::success_ok, in, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,9 +501,10 @@ namespace confighttp {
|
|||||||
print_req(request);
|
print_req(request);
|
||||||
|
|
||||||
std::ifstream in(WEB_DIR "images/logo-apollo-45.png", std::ios::binary);
|
std::ifstream in(WEB_DIR "images/logo-apollo-45.png", std::ios::binary);
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers {
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
{"Content-Type", "image/png"}
|
headers.emplace("Content-Type", "image/png");
|
||||||
};
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
response->write(SimpleWeb::StatusCode::success_ok, in, headers);
|
response->write(SimpleWeb::StatusCode::success_ok, in, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,6 +555,8 @@ namespace confighttp {
|
|||||||
}
|
}
|
||||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||||
headers.emplace("Content-Type", mimeType->second);
|
headers.emplace("Content-Type", mimeType->second);
|
||||||
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
std::ifstream in(filePath.string(), std::ios::binary);
|
std::ifstream in(filePath.string(), std::ios::binary);
|
||||||
response->write(SimpleWeb::StatusCode::success_ok, in, headers);
|
response->write(SimpleWeb::StatusCode::success_ok, in, headers);
|
||||||
}
|
}
|
||||||
@@ -631,6 +670,9 @@ namespace confighttp {
|
|||||||
* @api_examples{/api/apps/close| POST| null}
|
* @api_examples{/api/apps/close| POST| null}
|
||||||
*/
|
*/
|
||||||
void closeApp(resp_https_t response, req_https_t request) {
|
void closeApp(resp_https_t response, req_https_t request) {
|
||||||
|
if (!check_content_type(response, request, "application/json")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!authenticate(response, request)) {
|
if (!authenticate(response, request)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -936,7 +978,7 @@ namespace confighttp {
|
|||||||
* @api_examples{/api/clients/unpair-all| POST| null}
|
* @api_examples{/api/clients/unpair-all| POST| null}
|
||||||
*/
|
*/
|
||||||
void unpairAll(resp_https_t response, req_https_t request) {
|
void unpairAll(resp_https_t response, req_https_t request) {
|
||||||
if (!authenticate(response, request)) {
|
if (!validateContentType(response, request, "application/json"sv) || !authenticate(response, request)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -964,7 +1006,7 @@ namespace confighttp {
|
|||||||
nlohmann::json output_tree;
|
nlohmann::json output_tree;
|
||||||
output_tree["status"] = true;
|
output_tree["status"] = true;
|
||||||
output_tree["platform"] = SUNSHINE_PLATFORM;
|
output_tree["platform"] = SUNSHINE_PLATFORM;
|
||||||
output_tree["version"] = PROJECT_VER;
|
output_tree["version"] = PROJECT_VERSION;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
output_tree["vdisplayStatus"] = (int)proc::vDisplayDriverStatus;
|
output_tree["vdisplayStatus"] = (int)proc::vDisplayDriverStatus;
|
||||||
#endif
|
#endif
|
||||||
@@ -1109,6 +1151,8 @@ namespace confighttp {
|
|||||||
contentType += currentCodePageToCharset();
|
contentType += currentCodePageToCharset();
|
||||||
#endif
|
#endif
|
||||||
headers.emplace("Content-Type", contentType);
|
headers.emplace("Content-Type", contentType);
|
||||||
|
headers.emplace("X-Frame-Options", "DENY");
|
||||||
|
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||||
response->write(SimpleWeb::StatusCode::success_ok, content, headers);
|
response->write(SimpleWeb::StatusCode::success_ok, content, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1264,7 +1308,7 @@ namespace confighttp {
|
|||||||
* @api_examples{/api/reset-display-device-persistence| POST| null}
|
* @api_examples{/api/reset-display-device-persistence| POST| null}
|
||||||
*/
|
*/
|
||||||
void resetDisplayDevicePersistence(resp_https_t response, req_https_t request) {
|
void resetDisplayDevicePersistence(resp_https_t response, req_https_t request) {
|
||||||
if (!authenticate(response, request)) {
|
if (!validateContentType(response, request, "application/json"sv) || !authenticate(response, request)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1283,7 +1327,7 @@ namespace confighttp {
|
|||||||
* @api_examples{/api/restart| POST| null}
|
* @api_examples{/api/restart| POST| null}
|
||||||
*/
|
*/
|
||||||
void restart(resp_https_t response, req_https_t request) {
|
void restart(resp_https_t response, req_https_t request) {
|
||||||
if (!authenticate(response, request)) {
|
if (!validateContentType(response, request, "application/json"sv) || !authenticate(response, request)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "platform/common.h"
|
#include "platform/common.h"
|
||||||
#include "version.h"
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|||||||
11
src/main.cpp
11
src/main.cpp
@@ -103,6 +103,10 @@ int main(int argc, char *argv[]) {
|
|||||||
task_pool_util::TaskPool::task_id_t force_shutdown = nullptr;
|
task_pool_util::TaskPool::task_id_t force_shutdown = nullptr;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
// Avoid searching the PATH in case a user has configured their system insecurely
|
||||||
|
// by placing a user-writable directory in the system-wide PATH variable.
|
||||||
|
SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||||
|
|
||||||
setlocale(LC_ALL, "C");
|
setlocale(LC_ALL, "C");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -129,7 +133,7 @@ int main(int argc, char *argv[]) {
|
|||||||
// logging can begin at this point
|
// logging can begin at this point
|
||||||
// if anything is logged prior to this point, it will appear in stdout, but not in the log viewer in the UI
|
// if anything is logged prior to this point, it will appear in stdout, but not in the log viewer in the UI
|
||||||
// the version should be printed to the log before anything else
|
// the version should be printed to the log before anything else
|
||||||
BOOST_LOG(info) << PROJECT_NAME << " version: " << PROJECT_VER;
|
BOOST_LOG(info) << PROJECT_NAME << " version: " << PROJECT_VERSION << " commit: " << PROJECT_VERSION_COMMIT;
|
||||||
|
|
||||||
// Log publisher metadata
|
// Log publisher metadata
|
||||||
log_publisher_data();
|
log_publisher_data();
|
||||||
@@ -389,6 +393,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
std::thread httpThread {nvhttp::start};
|
std::thread httpThread {nvhttp::start};
|
||||||
std::thread configThread {confighttp::start};
|
std::thread configThread {confighttp::start};
|
||||||
|
std::thread rtspThread {rtsp_stream::start};
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// If we're using the default port and GameStream is enabled, warn the user
|
// If we're using the default port and GameStream is enabled, warn the user
|
||||||
@@ -398,10 +403,12 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rtsp_stream::rtpThread();
|
// Wait for shutdown
|
||||||
|
shutdown_event->view();
|
||||||
|
|
||||||
httpThread.join();
|
httpThread.join();
|
||||||
configThread.join();
|
configThread.join();
|
||||||
|
rtspThread.join();
|
||||||
|
|
||||||
task_pool.stop();
|
task_pool.stop();
|
||||||
task_pool.join();
|
task_pool.join();
|
||||||
|
|||||||
@@ -513,7 +513,7 @@ std::string get_local_ip_for_gateway() {
|
|||||||
// UDP GSO on Linux currently only supports sending 64K or 64 segments at a time
|
// UDP GSO on Linux currently only supports sending 64K or 64 segments at a time
|
||||||
size_t seg_index = 0;
|
size_t seg_index = 0;
|
||||||
const size_t seg_max = 65536 / 1500;
|
const size_t seg_max = 65536 / 1500;
|
||||||
struct iovec iovs[(send_info.headers ? std::min(seg_max, send_info.block_count) : 1) * max_iovs_per_msg] = {};
|
struct iovec iovs[(send_info.headers ? std::min(seg_max, send_info.block_count) : 1) * max_iovs_per_msg];
|
||||||
auto msg_size = send_info.header_size + send_info.payload_size;
|
auto msg_size = send_info.header_size + send_info.payload_size;
|
||||||
while (seg_index < send_info.block_count) {
|
while (seg_index < send_info.block_count) {
|
||||||
int iovlen = 0;
|
int iovlen = 0;
|
||||||
@@ -596,10 +596,11 @@ std::string get_local_ip_for_gateway() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
// If GSO is not supported, use sendmmsg() instead.
|
// If GSO is not supported, use sendmmsg() instead.
|
||||||
struct mmsghdr msgs[send_info.block_count] = {};
|
struct mmsghdr msgs[send_info.block_count];
|
||||||
struct iovec iovs[send_info.block_count * (send_info.headers ? 2 : 1)] = {};
|
struct iovec iovs[send_info.block_count * (send_info.headers ? 2 : 1)];
|
||||||
int iov_idx = 0;
|
int iov_idx = 0;
|
||||||
for (size_t i = 0; i < send_info.block_count; i++) {
|
for (size_t i = 0; i < send_info.block_count; i++) {
|
||||||
|
msgs[i].msg_len = 0;
|
||||||
msgs[i].msg_hdr.msg_iov = &iovs[iov_idx];
|
msgs[i].msg_hdr.msg_iov = &iovs[iov_idx];
|
||||||
msgs[i].msg_hdr.msg_iovlen = send_info.headers ? 2 : 1;
|
msgs[i].msg_hdr.msg_iovlen = send_info.headers ? 2 : 1;
|
||||||
|
|
||||||
@@ -617,6 +618,7 @@ std::string get_local_ip_for_gateway() {
|
|||||||
msgs[i].msg_hdr.msg_namelen = msg.msg_namelen;
|
msgs[i].msg_hdr.msg_namelen = msg.msg_namelen;
|
||||||
msgs[i].msg_hdr.msg_control = cmbuf.buf;
|
msgs[i].msg_hdr.msg_control = cmbuf.buf;
|
||||||
msgs[i].msg_hdr.msg_controllen = cmbuflen;
|
msgs[i].msg_hdr.msg_controllen = cmbuflen;
|
||||||
|
msgs[i].msg_hdr.msg_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call sendmmsg() until all messages are sent
|
// Call sendmmsg() until all messages are sent
|
||||||
@@ -709,7 +711,7 @@ std::string get_local_ip_for_gateway() {
|
|||||||
memcpy(CMSG_DATA(pktinfo_cm), &pktInfo, sizeof(pktInfo));
|
memcpy(CMSG_DATA(pktinfo_cm), &pktInfo, sizeof(pktInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iovec iovs[2] = {};
|
struct iovec iovs[2];
|
||||||
int iovlen = 0;
|
int iovlen = 0;
|
||||||
if (send_info.header) {
|
if (send_info.header) {
|
||||||
iovs[iovlen].iov_base = (void *) send_info.header;
|
iovs[iovlen].iov_base = (void *) send_info.header;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
+ (NSString *)getDisplayName:(CGDirectDisplayID)displayID {
|
+ (NSString *)getDisplayName:(CGDirectDisplayID)displayID {
|
||||||
for (NSScreen *screen in [NSScreen screens]) {
|
for (NSScreen *screen in [NSScreen screens]) {
|
||||||
if (screen.deviceDescription[@"NSScreenNumber"] == [NSNumber numberWithUnsignedInt:displayID]) {
|
if ([screen.deviceDescription[@"NSScreenNumber"] isEqualToNumber:[NSNumber numberWithUnsignedInt:displayID]]) {
|
||||||
return screen.localizedName;
|
return screen.localizedName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,10 +27,8 @@ DEFINE_PROPERTYKEY(PKEY_Device_DeviceDesc, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x2
|
|||||||
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14); // DEVPROP_TYPE_STRING
|
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14); // DEVPROP_TYPE_STRING
|
||||||
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_FriendlyName, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 2);
|
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_FriendlyName, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 2);
|
||||||
|
|
||||||
#if defined(__x86_64) || defined(_M_AMD64)
|
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64)
|
||||||
#define STEAM_DRIVER_SUBDIR L"x64"
|
#define STEAM_DRIVER_SUBDIR L"x64"
|
||||||
#elif defined(__i386) || defined(_M_IX86)
|
|
||||||
#define STEAM_DRIVER_SUBDIR L"x86"
|
|
||||||
#else
|
#else
|
||||||
#warning No known Steam audio driver for this architecture
|
#warning No known Steam audio driver for this architecture
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
/**
|
/**
|
||||||
* @file src/platform/windows/windows.rc.in
|
* @file src/platform/windows/windows.rc
|
||||||
* @brief Windows resource file template.
|
* @brief Windows resource file.
|
||||||
* @note The final `windows.rc` is generated from this file during the CMake build.
|
|
||||||
* @todo Use CMake definitions directly, instead of configuring this file.
|
|
||||||
*/
|
*/
|
||||||
#include "winver.h"
|
#include "winver.h"
|
||||||
|
|
||||||
|
#define STRINGIFY(x) #x
|
||||||
|
#define TOSTRING(x) STRINGIFY(x)
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
|
FILEVERSION PROJECT_VERSION_MAJOR,PROJECT_VERSION_MINOR,PROJECT_VERSION_PATCH,0
|
||||||
PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
|
PRODUCTVERSION PROJECT_VERSION_MAJOR,PROJECT_VERSION_MINOR,PROJECT_VERSION_PATCH,0
|
||||||
FILEOS VOS__WINDOWS32
|
FILEOS VOS__WINDOWS32
|
||||||
FILETYPE VFT_APP
|
FILETYPE VFT_APP
|
||||||
FILESUBTYPE VFT2_UNKNOWN
|
FILESUBTYPE VFT2_UNKNOWN
|
||||||
@@ -16,13 +18,13 @@ BEGIN
|
|||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "040904E4"
|
BLOCK "040904E4"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "SudoMaker\0"
|
VALUE "CompanyName", TOSTRING(PROJECT_VENDOR)
|
||||||
VALUE "FileDescription", "Apollo\0"
|
VALUE "FileDescription", TOSTRING(PROJECT_NAME)
|
||||||
VALUE "FileVersion", "@PROJECT_VERSION@\0"
|
VALUE "FileVersion", TOSTRING(PROJECT_VERSION)
|
||||||
VALUE "InternalName", "Apollo\0"
|
VALUE "InternalName", TOSTRING(PROJECT_NAME)
|
||||||
VALUE "LegalCopyright", "https://raw.githubusercontent.com/ClassicOldSong/Apollo/master/LICENSE\0"
|
VALUE "ProductName", TOSTRING(PROJECT_NAME)
|
||||||
VALUE "ProductName", "Apollo\0"
|
VALUE "ProductVersion", TOSTRING(PROJECT_VERSION)
|
||||||
VALUE "ProductVersion", "@PROJECT_VERSION@\0"
|
VALUE "LegalCopyright", "https://raw.githubusercontent.com/ClassicOldSong/Apollo/master/LICENSE"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
|
||||||
@@ -39,4 +41,4 @@ BEGIN
|
|||||||
|
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
SuperDuperAmazing ICON DISCARDABLE "@SUNSHINE_ICON_PATH@"
|
SuperDuperAmazing ICON DISCARDABLE PROJECT_ICON_PATH
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
#define gemm DECORATE_FUNC(gemm, ISA_SUFFIX)
|
#define gemm DECORATE_FUNC(gemm, ISA_SUFFIX)
|
||||||
#define invert_mat DECORATE_FUNC(invert_mat, ISA_SUFFIX)
|
#define invert_mat DECORATE_FUNC(invert_mat, ISA_SUFFIX)
|
||||||
|
|
||||||
#if defined(__x86_64__) || defined(__i386__)
|
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64)
|
||||||
|
|
||||||
// Compile a variant for SSSE3
|
// Compile a variant for SSSE3
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
@@ -122,7 +122,7 @@ reed_solomon_decode_t reed_solomon_decode_fn;
|
|||||||
* @details The streaming code will directly invoke these function pointers during encoding.
|
* @details The streaming code will directly invoke these function pointers during encoding.
|
||||||
*/
|
*/
|
||||||
void reed_solomon_init(void) {
|
void reed_solomon_init(void) {
|
||||||
#if defined(__x86_64__) || defined(__i386__)
|
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64)
|
||||||
if (__builtin_cpu_supports("avx512f") && __builtin_cpu_supports("avx512bw")) {
|
if (__builtin_cpu_supports("avx512f") && __builtin_cpu_supports("avx512bw")) {
|
||||||
reed_solomon_new_fn = reed_solomon_new_avx512;
|
reed_solomon_new_fn = reed_solomon_new_avx512;
|
||||||
reed_solomon_release_fn = reed_solomon_release_avx512;
|
reed_solomon_release_fn = reed_solomon_release_avx512;
|
||||||
|
|||||||
86
src/rtsp.cpp
86
src/rtsp.cpp
@@ -432,11 +432,6 @@ namespace rtsp_stream {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, class X>
|
|
||||||
void iterate(std::chrono::duration<T, X> timeout) {
|
|
||||||
io_context.run_one_for(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void handle_msg(tcp::socket &sock, launch_session_t &session, msg_t &&req) {
|
void handle_msg(tcp::socket &sock, launch_session_t &session, msg_t &&req) {
|
||||||
auto func = _map_cmd_cb.find(req->message.request.command);
|
auto func = _map_cmd_cb.find(req->message.request.command);
|
||||||
if (func != std::end(_map_cmd_cb)) {
|
if (func != std::end(_map_cmd_cb)) {
|
||||||
@@ -494,15 +489,24 @@ namespace rtsp_stream {
|
|||||||
* @param launch_session Streaming session information.
|
* @param launch_session Streaming session information.
|
||||||
*/
|
*/
|
||||||
void session_raise(std::shared_ptr<launch_session_t> launch_session) {
|
void session_raise(std::shared_ptr<launch_session_t> launch_session) {
|
||||||
auto now = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
// If a launch event is still pending, don't overwrite it.
|
// If a launch event is still pending, don't overwrite it.
|
||||||
if (raised_timeout > now && launch_event.peek()) {
|
if (launch_event.view(0s)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
raised_timeout = now + config::stream.ping_timeout;
|
|
||||||
|
|
||||||
|
// Raise the new launch session to prepare for the RTSP handshake
|
||||||
launch_event.raise(std::move(launch_session));
|
launch_event.raise(std::move(launch_session));
|
||||||
|
|
||||||
|
// Arm the timer to expire this launch session if the client times out
|
||||||
|
raised_timer.expires_after(config::stream.ping_timeout);
|
||||||
|
raised_timer.async_wait([this](const boost::system::error_code &ec) {
|
||||||
|
if (!ec) {
|
||||||
|
auto discarded = launch_event.pop(0s);
|
||||||
|
if (discarded) {
|
||||||
|
BOOST_LOG(debug) << "Event timeout: "sv << discarded->unique_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -517,6 +521,7 @@ namespace rtsp_stream {
|
|||||||
if (launch_session->id != launch_session_id) {
|
if (launch_session->id != launch_session_id) {
|
||||||
BOOST_LOG(error) << "Attempted to clear unexpected session: "sv << launch_session_id << " vs "sv << launch_session->id;
|
BOOST_LOG(error) << "Attempted to clear unexpected session: "sv << launch_session_id << " vs "sv << launch_session->id;
|
||||||
} else {
|
} else {
|
||||||
|
raised_timer.cancel();
|
||||||
launch_event.pop();
|
launch_event.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -541,14 +546,6 @@ namespace rtsp_stream {
|
|||||||
* @examples_end
|
* @examples_end
|
||||||
*/
|
*/
|
||||||
void clear(bool all = true) {
|
void clear(bool all = true) {
|
||||||
// if a launch event timed out --> Remove it.
|
|
||||||
if (raised_timeout < std::chrono::steady_clock::now()) {
|
|
||||||
auto discarded = launch_event.pop(0s);
|
|
||||||
if (discarded) {
|
|
||||||
BOOST_LOG(debug) << "Event timeout: "sv << discarded->unique_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lg = _session_slots.lock();
|
auto lg = _session_slots.lock();
|
||||||
|
|
||||||
for (auto i = _session_slots->begin(); i != _session_slots->end();) {
|
for (auto i = _session_slots->begin(); i != _session_slots->end();) {
|
||||||
@@ -583,6 +580,26 @@ namespace rtsp_stream {
|
|||||||
BOOST_LOG(info) << "New streaming session started [active sessions: "sv << _session_slots->size() << ']';
|
BOOST_LOG(info) << "New streaming session started [active sessions: "sv << _session_slots->size() << ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Runs an iteration of the RTSP server loop
|
||||||
|
*/
|
||||||
|
void iterate() {
|
||||||
|
// If we have a session, we will return to the server loop every
|
||||||
|
// 500ms to allow session cleanup to happen.
|
||||||
|
if (session_count() > 0) {
|
||||||
|
io_context.run_one_for(500ms);
|
||||||
|
} else {
|
||||||
|
io_context.run_one();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop the RTSP server.
|
||||||
|
*/
|
||||||
|
void stop() {
|
||||||
|
acceptor.close();
|
||||||
|
io_context.stop();
|
||||||
|
clear();
|
||||||
std::shared_ptr<stream::session_t>
|
std::shared_ptr<stream::session_t>
|
||||||
find_session(const std::string_view& uuid) {
|
find_session(const std::string_view& uuid) {
|
||||||
auto lg = _session_slots.lock();
|
auto lg = _session_slots.lock();
|
||||||
@@ -613,10 +630,9 @@ namespace rtsp_stream {
|
|||||||
|
|
||||||
sync_util::sync_t<std::set<std::shared_ptr<stream::session_t>>> _session_slots;
|
sync_util::sync_t<std::set<std::shared_ptr<stream::session_t>>> _session_slots;
|
||||||
|
|
||||||
std::chrono::steady_clock::time_point raised_timeout;
|
|
||||||
|
|
||||||
boost::asio::io_context io_context;
|
boost::asio::io_context io_context;
|
||||||
tcp::acceptor acceptor {io_context};
|
tcp::acceptor acceptor {io_context};
|
||||||
|
boost::asio::steady_timer raised_timer {io_context};
|
||||||
|
|
||||||
std::shared_ptr<socket_t> next_socket;
|
std::shared_ptr<socket_t> next_socket;
|
||||||
};
|
};
|
||||||
@@ -1163,9 +1179,8 @@ namespace rtsp_stream {
|
|||||||
respond(sock, session, &option, 200, "OK", req->sequenceNumber, {});
|
respond(sock, session, &option, 200, "OK", req->sequenceNumber, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void rtpThread() {
|
void start() {
|
||||||
auto shutdown_event = mail::man->event<bool>(mail::shutdown);
|
auto shutdown_event = mail::man->event<bool>(mail::shutdown);
|
||||||
auto broadcast_shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown);
|
|
||||||
|
|
||||||
server.map("OPTIONS"sv, &cmd_option);
|
server.map("OPTIONS"sv, &cmd_option);
|
||||||
server.map("DESCRIBE"sv, &cmd_describe);
|
server.map("DESCRIBE"sv, &cmd_describe);
|
||||||
@@ -1181,18 +1196,29 @@ namespace rtsp_stream {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!shutdown_event->peek()) {
|
std::thread rtsp_thread {[&shutdown_event] {
|
||||||
server.iterate(std::min(500ms, config::stream.ping_timeout));
|
auto broadcast_shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown);
|
||||||
|
|
||||||
if (broadcast_shutdown_event->peek()) {
|
while (!shutdown_event->peek()) {
|
||||||
server.clear();
|
server.iterate();
|
||||||
} else {
|
|
||||||
// cleanup all stopped sessions
|
if (broadcast_shutdown_event->peek()) {
|
||||||
server.clear(false);
|
server.clear();
|
||||||
|
} else {
|
||||||
|
// cleanup all stopped sessions
|
||||||
|
server.clear(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
server.clear();
|
server.clear();
|
||||||
|
}};
|
||||||
|
|
||||||
|
// Wait for shutdown
|
||||||
|
shutdown_event->view();
|
||||||
|
|
||||||
|
// Stop the server and join the server thread
|
||||||
|
server.stop();
|
||||||
|
rtsp_thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_msg(PRTSP_MESSAGE msg) {
|
void print_msg(PRTSP_MESSAGE msg) {
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ namespace rtsp_stream {
|
|||||||
*/
|
*/
|
||||||
void terminate_sessions();
|
void terminate_sessions();
|
||||||
|
|
||||||
void rtpThread();
|
/**
|
||||||
|
* @brief Runs the RTSP server loop.
|
||||||
|
*/
|
||||||
|
void start();
|
||||||
} // namespace rtsp_stream
|
} // namespace rtsp_stream
|
||||||
|
|||||||
@@ -51,7 +51,6 @@
|
|||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "src/entry_handler.h"
|
#include "src/entry_handler.h"
|
||||||
#include "version.h"
|
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
* @file src/upnp.cpp
|
* @file src/upnp.cpp
|
||||||
* @brief Definitions for UPnP port mapping.
|
* @brief Definitions for UPnP port mapping.
|
||||||
*/
|
*/
|
||||||
|
// standard includes
|
||||||
|
#include <stddef.h> // workaround for type_t error in miniupnpc 2.3.3, see https://github.com/miniupnp/miniupnp/commit/e263ab6f56c382e10fed31347ec68095d691a0e8
|
||||||
|
|
||||||
// lib includes
|
// lib includes
|
||||||
#include <miniupnpc/miniupnpc.h>
|
#include <miniupnpc/miniupnpc.h>
|
||||||
#include <miniupnpc/upnpcommands.h>
|
#include <miniupnpc/upnpcommands.h>
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file src/version.h.in
|
|
||||||
* @brief Version definitions for Sunshine.
|
|
||||||
* @note The final `version.h` is generated from this file during the CMake build.
|
|
||||||
* @todo Use CMake definitions directly, instead of configuring this file.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define PROJECT_NAME "@PROJECT_NAME@"
|
|
||||||
#define PROJECT_VER "@PROJECT_VERSION@"
|
|
||||||
#define PROJECT_VER_MAJOR "@PROJECT_VERSION_MAJOR@"
|
|
||||||
#define PROJECT_VER_MINOR "@PROJECT_VERSION_MINOR@"
|
|
||||||
#define PROJECT_VER_PATCH "@PROJECT_VERSION_PATCH@"
|
|
||||||
@@ -775,6 +775,18 @@ namespace video {
|
|||||||
{"usage"s, &config::video.amd.amd_usage_hevc},
|
{"usage"s, &config::video.amd.amd_usage_hevc},
|
||||||
{"vbaq"s, &config::video.amd.amd_vbaq},
|
{"vbaq"s, &config::video.amd.amd_vbaq},
|
||||||
{"enforce_hrd"s, &config::video.amd.amd_enforce_hrd},
|
{"enforce_hrd"s, &config::video.amd.amd_enforce_hrd},
|
||||||
|
{"level"s, [](const config_t &cfg) {
|
||||||
|
auto size = cfg.width * cfg.height;
|
||||||
|
// For 4K and below, try to use level 5.1 or 5.2 if possible
|
||||||
|
if (size <= 8912896) {
|
||||||
|
if (size * cfg.framerate <= 534773760) {
|
||||||
|
return "5.1"s;
|
||||||
|
} else if (size * cfg.framerate <= 1069547520) {
|
||||||
|
return "5.2"s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "auto"s;
|
||||||
|
}},
|
||||||
},
|
},
|
||||||
{}, // SDR-specific options
|
{}, // SDR-specific options
|
||||||
{}, // HDR-specific options
|
{}, // HDR-specific options
|
||||||
@@ -1672,7 +1684,7 @@ namespace video {
|
|||||||
ctx->thread_count = ctx->slices;
|
ctx->thread_count = ctx->slices;
|
||||||
|
|
||||||
AVDictionary *options {nullptr};
|
AVDictionary *options {nullptr};
|
||||||
auto handle_option = [&options](const encoder_t::option_t &option) {
|
auto handle_option = [&options, &config](const encoder_t::option_t &option) {
|
||||||
std::visit(
|
std::visit(
|
||||||
util::overloaded {
|
util::overloaded {
|
||||||
[&](int v) {
|
[&](int v) {
|
||||||
@@ -1686,7 +1698,7 @@ namespace video {
|
|||||||
av_dict_set_int(&options, option.name.c_str(), **v, 0);
|
av_dict_set_int(&options, option.name.c_str(), **v, 0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&](std::function<int()> v) {
|
[&](const std::function<int()> &v) {
|
||||||
av_dict_set_int(&options, option.name.c_str(), v(), 0);
|
av_dict_set_int(&options, option.name.c_str(), v(), 0);
|
||||||
},
|
},
|
||||||
[&](const std::string &v) {
|
[&](const std::string &v) {
|
||||||
@@ -1696,6 +1708,9 @@ namespace video {
|
|||||||
if (!v->empty()) {
|
if (!v->empty()) {
|
||||||
av_dict_set(&options, option.name.c_str(), v->c_str(), 0);
|
av_dict_set(&options, option.name.c_str(), v->c_str(), 0);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
[&](const std::function<const std::string(const config_t &cfg)> &v) {
|
||||||
|
av_dict_set(&options, option.name.c_str(), v(config).c_str(), 0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
option.value
|
option.value
|
||||||
@@ -1907,8 +1922,8 @@ namespace video {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// set minimum frame time, avoiding violation of client-requested target framerate
|
// set minimum frame time based on client-requested target framerate
|
||||||
auto minimum_frame_time = std::chrono::milliseconds(1000 / std::min(config.framerate, (config::video.min_fps_factor * 10)));
|
auto minimum_frame_time = std::chrono::milliseconds(1000 / config.framerate);
|
||||||
auto frame_threshold = std::chrono::microseconds(1000ms * 1000 / config.encodingFramerate);
|
auto frame_threshold = std::chrono::microseconds(1000ms * 1000 / config.encodingFramerate);
|
||||||
BOOST_LOG(debug) << "Minimum frame time set to "sv << minimum_frame_time.count() << "ms, based on min fps factor of "sv << config::video.min_fps_factor << "."sv;
|
BOOST_LOG(debug) << "Minimum frame time set to "sv << minimum_frame_time.count() << "ms, based on min fps factor of "sv << config::video.min_fps_factor << "."sv;
|
||||||
BOOST_LOG(info) << "Frame threshold: "sv << frame_threshold;
|
BOOST_LOG(info) << "Frame threshold: "sv << frame_threshold;
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ namespace video {
|
|||||||
option_t(const option_t &) = default;
|
option_t(const option_t &) = default;
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::variant<int, int *, std::optional<int> *, std::function<int()>, std::string, std::string *> value;
|
std::variant<int, int *, std::optional<int> *, std::function<int()>, std::string, std::string *, std::function<const std::string(const config_t &)>> value;
|
||||||
|
|
||||||
option_t(std::string &&name, decltype(value) &&value):
|
option_t(std::string &&name, decltype(value) &&value):
|
||||||
name {std::move(name)},
|
name {std::move(name)},
|
||||||
|
|||||||
@@ -206,7 +206,6 @@
|
|||||||
"headless_mode": "disabled",
|
"headless_mode": "disabled",
|
||||||
"double_refreshrate": "disabled",
|
"double_refreshrate": "disabled",
|
||||||
"dd_wa_hdr_toggle_delay": 0,
|
"dd_wa_hdr_toggle_delay": 0,
|
||||||
"min_fps_factor": 1,
|
|
||||||
"max_bitrate": 0,
|
"max_bitrate": 0,
|
||||||
"isolated_virtual_display_option": "disabled",
|
"isolated_virtual_display_option": "disabled",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ onMounted(() => {
|
|||||||
<label for="locale" class="form-label">{{ $t('config.locale') }}</label>
|
<label for="locale" class="form-label">{{ $t('config.locale') }}</label>
|
||||||
<select id="locale" class="form-select" v-model="config.locale">
|
<select id="locale" class="form-select" v-model="config.locale">
|
||||||
<option value="bg">Български (Bulgarian)</option>
|
<option value="bg">Български (Bulgarian)</option>
|
||||||
|
<option value="cs">Čeština (Czech)</option>
|
||||||
<option value="de">Deutsch (German)</option>
|
<option value="de">Deutsch (German)</option>
|
||||||
<option value="en">English</option>
|
<option value="en">English</option>
|
||||||
<option value="en_GB">English, UK</option>
|
<option value="en_GB">English, UK</option>
|
||||||
@@ -79,6 +80,7 @@ onMounted(() => {
|
|||||||
<option value="tr">Türkçe (Turkish)</option>
|
<option value="tr">Türkçe (Turkish)</option>
|
||||||
<option value="uk">Українська (Ukranian)</option>
|
<option value="uk">Українська (Ukranian)</option>
|
||||||
<option value="zh">简体中文 (Chinese Simplified)</option>
|
<option value="zh">简体中文 (Chinese Simplified)</option>
|
||||||
|
<option value="zh_TW">繁體中文 (Chinese Traditional)</option>
|
||||||
</select>
|
</select>
|
||||||
<div class="form-text">{{ $t('config.locale_desc') }}</div>
|
<div class="form-text">{{ $t('config.locale_desc') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,13 +11,6 @@ const config = ref(props.config)
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!--min_fps_factor-->
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="qp" class="form-label">{{ $t('config.min_fps_factor') }}</label>
|
|
||||||
<input type="number" min="1" max="3" class="form-control" id="min_fps_factor" placeholder="1" v-model="config.min_fps_factor" />
|
|
||||||
<div class="form-text">{{ $t('config.min_fps_factor_desc') }}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--max_bitrate-->
|
<!--max_bitrate-->
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="max_bitrate" class="form-label">{{ $t("config.max_bitrate") }}</label>
|
<label for="max_bitrate" class="form-label">{{ $t("config.max_bitrate") }}</label>
|
||||||
|
|||||||
455
src_assets/common/assets/web/public/assets/locale/cs.json
Normal file
455
src_assets/common/assets/web/public/assets/locale/cs.json
Normal file
@@ -0,0 +1,455 @@
|
|||||||
|
{
|
||||||
|
"_common": {
|
||||||
|
"apply": "Použít",
|
||||||
|
"auto": "Automaticky",
|
||||||
|
"autodetect": "Automatická detekce (doporučeno)",
|
||||||
|
"beta": "(beta)",
|
||||||
|
"cancel": "Zrušit",
|
||||||
|
"disabled": "Zakázáno",
|
||||||
|
"disabled_def": "Zakázáno (výchozí)",
|
||||||
|
"disabled_def_cbox": "Výchozí: nezaškrtnuto",
|
||||||
|
"dismiss": "Odmítnout",
|
||||||
|
"do_cmd": "Provést příkaz",
|
||||||
|
"elevated": "Zvýšené",
|
||||||
|
"enabled": "Povoleno",
|
||||||
|
"enabled_def": "Povoleno (výchozí)",
|
||||||
|
"enabled_def_cbox": "Výchozí: zaškrtnuto",
|
||||||
|
"error": "Chyba!",
|
||||||
|
"note": "Pozn.:",
|
||||||
|
"password": "Heslo",
|
||||||
|
"run_as": "Spustit jako správce",
|
||||||
|
"save": "Uložit",
|
||||||
|
"see_more": "Zobrazit více",
|
||||||
|
"success": "Úspěch!",
|
||||||
|
"undo_cmd": "Vrátit příkaz",
|
||||||
|
"username": "Uživatelské jméno",
|
||||||
|
"warning": "Varování!"
|
||||||
|
},
|
||||||
|
"apps": {
|
||||||
|
"actions": "Akce",
|
||||||
|
"add_cmds": "Přidat příkazy",
|
||||||
|
"add_new": "Přidat nový",
|
||||||
|
"app_name": "Název aplikace",
|
||||||
|
"app_name_desc": "Název aplikace, jak je uveden v aplikaci Moonlight",
|
||||||
|
"applications_desc": "Aplikace se obnovují pouze při restartování klienta",
|
||||||
|
"applications_title": "Aplikace",
|
||||||
|
"auto_detach": "Pokračovat ve streamování, pokud se aplikace rychle ukončí",
|
||||||
|
"auto_detach_desc": "Pokusí se automaticky detekovat aplikace typu launcher, které se po spuštění jiného programu nebo jeho instance rychle zavřou. Pokud je detekována aplikace typu launcher, je považována za odpojenou aplikaci.",
|
||||||
|
"cmd": "Příkaz",
|
||||||
|
"cmd_desc": "Hlavní aplikace ke spuštění. Pokud je prázdná, nebude spuštěna žádná aplikace.",
|
||||||
|
"cmd_note": "Pokud cesta ke spustitelnému příkazu obsahuje mezery, musíte ji uvést v uvozovkách.",
|
||||||
|
"cmd_prep_desc": "Seznam příkazů, které mají být spuštěny před/po této aplikaci. Pokud některý z přípravných příkazů selže, spuštění aplikace se přeruší.",
|
||||||
|
"cmd_prep_name": "Příprava příkazů",
|
||||||
|
"covers_found": "Nalezené obaly",
|
||||||
|
"delete": "Vymazat",
|
||||||
|
"detached_cmds": "Oddělené příkazy",
|
||||||
|
"detached_cmds_add": "Přidat oddělený příkaz",
|
||||||
|
"detached_cmds_desc": "Seznam příkazů, které mají být spuštěny na pozadí.",
|
||||||
|
"detached_cmds_note": "Pokud cesta k spustitelnému příkazu obsahuje mezery, musíte ji vložit do uvozovek.",
|
||||||
|
"edit": "Upravit",
|
||||||
|
"env_app_id": "ID aplikace",
|
||||||
|
"env_app_name": "Název aplikace",
|
||||||
|
"env_client_audio_config": "Nastavení zvuku požadované klientem (2.0/5.1/7.1)",
|
||||||
|
"env_client_enable_sops": "Klient požádal o možnost optimalizovat hru pro optimální streamování (true/false)",
|
||||||
|
"env_client_fps": "FPS požadované klientem (int)",
|
||||||
|
"env_client_gcmap": "Požadovaná maska gamepadu ve formátu bitset/bitfield (int)",
|
||||||
|
"env_client_hdr": "HDR je povoleno klientem (true/false)",
|
||||||
|
"env_client_height": "Výška požadovaná klientem (int)",
|
||||||
|
"env_client_host_audio": "Klient si vyžádal hostitelský zvuk (true/false)",
|
||||||
|
"env_client_width": "Šířka požadovaná klientem (int)",
|
||||||
|
"env_displayplacer_example": "Příklad - displayplacer pro automatizaci rozlišení:",
|
||||||
|
"env_qres_example": "Příklad – QR pro automatizaci rozlišení:",
|
||||||
|
"env_qres_path": "qres cesta",
|
||||||
|
"env_var_name": "Název Var",
|
||||||
|
"env_vars_about": "O proměnných prostředí",
|
||||||
|
"env_vars_desc": "Ve výchozím nastavení získávají tyto proměnné prostředí všechny příkazy:",
|
||||||
|
"env_xrandr_example": "Příklad - Xrandr pro automatizaci rozlišení:",
|
||||||
|
"exit_timeout": "Časový limit pro ukončení",
|
||||||
|
"exit_timeout_desc": "Počet sekund, po které se čeká na elegantní ukončení všech procesů aplikace, když je požadováno ukončení. Pokud není nastaveno, výchozí je čekat až 5 sekund. Je-li nastavena hodnota 0, aplikace bude ukončena okamžitě.",
|
||||||
|
"find_cover": "Najít obal",
|
||||||
|
"global_prep_desc": "Povolit/zakázat provádění globálních předběžných příkazů pro tuto aplikaci.",
|
||||||
|
"global_prep_name": "Globální předběžné příkazy",
|
||||||
|
"image": "Obrázek",
|
||||||
|
"image_desc": "Cesta k ikoně/obrázku aplikace, který bude odeslán klientovi. Obrázek musí být ve formátu PNG. Pokud není nastaven, Sunshine odešle výchozí obrázek schránky.",
|
||||||
|
"loading": "Načítám...",
|
||||||
|
"name": "Název",
|
||||||
|
"output_desc": "Soubor, kde je uložen výstup příkazu, pokud není zadán, výstup je ignorován",
|
||||||
|
"output_name": "Výstup",
|
||||||
|
"run_as_desc": "To může být nutné u některých aplikací, které ke správnému běhu vyžadují oprávnění správce.",
|
||||||
|
"wait_all": "Pokračujte ve streamování, dokud se neukončí všechny procesy aplikace",
|
||||||
|
"wait_all_desc": "Streamování bude pokračovat, dokud nebudou ukončeny všechny procesy spuštěné aplikací. Pokud není zaškrtnuto, streamování se zastaví, jakmile se ukončí počáteční proces aplikace, i když ostatní procesy aplikace stále běží.",
|
||||||
|
"working_dir": "Pracovní adresář",
|
||||||
|
"working_dir_desc": "Pracovní adresář, který má být předán procesu. Některé aplikace například používají pracovní adresář k vyhledávání konfiguračních souborů. Pokud není nastaven, bude Sunshine implicitně nastaven na nadřazený adresář příkazu"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"adapter_name": "Název adaptéru",
|
||||||
|
"adapter_name_desc_linux_1": "Ruční zadání GPU, která se má použít pro snímání.",
|
||||||
|
"adapter_name_desc_linux_2": "najít všechna zařízení schopná VAAPI",
|
||||||
|
"adapter_name_desc_linux_3": "Nahraďte ``renderD129`` zařízením z výše uvedeného seznamu, abyste vypsali název a schopnosti zařízení. Aby bylo zařízení Sunshine podporováno, musí mít minimálně:",
|
||||||
|
"adapter_name_desc_windows": "Ruční zadání GPU, která se má použít pro snímání. Pokud není nastaveno, je GPU vybrána automaticky. Důrazně doporučujeme ponechat toto pole prázdné, chcete-li použít automatický výběr GPU! Poznámka: Toto GPU musí mít připojený a zapnutý displej. Příslušné hodnoty lze zjistit pomocí následujícího příkazu:",
|
||||||
|
"adapter_name_placeholder_windows": "Řada Radeon RX 580",
|
||||||
|
"add": "Přidat",
|
||||||
|
"address_family": "Rodina adres",
|
||||||
|
"address_family_both": "IPv4+IPv6",
|
||||||
|
"address_family_desc": "Nastavení rodiny adres, kterou používá Sunshine",
|
||||||
|
"address_family_ipv4": "Pouze IPv4",
|
||||||
|
"always_send_scancodes": "Vždy odesílat Scancody",
|
||||||
|
"always_send_scancodes_desc": "Odesílání scancodes zvyšuje kompatibilitu s hrami a aplikacemi, ale může mít za následek nesprávný vstup na klávesnici od určitých klientů, kteří nepoužívají americké anglické rozložení klávesnice. Povolit, pokud vstup klávesnice v některých aplikacích vůbec nefunguje. Zakázat, pokud klíče klienta generují nesprávný vstup na hostitele.",
|
||||||
|
"amd_coder": "AMF kodér (H264)",
|
||||||
|
"amd_coder_desc": "Umožňuje vybrat entropie kódování pro upřednostnění kvality nebo rychlosti kódování. Pouze H.264.",
|
||||||
|
"amd_enforce_hrd": "Vymáhání hypotetického referenčního dekodéru (HRD) AMF",
|
||||||
|
"amd_enforce_hrd_desc": "Zvyšuje omezení regulace rychlosti, aby splňovala požadavky modelu HRD. To výrazně snižuje bitrate přetečení, ale může způsobit kódování artefaktů nebo nižší kvalitu na některých kartách.",
|
||||||
|
"amd_preanalysis": "Předběžná analýza AMF",
|
||||||
|
"amd_preanalysis_desc": "To umožňuje předběžnou analýzu kontroly sazeb, která může zvýšit kvalitu na úkor zvýšené latence kódování.",
|
||||||
|
"amd_quality": "Kvalita AMF",
|
||||||
|
"amd_quality_balanced": "vyrovnané -- vyvážené (výchozí)",
|
||||||
|
"amd_quality_desc": "Tím se řídí rovnováha mezi rychlostí kódování a kvalitou.",
|
||||||
|
"amd_quality_group": "Nastavení kvality AMF",
|
||||||
|
"amd_quality_quality": "kvalita -- preferovat kvalitu",
|
||||||
|
"amd_quality_speed": "Rychlost -- preferovat rychlost",
|
||||||
|
"amd_rc": "Ovládání AMF",
|
||||||
|
"amd_rc_cbr": "cbr -- konstantní bitrate (doporučujeme pokud je HRD zapnuto)",
|
||||||
|
"amd_rc_cqp": "cqp -- konstantní qp režim",
|
||||||
|
"amd_rc_desc": "Tím se řídí metoda řízení rychlosti, aby se zajistilo, že nepřekročíme cílový datový tok klienta. 'cqp' není vhodné pro cílování datového toku a ostatní možnosti kromě 'vbr_latency' závisí na HRD Enforcement, které pomáhají omezit přetečení datového toku.",
|
||||||
|
"amd_rc_group": "Nastavení řízení AMF",
|
||||||
|
"amd_rc_vbr_latency": "vbr_latency -- proměnný datový tok s omezenou latencí (doporučeno, pokud je HRD vypnuta; výchozí)",
|
||||||
|
"amd_rc_vbr_peak": "vbr_peak -- maximální nastavená proměnná bitrate",
|
||||||
|
"amd_usage": "Využití AMF",
|
||||||
|
"amd_usage_desc": "Nastaví základní profil kódování. Všechny níže uvedené možnosti přepíší podmnožinu uživatelského profilu, ale existují další skrytá nastavení, která nelze nastavit jinde.",
|
||||||
|
"amd_usage_lowlatency": "lowlatency - nízká latence (nejrychlejší)",
|
||||||
|
"amd_usage_lowlatency_high_quality": "lowlatency_high_quality - nízká latence, vysoká kvalita (rychlá)",
|
||||||
|
"amd_usage_transcoding": "překódování -- překódování (nejpomalejší)",
|
||||||
|
"amd_usage_ultralowlatency": "ultralowlatence - ultra nízká latence (nejrychlejší; výchozí)",
|
||||||
|
"amd_usage_webcam": "webová kamera -- webová kamera (pomalá)",
|
||||||
|
"amd_vbaq": "AMF adaptivní kvantifikace založená na rozptylu (VBAQ)",
|
||||||
|
"amd_vbaq_desc": "Lidský vizuální systém je obvykle méně citlivý na artefakty ve vysoce strukturovaných oblastech. V režimu VBAQ se rozptyl pixelů používá k označení složitosti prostorových textur, což umožňuje enkodéru přidělit více bitů do plynulejších oblastí. Povolení této funkce vede ke zlepšení subjektivní vizuální kvality s určitým obsahem.",
|
||||||
|
"apply_note": "Kliknutím na tlačítko \"Použít\" restartujte Sunshine a aplikujte změny. Tím se ukončí všechny spuštěné relace.",
|
||||||
|
"audio_sink": "Zvukový výřez",
|
||||||
|
"audio_sink_desc_linux": "Název skluzu zvuku, který se používá pro zvukovou smyčku. Pokud tuto proměnnou nevyberete, pulseaudio zvolí výchozí zařízení pro monitor. Název sklízení zvuku můžete najít pomocí některého příkazu:",
|
||||||
|
"audio_sink_desc_macos": "Název zvukového výřezu používaný pro Audio Loopback. Sunshine má přístup pouze k mikrofonům na macOS kvůli systémovým omezením. Pro streamování zvuku systému pomocí Soundflower nebo BlackHole.",
|
||||||
|
"audio_sink_desc_windows": "Ručně zadejte konkrétní zvukové zařízení pro zachycení. Pokud je zařízení odstaveno, je vybráno automaticky. Důrazně doporučujeme ponechat toto pole prázdné pro automatický výběr zařízení! Pokud máte více zvukových zařízení se stejnými jmény, můžete získat ID zařízení pomocí následujícího příkazu:",
|
||||||
|
"audio_sink_placeholder_macos": "BlackHole 2ch",
|
||||||
|
"audio_sink_placeholder_windows": "Reproduktory (High Definition Audio Device)",
|
||||||
|
"av1_mode": "AV1 podpora",
|
||||||
|
"av1_mode_0": "Sunshine bude inzerovat podporu AV1 na základě schopností kodéru (doporučeno)",
|
||||||
|
"av1_mode_1": "Sunshine nebude inzerovat podporu AV1",
|
||||||
|
"av1_mode_2": "Sunshine bude inzerovat podporu hlavního 8bitového profilu AV1",
|
||||||
|
"av1_mode_3": "Sunshine bude inzerovat podporu hlavních 8bitových a 10bitových profilů AV1 (HDR)",
|
||||||
|
"av1_mode_desc": "Umožňuje klientovi požádat o AV1 hlavní 8-bitové nebo 10-bitové video streamy. AV1 je intenzivnější na CPU kódování, takže díky tomu může dojít ke snížení výkonu při používání kódování softwaru.",
|
||||||
|
"back_button_timeout": "Časový limit emulace tlačítka Domů/Návod",
|
||||||
|
"back_button_timeout_desc": "Pokud je tlačítko Zpět/Výběr podrženo pro zadaný počet milisekund, je emulováno stisknutí tlačítka Domů/Průvodce. Je-li nastaveno na hodnotu < 0 (výchozí), podržením tlačítka Zpět/Výběr nebude tlačítko Domů/Průvodce emulováno.",
|
||||||
|
"capture": "Vynutit specifickou metodu snímání",
|
||||||
|
"capture_desc": "V automatickém režimu bude Sunshine používat ten první, který funguje. NvFBC vyžaduje upravené nvidia ovladače.",
|
||||||
|
"cert": "Osvědčení",
|
||||||
|
"cert_desc": "Certifikát používaný pro párování webových UI a Moonlight klientů. Pro nejlepší kompatibilitu by měl mít veřejný klíč RSA-2048.",
|
||||||
|
"channels": "Maximální počet připojených klientů",
|
||||||
|
"channels_desc_1": "Sluneční svár může umožnit sdílení jediné streamovací relace s více klienty současně.",
|
||||||
|
"channels_desc_2": "Některé hardwarové enkodéry mohou mít omezení, která snižují výkon s více streamy.",
|
||||||
|
"coder_cabac": "cabac -- kontextové binární aritmetické kódování – vyšší kvalita",
|
||||||
|
"coder_cavlc": "cavlc -- kontextové adaptivní kódování variabilní délky - rychlejší dekódování",
|
||||||
|
"configuration": "Konfigurace",
|
||||||
|
"controller": "Enable Gamepad Input",
|
||||||
|
"controller_desc": "Umožňuje hostům ovládat hostitelský systém pomocí gamepad / controller",
|
||||||
|
"credentials_file": "Soubor pověření",
|
||||||
|
"credentials_file_desc": "Uložit uživatelské jméno/heslo odděleně od souboru se stavem Sunshine.",
|
||||||
|
"dd_config_ensure_active": "Automaticky aktivovat displej",
|
||||||
|
"dd_config_ensure_only_display": "Deaktivovat další displeje a aktivovat pouze zadaný displej",
|
||||||
|
"dd_config_ensure_primary": "Automaticky aktivovat displej a učinit jej primárním displejem",
|
||||||
|
"dd_config_label": "Konfigurace zařízení",
|
||||||
|
"dd_config_revert_delay": "Zpoždění nastavení zpětného chodu",
|
||||||
|
"dd_config_revert_delay_desc": "Další zpoždění v milisekundách čeká na obnovení konfigurace při zavření aplikace nebo ukončení poslední relace. Hlavním účelem je zajistit hladký přechod při rychlém přepínání mezi aplikacemi.",
|
||||||
|
"dd_config_revert_on_disconnect": "Konfigurace se vrátí po odpojení",
|
||||||
|
"dd_config_revert_on_disconnect_desc": "Vrátit konfiguraci po odpojení všech klientů namísto zavření aplikace nebo posledního ukončení relace.",
|
||||||
|
"dd_config_verify_only": "Ověřte, zda je displej povolen",
|
||||||
|
"dd_hdr_option": "HDR",
|
||||||
|
"dd_hdr_option_auto": "Zapnout/vypnout HDR režim podle požadavku klienta (výchozí)",
|
||||||
|
"dd_hdr_option_disabled": "Neměnit nastavení HDR",
|
||||||
|
"dd_mode_remapping": "Režim zobrazení přemapování",
|
||||||
|
"dd_mode_remapping_add": "Přidat položku pro nové mapování",
|
||||||
|
"dd_mode_remapping_desc_1": "Určete položky pro nové mapování pro změnu požadovaného rozlišení a/nebo obnovení frekvence na jiné hodnoty.",
|
||||||
|
"dd_mode_remapping_desc_2": "Seznam se iteruje shora dolů a použije se první shoda.",
|
||||||
|
"dd_mode_remapping_desc_3": "Pole \"Požadováno\" mohou být ponechána prázdná, aby odpovídala libovolné požadované hodnotě.",
|
||||||
|
"dd_mode_remapping_desc_4_final_values_mixed": "Alespoň jedno pole \"Final\" musí být zadáno. Nespecifikované rozlišení nebo obnovovací frekvence se nezmění.",
|
||||||
|
"dd_mode_remapping_desc_4_final_values_non_mixed": "Pole \"Final\" musí být zadáno a nesmí být prázdné.",
|
||||||
|
"dd_mode_remapping_desc_5_sops_mixed_only": "Možnost \"Optimalizovat nastavení hry\" musí být povolena v klientovi Měsíční světlo, jinak budou přeskočeny záznamy s libovolnými vybranými rozlišeními polí.",
|
||||||
|
"dd_mode_remapping_desc_5_sops_resolution_only": "Možnost \"Optimalizovat nastavení hry\" musí být povolena v klientovi Měsíční světlo, jinak je mapování přeskočeno.",
|
||||||
|
"dd_mode_remapping_final_refresh_rate": "Konečná obnovovací frekvence",
|
||||||
|
"dd_mode_remapping_final_resolution": "Konečné řešení",
|
||||||
|
"dd_mode_remapping_requested_fps": "Požadovaná FPS",
|
||||||
|
"dd_mode_remapping_requested_resolution": "Požadované rozlišení",
|
||||||
|
"dd_options_header": "Rozšířené možnosti displeje",
|
||||||
|
"dd_refresh_rate_option": "Obnovovací frekvence",
|
||||||
|
"dd_refresh_rate_option_auto": "Použít FPS hodnotu poskytnutou klientem (výchozí)",
|
||||||
|
"dd_refresh_rate_option_disabled": "Neměnit obnovovací frekvenci",
|
||||||
|
"dd_refresh_rate_option_manual": "Použít ručně zadanou obnovovací frekvenci",
|
||||||
|
"dd_refresh_rate_option_manual_desc": "Zadejte obnovovací frekvenci pro použití",
|
||||||
|
"dd_resolution_option": "Rozlišení",
|
||||||
|
"dd_resolution_option_auto": "Použít rozlišení poskytované klientem (výchozí)",
|
||||||
|
"dd_resolution_option_disabled": "Neměnit rozlišení",
|
||||||
|
"dd_resolution_option_manual": "Použít ručně zadané rozlišení",
|
||||||
|
"dd_resolution_option_manual_desc": "Zadejte rozlišení, které má být použito",
|
||||||
|
"dd_resolution_option_ogs_desc": "Možnost \"Optimalizovat nastavení hry\" musí být povolena na klientovi Moonlight aby to fungovalo.",
|
||||||
|
"dd_wa_hdr_toggle_delay_desc_1": "Při použití virtuálního displeje (VDD) pro vysílání může nesprávně zobrazit barvu HDR. Sluneční svár se může pokusit tento problém zmírnit tím, že vypne HDR a poté znovu vypne.",
|
||||||
|
"dd_wa_hdr_toggle_delay_desc_2": "Pokud je hodnota nastavena na 0, je práce zakázána (výchozí). Pokud je hodnota mezi 0 a 3000 milisekundami, sunshine vypne HDR, počkejte na stanovený čas a pak znovu zapněte HDR. Doporučená doba zpoždění je ve většině případů přibližně 500 milisekund.",
|
||||||
|
"dd_wa_hdr_toggle_delay_desc_3": "NEPOUŽÍVEJTE toto fungování, pokud nemáte problémy s HDR protože přímo ovlivňuje počáteční čas!",
|
||||||
|
"dd_wa_hdr_toggle_delay": "Práce na vysokém kontrastu pro HDR",
|
||||||
|
"ds4_back_as_touchpad_click": "Mapa zpátky/Vyberte pro klepnutí na Touchpad",
|
||||||
|
"ds4_back_as_touchpad_click_desc": "Při vynucení emulace DS4 mapa zpět/Vyberte na Touchpad kliknutí",
|
||||||
|
"encoder": "Vynutit specifický enkodér",
|
||||||
|
"encoder_desc": "Vynutit konkrétní enkodér, jinak Sunshine vybere nejlepší dostupnou možnost. Poznámka: Pokud zadáte hardwarový enkodér v systému Windows, musí odpovídat GPU, kde je displej připojen.",
|
||||||
|
"encoder_software": "Programové vybavení",
|
||||||
|
"external_ip": "Externí IP",
|
||||||
|
"external_ip_desc": "Pokud není zadána žádná externí IP adresa, Sluneční server automaticky rozpozná externí IP adresu",
|
||||||
|
"fec_percentage": "Procento FEC",
|
||||||
|
"fec_percentage_desc": "Procento chyb při opravě paketů na datových paketech v každém video snímku. Vyšší hodnoty mohou opravit větší ztrátu síťových paketů, ale za cenu zvýšení využití šířky pásma.",
|
||||||
|
"ffmpeg_auto": "auto -- nechat rozhodnutí ffmpeg (výchozí)",
|
||||||
|
"file_apps": "Soubor aplikací",
|
||||||
|
"file_apps_desc": "Soubor, kde jsou uloženy aktuální aplikace Sunshine.",
|
||||||
|
"file_state": "Státní soubor",
|
||||||
|
"file_state_desc": "Soubor, ve kterém je uložen aktuální stav sunshine",
|
||||||
|
"gamepad": "Emulovaný typ hry",
|
||||||
|
"gamepad_auto": "Možnosti automatického výběru",
|
||||||
|
"gamepad_desc": "Vyberte typ gamepadu, který chcete emulovat na hostiteli",
|
||||||
|
"gamepad_ds4": "DS4 (PS4)",
|
||||||
|
"gamepad_ds4_manual": "Možnosti výběru DS4",
|
||||||
|
"gamepad_ds5": "DS5 (PS5)",
|
||||||
|
"gamepad_switch": "Nintendo Pro (Switch)",
|
||||||
|
"gamepad_manual": "Možnosti manuálního DS4",
|
||||||
|
"gamepad_x360": "X360 (Xbox 360)",
|
||||||
|
"gamepad_xone": "Xone (Xbox Jedna)",
|
||||||
|
"global_prep_cmd": "Příprava příkazů",
|
||||||
|
"global_prep_cmd_desc": "Konfigurace seznamu příkazů, které mají být provedeny před spuštěním jakékoli aplikace nebo po ní. Pokud některý z určených příkazů neuspěje, proces spuštění aplikace bude přerušen.",
|
||||||
|
"hevc_mode": "Podpora HEVC",
|
||||||
|
"hevc_mode_0": "Sunshine bude propagovat podporu pro HEVC na základě možností enkodéru (doporučeno)",
|
||||||
|
"hevc_mode_1": "Sluneční síť nebude propagovat podporu HEVC",
|
||||||
|
"hevc_mode_2": "Sluneční svaz bude propagovat podporu hlavního profilu HEVC",
|
||||||
|
"hevc_mode_3": "Sluneční svaz bude propagovat podporu profilů HEVC Main a Main10 (HDR)",
|
||||||
|
"hevc_mode_desc": "Umožňuje klientovi vyžádat si HEVC Main nebo HEVC Main10 video streamy. HEVC je intenzivnější na CPU kódování, takže povolení může snížit výkon při používání kódování softwaru.",
|
||||||
|
"high_resolution_scrolling": "Podpora rolování s vysokým rozlišením",
|
||||||
|
"high_resolution_scrolling_desc": "Pokud je povoleno, sunshine projde událostmi posunu s vysokým rozlišením od klientů Moonight. To může být užitečné pro vypnutí starších aplikací, které se posouvají příliš rychle při posunu s vysokým rozlišením.",
|
||||||
|
"install_steam_audio_drivers": "Nainstalujte Steam Audio Drivers",
|
||||||
|
"install_steam_audio_drivers_desc": "Pokud je Steam nainstalován, tak se automaticky nainstaluje ovladač Steam Streaming Speakers pro podporu 5.1/7.1 prostorového zvuku a ztlumení zvuku.",
|
||||||
|
"key_repeat_delay": "Zpoždění opakování klíče",
|
||||||
|
"key_repeat_delay_desc": "Ovládejte, jak rychle se budou klíče opakovat. Počáteční zpoždění v milisekundách před opakováním klíčů.",
|
||||||
|
"key_repeat_frequency": "Frekvence opakování klíče",
|
||||||
|
"key_repeat_frequency_desc": "Jak často se klíče opakují každou vteřinu. Tato konfigurovatelná volba podporuje desetinná místa.",
|
||||||
|
"key_rightalt_to_key_win": "Mapovat pravý Alt klíč k klíči Windows",
|
||||||
|
"key_rightalt_to_key_win_desc": "Může být možné, že z Moonlight nemůžete přímo odeslat klíč pro Windows. V těchto případech může být užitečné udělat sunshine si myslet, že klíč pravý Alt je klíč pro Windows",
|
||||||
|
"keyboard": "Povolit vstup klávesnice",
|
||||||
|
"keyboard_desc": "Umožňuje hostům ovládat hostitelský systém pomocí klávesnice",
|
||||||
|
"lan_encryption_mode": "Režim šifrování LAN",
|
||||||
|
"lan_encryption_mode_1": "Povoleno pro podporované klienty",
|
||||||
|
"lan_encryption_mode_2": "Vyžadováno pro všechny klienty",
|
||||||
|
"lan_encryption_mode_desc": "Určuje, kdy bude šifrování použito při streamování přes místní síť. Šifrování může snížit výkon streamování, zejména u méně výkonných hostitelů a klientů.",
|
||||||
|
"locale": "Místní prostředí",
|
||||||
|
"locale_desc": "Lokální prostředí používané pro uživatelské rozhraní Sunshine.",
|
||||||
|
"log_level": "Úroveň logu",
|
||||||
|
"log_level_0": "Verbose",
|
||||||
|
"log_level_1": "Debug",
|
||||||
|
"log_level_2": "Info",
|
||||||
|
"log_level_3": "Varování",
|
||||||
|
"log_level_4": "Chyba",
|
||||||
|
"log_level_5": "Fatal",
|
||||||
|
"log_level_6": "Nic",
|
||||||
|
"log_level_desc": "Minimální úroveň logu vytištěná pro standardizaci",
|
||||||
|
"log_path": "Cesta k logu",
|
||||||
|
"log_path_desc": "Soubor s aktuálními protokoly sunshine jsou uloženy.",
|
||||||
|
"max_bitrate": "Maximální bitrate",
|
||||||
|
"max_bitrate_desc": "Maximální bitrate (v Kbps) zakódovaný sunshine streamem. Je-li nastaveno na 0, bude vždy používat bitrate požadovaný Moonlight.",
|
||||||
|
"min_threads": "Minimální počet CPU vláken",
|
||||||
|
"min_threads_desc": "Zvýšení hodnoty mírně snižuje efektivitu kódování, ale tento kompromis obvykle stojí za to získat více jader CPU pro kódování. Ideální hodnota je nejnižší hodnota, která může spolehlivě kódovat v požadovaném nastavení streamu do vašeho hardwaru.",
|
||||||
|
"misc": "Různé možnosti",
|
||||||
|
"motion_as_ds4": "Emulovat DS4 gamepad pokud jsou přítomny snímače pohybu",
|
||||||
|
"motion_as_ds4_desc": "Je-li zakázáno, nebudou při výběru typu gamepadu brány v úvahu snímače pohybu.",
|
||||||
|
"mouse": "Povolit vstup myši",
|
||||||
|
"mouse_desc": "Umožňuje hostům ovládat systém pomocí myši",
|
||||||
|
"native_pen_touch": "Nativní Peněžení/Dotkněte se podpory",
|
||||||
|
"native_pen_touch_desc": "Pokud je povoleno, Sunshine projde nativní per/dotyk od klientů Moonlight událostí. To může být užitečné pro vypnutí starších aplikací bez nativní podpory pen/dotyku.",
|
||||||
|
"notify_pre_releases": "Oznámení před vydáním",
|
||||||
|
"notify_pre_releases_desc": "Zda mají být informovány o nových předběžných verzích Sunshine",
|
||||||
|
"nvenc_h264_cavlc": "Preferovat CAVLC před CABAC v H.264",
|
||||||
|
"nvenc_h264_cavlc_desc": "Jednoduchá forma entropizace. CAVLC potřebuje asi o 10 % více bitratu ve stejné kvalitě. Je relevantní pouze pro opravdu staré dekódování zařízení.",
|
||||||
|
"nvenc_latency_over_power": "Preferovat nižší latenci kódování před úsporami energie",
|
||||||
|
"nvenc_latency_over_power_desc": "Sluneční požadavky vyžadují maximální rychlost GPU hodin při streamování, aby se snížila latence kódování. Vypnutí se nedoporučuje, protože to může vést k výraznému zvýšení latence kódování.",
|
||||||
|
"nvenc_opengl_vulkan_on_dxgi": "Současný OpenGL/Vulkan nad DXGI",
|
||||||
|
"nvenc_opengl_vulkan_on_dxgi_desc": "Sluneční neschopný zachytit programy OpenGL a Vulkan při plném snímku, pokud nejsou přítomny na vrcholu DXGI. Toto je systémové nastavení, které je vráceno při ukončení slunečního programu.",
|
||||||
|
"nvenc_preset": "Předvolba výkonu",
|
||||||
|
"nvenc_preset_1": "(nejrychlejší, výchozí)",
|
||||||
|
"nvenc_preset_7": "(nejmenší)",
|
||||||
|
"nvenc_preset_desc": "Vyšší čísla zlepšují kompresi (kvalita při dané bitové rychlosti) za cenu zvýšeného zpoždění kódování. Změnu doporučujeme pouze v případě, že je omezena sítí nebo dekodérem, jinak lze dosáhnout podobného efektu zvýšením bitrate.",
|
||||||
|
"nvenc_realtime_hags": "Použít prioritu v reálném čase v hardwarově akcelerovaném plánování",
|
||||||
|
"nvenc_realtime_hags_desc": "V současné době mohou ovladače NVIDIA zmrazit v enkodéru, pokud je HAGS povoleno, je použita priorita v reálném čase a využití VRAM je blízko maximu. Zakázání této možnosti snižuje prioritu na vysokou úroveň, vyhýbá se zmrazení za cenu snížení výkonu zachytávání při vysoké zátěži.",
|
||||||
|
"nvenc_spatial_aq": "Spatial AQ",
|
||||||
|
"nvenc_spatial_aq_desc": "Přiřadit vyšší hodnoty QP plochým oblastem videa. Doporučeno povolit při streamování při nižších bitech.",
|
||||||
|
"nvenc_twopass": "Režim obousměrného průjezdu",
|
||||||
|
"nvenc_twopass_desc": "Přidá předběžné kódování. To umožňuje detekovat více vektorů pohybu, lépe distribuovat bitrate napříč rámcem a přesněji dodržovat limity bitratu. Vypnutí se nedoporučuje, protože to může způsobit občasné překročení bitratu a následnou ztrátu paketů.",
|
||||||
|
"nvenc_twopass_disabled": "Zakázáno (nejrychlejší, nedoporučeno)",
|
||||||
|
"nvenc_twopass_full_res": "Úplné rozlišení (pomalejší)",
|
||||||
|
"nvenc_twopass_quarter_res": "Čtvrtletní rozlišení (rychlejší, výchozí)",
|
||||||
|
"nvenc_vbv_increase": "Zvýšení procenta jednoho snímku VBV/HRD",
|
||||||
|
"nvenc_vbv_increase_desc": "Ve výchozím nastavení používá sluneční záření jednosnímkový VBV/HRD, což znamená, že se neočekává, že by žádná velikost zakódovaného video snímku překročila požadovanou bitrate dělenou požadovanou frekvencí snímku. zmírnění tohoto omezení může být prospěšné a fungovat jako variabilní bitrate s nízkou latencí, ale může také vést ke ztrátě paketů, pokud síť nemá mezipaměnnou mezipaměť pro zvládání výkyvů bitratů. Maximální přípustná hodnota je 400, což odpovídá 5x zvýšenému limitu horní velikosti zakódovaného video snímku.",
|
||||||
|
"origin_web_ui_allowed": "Origin Web UI povoleno",
|
||||||
|
"origin_web_ui_allowed_desc": "Původ adresy vzdáleného koncového bodu, které není odepřen přístup k webovému uživatelskému rozhraní",
|
||||||
|
"origin_web_ui_allowed_lan": "Přístup k webovému uživatelskému rozhraní mohou mít pouze uživatelé LAN",
|
||||||
|
"origin_web_ui_allowed_pc": "Pouze localhost může přistupovat k webovému rozhraní",
|
||||||
|
"origin_web_ui_allowed_wan": "Kdokoli může přistupovat k webovému rozhraní",
|
||||||
|
"output_name_desc_unix": "Při spuštění pomocí slunečního svitu byste měli vidět seznam rozpoznaných displejů. Poznámka: Je třeba použít id hodnotu uvnitř závorky. Níže je příklad; skutečný výstup lze nalézt v záložce řešení problémů.",
|
||||||
|
"output_name_desc_windows": "Ručně zadejte id zobrazovacího zařízení pro zachycení. Pokud je odpojen, primární obrazovka je zachycena. Poznámka: Pokud jste zadali GPU výše, musí být tento displej připojen k grafické kartě. Při spouštění přes Sunshine byste měli vidět seznam detekovaných displejů. Níže je příklad; skutečný výstup lze nalézt v záložce Řešení problémů.",
|
||||||
|
"output_name_unix": "Zobrazit číslo",
|
||||||
|
"output_name_windows": "Zobrazit ID zařízení",
|
||||||
|
"ping_timeout": "Časový limit Ping",
|
||||||
|
"ping_timeout_desc": "Jak dlouho čekat v milisekundách na data z Měsíčního světla před vypnutím proudu",
|
||||||
|
"pkey": "Soukromý klíč",
|
||||||
|
"pkey_desc": "Soukromý klíč používaný pro párování webových UI a Moonlight klientů. Pro nejlepší kompatibilitu by měl být soukromý klíč RSA-2048.",
|
||||||
|
"port": "Přístav",
|
||||||
|
"port_alert_1": "Sluneční svaz nemůže používat přístavy pod 1024!",
|
||||||
|
"port_alert_2": "Přístavy nad 65535 nejsou k dispozici!",
|
||||||
|
"port_desc": "Nastavte rodinu přístavů používaných sunshine",
|
||||||
|
"port_http_port_note": "Použijte tento port pro připojení k měsíčnímu světlu.",
|
||||||
|
"port_note": "Poznámka",
|
||||||
|
"port_port": "Přístav",
|
||||||
|
"port_protocol": "Protocol",
|
||||||
|
"port_tcp": "TCP",
|
||||||
|
"port_udp": "UDP",
|
||||||
|
"port_warning": "Vystavení webového uživatelského rozhraní na internet je bezpečnostní riziko! Pokračujte na vlastní nebezpečí!",
|
||||||
|
"port_web_ui": "Web UI",
|
||||||
|
"qp": "Parametr kvantizace",
|
||||||
|
"qp_desc": "Některá zařízení nemusí podporovat Constant Bit Rate. Pro tato zařízení se místo toho používá QP. Vyšší hodnota znamená větší kompresi, ale menší kvalitu.",
|
||||||
|
"qsv_coder": "Kodér QuickSync (H264)",
|
||||||
|
"qsv_preset": "QuickSync Preset",
|
||||||
|
"qsv_preset_fast": "rychlá (nízká kvalita)",
|
||||||
|
"qsv_preset_faster": "rychlejší (nižší kvalita)",
|
||||||
|
"qsv_preset_medium": "střední (výchozí)",
|
||||||
|
"qsv_preset_slow": "pomalý (dobrá kvalita)",
|
||||||
|
"qsv_preset_slower": "pomalejší (lepší kvalita)",
|
||||||
|
"qsv_preset_slowest": "nejpomalejší (nejlepší kvalita)",
|
||||||
|
"qsv_preset_veryfast": "nejrychlejší (nejnižší jakost)",
|
||||||
|
"qsv_slow_hevc": "Povolit pomalé kódování HEVC",
|
||||||
|
"qsv_slow_hevc_desc": "To může povolit HEVC kódování na starších Intel GPU, za cenu vyšší spotřeby GPU a horšího výkonu.",
|
||||||
|
"restart_note": "Sluneční brýle se restartuje a aplikuje změny.",
|
||||||
|
"stream_audio": "Stream zvuk",
|
||||||
|
"stream_audio_desc": "Zakázání zvuku může být užitečné pro streamování bezhlavých displejů jako druhý monitor.",
|
||||||
|
"sunshine_name": "Sluneční jméno",
|
||||||
|
"sunshine_name_desc": "Jméno zobrazené podle měsíčního světla. Není-li zadáno, použije se hostname počítače",
|
||||||
|
"sw_preset": "SW přednastavení",
|
||||||
|
"sw_preset_desc": "Optimalizujte kompromis mezi rychlostí kódování (kódované snímky za sekundu) a efektivitou komprese (kvalita na bit v bitovém toku). Výchozí nastavení je superrychlé.",
|
||||||
|
"sw_preset_fast": "rychlá",
|
||||||
|
"sw_preset_faster": "rychleji",
|
||||||
|
"sw_preset_medium": "střední",
|
||||||
|
"sw_preset_slow": "pomalu",
|
||||||
|
"sw_preset_slower": "pomalejší",
|
||||||
|
"sw_preset_superfast": "superfast (výchozí)",
|
||||||
|
"sw_preset_ultrafast": "ultrafast",
|
||||||
|
"sw_preset_veryfast": "veryfast",
|
||||||
|
"sw_preset_veryslow": "veryslow",
|
||||||
|
"sw_tune": "SW melodie",
|
||||||
|
"sw_tune_animation": "animace -- dobré pro karikatury; používá vyšší deblokovací a více referenčních rámců",
|
||||||
|
"sw_tune_desc": "Vyladění možností, které jsou aplikovány po předvolbě. Výchozí nastavení je nula.",
|
||||||
|
"sw_tune_fastdecode": "fastdecode -- umožňuje rychlejší dekódování vypnutím určitých filtrů",
|
||||||
|
"sw_tune_film": "film -- používá pro vysoce kvalitní filmový obsah; snižuje odblokování",
|
||||||
|
"sw_tune_grain": "zrno – zachovává strukturu zrn ve starém, zrním materiálu",
|
||||||
|
"sw_tune_stillimage": "stillimage -- dobré pro slideshow-like obsah",
|
||||||
|
"sw_tune_zerolatency": "nulová latence -- dobrá pro rychlé kódování a nízká latence streamování (výchozí)",
|
||||||
|
"touchpad_as_ds4": "Emulovat DS4 gamepad pokud klient nahlásí přítomnost touchpadu",
|
||||||
|
"touchpad_as_ds4_desc": "Je-li zakázáno, během výběru typu gamepadu nebude brána v úvahu přítomnost touchpadu.",
|
||||||
|
"upnp": "UPnP",
|
||||||
|
"upnp_desc": "Automaticky konfigurovat přesměrování portů pro streamování přes Internet",
|
||||||
|
"vaapi_strict_rc_buffer": "Striktně prosazovat limity bitrate pro H.264/HEVC na AMD GPU.",
|
||||||
|
"vaapi_strict_rc_buffer_desc": "Povolením této volby se během změn scény vyhnete shození snímků přes síť, ale kvalita videa může být během pohybu snížena.",
|
||||||
|
"virtual_sink": "Virtuální šinek",
|
||||||
|
"virtual_sink_desc": "Ručně zadejte virtuální audio zařízení, které má být použito. Pokud je zařízení odstaveno, je vybráno automaticky. Důrazně doporučujeme ponechat toto pole prázdné pro automatický výběr zařízení!",
|
||||||
|
"virtual_sink_placeholder": "Reproduktory pro streamování přes Steam",
|
||||||
|
"vt_coder": "VideoToolbox Coder",
|
||||||
|
"vt_realtime": "Video Toolbox v reálném čase enkódování",
|
||||||
|
"vt_software": "Softwarové kódování video nástrojů",
|
||||||
|
"vt_software_allowed": "Povoleno",
|
||||||
|
"vt_software_forced": "Vynucené",
|
||||||
|
"wan_encryption_mode": "Režim šifrování WAN",
|
||||||
|
"wan_encryption_mode_1": "Povoleno pro podporované klienty (výchozí)",
|
||||||
|
"wan_encryption_mode_2": "Vyžadováno pro všechny klienty",
|
||||||
|
"wan_encryption_mode_desc": "Určuje, kdy bude šifrování použito při streamování přes internet. Šifrování může snížit streamovací výkon, zejména u méně výkonných hostitelů a klientů."
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"description": "Sluneční stream je hostitelem pro Měsíční světlo.",
|
||||||
|
"download": "Stáhnout",
|
||||||
|
"installed_version_not_stable": "Používáte předverzi Sunshine. Můžete zaznamenat chyby nebo jiné problémy. Prosím nahlaste všechny problémy, se kterými se setkáváte. Děkujeme, že jste pomohli udělat sunshine lepší software!",
|
||||||
|
"loading_latest": "Načítání nejnovější verze...",
|
||||||
|
"new_pre_release": "Je k dispozici nová verze před-vydání!",
|
||||||
|
"new_stable": "K dispozici je nová stabilní verze!",
|
||||||
|
"startup_errors": "<b>Pozor!</b> Sunshine detekoval tyto chyby během spuštění. <b>STRONGLY RECOMMEND</b> je opraví před vysíláním.",
|
||||||
|
"version_dirty": "Děkujeme, že jste pomohli udělat sunshine lepší software!",
|
||||||
|
"version_latest": "Používáte nejnovější verzi Sunshine",
|
||||||
|
"welcome": "Ahoj, sunshine!"
|
||||||
|
},
|
||||||
|
"navbar": {
|
||||||
|
"applications": "Aplikace",
|
||||||
|
"configuration": "Konfigurace",
|
||||||
|
"home": "Domů",
|
||||||
|
"password": "Změnit heslo",
|
||||||
|
"pin": "PIN",
|
||||||
|
"theme_auto": "Automaticky",
|
||||||
|
"theme_dark": "Tmavý",
|
||||||
|
"theme_light": "Světlý",
|
||||||
|
"toggle_theme": "Téma",
|
||||||
|
"troubleshoot": "Řešení problémů"
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"confirm_password": "Potvrzení hesla",
|
||||||
|
"current_creds": "Aktuální přihlašovací údaje",
|
||||||
|
"new_creds": "Nové přihlašovací údaje",
|
||||||
|
"new_username_desc": "Pokud není zadáno, uživatelské jméno se nezmění",
|
||||||
|
"password_change": "Změna hesla",
|
||||||
|
"success_msg": "Heslo bylo úspěšně změněno! Tato stránka se brzy obnoví, váš prohlížeč vás požádá o nové přihlašovací údaje."
|
||||||
|
},
|
||||||
|
"pin": {
|
||||||
|
"device_name": "Název zařízení",
|
||||||
|
"pair_failure": "Spárování se nezdařilo: Zkontrolujte, zda je PIN správně zadán",
|
||||||
|
"pair_success": "Úspěch! Prosím, zkontrolujte Moonlight pro pokračování",
|
||||||
|
"pin_pairing": "PIN Pairing",
|
||||||
|
"send": "Poslat",
|
||||||
|
"warning_msg": "Ujistěte se, že máte přístup k klientovi, se kterým spárujete. Tento software může poskytnout vašemu počítači úplnou kontrolu, takže buďte opatrní!"
|
||||||
|
},
|
||||||
|
"resource_card": {
|
||||||
|
"github_discussions": "GitHub Discussions",
|
||||||
|
"legal": "Právní předpisy",
|
||||||
|
"legal_desc": "Pokračováním v používání tohoto softwaru souhlasíte s podmínkami v následujících dokumentech.",
|
||||||
|
"license": "Licence",
|
||||||
|
"lizardbyte_website": "Webové stránky LizardByte",
|
||||||
|
"resources": "Zdroje",
|
||||||
|
"resources_desc": "Zdroje pro sunnity!",
|
||||||
|
"third_party_notice": "Oznámení třetí strany"
|
||||||
|
},
|
||||||
|
"troubleshooting": {
|
||||||
|
"dd_reset": "Obnovit nastavení trvalého zobrazení zařízení",
|
||||||
|
"dd_reset_desc": "Pokud se sluneční svaz zasekne o obnovení změněného nastavení zobrazovacího zařízení, můžete obnovit nastavení a pokračovat v obnově stavu displeje ručně.",
|
||||||
|
"dd_reset_error": "Chyba při obnovování trvalosti!",
|
||||||
|
"dd_reset_success": "Úspěch resetování trvalosti!",
|
||||||
|
"force_close": "Vynutit zavření",
|
||||||
|
"force_close_desc": "Pokud si Měsíc stěžuje na právě spuštěnou aplikaci, vynucené zavření aplikace by mělo problém vyřešit.",
|
||||||
|
"force_close_error": "Chyba při zavírání aplikace",
|
||||||
|
"force_close_success": "Aplikace úspěšně uzavřena!",
|
||||||
|
"logs": "Logy",
|
||||||
|
"logs_desc": "Podívejte se na logy nahrané sunshine",
|
||||||
|
"logs_find": "Najít...",
|
||||||
|
"restart_sunshine": "Restartovat Sunshine",
|
||||||
|
"restart_sunshine_desc": "Pokud sluneční svit nefunguje správně, můžete jej zkusit restartovat. To ukončí všechny spuštěné relace.",
|
||||||
|
"restart_sunshine_success": "Sunshine se restartuje",
|
||||||
|
"troubleshooting": "Řešení problémů",
|
||||||
|
"unpair_all": "Zrušit spárování vše",
|
||||||
|
"unpair_all_error": "Chyba při nepárování",
|
||||||
|
"unpair_all_success": "Všechna zařízení nejsou spárována.",
|
||||||
|
"unpair_desc": "Odstranit spárovaná zařízení. Jednotlivě nespárovaná zařízení s aktivní relací zůstanou připojena, ale nemohou spustit nebo obnovit relaci.",
|
||||||
|
"unpair_single_no_devices": "Neexistují žádná spárovaná zařízení.",
|
||||||
|
"unpair_single_success": "Zařízení však mohou být stále v aktivní relaci. Použijte tlačítko 'Vynutit zavření' pro ukončení všech otevřených relací.",
|
||||||
|
"unpair_single_unknown": "Neznámý klient",
|
||||||
|
"unpair_title": "Zrušit párování"
|
||||||
|
},
|
||||||
|
"welcome": {
|
||||||
|
"confirm_password": "Potvrdit heslo",
|
||||||
|
"create_creds": "Před spuštěním potřebujeme, abyste vytvořili nové uživatelské jméno a heslo pro přístup k webovému uživatelskému rozhraní.",
|
||||||
|
"create_creds_alert": "Níže uvedené přihlašovací údaje jsou potřebné pro přístup k webovému rozhraní Sunshine. Uchovávejte je v bezpečí, protože je už nikdy nebudete vidět!",
|
||||||
|
"greeting": "Vítejte v Sunshine!",
|
||||||
|
"login": "Přihlásit se",
|
||||||
|
"welcome_success": "Tato stránka se brzy obnoví, váš prohlížeč vás požádá o nové přihlašovací údaje."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -337,8 +337,6 @@
|
|||||||
"log_path_desc": "The file where the current logs of Apollo are stored.",
|
"log_path_desc": "The file where the current logs of Apollo are stored.",
|
||||||
"max_bitrate": "Maximum Bitrate",
|
"max_bitrate": "Maximum Bitrate",
|
||||||
"max_bitrate_desc": "The maximum bitrate (in Kbps) that Apollo will encode the stream at. If set to 0, it will always use the bitrate requested by Artemis/Moonlight.",
|
"max_bitrate_desc": "The maximum bitrate (in Kbps) that Apollo will encode the stream at. If set to 0, it will always use the bitrate requested by Artemis/Moonlight.",
|
||||||
"min_fps_factor": "Minimum FPS Factor",
|
|
||||||
"min_fps_factor_desc": "Apollo will use this factor to calculate the minimum time between frames. Increasing this value slightly may help when streaming mostly static content. Higher values will consume more bandwidth.",
|
|
||||||
"min_threads": "Minimum CPU Thread Count",
|
"min_threads": "Minimum CPU Thread Count",
|
||||||
"min_threads_desc": "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.",
|
"min_threads_desc": "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.",
|
||||||
"misc": "Miscellaneous options",
|
"misc": "Miscellaneous options",
|
||||||
|
|||||||
@@ -330,8 +330,6 @@
|
|||||||
"log_level_desc": "打印到标准输出的最小日志级别",
|
"log_level_desc": "打印到标准输出的最小日志级别",
|
||||||
"log_path": "日志文件路径",
|
"log_path": "日志文件路径",
|
||||||
"log_path_desc": "Apollo 当前日志存储的文件。",
|
"log_path_desc": "Apollo 当前日志存储的文件。",
|
||||||
"min_fps_factor": "最小帧率系数",
|
|
||||||
"min_fps_factor_desc": "Apollo 将使用此系数来计算帧之间的最小时间。当串流的内容主要为静态内容时,稍微增加此值可能会有帮助。更大的值将会使用更大的带宽。",
|
|
||||||
"min_threads": "最低 CPU 线程数",
|
"min_threads": "最低 CPU 线程数",
|
||||||
"min_threads_desc": "提高该值会略微降低编码效率,但为了获得更多的 CPU 内核用于编码,通常是值得的。理想值是在您的硬件配置上以所需的串流设置进行可靠编码的最低值。",
|
"min_threads_desc": "提高该值会略微降低编码效率,但为了获得更多的 CPU 内核用于编码,通常是值得的。理想值是在您的硬件配置上以所需的串流设置进行可靠编码的最低值。",
|
||||||
"misc": "杂项选项",
|
"misc": "杂项选项",
|
||||||
|
|||||||
455
src_assets/common/assets/web/public/assets/locale/zh_TW.json
Normal file
455
src_assets/common/assets/web/public/assets/locale/zh_TW.json
Normal file
@@ -0,0 +1,455 @@
|
|||||||
|
{
|
||||||
|
"_common": {
|
||||||
|
"apply": "套用",
|
||||||
|
"auto": "自動",
|
||||||
|
"autodetect": "自動偵測(建議)",
|
||||||
|
"beta": "(測試版)",
|
||||||
|
"cancel": "取消",
|
||||||
|
"disabled": "已停用",
|
||||||
|
"disabled_def": "已停用(預設)",
|
||||||
|
"disabled_def_cbox": "預設值:未勾選",
|
||||||
|
"dismiss": "關閉",
|
||||||
|
"do_cmd": "執行指令",
|
||||||
|
"elevated": "提高權限",
|
||||||
|
"enabled": "已啟用",
|
||||||
|
"enabled_def": "已啟用(預設值)",
|
||||||
|
"enabled_def_cbox": "預設值:已勾選",
|
||||||
|
"error": "錯誤!",
|
||||||
|
"note": "請注意:",
|
||||||
|
"password": "密碼",
|
||||||
|
"run_as": "以系統管理員身份執行",
|
||||||
|
"save": "節省",
|
||||||
|
"see_more": "查看更多資訊",
|
||||||
|
"success": "成功!",
|
||||||
|
"undo_cmd": "復原指令",
|
||||||
|
"username": "使用者名稱",
|
||||||
|
"warning": "警告!"
|
||||||
|
},
|
||||||
|
"apps": {
|
||||||
|
"actions": "行動",
|
||||||
|
"add_cmds": "新增指令",
|
||||||
|
"add_new": "新增",
|
||||||
|
"app_name": "應用程式名稱",
|
||||||
|
"app_name_desc": "應用程式名稱(在 Moonlight 上顯示的名稱)",
|
||||||
|
"applications_desc": "應用程式清單僅在用戶端重新啟動時更新",
|
||||||
|
"applications_title": "應用程式一覽",
|
||||||
|
"auto_detach": "即使應用程式瞬間關閉,仍會繼續串流。",
|
||||||
|
"auto_detach_desc": "此功能會自動偵測那些在啟動其他程式或自身的另一個執行個體後,立即關閉的啟動器類應用程式。一旦偵測到這類應用程式,系統會將其視為獨立運行的應用程式。",
|
||||||
|
"cmd": "指令",
|
||||||
|
"cmd_desc": "這是要啟動的主要應用程式。如果留空,則不會啟動任何程式。",
|
||||||
|
"cmd_note": "如果指令執行檔的路徑有空格,請將路徑放在引號中。",
|
||||||
|
"cmd_prep_desc": "這是啟動應用程式前後要執行的指令清單。如果任何準備指令執行失敗,應用程式將無法啟動。",
|
||||||
|
"cmd_prep_name": "指令準備",
|
||||||
|
"covers_found": "找到封面圖片",
|
||||||
|
"delete": "刪除",
|
||||||
|
"detached_cmds": "獨立指令",
|
||||||
|
"detached_cmds_add": "新增獨立指令",
|
||||||
|
"detached_cmds_desc": "在背景執行的指令清單。",
|
||||||
|
"detached_cmds_note": "如果指令執行檔的路徑有空格,請將路徑放在引號中。",
|
||||||
|
"edit": "編輯",
|
||||||
|
"env_app_id": "應用程式 ID",
|
||||||
|
"env_app_name": "應用程式名稱",
|
||||||
|
"env_client_audio_config": "用戶端要求的音訊設定 (2.0/5.1/7.1)",
|
||||||
|
"env_client_enable_sops": "用戶端要求將遊戲進行最佳化,以達到最佳串流效果 (true/false)",
|
||||||
|
"env_client_fps": "用戶端要求的 FPS(整數)",
|
||||||
|
"env_client_gcmap": "要求的遊戲手把遮罩,使用位元集合/位元欄位格式 (整數)",
|
||||||
|
"env_client_hdr": "HDR 由用戶端啟用 (true/false)",
|
||||||
|
"env_client_height": "用戶端要求的高度(整數)",
|
||||||
|
"env_client_host_audio": "用戶端要求的主機音訊 (true/false)",
|
||||||
|
"env_client_width": "用戶端要求的寬度(整數)",
|
||||||
|
"env_displayplacer_example": "範例 - 用於解析度自動化的 displayplacer:",
|
||||||
|
"env_qres_example": "範例 - 用於解析度自動化的 QRes:",
|
||||||
|
"env_qres_path": "qres 路徑",
|
||||||
|
"env_var_name": "變數名稱",
|
||||||
|
"env_vars_about": "關於環境變數",
|
||||||
|
"env_vars_desc": "所有指令預設會獲得這些環境變數:",
|
||||||
|
"env_xrandr_example": "範例 - 用於解析度自動化的 Xrandr:",
|
||||||
|
"exit_timeout": "結束逾時設定",
|
||||||
|
"exit_timeout_desc": "當要求結束時,等待所有應用程式處理程序正常結束的秒數。如果未設定,預設會等待最多 5 秒。如果設為 0,應用程式將立即終止。",
|
||||||
|
"find_cover": "尋找封面圖片",
|
||||||
|
"global_prep_desc": "啟用/停用此應用程式的全域準備指令執行。",
|
||||||
|
"global_prep_name": "全域準備指令",
|
||||||
|
"image": "圖片",
|
||||||
|
"image_desc": "將傳送至用戶端的應用程式圖示/圖片/圖片路徑。圖片必須是 PNG 格式。如果未設定,Sunshine 將傳送預設的盒狀圖示。",
|
||||||
|
"loading": "載入中…",
|
||||||
|
"name": "名稱",
|
||||||
|
"output_desc": "指令輸出的儲存檔案。如果未指定,輸出將被忽略",
|
||||||
|
"output_name": "輸出",
|
||||||
|
"run_as_desc": "某些需要管理員權限才能正常運行的應用程式,可能需要這個設定。",
|
||||||
|
"wait_all": "繼續串流,直到所有應用程式處理程序結束",
|
||||||
|
"wait_all_desc": "這會繼續串流,直到應用程式啟動的所有處理程序都結束。如果未勾選,當最初的應用程式處理程序結束時,串流就會停止,即使還有其他處理程序在運行。",
|
||||||
|
"working_dir": "工作目錄",
|
||||||
|
"working_dir_desc": "這是要傳遞給處理程序的工作目錄。例如,有些應用程式會使用這個目錄來搜尋設定檔。如果沒有設定,Sunshine 會自動使用指令所在的目錄"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"adapter_name": "顯示卡名稱",
|
||||||
|
"adapter_name_desc_linux_1": "手動指定用於擷取的 GPU。",
|
||||||
|
"adapter_name_desc_linux_2": "找出所有支援 VAAPI 的裝置",
|
||||||
|
"adapter_name_desc_linux_3": "將 ``renderD129`` 替換為上面提到的裝置,以列出裝置的名稱和功能。要被 Sunshine 支援,裝置至少需要具備以下條件:",
|
||||||
|
"adapter_name_desc_windows": "手動指定用於擷取的 GPU。如果未設定,系統會自動選擇 GPU。我們強烈建議保持此欄位為空,以使用自動 GPU 選擇!注意:此 GPU 必須已連接顯示器並開啟電源。可以使用以下指令來查找適當的值:",
|
||||||
|
"adapter_name_placeholder_windows": "Radeon RX 580 系列",
|
||||||
|
"add": "新增",
|
||||||
|
"address_family": "地址家庭",
|
||||||
|
"address_family_both": "IPv4+IPv6",
|
||||||
|
"address_family_desc": "設定 Sunshine 使用的位址族",
|
||||||
|
"address_family_ipv4": "僅 IPv4",
|
||||||
|
"always_send_scancodes": "永遠傳送掃描碼",
|
||||||
|
"always_send_scancodes_desc": "傳送掃描碼可以增強與遊戲和應用程式的相容性,但可能會導致某些未使用美式英語鍵盤佈局的用戶端輸入錯誤。若某些應用程式的鍵盤輸入完全無效,請啟用此選項。若用戶端的鍵盤輸入在主機端產生錯誤輸入,則請停用此選項。",
|
||||||
|
"amd_coder": "AMF 編碼器 (H264)",
|
||||||
|
"amd_coder_desc": "允許您選擇熵編碼,以優先品質或編碼速度。僅限 H.264。",
|
||||||
|
"amd_enforce_hrd": "AMF 假想參考解碼器 (HRD) 強制執行",
|
||||||
|
"amd_enforce_hrd_desc": "增加速率控制的限制,以符合 HRD 模型的要求。這可大幅減少比特率溢出,但可能會在某些卡上造成編碼假象或降低品質。",
|
||||||
|
"amd_preanalysis": "AMF 預分析",
|
||||||
|
"amd_preanalysis_desc": "這可進行速率控制預分析,以增加編碼延遲為代價來提高品質。",
|
||||||
|
"amd_quality": "AMF 品質",
|
||||||
|
"amd_quality_balanced": "balanced—平衡(預設)",
|
||||||
|
"amd_quality_desc": "這可以控制編碼速度和品質之間的平衡。",
|
||||||
|
"amd_quality_group": "AMF 品質設定",
|
||||||
|
"amd_quality_quality": "quality—偏好品質",
|
||||||
|
"amd_quality_speed": "speed—偏好速度",
|
||||||
|
"amd_rc": "AMF 速率控制",
|
||||||
|
"amd_rc_cbr": "cbr—固定位元率(如果啟用 HRD,建議使用)",
|
||||||
|
"amd_rc_cqp": "cqp—常數 qp 模式",
|
||||||
|
"amd_rc_desc": "這個選項控制了速率控制方法,確保不超過客戶端的位元率目標。'cqp' 不適用於位元率目標設定,除了 'vbr_latency' 外,其他選項依賴 HRD 強制執行來幫助限制位元率溢出。",
|
||||||
|
"amd_rc_group": "AMF 速率控制設定",
|
||||||
|
"amd_rc_vbr_latency": "vbr_latency—受延遲限制的可變位元率(如果停用 HRD,建議使用此選項;預設)",
|
||||||
|
"amd_rc_vbr_peak": "vbr_peak—峰值受限的可變位元率",
|
||||||
|
"amd_usage": "AMF 使用情況",
|
||||||
|
"amd_usage_desc": "這會設定基本的編碼設定檔。以下顯示的所有選項都會覆蓋部分設定檔的設定,但設定檔還包含其他無法在其他地方調整的隱藏設定。",
|
||||||
|
"amd_usage_lowlatency": "lowlatency—低延遲(最快)",
|
||||||
|
"amd_usage_lowlatency_high_quality": "lowlatency_high_quality—低延遲、高品質(快速)",
|
||||||
|
"amd_usage_transcoding": "transcoding—轉碼(最慢)",
|
||||||
|
"amd_usage_ultralowlatency": "ultralowlatency—超低延遲(最快;預設值)",
|
||||||
|
"amd_usage_webcam": "webcam—網路攝影機(慢速)",
|
||||||
|
"amd_vbaq": "AMF 基於方差的自適應量化 (VBAQ)",
|
||||||
|
"amd_vbaq_desc": "人類的視覺系統通常對高度紋理區域中的壓縮失真較不敏感。在 VBAQ 模式下,像素變異用於指示空間紋理的複雜度,使編碼器能夠將更多位元分配給較平滑的區域。啟用此功能可在某些內容上提升主觀視覺品質。",
|
||||||
|
"apply_note": "點選「套用」以重新啟動 Sunshine 並應用變更。這將終止所有正在進行的工作階段。",
|
||||||
|
"audio_sink": "音訊水槽",
|
||||||
|
"audio_sink_desc_linux": "用於 Audio Loopback 的音訊輸出的名稱。如果您沒有指定這個變數,pulseaudio 將會選擇預設的監視裝置。您可以使用以下任一指令找出音訊輸出裝置的名稱:",
|
||||||
|
"audio_sink_desc_macos": "用於音訊環回的音訊槽名稱。由於系統限制,Sunshine 只能在 macOS 上存取麥克風。要使用 Soundflower 或 BlackHole 串流系統音訊。",
|
||||||
|
"audio_sink_desc_windows": "手動指定要擷取的特定音訊裝置。若未設定,系統會自動選擇裝置。我們強烈建議將此欄位留空以使用自動裝置選擇!若您有多個名稱相同的音訊裝置,您可以使用以下指令來取得裝置 ID:",
|
||||||
|
"audio_sink_placeholder_macos": "黑洞 2ch",
|
||||||
|
"audio_sink_placeholder_windows": "揚聲器(高解析度音訊裝置)",
|
||||||
|
"av1_mode": "AV1 支援",
|
||||||
|
"av1_mode_0": "Sunshine 將根據編碼器功能來宣告是否支援 AV1(建議)",
|
||||||
|
"av1_mode_1": "Sunshine 不會宣告支援 AV1",
|
||||||
|
"av1_mode_2": "Sunshine 將宣告支援 AV1 Main 8 位元設定檔",
|
||||||
|
"av1_mode_3": "Sunshine 將宣告支援 AV1 Main 8 位元和 10 位元 (HDR) 設定檔",
|
||||||
|
"av1_mode_desc": "允許用戶端要求 AV1 Main 8 位元或 10 位元視訊串流。AV1 的編碼較耗費 CPU,因此使用軟體編碼時,啟用此功能可能會降低效能。",
|
||||||
|
"back_button_timeout": "主畫面/導覽按鈕模擬超時",
|
||||||
|
"back_button_timeout_desc": "如果按住 Back/Select 按鈕達到指定的毫秒數,系統會模擬 Home/Guide 按鈕的按下動作。若設定為小於 0(預設值),則按住 Back/Select 按鈕不會模擬 Home/Guide 按鈕。",
|
||||||
|
"capture": "強制使用特定的擷取方式",
|
||||||
|
"capture_desc": "在自動模式下,Sunshine 會使用第一個有效的驅動程式。NvFBC 需要已修補的 nvidia 驅動程式。",
|
||||||
|
"cert": "證書",
|
||||||
|
"cert_desc": "用於網頁 UI 和 Moonlight 客戶端配對的私鑰。為了確保最佳相容性,應使用 RSA-2048 私鑰。",
|
||||||
|
"channels": "最大連線用戶端數量",
|
||||||
|
"channels_desc_1": "Sunshine 可讓單一串流工作階段同時與多個裝置共享。",
|
||||||
|
"channels_desc_2": "某些硬體編碼器可能會因多重串流而受到性能限制。",
|
||||||
|
"coder_cabac": "cabac—上下文自適應二元算術編碼,更高的品質",
|
||||||
|
"coder_cavlc": "cavlc—上下文自適應可變長度編碼 - 解碼速度較快",
|
||||||
|
"configuration": "組態",
|
||||||
|
"controller": "啟用遊戲手把輸入",
|
||||||
|
"controller_desc": "允許訪客使用遊戲手把或遊戲控制器操作主機系統。",
|
||||||
|
"credentials_file": "憑證檔案",
|
||||||
|
"credentials_file_desc": "將用戶名稱/密碼儲存在與 Sunshine 狀態檔案不同的位置。",
|
||||||
|
"dd_config_ensure_active": "自動啟用顯示器",
|
||||||
|
"dd_config_ensure_only_display": "停用其他顯示器,並只啟用指定的顯示器",
|
||||||
|
"dd_config_ensure_primary": "自動啟用顯示器並設定為主要顯示器",
|
||||||
|
"dd_config_label": "裝置設定",
|
||||||
|
"dd_config_revert_delay": "設定回復延遲",
|
||||||
|
"dd_config_revert_delay_desc": "當應用程式關閉或最後一個工作階段結束時,將會額外等待的延遲時間再恢復設定,以毫秒為單位。這樣做的主要目的是讓在快速切換應用程式時能夠更順暢。",
|
||||||
|
"dd_config_revert_on_disconnect": "斷線時恢復設定",
|
||||||
|
"dd_config_revert_on_disconnect_desc": "在所有用戶端斷線時恢復設定,而不是應用程式關閉或最後一個工作階段結束時。",
|
||||||
|
"dd_config_verify_only": "確認顯示器已啟用",
|
||||||
|
"dd_hdr_option": "HDR",
|
||||||
|
"dd_hdr_option_auto": "根據用戶端的要求開啟/關閉 HDR 模式(預設值)",
|
||||||
|
"dd_hdr_option_disabled": "不更改 HDR 設定",
|
||||||
|
"dd_mode_remapping": "顯示模式重新映射",
|
||||||
|
"dd_mode_remapping_add": "新增重新映射項目",
|
||||||
|
"dd_mode_remapping_desc_1": "指定重新映射項目以將請求的解析度和/或更新率更改為其他值。",
|
||||||
|
"dd_mode_remapping_desc_2": "清單會從上到下迭代,並使用第一個匹配項目。",
|
||||||
|
"dd_mode_remapping_desc_3": "「要求的」欄位可以留空,以匹配任何要求的值。",
|
||||||
|
"dd_mode_remapping_desc_4_final_values_mixed": "必須指定至少一個「最終」欄位。未指定的解析度或更新率將不會被更改。",
|
||||||
|
"dd_mode_remapping_desc_4_final_values_non_mixed": "必須指定「最終」欄位,且不能為空。",
|
||||||
|
"dd_mode_remapping_desc_5_sops_mixed_only": "必須在 Moonlight 用戶端啟用「最佳化遊戲設定」選項,否則指定了解析度欄位的項目將被跳過。",
|
||||||
|
"dd_mode_remapping_desc_5_sops_resolution_only": "必須在 Moonlight 用戶端啟用「最佳化遊戲設定」選項,否則映射將被跳過。",
|
||||||
|
"dd_mode_remapping_final_refresh_rate": "最終更新率",
|
||||||
|
"dd_mode_remapping_final_resolution": "最終解析度",
|
||||||
|
"dd_mode_remapping_requested_fps": "要求的 FPS",
|
||||||
|
"dd_mode_remapping_requested_resolution": "要求的解析度",
|
||||||
|
"dd_options_header": "進階顯示裝置選項",
|
||||||
|
"dd_refresh_rate_option": "更新率",
|
||||||
|
"dd_refresh_rate_option_auto": "使用用戶端提供的 FPS 值(預設)",
|
||||||
|
"dd_refresh_rate_option_disabled": "不變更更新率",
|
||||||
|
"dd_refresh_rate_option_manual": "使用手動輸入的更新率",
|
||||||
|
"dd_refresh_rate_option_manual_desc": "請輸入要使用的更新率",
|
||||||
|
"dd_resolution_option": "解析度",
|
||||||
|
"dd_resolution_option_auto": "使用客戶端提供的解析度(預設)",
|
||||||
|
"dd_resolution_option_disabled": "不更改解析度",
|
||||||
|
"dd_resolution_option_manual": "使用手動輸入的解析度",
|
||||||
|
"dd_resolution_option_manual_desc": "請輸入要使用的解析度",
|
||||||
|
"dd_resolution_option_ogs_desc": "必須在 Moonlight 客戶端啟用「最佳化遊戲設定」選項,才能讓這個功能正常運作。",
|
||||||
|
"dd_wa_hdr_toggle_delay_desc_1": "使用虛擬顯示裝置 (VDD) 進行串流時,可能會不正確顯示 HDR 顏色。陽光可以嘗試關閉 HDR,然後再開啟,以減少此問題。",
|
||||||
|
"dd_wa_hdr_toggle_delay_desc_2": "如果該值設為 0,則會停用變通(預設)。如果值介於 0 和 3000 毫秒之間,Sunshine 會關閉 HDR,等待指定的時間,然後再開啟 HDR。在大多數情況下,建議的延遲時間約為 500 毫秒。",
|
||||||
|
"dd_wa_hdr_toggle_delay_desc_3": "除非您真的有 HDR 問題,否則請勿使用此變通技術,因為它會直接影響串流的啟動時間!",
|
||||||
|
"dd_wa_hdr_toggle_delay": "HDR 的高對比度解決方案",
|
||||||
|
"ds4_back_as_touchpad_click": "地圖 Back/Select 至觸控板點選",
|
||||||
|
"ds4_back_as_touchpad_click_desc": "當強制啟用 DS4 模擬時,將返回/選擇按鈕映射為觸控板點擊",
|
||||||
|
"encoder": "強制指定編碼器",
|
||||||
|
"encoder_desc": "強制指定特定的編碼器,否則 Sunshine 將選擇最佳的可用選項。注意:如果您在 Windows 上指定硬體編碼器,則必須與顯示器連接的 GPU 符合。",
|
||||||
|
"encoder_software": "軟體",
|
||||||
|
"external_ip": "外部 IP",
|
||||||
|
"external_ip_desc": "如果未提供外部 IP 位址,Sunshine 會自動偵測外部 IP 位址。",
|
||||||
|
"fec_percentage": "FEC 比例",
|
||||||
|
"fec_percentage_desc": "每個視訊影格中每個資料封包的錯誤修正封包百分比。較高的值可以修正更多的網路封包遺失,但代價是增加頻寬使用量。",
|
||||||
|
"ffmpeg_auto": "auto—由 ffmpeg 決定(預設)",
|
||||||
|
"file_apps": "應用程式檔案",
|
||||||
|
"file_apps_desc": "Sunshine 目前的應用程式所儲存的檔案。",
|
||||||
|
"file_state": "狀態檔案",
|
||||||
|
"file_state_desc": "儲存目前 Sunshine 狀態的檔案",
|
||||||
|
"gamepad": "模擬遊戲手把類型",
|
||||||
|
"gamepad_auto": "自動選擇選項",
|
||||||
|
"gamepad_desc": "選擇要在主機上模擬的遊戲手把類型",
|
||||||
|
"gamepad_ds4": "DS4 (PS4)",
|
||||||
|
"gamepad_ds4_manual": "DS4 選擇選項",
|
||||||
|
"gamepad_ds5": "DS5 (PS5)",
|
||||||
|
"gamepad_switch": "Nintendo Pro (Switch)",
|
||||||
|
"gamepad_manual": "手動 DS4 選項",
|
||||||
|
"gamepad_x360": "X360 (Xbox 360)",
|
||||||
|
"gamepad_xone": "XOne (Xbox One)",
|
||||||
|
"global_prep_cmd": "指令準備",
|
||||||
|
"global_prep_cmd_desc": "設定在執行任何應用程式之前或之後執行的指令清單。如果任何指定的準備指令失敗,應用程式的啟動程序將會中止。",
|
||||||
|
"hevc_mode": "HEVC 支援",
|
||||||
|
"hevc_mode_0": "Sunshine 將根據編碼器的能力宣告是否支援 HEVC(建議)",
|
||||||
|
"hevc_mode_1": "Sunshine 不會宣告支援 HEVC",
|
||||||
|
"hevc_mode_2": "Sunshine 將宣告支援 HEVC Main 設定檔",
|
||||||
|
"hevc_mode_3": "Sunshine 會宣告支援 HEVC Main 和 Main10 (HDR) 設定檔",
|
||||||
|
"hevc_mode_desc": "允許用戶端要求 HEVC Main 或 HEVC Main10 視訊串流。HEVC 的編碼較耗費 CPU,因此使用軟體編碼時,啟用此功能可能會降低效能。",
|
||||||
|
"high_resolution_scrolling": "支援高解析度捲動",
|
||||||
|
"high_resolution_scrolling_desc": "啟用後,Sunshine 會傳遞來自 Moonlight 用戶端的高解析度捲動事件。對於某些在高解析度捲動時捲動速度過快的舊應用程式,建議將此選項停用。",
|
||||||
|
"install_steam_audio_drivers": "安裝 Steam 音訊驅動程式",
|
||||||
|
"install_steam_audio_drivers_desc": "如果已安裝 Steam,這將會自動安裝 Steam Streaming Speakers 驅動程式,以支援 5.1/7.1 環繞音效和主機音訊靜音。",
|
||||||
|
"key_repeat_delay": "按鍵重複延遲",
|
||||||
|
"key_repeat_delay_desc": "控制按鍵重複的速度。設定按鍵重複前的初始延遲時間,以毫秒為單位。",
|
||||||
|
"key_repeat_frequency": "按鍵重複頻率",
|
||||||
|
"key_repeat_frequency_desc": "每秒按鍵重複的頻率。此選項支援小數點。",
|
||||||
|
"key_rightalt_to_key_win": "將右 Alt 鍵映射為 Windows 鍵",
|
||||||
|
"key_rightalt_to_key_win_desc": "Moonlight 可能無法直接發送 Windows 鍵。在這種情況下,讓 Sunshine 認為右 Alt 鍵是 Windows 鍵可能會很有用",
|
||||||
|
"keyboard": "啟用鍵盤輸入",
|
||||||
|
"keyboard_desc": "允許訪客使用鍵盤控制主機系統",
|
||||||
|
"lan_encryption_mode": "區域網路加密模式",
|
||||||
|
"lan_encryption_mode_1": "當用戶端支援時啟用",
|
||||||
|
"lan_encryption_mode_2": "所有用戶端都需要",
|
||||||
|
"lan_encryption_mode_desc": "這會決定在本地網路上進行串流時何時使用加密。加密可能會降低串流效能,特別是在較不強大的主機和客戶端上。",
|
||||||
|
"locale": "語系",
|
||||||
|
"locale_desc": "Sunshine 使用的使用者介面語言設定。",
|
||||||
|
"log_level": "日誌層級",
|
||||||
|
"log_level_0": "詳細",
|
||||||
|
"log_level_1": "除錯",
|
||||||
|
"log_level_2": "資訊",
|
||||||
|
"log_level_3": "警告",
|
||||||
|
"log_level_4": "錯誤",
|
||||||
|
"log_level_5": "嚴重錯誤",
|
||||||
|
"log_level_6": "無",
|
||||||
|
"log_level_desc": "列印到標準輸出的最小日誌層級",
|
||||||
|
"log_path": "記錄檔路徑",
|
||||||
|
"log_path_desc": "儲存目前 Sunshine 記錄的檔案。",
|
||||||
|
"max_bitrate": "最大位元率",
|
||||||
|
"max_bitrate_desc": "Sunshine 會以最大位元率(單位為 Kbps)來編碼串流。如果設為0,則會使用Moonlight所要求的位元率。",
|
||||||
|
"min_threads": "最低 CPU 線程數",
|
||||||
|
"min_threads_desc": "增加該值會稍微降低編碼效率,但為了能使用更多 CPU 核心進行編碼,這樣的折衷通常是值得的。理想的值是在您的硬體上,能以您所需的串流設定進行可靠編碼的最低值。",
|
||||||
|
"misc": "其他選項",
|
||||||
|
"motion_as_ds4": "如果客戶端的遊戲手把報告有運動感應器,則會模擬 DS4 遊戲手把",
|
||||||
|
"motion_as_ds4_desc": "如果禁用,則在選擇遊戲手把類型時不會考慮運動感應器的存在。",
|
||||||
|
"mouse": "啟用滑鼠輸入",
|
||||||
|
"mouse_desc": "允許訪客使用滑鼠控制主機系統",
|
||||||
|
"native_pen_touch": "原生筆/觸控支援",
|
||||||
|
"native_pen_touch_desc": "啟用後,Sunshine 將從 Moonlight 用戶端傳遞本機筆觸事件。對於沒有原生筆/觸控支援的舊版應用程式來說,停用此功能可能很有用。",
|
||||||
|
"notify_pre_releases": "發佈前通知",
|
||||||
|
"notify_pre_releases_desc": "是否接收 Sunshine 的新預發佈版本通知",
|
||||||
|
"nvenc_h264_cavlc": "在 H.264 中選擇 CAVLC 而非 CABAC",
|
||||||
|
"nvenc_h264_cavlc_desc": "較簡單的熵編碼形式。CAVLC需要約多10%的位元率才能達到相同的畫質。這僅對非常舊的解碼裝置有影響。",
|
||||||
|
"nvenc_latency_over_power": "相較於省電,更傾向於較低的編碼延遲",
|
||||||
|
"nvenc_latency_over_power_desc": "Sunshine會在進行串流時請求最大 GPU 時脈速度,以減少編碼延遲。建議不要停用此選項,因為這樣可能會顯著增加編碼延遲。",
|
||||||
|
"nvenc_opengl_vulkan_on_dxgi": "在 DXGI 之上呈現 OpenGL/Vulkan",
|
||||||
|
"nvenc_opengl_vulkan_on_dxgi_desc": "Sunshine 無法以完整幀率捕捉全螢幕的 OpenGL 和 Vulkan 程式,除非它們顯示在 DXGI 之上。這是系統範圍的設定,會在Sunshine程式退出時還原。",
|
||||||
|
"nvenc_preset": "性能預設參數",
|
||||||
|
"nvenc_preset_1": "(最快,預設值)",
|
||||||
|
"nvenc_preset_7": "(最慢)",
|
||||||
|
"nvenc_preset_desc": "數值越高,在增加編碼延遲的情況下,可提高壓縮率(在指定位元率下的品質)。建議僅在受限於網路或解碼器時才進行調整,否則可以透過增加位元率來達成類似的效果。",
|
||||||
|
"nvenc_realtime_hags": "在硬體加速 GPU 排程中使用即時優先順序",
|
||||||
|
"nvenc_realtime_hags_desc": "目前NVIDIA 驅動程式在啟用 HAGS、使用即時優先權且 VRAM 使用率接近最大值時,可能會在編碼器中凍結。停用此選項會將優先權降低至高,藉此避開凍結,但在 GPU 重度負載時擷取效能會降低。",
|
||||||
|
"nvenc_spatial_aq": "Spatial AQ",
|
||||||
|
"nvenc_spatial_aq_desc": "為視訊的平坦區域指定較高的 QP 值。建議在以較低位元率串流時啟用。",
|
||||||
|
"nvenc_twopass": "兩次編碼模式",
|
||||||
|
"nvenc_twopass_desc": "新增初步編碼過程,能夠檢測更多的運動向量,將位元率更均勻地分佈於畫面,並更精確地遵守位元率限制。建議不要停用這個功能,因為停用後可能會偶爾出現位元率超過限制,並導致資料包丟失。",
|
||||||
|
"nvenc_twopass_disabled": "停用(最快,不建議使用)",
|
||||||
|
"nvenc_twopass_full_res": "全解析度(較慢)",
|
||||||
|
"nvenc_twopass_quarter_res": "四分之一解析度(更快,預設值)",
|
||||||
|
"nvenc_vbv_increase": "單幅 VBV/HRD 百分比增加",
|
||||||
|
"nvenc_vbv_increase_desc": "預設 sunshine 使用單幀 VBV/HRD,這表示任何編碼視訊幀大小都不會超過要求的位元率除以要求的幀速率。放寬此限制可能有益並可作為低延遲的可變位元率,但如果網路沒有緩衝空間處理比特率峰值,也可能導致封包遺失。可接受的最大值是 400,相當於 5 倍增加的編碼視訊畫格上限。",
|
||||||
|
"origin_web_ui_allowed": "允許使用 Origin 網頁 UI",
|
||||||
|
"origin_web_ui_allowed_desc": "用於網頁 UI 和 Moonlight 用戶端配對的憑證。為了確保最佳相容性,建議使用 RSA-2048 公開金鑰。",
|
||||||
|
"origin_web_ui_allowed_lan": "只有區域網路中的人可以存取網頁 UI",
|
||||||
|
"origin_web_ui_allowed_pc": "只有 localhost 可以存取網頁 UI",
|
||||||
|
"origin_web_ui_allowed_wan": "任何人都可以存取網頁 UI",
|
||||||
|
"output_name_desc_unix": "在 Sunshine 啟動時,您應該會看到檢測到的顯示器清單。請注意:需要使用括弧內的 ID 值。以下是範例,實際輸出可以在「故障排除」分頁中找到。",
|
||||||
|
"output_name_desc_windows": "手動指定要用於擷取的顯示器設備 ID。如果未設定,則擷取主要顯示器。注意:如果您在上方指定了 GPU,則此顯示器必須連接到該 GPU。在 Sunshine 啟動時,您應該會看到檢測到的顯示器清單。以下是範例,實際輸出可以在「故障排除」分頁中找到。",
|
||||||
|
"output_name_unix": "顯示號碼",
|
||||||
|
"output_name_windows": "顯示裝置 ID",
|
||||||
|
"ping_timeout": "Ping 逾時",
|
||||||
|
"ping_timeout_desc": "在關閉串流前,等待來自 Moonlight 的資料,以毫秒為單位",
|
||||||
|
"pkey": "私人密碼匙",
|
||||||
|
"pkey_desc": "用於網頁 UI 和 Moonlight 客戶端配對的私鑰。為了確保最佳相容性,建議使用 RSA-2048 私鑰。",
|
||||||
|
"port": "連接埠",
|
||||||
|
"port_alert_1": "Sunshine 不能使用低於 1024 的連接埠!",
|
||||||
|
"port_alert_2": "65535 以上的連接埠無法使用!",
|
||||||
|
"port_desc": "設定 Sunshine 使用的連接埠系列",
|
||||||
|
"port_http_port_note": "使用此連接埠與 Moonlight 連線。",
|
||||||
|
"port_note": "注意事項",
|
||||||
|
"port_port": "連接埠",
|
||||||
|
"port_protocol": "通訊協定",
|
||||||
|
"port_tcp": "TCP",
|
||||||
|
"port_udp": "UDP",
|
||||||
|
"port_warning": "將網頁 UI 暴露於網際網路存在安全風險!請自行承擔風險!",
|
||||||
|
"port_web_ui": "網頁 UI",
|
||||||
|
"qp": "量化參數",
|
||||||
|
"qp_desc": "某些裝置可能不支援 Constant Bit Rate。對於這些裝置,會使用 QP 來取代。值越高表示壓縮越多,但品質越低。",
|
||||||
|
"qsv_coder": "QuickSync 編碼器(H264)",
|
||||||
|
"qsv_preset": "QuickSync 預設值",
|
||||||
|
"qsv_preset_fast": "快(低畫質)",
|
||||||
|
"qsv_preset_faster": "更快(品質較低)",
|
||||||
|
"qsv_preset_medium": "中(預設值)",
|
||||||
|
"qsv_preset_slow": "慢(高畫質)",
|
||||||
|
"qsv_preset_slower": "速度較慢(品質較佳)",
|
||||||
|
"qsv_preset_slowest": "最慢(最高畫質)",
|
||||||
|
"qsv_preset_veryfast": "最快(最低畫質)",
|
||||||
|
"qsv_slow_hevc": "允許慢速 HEVC 編碼",
|
||||||
|
"qsv_slow_hevc_desc": "這樣可以在較舊的 Intel GPU 上進行 HEVC 編碼,但代價是 GPU 使用量較高,效能較差。",
|
||||||
|
"restart_note": "Sunshine 正在重新啟動以套用變更。",
|
||||||
|
"stream_audio": "串流音訊",
|
||||||
|
"stream_audio_desc": "是否串流音訊。停用此功能對於串流無頭顯示器作為第二台顯示器很有用。",
|
||||||
|
"sunshine_name": "Sunshine 名稱",
|
||||||
|
"sunshine_name_desc": "Moonlight 顯示的名稱。如果未指定,則使用 PC 的主機名稱。",
|
||||||
|
"sw_preset": "SW 預設值",
|
||||||
|
"sw_preset_desc": "最佳化編碼速度(每秒編碼幀數)與壓縮效率(位元流中每位元的品質)之間的權衡。預設為 superfast。",
|
||||||
|
"sw_preset_fast": "快速",
|
||||||
|
"sw_preset_faster": "更快",
|
||||||
|
"sw_preset_medium": "中等",
|
||||||
|
"sw_preset_slow": "慢速",
|
||||||
|
"sw_preset_slower": "更慢",
|
||||||
|
"sw_preset_superfast": "超快(預設)",
|
||||||
|
"sw_preset_ultrafast": "超快",
|
||||||
|
"sw_preset_veryfast": "非常快",
|
||||||
|
"sw_preset_veryslow": "非常慢速",
|
||||||
|
"sw_tune": "SW 調音",
|
||||||
|
"sw_tune_animation": "animation—適用於卡通,使用較多的去區塊效應處理和更多的參考影格。",
|
||||||
|
"sw_tune_desc": "調整選項,在預設值之後套用。預設為 zerolatency。",
|
||||||
|
"sw_tune_fastdecode": "fastdecode—藉由停用某些過濾器來加快解碼速度",
|
||||||
|
"sw_tune_film": "film—適用於高品質的電影內容,降低去區塊效應處理。",
|
||||||
|
"sw_tune_grain": "grain—保留老電影畫面的顆粒結構",
|
||||||
|
"sw_tune_stillimage": "stillimage—適用於類似投影片的內容。",
|
||||||
|
"sw_tune_zerolatency": "zerolatency—適合快速編碼和低延遲串流(預設值)",
|
||||||
|
"touchpad_as_ds4": "當用戶端的遊戲手把報告存在觸控板時,模擬 DS4 遊戲手把",
|
||||||
|
"touchpad_as_ds4_desc": "若停用,選擇遊戲手把類型時將不會考慮觸控板的存在。",
|
||||||
|
"upnp": "UPnP",
|
||||||
|
"upnp_desc": "自動設定透過網際網路串流的連接埠轉發",
|
||||||
|
"vaapi_strict_rc_buffer": "在 AMD GPU 上嚴格執行 H.264/HEVC 的幀位元率限制",
|
||||||
|
"vaapi_strict_rc_buffer_desc": "啟用此選項可以避免場景變換時在網路上發生畫面掉幀,但可能會降低畫面移動時的影像品質。",
|
||||||
|
"virtual_sink": "虛擬音訊輸出",
|
||||||
|
"virtual_sink_desc": "手動指定要使用的虛擬音訊裝置。如果未設定,則會自動選擇裝置。我們強烈建議將此欄位留空,以使用自動裝置選擇!",
|
||||||
|
"virtual_sink_placeholder": "Steam 串流喇叭",
|
||||||
|
"vt_coder": "VideoToolbox 編碼器",
|
||||||
|
"vt_realtime": "VideoToolbox 即時編碼",
|
||||||
|
"vt_software": "VideoToolbox 軟體編碼",
|
||||||
|
"vt_software_allowed": "允許",
|
||||||
|
"vt_software_forced": "強制",
|
||||||
|
"wan_encryption_mode": "WAN 加密模式",
|
||||||
|
"wan_encryption_mode_1": "對支援的用戶端啟用(預設)",
|
||||||
|
"wan_encryption_mode_2": "所有客戶都需要",
|
||||||
|
"wan_encryption_mode_desc": "這會決定在網際網路上串流時,何時會使用加密。加密可能會降低串流效能,尤其是在效能較低的主機和用戶端上。"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"description": "Sunshine 是 Moonlight 的自架遊戲串流主機。",
|
||||||
|
"download": "下載",
|
||||||
|
"installed_version_not_stable": "您正在運行的是 Sunshine 的預發行版本。您可能會遇到錯誤或其他問題。請報告您遇到的任何問題。感謝您的協助,讓 Sunshine 成為更好的軟體!",
|
||||||
|
"loading_latest": "正在載入最新版本…",
|
||||||
|
"new_pre_release": "提供新的預發行版本!",
|
||||||
|
"new_stable": "有新的穩定版本可用!",
|
||||||
|
"startup_errors": "<b>注意!</b> Sunshine 在啟動時檢測到這些錯誤。我們<b>強烈建議</b>在開始串流之前修復它們。",
|
||||||
|
"version_dirty": "感謝您的協助,讓 Sunshine 成為更好的軟體!",
|
||||||
|
"version_latest": "您正在執行最新版本的 Sunshine",
|
||||||
|
"welcome": "你好,Sunshine!"
|
||||||
|
},
|
||||||
|
"navbar": {
|
||||||
|
"applications": "應用程式",
|
||||||
|
"configuration": "組態",
|
||||||
|
"home": "首頁",
|
||||||
|
"password": "變更密碼",
|
||||||
|
"pin": "Pin 碼",
|
||||||
|
"theme_auto": "自動",
|
||||||
|
"theme_dark": "深色主題",
|
||||||
|
"theme_light": "淺色主題",
|
||||||
|
"toggle_theme": "主題",
|
||||||
|
"troubleshoot": "疑難排解"
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"confirm_password": "確認密碼",
|
||||||
|
"current_creds": "目前的憑證",
|
||||||
|
"new_creds": "新憑證",
|
||||||
|
"new_username_desc": "如果未指定,使用者名稱不會變更",
|
||||||
|
"password_change": "密碼變更",
|
||||||
|
"success_msg": "密碼已成功變更!此頁面將很快重新載入,您的瀏覽器將要求輸入新的憑證。"
|
||||||
|
},
|
||||||
|
"pin": {
|
||||||
|
"device_name": "裝置名稱",
|
||||||
|
"pair_failure": "配對失敗:請確認 PIN 碼是否輸入正確",
|
||||||
|
"pair_success": "成功!請檢查 Moonlight 來繼續",
|
||||||
|
"pin_pairing": "PIN 碼配對",
|
||||||
|
"send": "發送",
|
||||||
|
"warning_msg": "請確保您可以存取要配對的用戶端。此軟體可讓對方完全控制您的電腦,請小心使用!"
|
||||||
|
},
|
||||||
|
"resource_card": {
|
||||||
|
"github_discussions": "GitHub 討論區",
|
||||||
|
"legal": "法律資訊",
|
||||||
|
"legal_desc": "繼續使用本軟體即表示您同意下列文件中的條款和條件。",
|
||||||
|
"license": "許可證",
|
||||||
|
"lizardbyte_website": "LizardByte 網站",
|
||||||
|
"resources": "資源",
|
||||||
|
"resources_desc": "Sunshine 相關資源!",
|
||||||
|
"third_party_notice": "第三方通知"
|
||||||
|
},
|
||||||
|
"troubleshooting": {
|
||||||
|
"dd_reset": "重置為既存的顯示裝置設定",
|
||||||
|
"dd_reset_desc": "如果 Sunshine 在嘗試恢復更改過的顯示裝置設定時卡住,您可以重置設定並手動恢復顯示狀態。",
|
||||||
|
"dd_reset_error": "重置為既存設定時發生錯誤!",
|
||||||
|
"dd_reset_success": "成功重置為既存設定!",
|
||||||
|
"force_close": "強制關閉",
|
||||||
|
"force_close_desc": "如果 Moonlight 抱怨目前的應用程式已經在執行,強制關閉該應用程式應該可以解決問題。",
|
||||||
|
"force_close_error": "關閉應用程式時發生錯誤",
|
||||||
|
"force_close_success": "應用程式已成功結束!",
|
||||||
|
"logs": "日誌",
|
||||||
|
"logs_desc": "查看 Sunshine 上傳的日誌",
|
||||||
|
"logs_find": "尋找…",
|
||||||
|
"restart_sunshine": "重新啟動 Sunshine",
|
||||||
|
"restart_sunshine_desc": "如果 Sunshine 沒有正常運作,您可以嘗試重新啟動。這會終止所有正在執行的工作階段。",
|
||||||
|
"restart_sunshine_success": "Sunshine 正在重新啟動",
|
||||||
|
"troubleshooting": "疑難排解",
|
||||||
|
"unpair_all": "全部解除配對",
|
||||||
|
"unpair_all_error": "解除配對時發生錯誤",
|
||||||
|
"unpair_all_success": "已取消配對所有裝置。",
|
||||||
|
"unpair_desc": "刪除已配對的裝置。未配對的裝置若有使用中的工作階段,將保持連線,但無法啟動或恢復工作階段。",
|
||||||
|
"unpair_single_no_devices": "沒有已配對的裝置。",
|
||||||
|
"unpair_single_success": "然而,該裝置仍可能處於使用中的工作階段。請使用上方的「強制關閉」按鈕結束任何使用中的工作階段。",
|
||||||
|
"unpair_single_unknown": "未知的用戶端",
|
||||||
|
"unpair_title": "解除配對裝置"
|
||||||
|
},
|
||||||
|
"welcome": {
|
||||||
|
"confirm_password": "確認密碼",
|
||||||
|
"create_creds": "在開始之前,我們需要您建立新的使用者名稱和密碼,以便存取網頁 UI。",
|
||||||
|
"create_creds_alert": "以下的憑證是存取 Sunshine 網頁介面所需的。請妥善保管,因為您將無法再查看這些憑證!",
|
||||||
|
"greeting": "歡迎來到 Sunshine!",
|
||||||
|
"login": "登入",
|
||||||
|
"welcome_success": "此頁面將很快重新載入,您的瀏覽器會要求您提供新的憑證"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -182,7 +182,9 @@
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
refreshLogs() {
|
refreshLogs() {
|
||||||
fetch("./api/logs", { credentials: 'include' })
|
fetch("./api/logs", {
|
||||||
|
credentials: 'include'
|
||||||
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
// Retrieve the Content-Type header
|
// Retrieve the Content-Type header
|
||||||
const contentType = response.headers.get("Content-Type") || "";
|
const contentType = response.headers.get("Content-Type") || "";
|
||||||
@@ -205,7 +207,10 @@
|
|||||||
this.closeAppPressed = true;
|
this.closeAppPressed = true;
|
||||||
fetch("./api/apps/close", {
|
fetch("./api/apps/close", {
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
method: 'POST'
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.then((r) => r.json())
|
.then((r) => r.json())
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
@@ -227,6 +232,9 @@
|
|||||||
fetch("./api/restart", {
|
fetch("./api/restart", {
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
if (resp.status !== 200) {
|
if (resp.status !== 200) {
|
||||||
@@ -251,6 +259,9 @@
|
|||||||
fetch("./api/quit", {
|
fetch("./api/quit", {
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.serverQuitting = false;
|
this.serverQuitting = false;
|
||||||
@@ -267,7 +278,10 @@
|
|||||||
this.ddResetPressed = true;
|
this.ddResetPressed = true;
|
||||||
fetch("/api/reset-display-device-persistence", {
|
fetch("/api/reset-display-device-persistence", {
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
method: 'POST'
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.then((r) => r.json())
|
.then((r) => r.json())
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<div class="card p-2">
|
<div class="card p-2">
|
||||||
<header>
|
<header>
|
||||||
<h1 class="mb-0">
|
<h1 class="mb-0">
|
||||||
<img src="./images/logo-apollo-45.png" height="45" alt="">
|
<img src="./images/logo-sunshine-45.png" height="45" alt="">
|
||||||
{{ $t('welcome.greeting') }}
|
{{ $t('welcome.greeting') }}
|
||||||
</h1>
|
</h1>
|
||||||
</header>
|
</header>
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
success: false,
|
success: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
passwordData: {
|
passwordData: {
|
||||||
newUsername: "apollo",
|
newUsername: "sunshine",
|
||||||
newPassword: "",
|
newPassword: "",
|
||||||
confirmNewPassword: "",
|
confirmNewPassword: "",
|
||||||
},
|
},
|
||||||
@@ -74,17 +74,13 @@
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
save() {
|
save() {
|
||||||
if (this.passwordData.newPassword !== this.passwordData.confirmNewPassword) {
|
|
||||||
this.error = "Password mismatch";
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
this.error = null;
|
this.error = null;
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
fetch("./api/password", {
|
fetch("./api/password", {
|
||||||
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(this.passwordData),
|
body: JSON.stringify(this.passwordData),
|
||||||
}).then((r) => {
|
}).then((r) => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
|||||||
2
third-party/TPCircularBuffer
vendored
2
third-party/TPCircularBuffer
vendored
Submodule third-party/TPCircularBuffer updated: 8833b3a73f...cc52039750
2
third-party/build-deps
vendored
2
third-party/build-deps
vendored
Submodule third-party/build-deps updated: d60197e154...a9a7f86328
2
third-party/doxyconfig
vendored
2
third-party/doxyconfig
vendored
Submodule third-party/doxyconfig updated: 4501c7b191...a73f908fb7
2
third-party/googletest
vendored
2
third-party/googletest
vendored
Submodule third-party/googletest updated: 04ee1b4f2a...52eb8108c5
2
third-party/inputtino
vendored
2
third-party/inputtino
vendored
Submodule third-party/inputtino updated: 17a9b9ce85...83cf70ef33
2
third-party/libdisplaydevice
vendored
2
third-party/libdisplaydevice
vendored
Submodule third-party/libdisplaydevice updated: 13a4aca3c2...a0674741ec
2
third-party/moonlight-common-c
vendored
2
third-party/moonlight-common-c
vendored
Submodule third-party/moonlight-common-c updated: 40a4e68787...ad329b240f
2
third-party/tray
vendored
2
third-party/tray
vendored
Submodule third-party/tray updated: d45306e686...db96aeab04
2
third-party/wayland-protocols
vendored
2
third-party/wayland-protocols
vendored
Submodule third-party/wayland-protocols updated: 810f1adaf3...0091197f5c
2
third-party/wlr-protocols
vendored
2
third-party/wlr-protocols
vendored
Submodule third-party/wlr-protocols updated: 2ec67ebd26...a5028afbe4
@@ -15,6 +15,7 @@ target_compile_options(dxgi-info PRIVATE ${SUNSHINE_COMPILE_OPTIONS})
|
|||||||
add_executable(audio-info audio.cpp utils.cpp)
|
add_executable(audio-info audio.cpp utils.cpp)
|
||||||
set_target_properties(audio-info PROPERTIES CXX_STANDARD 20)
|
set_target_properties(audio-info PROPERTIES CXX_STANDARD 20)
|
||||||
target_link_libraries(audio-info
|
target_link_libraries(audio-info
|
||||||
|
${Boost_LIBRARIES}
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
ksuser
|
ksuser
|
||||||
${PLATFORM_LIBRARIES})
|
${PLATFORM_LIBRARIES})
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "src/utility.h"
|
#include "src/utility.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
// platform includes
|
||||||
#include <audioclient.h>
|
#include <audioclient.h>
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -14,7 +15,6 @@
|
|||||||
#include <roapi.h>
|
#include <roapi.h>
|
||||||
#include <synchapi.h>
|
#include <synchapi.h>
|
||||||
|
|
||||||
#include <io.h>
|
|
||||||
|
|
||||||
DEFINE_PROPERTYKEY(PKEY_Device_DeviceDesc, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 2); // DEVPROP_TYPE_STRING
|
DEFINE_PROPERTYKEY(PKEY_Device_DeviceDesc, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 2); // DEVPROP_TYPE_STRING
|
||||||
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14); // DEVPROP_TYPE_STRING
|
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14); // DEVPROP_TYPE_STRING
|
||||||
|
|||||||
Reference in New Issue
Block a user