mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-08-10 00:52:16 +00:00
Compare commits
70 Commits
ci/homebre
...
feat/insta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07c0044df3 | ||
|
|
7e95d536a9 | ||
|
|
2259141bd2 | ||
|
|
5ef3f2ff5c | ||
|
|
9f399eef5c | ||
|
|
6f78404c18 | ||
|
|
5a40190830 | ||
|
|
d3ef63bd9b | ||
|
|
c0e029117d | ||
|
|
5b1da1c1ab | ||
|
|
65f14e1003 | ||
|
|
27f71c3895 | ||
|
|
2f27a57d01 | ||
|
|
738ac93a0e | ||
|
|
d6820ba019 | ||
|
|
4cdb5cd452 | ||
|
|
ced363833c | ||
|
|
f62299d018 | ||
|
|
6203e8118a | ||
|
|
63229ac28b | ||
|
|
543e239f83 | ||
|
|
373df9d7f7 | ||
|
|
684530af1f | ||
|
|
597bccef92 | ||
|
|
986aa176ee | ||
|
|
926cafa6a9 | ||
|
|
fb51c2c649 | ||
|
|
8e061c44c5 | ||
|
|
b48e6303ea | ||
|
|
958d783d94 | ||
|
|
6c2efced6d | ||
|
|
919f54495b | ||
|
|
64e6c48577 | ||
|
|
9db11a9061 | ||
|
|
1e082ab790 | ||
|
|
a212a542a0 | ||
|
|
7017b8e88c | ||
|
|
c9a06fd8a7 | ||
|
|
b2d44f5ba9 | ||
|
|
e7a8f3b3ce | ||
|
|
9248231510 | ||
|
|
0ad1b1234e | ||
|
|
8afb672bb8 | ||
|
|
7291fa5f12 | ||
|
|
878437362e | ||
|
|
1984d822be | ||
|
|
e40b7cb731 | ||
|
|
0a98094613 | ||
|
|
eaa434ab45 | ||
|
|
a80ec75465 | ||
|
|
1938385bf0 | ||
|
|
0de8cc864c | ||
|
|
a857c8b715 | ||
|
|
eeef57b168 | ||
|
|
356545fa7d | ||
|
|
883eff5d24 | ||
|
|
673e0fa4f4 | ||
|
|
3ad90cd7f1 | ||
|
|
ef5253a61d | ||
|
|
0bdc9188c3 | ||
|
|
ae1ee8fb45 | ||
|
|
5e049e3c61 | ||
|
|
9effeba5fe | ||
|
|
3092471be5 | ||
|
|
9c08c75a44 | ||
|
|
8ca976f2d0 | ||
|
|
2ca2ea435f | ||
|
|
7b873e9ea4 | ||
|
|
8f6cd37a62 | ||
|
|
1a5f5e59de |
@@ -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
|
||||
max-line-length = 120
|
||||
extend-exclude =
|
||||
.venv/
|
||||
venv/
|
||||
|
||||
49
.github/label-actions.yml
vendored
49
.github/label-actions.yml
vendored
@@ -1,49 +0,0 @@
|
||||
---
|
||||
# This file is centrally managed in https://github.com/<organization>/.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.
|
||||
|
||||
# Configuration for Label Actions - https://github.com/dessant/label-actions
|
||||
|
||||
added:
|
||||
comment: >
|
||||
This feature has been added and will be available in the next release.
|
||||
fixed:
|
||||
comment: >
|
||||
This issue has been fixed and will be available in the next release.
|
||||
invalid:duplicate:
|
||||
comment: >
|
||||
:wave: @{issue-author}, this appears to be a duplicate of a pre-existing issue.
|
||||
close: true
|
||||
lock: true
|
||||
unlabel: 'status:awaiting-triage'
|
||||
|
||||
-invalid:duplicate:
|
||||
reopen: true
|
||||
unlock: true
|
||||
|
||||
invalid:support:
|
||||
comment: >
|
||||
:wave: @{issue-author}, we use the issue tracker exclusively for bug reports.
|
||||
However, this issue appears to be a support request. Please use our
|
||||
[Support Center](https://app.lizardbyte.dev/support) for support issues. Thanks.
|
||||
close: true
|
||||
lock: true
|
||||
lock-reason: 'off-topic'
|
||||
unlabel: 'status:awaiting-triage'
|
||||
|
||||
-invalid:support:
|
||||
reopen: true
|
||||
unlock: true
|
||||
|
||||
invalid:template-incomplete:
|
||||
issues:
|
||||
comment: >
|
||||
:wave: @{issue-author}, please edit your issue to complete the template with
|
||||
all the required info. Your issue will be automatically closed in 5 days if
|
||||
the template is not completed. Thanks.
|
||||
prs:
|
||||
comment: >
|
||||
:wave: @{issue-author}, please edit your PR to complete the template with
|
||||
all the required info. Your PR will be automatically closed in 5 days if
|
||||
the template is not completed. Thanks.
|
||||
1
.github/semantic.yml
vendored
1
.github/semantic.yml
vendored
@@ -12,3 +12,4 @@ titleAndCommits: false
|
||||
anyCommit: false
|
||||
allowMergeCommits: false
|
||||
allowRevertCommits: false
|
||||
targetUrl: https://docs.lizardbyte.dev/latest/developers/contributing.html#creating-a-pull-request
|
||||
|
||||
1060
.github/workflows/CI.yml
vendored
1060
.github/workflows/CI.yml
vendored
File diff suppressed because it is too large
Load Diff
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 }}
|
||||
@@ -1,10 +1,8 @@
|
||||
---
|
||||
# This workflow is centrally managed in https://github.com/<organization>/.github/
|
||||
# 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.
|
||||
|
||||
# Update changelog on release events.
|
||||
|
||||
name: Update changelog
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -24,14 +22,10 @@ concurrency:
|
||||
jobs:
|
||||
update-changelog:
|
||||
name: Update Changelog
|
||||
uses: LizardByte/.github/.github/workflows/__call-update-changelog.yml@master
|
||||
if: >-
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(!github.event.release.prerelease && !github.event.release.draft)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update Changelog
|
||||
uses: LizardByte/update-changelog-action@v2024.919.152649
|
||||
with:
|
||||
changelogBranch: changelog
|
||||
changelogFile: CHANGELOG.md
|
||||
token: ${{ secrets.GH_BOT_TOKEN }}
|
||||
github.repository_owner == 'LizardByte' &&
|
||||
(github.event_name == 'workflow_dispatch' ||
|
||||
(!github.event.release.prerelease && !github.event.release.draft))
|
||||
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 }}
|
||||
19
.github/workflows/ci-copr.yml
vendored
19
.github/workflows/ci-copr.yml
vendored
@@ -1,23 +1,24 @@
|
||||
---
|
||||
name: CI Copr
|
||||
name: CI-Copr
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
release:
|
||||
types:
|
||||
- prereleased
|
||||
- released
|
||||
workflow_call:
|
||||
secrets:
|
||||
COPR_BETA_WEBHOOK_TOKEN:
|
||||
required: false
|
||||
COPR_STABLE_WEBHOOK_TOKEN:
|
||||
required: false
|
||||
COPR_CLI_CONFIG:
|
||||
required: false
|
||||
|
||||
concurrency:
|
||||
group: "${{ github.workflow }}-${{ github.ref }}"
|
||||
group: "_${{ github.workflow }}-${{ github.ref }}"
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
|
||||
380
.github/workflows/ci-docker.yml
vendored
380
.github/workflows/ci-docker.yml
vendored
@@ -1,380 +0,0 @@
|
||||
---
|
||||
# This workflow is centrally managed in https://github.com/<organization>/.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.
|
||||
|
||||
# This workflow is intended to work with all our organization Docker projects. A readme named `DOCKER_README.md`
|
||||
# will be used to update the description on Docker hub.
|
||||
|
||||
# custom comments in dockerfiles:
|
||||
|
||||
# `# platforms: `
|
||||
# Comma separated list of platforms, i.e. `# platforms: linux/386,linux/amd64`. Docker platforms can alternatively
|
||||
# be listed in a file named `.docker_platforms`.
|
||||
# `# platforms_pr: `
|
||||
# Comma separated list of platforms to run for PR events, i.e. `# platforms_pr: linux/amd64`. This will take
|
||||
# precedence over the `# platforms: ` directive.
|
||||
# `# artifacts: `
|
||||
# `true` to build in two steps, stopping at `artifacts` build stage and extracting the image from there to the
|
||||
# GitHub runner.
|
||||
|
||||
name: CI Docker
|
||||
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:
|
||||
check_dockerfiles:
|
||||
name: Check Dockerfiles
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Find dockerfiles
|
||||
id: find
|
||||
run: |
|
||||
dockerfiles=$(find . -type f -iname "Dockerfile" -o -iname "*.dockerfile")
|
||||
|
||||
echo "found dockerfiles: ${dockerfiles}"
|
||||
|
||||
# do not quote to keep this as a single line
|
||||
echo dockerfiles=${dockerfiles} >> $GITHUB_OUTPUT
|
||||
|
||||
MATRIX_COMBINATIONS=""
|
||||
for FILE in ${dockerfiles}; do
|
||||
# extract tag from file name
|
||||
tag=$(echo $FILE | sed -r -z -e 's/(\.\/)*.*\/(Dockerfile)/None/gm')
|
||||
if [[ $tag == "None" ]]; then
|
||||
MATRIX_COMBINATIONS="$MATRIX_COMBINATIONS {\"dockerfile\": \"$FILE\"},"
|
||||
else
|
||||
tag=$(echo $FILE | sed -r -z -e 's/(\.\/)*.*\/(.+)(\.dockerfile)/-\2/gm')
|
||||
MATRIX_COMBINATIONS="$MATRIX_COMBINATIONS {\"dockerfile\": \"$FILE\", \"tag\": \"$tag\"},"
|
||||
fi
|
||||
done
|
||||
|
||||
# removes the last character (i.e. comma)
|
||||
MATRIX_COMBINATIONS=${MATRIX_COMBINATIONS::-1}
|
||||
|
||||
# setup matrix for later jobs
|
||||
matrix=$((
|
||||
echo "{ \"include\": [$MATRIX_COMBINATIONS] }"
|
||||
) | jq -c .)
|
||||
|
||||
echo $matrix
|
||||
echo $matrix | jq .
|
||||
echo "matrix=$matrix" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Find dotnet solution file
|
||||
id: find_dotnet
|
||||
run: |
|
||||
solution=$(find . -maxdepth 1 -type f -iname "*.sln")
|
||||
|
||||
echo "found solution: ${solution}"
|
||||
|
||||
# do not quote to keep this as a single line
|
||||
echo solution=${solution} >> $GITHUB_OUTPUT
|
||||
|
||||
if [[ $solution != "" ]]; then
|
||||
echo "dotnet=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "dotnet=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
outputs:
|
||||
dockerfiles: ${{ steps.find.outputs.dockerfiles }}
|
||||
matrix: ${{ steps.find.outputs.matrix }}
|
||||
dotnet: ${{ steps.find_dotnet.outputs.dotnet }}
|
||||
solution: ${{ steps.find_dotnet.outputs.solution }}
|
||||
|
||||
setup_release:
|
||||
name: Setup Release
|
||||
if: needs.check_dockerfiles.outputs.dockerfiles
|
||||
needs: check_dockerfiles
|
||||
outputs:
|
||||
publish_release: ${{ steps.setup_release.outputs.publish_release }}
|
||||
release_body: ${{ steps.setup_release.outputs.release_body }}
|
||||
release_commit: ${{ steps.setup_release.outputs.release_commit }}
|
||||
release_generate_release_notes: ${{ steps.setup_release.outputs.release_generate_release_notes }}
|
||||
release_tag: ${{ steps.setup_release.outputs.release_tag }}
|
||||
release_version: ${{ steps.setup_release.outputs.release_version }}
|
||||
permissions:
|
||||
contents: write # read does not work to check squash and merge details
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Release
|
||||
id: setup_release
|
||||
uses: LizardByte/setup-release-action@v2025.426.225
|
||||
with:
|
||||
dotnet: ${{ needs.check_dockerfiles.outputs.dotnet }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
docker:
|
||||
name: Docker${{ matrix.tag }}
|
||||
if: needs.check_dockerfiles.outputs.dockerfiles
|
||||
needs:
|
||||
- check_dockerfiles
|
||||
- setup_release
|
||||
permissions:
|
||||
packages: write
|
||||
contents: write
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.check_dockerfiles.outputs.matrix) }}
|
||||
steps:
|
||||
- name: Maximize build space
|
||||
uses: easimon/maximize-build-space@v10
|
||||
with:
|
||||
root-reserve-mb: 30720 # https://github.com/easimon/maximize-build-space#caveats
|
||||
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: Prepare
|
||||
id: prepare
|
||||
env:
|
||||
NV: ${{ needs.setup_release.outputs.release_tag }}
|
||||
run: |
|
||||
# get branch name
|
||||
BRANCH=${GITHUB_HEAD_REF}
|
||||
|
||||
RELEASE=${{ needs.setup_release.outputs.publish_release }}
|
||||
COMMIT=${{ needs.setup_release.outputs.release_commit }}
|
||||
|
||||
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 PULL REQUEST event"
|
||||
CLONE_URL=${{ github.event.pull_request.head.repo.clone_url }}
|
||||
fi
|
||||
|
||||
# determine to push image to dockerhub and ghcr or not
|
||||
if [[ $GITHUB_EVENT_NAME == "push" ]]; then
|
||||
PUSH=true
|
||||
else
|
||||
PUSH=false
|
||||
fi
|
||||
|
||||
# setup the tags
|
||||
REPOSITORY=${{ github.repository }}
|
||||
BASE_TAG=$(echo $REPOSITORY | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
TAGS="${BASE_TAG}:${COMMIT:0:7}${{ matrix.tag }},ghcr.io/${BASE_TAG}:${COMMIT:0:7}${{ matrix.tag }}"
|
||||
|
||||
if [[ $GITHUB_REF == refs/heads/master ]]; then
|
||||
TAGS="${TAGS},${BASE_TAG}:latest${{ matrix.tag }},ghcr.io/${BASE_TAG}:latest${{ matrix.tag }}"
|
||||
TAGS="${TAGS},${BASE_TAG}:master${{ matrix.tag }},ghcr.io/${BASE_TAG}:master${{ matrix.tag }}"
|
||||
else
|
||||
TAGS="${TAGS},${BASE_TAG}:test${{ matrix.tag }},ghcr.io/${BASE_TAG}:test${{ matrix.tag }}"
|
||||
fi
|
||||
|
||||
if [[ ${NV} != "" ]]; then
|
||||
TAGS="${TAGS},${BASE_TAG}:${NV}${{ matrix.tag }},ghcr.io/${BASE_TAG}:${NV}${{ matrix.tag }}"
|
||||
fi
|
||||
|
||||
# parse custom directives out of dockerfile
|
||||
# try to get the platforms from the dockerfile custom directive, i.e. `# platforms: xxx,yyy`
|
||||
# directives for PR event, i.e. not push event
|
||||
if [[ ${RELEASE} == "false" ]]; then
|
||||
while read -r line; do
|
||||
if [[ $line == "# platforms_pr: "* && $PLATFORMS == "" ]]; then
|
||||
# echo the line and use `sed` to remove the custom directive
|
||||
PLATFORMS=$(echo -e "$line" | sed 's/# platforms_pr: //')
|
||||
elif [[ $PLATFORMS != "" ]]; then
|
||||
# break while loop once all custom "PR" event directives are found
|
||||
break
|
||||
fi
|
||||
done <"${{ matrix.dockerfile }}"
|
||||
fi
|
||||
# directives for all events... above directives will not be parsed if they were already found
|
||||
while read -r line; do
|
||||
if [[ $line == "# platforms: "* && $PLATFORMS == "" ]]; then
|
||||
# echo the line and use `sed` to remove the custom directive
|
||||
PLATFORMS=$(echo -e "$line" | sed 's/# platforms: //')
|
||||
elif [[ $line == "# artifacts: "* && $ARTIFACTS == "" ]]; then
|
||||
# echo the line and use `sed` to remove the custom directive
|
||||
ARTIFACTS=$(echo -e "$line" | sed 's/# artifacts: //')
|
||||
elif [[ $line == "# no-cache-filters: "* && $NO_CACHE_FILTERS == "" ]]; then
|
||||
# echo the line and use `sed` to remove the custom directive
|
||||
NO_CACHE_FILTERS=$(echo -e "$line" | sed 's/# no-cache-filters: //')
|
||||
elif [[ $PLATFORMS != "" && $ARTIFACTS != "" && $NO_CACHE_FILTERS != "" ]]; then
|
||||
# break while loop once all custom directives are found
|
||||
break
|
||||
fi
|
||||
done <"${{ matrix.dockerfile }}"
|
||||
# if PLATFORMS is blank, fall back to the legacy method of reading from the `.docker_platforms` file
|
||||
if [[ $PLATFORMS == "" ]]; then
|
||||
# read the platforms from `.docker_platforms`
|
||||
PLATFORMS=$(<.docker_platforms)
|
||||
fi
|
||||
# if PLATFORMS is still blank, fall back to `linux/amd64`
|
||||
if [[ $PLATFORMS == "" ]]; then
|
||||
PLATFORMS="linux/amd64"
|
||||
fi
|
||||
|
||||
echo "branch=${BRANCH}" >> $GITHUB_OUTPUT
|
||||
echo "build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
|
||||
echo "clone_url=${CLONE_URL}" >> $GITHUB_OUTPUT
|
||||
echo "artifacts=${ARTIFACTS}" >> $GITHUB_OUTPUT
|
||||
echo "no_cache_filters=${NO_CACHE_FILTERS}" >> $GITHUB_OUTPUT
|
||||
echo "platforms=${PLATFORMS}" >> $GITHUB_OUTPUT
|
||||
echo "tags=${TAGS}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set Up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
id: buildx
|
||||
|
||||
- name: Cache Docker Layers
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: Docker-buildx${{ matrix.tag }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
Docker-buildx${{ matrix.tag }}-
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
if: needs.setup_release.outputs.publish_release == 'true' # PRs do not have access to secrets
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||
|
||||
- name: Log in to the Container registry
|
||||
if: needs.setup_release.outputs.publish_release == 'true' # PRs do not have access to secrets
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ secrets.GH_BOT_NAME }}
|
||||
password: ${{ secrets.GH_BOT_TOKEN }}
|
||||
|
||||
- name: Build artifacts
|
||||
if: steps.prepare.outputs.artifacts == 'true'
|
||||
id: build_artifacts
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ./
|
||||
file: ${{ matrix.dockerfile }}
|
||||
target: artifacts
|
||||
outputs: type=local,dest=artifacts
|
||||
push: false
|
||||
platforms: ${{ steps.prepare.outputs.platforms }}
|
||||
build-args: |
|
||||
BRANCH=${{ steps.prepare.outputs.branch }}
|
||||
BUILD_DATE=${{ steps.prepare.outputs.build_date }}
|
||||
BUILD_VERSION=${{ needs.setup_release.outputs.release_tag }}
|
||||
COMMIT=${{ needs.setup_release.outputs.release_commit }}
|
||||
CLONE_URL=${{ steps.prepare.outputs.clone_url }}
|
||||
RELEASE=${{ needs.setup_release.outputs.publish_release }}
|
||||
tags: ${{ steps.prepare.outputs.tags }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache
|
||||
no-cache-filters: ${{ steps.prepare.outputs.no_cache_filters }}
|
||||
|
||||
- name: Build and push
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ./
|
||||
file: ${{ matrix.dockerfile }}
|
||||
push: ${{ needs.setup_release.outputs.publish_release }}
|
||||
platforms: ${{ steps.prepare.outputs.platforms }}
|
||||
build-args: |
|
||||
BRANCH=${{ steps.prepare.outputs.branch }}
|
||||
BUILD_DATE=${{ steps.prepare.outputs.build_date }}
|
||||
BUILD_VERSION=${{ needs.setup_release.outputs.release_tag }}
|
||||
COMMIT=${{ needs.setup_release.outputs.release_commit }}
|
||||
CLONE_URL=${{ steps.prepare.outputs.clone_url }}
|
||||
RELEASE=${{ needs.setup_release.outputs.publish_release }}
|
||||
tags: ${{ steps.prepare.outputs.tags }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache
|
||||
no-cache-filters: ${{ steps.prepare.outputs.no_cache_filters }}
|
||||
|
||||
- name: Arrange Artifacts
|
||||
if: steps.prepare.outputs.artifacts == 'true'
|
||||
working-directory: artifacts
|
||||
run: |
|
||||
# debug directory
|
||||
echo "Current directory: $(pwd)"
|
||||
echo "Directory contents: $(ls -Ra)"
|
||||
|
||||
# artifacts will be in sub directories named after the docker target platform, e.g. `linux_amd64`
|
||||
# so move files to the artifacts directory
|
||||
# https://unix.stackexchange.com/a/52816
|
||||
find \
|
||||
./ \
|
||||
-maxdepth 2 \
|
||||
-mindepth 2 \
|
||||
-type f \
|
||||
-not -name 'provenance.json' \
|
||||
-exec mv -t ./ -n '{}' +
|
||||
|
||||
# remove provenance file
|
||||
rm -f ./provenance.json
|
||||
|
||||
- name: Upload Artifacts
|
||||
if: steps.prepare.outputs.artifacts == 'true'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Docker${{ matrix.tag }}
|
||||
path: artifacts/
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Create/Update GitHub Release
|
||||
if: >
|
||||
needs.setup_release.outputs.publish_release == 'true' &&
|
||||
steps.prepare.outputs.artifacts == 'true'
|
||||
uses: LizardByte/create-release-action@v2025.426.1549
|
||||
with:
|
||||
allowUpdates: true
|
||||
artifacts: "*artifacts/*"
|
||||
body: ${{ needs.setup_release.outputs.release_body }}
|
||||
generateReleaseNotes: ${{ needs.setup_release.outputs.release_generate_release_notes }}
|
||||
name: ${{ needs.setup_release.outputs.release_tag }}
|
||||
prerelease: true
|
||||
tag: ${{ needs.setup_release.outputs.release_tag }}
|
||||
token: ${{ secrets.GH_BOT_TOKEN }}
|
||||
|
||||
- name: Update Docker Hub Description
|
||||
if: >
|
||||
github.event_name == 'push' &&
|
||||
github.ref == 'refs/heads/master'
|
||||
uses: peter-evans/dockerhub-description@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }} # token is not currently supported
|
||||
repository: ${{ env.BASE_TAG }}
|
||||
short-description: ${{ github.event.repository.description }}
|
||||
readme-filepath: ./DOCKER_README.md
|
||||
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.703.21447
|
||||
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.703.21447
|
||||
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
|
||||
357
.github/workflows/ci-windows.yml
vendored
Normal file
357
.github/workflows/ci-windows.yml
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
---
|
||||
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 dotnet # needed for wix
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '9.x'
|
||||
|
||||
- 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 WIX
|
||||
cpack -G ZIP
|
||||
|
||||
# move
|
||||
mv ./cpack_artifacts/Sunshine.exe ../artifacts/Sunshine-${{ matrix.name }}-installer.exe
|
||||
mv ./cpack_artifacts/Sunshine.msi ../artifacts/Sunshine-${{ matrix.name }}-installer.msi
|
||||
mv ./cpack_artifacts/Sunshine.zip ../artifacts/Sunshine-${{ matrix.name }}-portable.zip
|
||||
|
||||
- name: Debug wix
|
||||
if: always()
|
||||
shell: msys2 {0}
|
||||
run: cat /d/a/Sunshine/Sunshine/build/cpack_artifacts/_CPack_Packages/win64/WIX/wix.log
|
||||
|
||||
- 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
|
||||
215
.github/workflows/ci.yml
vendored
Normal file
215
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
---
|
||||
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.703.21447
|
||||
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-copr
|
||||
- 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.703.21447
|
||||
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 }}
|
||||
250
.github/workflows/codeql.yml
vendored
250
.github/workflows/codeql.yml
vendored
@@ -1,250 +0,0 @@
|
||||
---
|
||||
# This workflow is centrally managed in https://github.com/<organization>/.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.
|
||||
|
||||
# This workflow will analyze all supported languages in the repository using CodeQL Analysis.
|
||||
|
||||
name: "CodeQL"
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
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:
|
||||
languages:
|
||||
name: Get language matrix
|
||||
outputs:
|
||||
matrix: ${{ steps.lang.outputs.result }}
|
||||
continue: ${{ steps.continue.outputs.result }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get repo languages
|
||||
id: lang
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// CodeQL supports ['cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift']
|
||||
// Use only 'java' to analyze code written in Java, Kotlin or both
|
||||
// Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
|
||||
// Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
const supported_languages = ['cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift']
|
||||
|
||||
const remap_languages = {
|
||||
'c++': 'cpp',
|
||||
'c#': 'csharp',
|
||||
'kotlin': 'java',
|
||||
'typescript': 'javascript',
|
||||
}
|
||||
|
||||
const repo = context.repo
|
||||
const response = await github.rest.repos.listLanguages(repo)
|
||||
let matrix = {
|
||||
"include": []
|
||||
}
|
||||
|
||||
// Track languages we've already added to avoid duplicates
|
||||
const addedLanguages = new Set()
|
||||
|
||||
// Check if workflow files exist to determine if we should add actions language
|
||||
const fs = require('fs');
|
||||
const hasYmlFiles = fs.existsSync('.github/workflows') &&
|
||||
fs.readdirSync('.github/workflows').some(file => file.endsWith('.yml') || file.endsWith('.yaml'));
|
||||
|
||||
// Add actions language if workflow files exist
|
||||
if (hasYmlFiles) {
|
||||
console.log('Found GitHub Actions workflow files. Adding actions to the matrix.');
|
||||
matrix['include'].push({
|
||||
"category": "/language:actions",
|
||||
"language": "actions",
|
||||
"name": "actions",
|
||||
"os": "ubuntu-latest"
|
||||
});
|
||||
}
|
||||
|
||||
for (let [key, value] of Object.entries(response.data)) {
|
||||
// remap language
|
||||
if (remap_languages[key.toLowerCase()]) {
|
||||
console.log(`Remapping language: ${key} to ${remap_languages[key.toLowerCase()]}`)
|
||||
key = remap_languages[key.toLowerCase()]
|
||||
}
|
||||
|
||||
const normalizedKey = key.toLowerCase()
|
||||
|
||||
if (supported_languages.includes(normalizedKey) && !addedLanguages.has(normalizedKey)) {
|
||||
// Mark this language as added
|
||||
addedLanguages.add(normalizedKey)
|
||||
|
||||
console.log(`Found supported language: ${normalizedKey}`)
|
||||
let osList = ['ubuntu-latest'];
|
||||
if (normalizedKey === 'swift') {
|
||||
osList = ['macos-latest'];
|
||||
} else if (normalizedKey === 'cpp') {
|
||||
osList = ['macos-latest', 'ubuntu-latest', 'windows-latest'];
|
||||
}
|
||||
for (let os of osList) {
|
||||
// set name for matrix
|
||||
let name = osList.length === 1 ? normalizedKey : `${normalizedKey}, ${os}`
|
||||
|
||||
// set category for matrix
|
||||
let category = `/language:${normalizedKey}`
|
||||
if (normalizedKey === 'cpp') {
|
||||
category = `/language:cpp-${os.split('-')[0]}`
|
||||
}
|
||||
|
||||
// add to matrix
|
||||
matrix['include'].push({
|
||||
"category": category,
|
||||
"language": normalizedKey,
|
||||
"name": name,
|
||||
"os": os
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print languages
|
||||
console.log(`matrix: ${JSON.stringify(matrix)}`)
|
||||
|
||||
return matrix
|
||||
|
||||
- name: Continue
|
||||
id: continue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// if matrix['include'] is an empty list return false, otherwise true
|
||||
const matrix = ${{ steps.lang.outputs.result }} // this is already json encoded
|
||||
|
||||
if (matrix['include'].length == 0) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
|
||||
analyze:
|
||||
name: Analyze (${{ matrix.name }})
|
||||
if: needs.languages.outputs.continue == 'true'
|
||||
defaults:
|
||||
run:
|
||||
shell: ${{ matrix.os == 'windows-latest' && 'msys2 {0}' || 'bash' }}
|
||||
env:
|
||||
GITHUB_CODEQL_BUILD: true
|
||||
needs: languages
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
runs-on: ${{ matrix.os || 'ubuntu-latest' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.languages.outputs.matrix) }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
steps:
|
||||
- name: Maximize build space
|
||||
if: >-
|
||||
runner.os == 'Linux' &&
|
||||
matrix.language == 'cpp'
|
||||
uses: easimon/maximize-build-space@v10
|
||||
with:
|
||||
root-reserve-mb: 30720
|
||||
remove-dotnet: ${{ (matrix.language == 'csharp' && 'false') || 'true' }}
|
||||
remove-android: 'true'
|
||||
remove-haskell: 'true'
|
||||
remove-codeql: 'false'
|
||||
remove-docker-images: 'true'
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup msys2
|
||||
if: >-
|
||||
runner.os == 'Windows' &&
|
||||
matrix.language == 'cpp'
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ucrt64
|
||||
update: true
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# yamllint disable-line rule:line-length
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
config: |
|
||||
paths-ignore:
|
||||
- build
|
||||
- node_modules
|
||||
- third-party
|
||||
|
||||
# Pre autobuild
|
||||
# create a file named .codeql-prebuild-${{ matrix.language }}-${{ runner.os }}.sh in the root of your repository
|
||||
- name: Prebuild
|
||||
id: prebuild
|
||||
run: |
|
||||
# check if prebuild script exists
|
||||
filename=".codeql-prebuild-${{ matrix.language }}-${{ runner.os }}.sh"
|
||||
if [ -f "./${filename}" ]; then
|
||||
echo "Running prebuild script: ${filename}"
|
||||
./${filename}
|
||||
fi
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
||||
- name: Autobuild
|
||||
if: steps.prebuild.outputs.skip_autobuild != 'true'
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "${{ matrix.category }}"
|
||||
output: sarif-results
|
||||
upload: failure-only
|
||||
|
||||
- name: filter-sarif
|
||||
uses: advanced-security/filter-sarif@v1
|
||||
with:
|
||||
input: sarif-results/${{ matrix.language }}.sarif
|
||||
output: sarif-results/${{ matrix.language }}.sarif
|
||||
patterns: |
|
||||
-build/**
|
||||
-node_modules/**
|
||||
-third\-party/**
|
||||
|
||||
- name: Upload SARIF
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
category: "${{ matrix.category }}"
|
||||
sarif_file: sarif-results/${{ matrix.language }}.sarif
|
||||
|
||||
- name: Upload loc as a Build Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sarif-results-${{ matrix.language }}-${{ runner.os }}
|
||||
path: sarif-results
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
273
.github/workflows/common-lint.yml
vendored
273
.github/workflows/common-lint.yml
vendored
@@ -1,273 +0,0 @@
|
||||
---
|
||||
# This workflow is centrally managed in https://github.com/<organization>/.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.
|
||||
|
||||
# Common linting.
|
||||
|
||||
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
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade \
|
||||
pip \
|
||||
setuptools \
|
||||
wheel \
|
||||
cmakelang \
|
||||
flake8 \
|
||||
nb-clean \
|
||||
nbqa[toolchain]
|
||||
|
||||
- name: C++ - find files
|
||||
id: cpp_files
|
||||
run: |
|
||||
# find files
|
||||
found_files=$(find . -type f \
|
||||
-iname "*.c" -o \
|
||||
-iname "*.cpp" -o \
|
||||
-iname "*.h" -o \
|
||||
-iname "*.hpp" -o \
|
||||
-iname "*.m" -o \
|
||||
-iname "*.mm" \
|
||||
)
|
||||
ignore_files=$(find . -type f -iname ".clang-format-ignore")
|
||||
|
||||
# Loop through each C++ file
|
||||
for file in $found_files; do
|
||||
for ignore_file in $ignore_files; do
|
||||
ignore_directory=$(dirname "$ignore_file")
|
||||
# if directory of ignore_file is beginning of file
|
||||
if [[ "$file" == "$ignore_directory"* ]]; then
|
||||
echo "ignoring file: ${file}"
|
||||
found_files="${found_files//${file}/}"
|
||||
break 1
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# remove empty lines
|
||||
found_files=$(echo "$found_files" | sed '/^\s*$/d')
|
||||
|
||||
echo "found cpp files: ${found_files}"
|
||||
|
||||
# do not quote to keep this as a single line
|
||||
echo found_files=${found_files} >> $GITHUB_OUTPUT
|
||||
|
||||
- name: C++ - Clang format lint
|
||||
if: always() && steps.cpp_files.outputs.found_files
|
||||
uses: DoozyX/clang-format-lint-action@v0.20
|
||||
with:
|
||||
source: ${{ steps.cpp_files.outputs.found_files }}
|
||||
clangFormatVersion: '20'
|
||||
extensions: 'c,cpp,h,hpp,m,mm'
|
||||
style: file
|
||||
inplace: false
|
||||
|
||||
- name: CMake - find files
|
||||
id: cmake_files
|
||||
if: always()
|
||||
run: |
|
||||
# find files
|
||||
found_files=$(find . -type f -iname "CMakeLists.txt" -o -iname "*.cmake")
|
||||
ignore_files=$(find . -type f -iname ".cmake-lint-ignore")
|
||||
|
||||
# Loop through each C++ file
|
||||
for file in $found_files; do
|
||||
for ignore_file in $ignore_files; do
|
||||
ignore_directory=$(dirname "$ignore_file")
|
||||
# if directory of ignore_file is beginning of file
|
||||
if [[ "$file" == "$ignore_directory"* ]]; then
|
||||
echo "ignoring file: ${file}"
|
||||
found_files="${found_files//${file}/}"
|
||||
break 1
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# remove empty lines
|
||||
found_files=$(echo "$found_files" | sed '/^\s*$/d')
|
||||
|
||||
echo "found cmake files: ${found_files}"
|
||||
|
||||
# do not quote to keep this as a single line
|
||||
echo found_files=${found_files} >> $GITHUB_OUTPUT
|
||||
|
||||
- name: CMake - cmake-lint
|
||||
if: always() && steps.cmake_files.outputs.found_files
|
||||
run: |
|
||||
cmake-lint --line-width 120 --tab-size 4 ${{ steps.cmake_files.outputs.found_files }}
|
||||
|
||||
- name: Docker - find files
|
||||
id: dokcer_files
|
||||
if: always()
|
||||
run: |
|
||||
found_files=$(find . -type f -iname "Dockerfile" -o -iname "*.dockerfile")
|
||||
|
||||
echo "found_files: ${found_files}"
|
||||
|
||||
# do not quote to keep this as a single line
|
||||
echo found_files=${found_files} >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Docker - hadolint
|
||||
if: always() && steps.dokcer_files.outputs.found_files
|
||||
run: |
|
||||
docker pull hadolint/hadolint
|
||||
|
||||
# create hadolint config file
|
||||
cat <<EOF > .hadolint.yaml
|
||||
---
|
||||
ignored:
|
||||
- DL3008
|
||||
- DL3013
|
||||
- DL3016
|
||||
- DL3018
|
||||
- DL3028
|
||||
- DL3059
|
||||
EOF
|
||||
|
||||
failed=0
|
||||
failed_files=""
|
||||
|
||||
for file in ${{ steps.dokcer_files.outputs.found_files }}; do
|
||||
echo "::group::${file}"
|
||||
docker run --rm -i \
|
||||
-e "NO_COLOR=0" \
|
||||
-e "HADOLINT_VERBOSE=1" \
|
||||
-v $(pwd)/.hadolint.yaml:/.config/hadolint.yaml \
|
||||
hadolint/hadolint < $file || {
|
||||
failed=1
|
||||
failed_files="$failed_files $file"
|
||||
}
|
||||
echo "::endgroup::"
|
||||
done
|
||||
|
||||
if [ $failed -ne 0 ]; then
|
||||
echo "::error:: hadolint failed for the following files: $failed_files"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Python - flake8
|
||||
if: always()
|
||||
run: |
|
||||
python -m flake8 \
|
||||
--color=always \
|
||||
--verbose
|
||||
|
||||
- name: Python - nbqa flake8
|
||||
if: always()
|
||||
run: |
|
||||
python -m nbqa flake8 \
|
||||
--color=always \
|
||||
--verbose \
|
||||
.
|
||||
|
||||
- name: Python - nb-clean
|
||||
if: always()
|
||||
run: |
|
||||
output=$(find . -name '*.ipynb' -exec nb-clean check {} \;)
|
||||
|
||||
# fail if there are any issues
|
||||
if [ -n "$output" ]; then
|
||||
echo "$output"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Rust - find Cargo.toml
|
||||
id: run_cargo
|
||||
if: always()
|
||||
run: |
|
||||
# check if Cargo.toml exists
|
||||
if [ -f "Cargo.toml" ]; then
|
||||
echo "found_cargo=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "found_cargo=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Rust - setup toolchain
|
||||
if: always() && steps.run_cargo.outputs.found_cargo == 'true'
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: rustfmt
|
||||
|
||||
- name: Rust - cargo fmt
|
||||
if: always() && steps.run_cargo.outputs.found_cargo == 'true'
|
||||
run: |
|
||||
cargo fmt -- --check
|
||||
|
||||
- name: YAML - find files
|
||||
id: yaml_files
|
||||
if: always()
|
||||
run: |
|
||||
# space separated list of files
|
||||
FILES=.clang-format
|
||||
|
||||
# empty placeholder
|
||||
found_files=""
|
||||
|
||||
for FILE in ${FILES}; do
|
||||
if [ -f "$FILE" ]
|
||||
then
|
||||
found_files="$found_files $FILE"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "found_files=${found_files}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: YAML - yamllint
|
||||
id: yamllint
|
||||
if: always()
|
||||
uses: ibiqlik/action-yamllint@v3
|
||||
with:
|
||||
# https://yamllint.readthedocs.io/en/stable/configuration.html#default-configuration
|
||||
config_data: |
|
||||
extends: default
|
||||
rules:
|
||||
comments:
|
||||
level: error
|
||||
document-start:
|
||||
level: error
|
||||
line-length:
|
||||
max: 120
|
||||
new-line-at-end-of-file:
|
||||
level: error
|
||||
new-lines:
|
||||
type: unix
|
||||
truthy:
|
||||
# GitHub uses "on" for workflow event triggers
|
||||
# .clang-format file has options of "Yes" "No" that will be caught by this, so changed to "warning"
|
||||
allowed-values: ['true', 'false', 'on']
|
||||
check-keys: true
|
||||
level: warning
|
||||
file_or_dir: . ${{ steps.yaml_files.outputs.found_files }}
|
||||
|
||||
- name: YAML - log
|
||||
if: always() && steps.yamllint.outcome == 'failure'
|
||||
run: cat "${{ steps.yamllint.outputs.logfile }}" >> $GITHUB_STEP_SUMMARY
|
||||
30
.github/workflows/issues.yml
vendored
30
.github/workflows/issues.yml
vendored
@@ -1,30 +0,0 @@
|
||||
---
|
||||
# This workflow is centrally managed in https://github.com/<organization>/.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.
|
||||
|
||||
# Label and un-label actions using `../label-actions.yml`.
|
||||
|
||||
name: Issues
|
||||
permissions: {}
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- labeled
|
||||
- unlabeled
|
||||
discussion:
|
||||
types:
|
||||
- labeled
|
||||
- unlabeled
|
||||
|
||||
jobs:
|
||||
label:
|
||||
name: Label Actions
|
||||
if: startsWith(github.repository, 'LizardByte/')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Label Actions
|
||||
uses: dessant/label-actions@v4
|
||||
with:
|
||||
github-token: ${{ secrets.GH_BOT_TOKEN }}
|
||||
137
.github/workflows/release-notifier.yml
vendored
137
.github/workflows/release-notifier.yml
vendored
@@ -1,137 +0,0 @@
|
||||
---
|
||||
# This workflow is centrally managed in https://github.com/<organization>/.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
|
||||
if: github.repository_owner == 'LizardByte'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check topics
|
||||
env:
|
||||
TOPIC: replicator-release-notifications
|
||||
id: check-label
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const topic = process.env.TOPIC;
|
||||
console.log(`Checking if repo has topic: ${topic}`);
|
||||
|
||||
const repoTopics = await github.rest.repos.getAllTopics({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
console.log(`Repo topics: ${repoTopics.data.names}`);
|
||||
|
||||
const hasTopic = repoTopics.data.names.includes(topic);
|
||||
console.log(`Has topic: ${hasTopic}`);
|
||||
|
||||
core.setOutput('hasTopic', hasTopic);
|
||||
|
||||
- name: Check if latest GitHub release
|
||||
id: check-release
|
||||
if: steps.check-label.outputs.hasTopic == 'true'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const latestRelease = await github.rest.repos.getLatestRelease({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
|
||||
core.setOutput('isLatestRelease', latestRelease.data.tag_name === context.payload.release.tag_name);
|
||||
|
||||
- name: Checkout blog
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: "LizardByte/LizardByte.github.io"
|
||||
|
||||
- name: Create blog post
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
run: |
|
||||
# setup variables
|
||||
tag_name="${{ github.event.release.tag_name }}"
|
||||
semver="${tag_name#v}"
|
||||
repo_lower="$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]')"
|
||||
|
||||
# extract year, month, and day
|
||||
year="${semver%%.*}"
|
||||
month_day="${semver#*.}"
|
||||
month_day="${month_day%%.*}"
|
||||
|
||||
# ensure month_day is 4 digits
|
||||
month_day=$(printf "%04d" "$month_day")
|
||||
|
||||
# create the filename
|
||||
file_name="_posts/releases/${repo_lower}/${year}-${month_day:0:2}-${month_day:2:2}-v${semver}.md"
|
||||
mkdir -p "$(dirname "${file_name}")"
|
||||
|
||||
# create jekyll blog post
|
||||
echo "---" > "${file_name}"
|
||||
echo "layout: release" >> "${file_name}"
|
||||
echo "title: ${{ github.event.repository.name }} ${tag_name} Released" >> "${file_name}"
|
||||
echo "release-tag: ${tag_name}" >> "${file_name}"
|
||||
echo "gh-repo: ${{ github.repository }}" >> "${file_name}"
|
||||
echo "gh-badge: [follow, fork, star]" >> "${file_name}"
|
||||
echo "tags: [release, ${repo_lower}]" >> "${file_name}"
|
||||
echo "comments: true" >> "${file_name}"
|
||||
echo "author: LizardByte-bot" >> "${file_name}"
|
||||
echo "---" >> "${file_name}"
|
||||
echo "" >> "${file_name}"
|
||||
|
||||
release_body=$(cat <<EOF
|
||||
${{ github.event.release.body }}
|
||||
EOF
|
||||
)
|
||||
|
||||
echo "${release_body}" >> "${file_name}"
|
||||
|
||||
- name: Create/Update Pull Request
|
||||
id: create-pr
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.GH_BOT_TOKEN }}
|
||||
commit-message: |
|
||||
chore: Add blog post for ${{ github.event.repository.name }} release ${{ github.event.release.tag_name }}
|
||||
branch: bot/add-${{ github.event.repository.name }}-${{ github.event.release.tag_name }}
|
||||
delete-branch: true
|
||||
title: |
|
||||
chore: Add blog post for ${{ github.event.repository.name }} release ${{ github.event.release.tag_name }}
|
||||
body: ${{ github.event.release.body }}
|
||||
labels:
|
||||
blog
|
||||
|
||||
- name: Automerge PR
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
run: |
|
||||
gh pr merge \
|
||||
--auto \
|
||||
--delete-branch \
|
||||
--repo "LizardByte/LizardByte.github.io" \
|
||||
--squash \
|
||||
"${{ steps.create-pr.outputs.pull-request-number }}"
|
||||
99
.github/workflows/update-docs.yml
vendored
99
.github/workflows/update-docs.yml
vendored
@@ -1,99 +0,0 @@
|
||||
---
|
||||
# This workflow is centrally managed in https://github.com/<organization>/.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:
|
||||
env:
|
||||
RTD_SLUG: ${{ vars.READTHEDOCS_SLUG }}
|
||||
RTD_TOKEN: ${{ secrets.READTHEDOCS_TOKEN }}
|
||||
TAG: ${{ github.event.release.tag_name }}
|
||||
if: >-
|
||||
!github.event.release.draft
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get RTD_SLUG
|
||||
run: |
|
||||
# if the RTD_SLUG is not set, use the repository name in lowercase
|
||||
if [ -z "${RTD_SLUG}" ]; then
|
||||
RTD_SLUG=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]')
|
||||
fi
|
||||
echo "RTD_SLUG=${RTD_SLUG}" >> $GITHUB_ENV
|
||||
|
||||
- name: Deactivate deleted release
|
||||
if: >-
|
||||
github.event_name == 'release' &&
|
||||
github.event.action == 'deleted'
|
||||
run: |
|
||||
json_body=$(jq -n \
|
||||
--arg active "false" \
|
||||
--arg hidden "false" \
|
||||
--arg privacy_level "public" \
|
||||
'{active: $active, hidden: $hidden, privacy_level: $privacy_level}')
|
||||
|
||||
curl \
|
||||
-X PATCH \
|
||||
-H "Authorization: Token ${RTD_TOKEN}" \
|
||||
https://readthedocs.org/api/v3/projects/${RTD_SLUG}/versions/${TAG}/ \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$json_body"
|
||||
|
||||
- name: Check if edited release is latest GitHub release
|
||||
id: check
|
||||
if: >-
|
||||
github.event_name == 'release' &&
|
||||
github.event.action == 'edited'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const latestRelease = await github.rest.repos.getLatestRelease({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
|
||||
core.setOutput('isLatestRelease', latestRelease.data.tag_name === context.payload.release.tag_name);
|
||||
|
||||
- name: Update RTD project
|
||||
# changing the default branch in readthedocs makes "latest" point to that branch/tag
|
||||
# we can also update other properties like description, etc.
|
||||
if: steps.check.outputs.isLatestRelease == 'true'
|
||||
run: |
|
||||
json_body=$(jq -n \
|
||||
--arg default_branch "${TAG}" \
|
||||
--arg description "${{ github.event.repository.description }}" \
|
||||
'{default_branch: $default_branch}')
|
||||
|
||||
# change the default branch to the latest release
|
||||
curl \
|
||||
-X PATCH \
|
||||
-H "Authorization: Token ${RTD_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
https://readthedocs.org/api/v3/projects/${RTD_SLUG}/ \
|
||||
-d "$json_body"
|
||||
|
||||
# trigger a build for the latest version
|
||||
curl \
|
||||
-X POST \
|
||||
-H "Authorization: Token ${RTD_TOKEN}" \
|
||||
https://readthedocs.org/api/v3/projects/${RTD_SLUG}/versions/latest/builds/
|
||||
206
.github/workflows/update-flathub-repo.yml
vendored
206
.github/workflows/update-flathub-repo.yml
vendored
@@ -1,206 +0,0 @@
|
||||
---
|
||||
# This workflow is centrally managed in https://github.com/<organization>/.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:
|
||||
env:
|
||||
FLATHUB_PKG: dev.lizardbyte.app.${{ github.event.repository.name }}
|
||||
if: github.repository_owner == 'LizardByte'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check if flathub repo
|
||||
id: check-label
|
||||
env:
|
||||
TOPIC: flathub-pkg
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const topic = process.env.TOPIC;
|
||||
console.log(`Checking if repo has topic: ${topic}`);
|
||||
|
||||
const repoTopics = await github.rest.repos.getAllTopics({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
console.log(`Repo topics: ${repoTopics.data.names}`);
|
||||
|
||||
const hasTopic = repoTopics.data.names.includes(topic);
|
||||
console.log(`Has topic: ${hasTopic}`);
|
||||
|
||||
core.setOutput('hasTopic', hasTopic);
|
||||
|
||||
- name: Check if latest GitHub release
|
||||
id: check-release
|
||||
if: steps.check-label.outputs.hasTopic == 'true'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const latestRelease = await github.rest.repos.getLatestRelease({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
|
||||
core.setOutput('isLatestRelease', latestRelease.data.tag_name === context.payload.release.tag_name);
|
||||
|
||||
- name: Checkout
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Checkout flathub-repo
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: "flathub/${{ env.FLATHUB_PKG }}"
|
||||
path: "flathub/${{ env.FLATHUB_PKG }}"
|
||||
|
||||
- name: Clean up legacy files
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
working-directory: flathub/${{ env.FLATHUB_PKG }}
|
||||
run: |
|
||||
rm -rf ./*
|
||||
|
||||
- name: Copy github files
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
working-directory: flathub/${{ env.FLATHUB_PKG }}
|
||||
run: |
|
||||
mkdir -p .github/ISSUE_TEMPLATE
|
||||
|
||||
# sponsors
|
||||
curl -sSL https://github.com/LizardByte/.github/raw/refs/heads/master/.github/FUNDING.yml \
|
||||
-o .github/FUNDING.yml
|
||||
# pull request template
|
||||
curl -sSL https://github.com/LizardByte/.github/raw/refs/heads/master/.github/pull_request_template.md \
|
||||
-o .github/pull_request_template.md
|
||||
# issue config
|
||||
curl -sSL https://github.com/LizardByte/.github/raw/refs/heads/master/.github/ISSUE_TEMPLATE/config.yml \
|
||||
-o .github/ISSUE_TEMPLATE/config.yml
|
||||
|
||||
- name: Download release asset
|
||||
id: download
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
uses: robinraju/release-downloader@v1.12
|
||||
with:
|
||||
repository: "${{ github.repository }}"
|
||||
tag: "${{ github.event.release.tag_name }}"
|
||||
fileName: "flathub.tar.gz"
|
||||
tarBall: false
|
||||
zipBall: false
|
||||
out-file-path: "flathub/${{ env.FLATHUB_PKG }}"
|
||||
extract: true
|
||||
|
||||
- name: Delete archive
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
run: |
|
||||
rm -f flathub/${{ env.FLATHUB_PKG }}/flathub.tar.gz
|
||||
|
||||
- name: Update metainfo.xml
|
||||
id: update_metainfo
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
run: |
|
||||
xml_file="flathub/${{ env.FLATHUB_PKG }}/${{ env.FLATHUB_PKG }}.metainfo.xml"
|
||||
|
||||
# Extract release information
|
||||
version="${{ github.event.release.tag_name }}" && version="${version#v}"
|
||||
date="${{ github.event.release.published_at }}" && date="${date%%T*}"
|
||||
changelog="${{ github.event.release.body }}" && changelog="${changelog//&/&}" && \
|
||||
changelog="${changelog//</<}" && changelog="${changelog//>/>}"
|
||||
|
||||
# Store the old release information into a temp file to be used for precise replacement
|
||||
tmpfile=$(mktemp)
|
||||
|
||||
# Match the existing <release> block, replace it with the new data
|
||||
awk -v version="$version" -v date="$date" -v changelog="$changelog" '
|
||||
BEGIN { replaced = 0 }
|
||||
/<release version=.*>/ {
|
||||
if (!replaced) {
|
||||
print " <release version=\"" version "\" date=\"" date "\">"
|
||||
print " <description><p>" changelog "</p></description>"
|
||||
print " </release>"
|
||||
replaced = 1
|
||||
}
|
||||
}
|
||||
!/<release version=.*>/ && !/<\/release>/ { print $0 }
|
||||
' "$xml_file" > "$tmpfile"
|
||||
|
||||
# Move the updated file back to the original location
|
||||
mv "$tmpfile" "$xml_file"
|
||||
|
||||
- name: Update submodule
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
run: |
|
||||
# Get the current commit of the submodule in the main repository
|
||||
git submodule update --init packaging/linux/flatpak/deps/shared-modules
|
||||
cd ${{ github.workspace }}/packaging/linux/flatpak/deps/shared-modules
|
||||
main_commit=$(git rev-parse HEAD)
|
||||
|
||||
# update submodules
|
||||
cd ${{ github.workspace }}/flathub/${{ env.FLATHUB_PKG }}
|
||||
git submodule update --init shared-modules
|
||||
cd shared-modules
|
||||
git checkout $main_commit
|
||||
|
||||
- name: Create/Update Pull Request
|
||||
id: create-pr
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true' &&
|
||||
fromJson(steps.download.outputs.downloaded_files)[0]
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
path: "flathub/${{ env.FLATHUB_PKG }}"
|
||||
token: ${{ secrets.GH_BOT_TOKEN }}
|
||||
commit-message: "chore: Update ${{ env.FLATHUB_PKG }} to ${{ github.event.release.tag_name }}"
|
||||
branch: bot/bump-${{ env.FLATHUB_PKG }}-${{ github.event.release.tag_name }}
|
||||
delete-branch: true
|
||||
title: "chore: Update ${{ env.FLATHUB_PKG }} to ${{ github.event.release.tag_name }}"
|
||||
body: ${{ github.event.release.body }}
|
||||
|
||||
- name: Automerge PR
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true' &&
|
||||
fromJson(steps.download.outputs.downloaded_files)[0]
|
||||
run: |
|
||||
gh pr merge \
|
||||
--auto \
|
||||
--delete-branch \
|
||||
--repo "flathub/${{ env.FLATHUB_PKG }}" \
|
||||
--squash \
|
||||
"${{ steps.create-pr.outputs.pull-request-number }}"
|
||||
73
.github/workflows/update-homebrew-release.yml
vendored
73
.github/workflows/update-homebrew-release.yml
vendored
@@ -1,73 +0,0 @@
|
||||
---
|
||||
# This workflow is centrally managed in https://github.com/<organization>/.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 release
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- released
|
||||
|
||||
concurrency:
|
||||
group: "${{ github.workflow }}-${{ github.event.release.tag_name }}"
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
update-homebrew-release:
|
||||
if: github.repository_owner == 'LizardByte'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check if Homebrew repo
|
||||
id: check-label
|
||||
env:
|
||||
TOPIC: homebrew-pkg
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const topic = process.env.TOPIC;
|
||||
console.log(`Checking if repo has topic: ${topic}`);
|
||||
|
||||
const repoTopics = await github.rest.repos.getAllTopics({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
console.log(`Repo topics: ${repoTopics.data.names}`);
|
||||
|
||||
const hasTopic = repoTopics.data.names.includes(topic);
|
||||
console.log(`Has topic: ${hasTopic}`);
|
||||
|
||||
core.setOutput('hasTopic', hasTopic);
|
||||
|
||||
- name: Download release asset
|
||||
id: download
|
||||
if: steps.check-label.outputs.hasTopic == 'true'
|
||||
uses: robinraju/release-downloader@v1.12
|
||||
with:
|
||||
repository: "${{ github.repository }}"
|
||||
tag: "${{ github.event.release.tag_name }}"
|
||||
fileName: "*.rb"
|
||||
tarBall: false
|
||||
zipBall: false
|
||||
out-file-path: "release_downloads"
|
||||
extract: false
|
||||
|
||||
- name: Publish Homebrew Formula
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
fromJson(steps.download.outputs.downloaded_files)[0]
|
||||
uses: LizardByte/homebrew-release-action@v2024.1115.14934
|
||||
with:
|
||||
formula_file: ${{ fromJson(steps.download.outputs.downloaded_files)[0] }}
|
||||
git_email: ${{ secrets.GH_BOT_EMAIL }}
|
||||
git_username: ${{ secrets.GH_BOT_NAME }}
|
||||
publish: true
|
||||
token: ${{ secrets.GH_BOT_TOKEN }}
|
||||
validate: false
|
||||
134
.github/workflows/update-pacman-repo.yml
vendored
134
.github/workflows/update-pacman-repo.yml
vendored
@@ -1,134 +0,0 @@
|
||||
---
|
||||
# This workflow is centrally managed in https://github.com/<organization>/.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:
|
||||
if: github.repository_owner == 'LizardByte'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check if pacman repo
|
||||
id: check-label
|
||||
env:
|
||||
TOPIC: pacman-pkg
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const topic = process.env.TOPIC;
|
||||
console.log(`Checking if repo has topic: ${topic}`);
|
||||
|
||||
const repoTopics = await github.rest.repos.getAllTopics({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
console.log(`Repo topics: ${repoTopics.data.names}`);
|
||||
|
||||
const hasTopic = repoTopics.data.names.includes(topic);
|
||||
console.log(`Has topic: ${hasTopic}`);
|
||||
|
||||
core.setOutput('hasTopic', hasTopic);
|
||||
|
||||
- name: Check if latest GitHub release
|
||||
id: check-release
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const latestRelease = await github.rest.repos.getLatestRelease({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
|
||||
core.setOutput('isLatestRelease', latestRelease.data.tag_name === context.payload.release.tag_name);
|
||||
|
||||
- name: Checkout pacman-repo
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/pacman-repo
|
||||
|
||||
- name: Prep
|
||||
id: prep
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
run: |
|
||||
echo "pkg_name=$(echo ${{ github.event.repository.name }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Download release asset
|
||||
id: download
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true'
|
||||
uses: robinraju/release-downloader@v1.12
|
||||
with:
|
||||
repository: "${{ github.repository }}"
|
||||
tag: "${{ github.event.release.tag_name }}"
|
||||
fileName: "*.pkg.tar.gz"
|
||||
tarBall: false
|
||||
zipBall: false
|
||||
out-file-path: "pkgbuilds/${{ steps.prep.outputs.pkg_name }}"
|
||||
extract: true
|
||||
|
||||
- name: Remove pkg.tar.gz
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true' &&
|
||||
fromJson(steps.download.outputs.downloaded_files)[0]
|
||||
run: |
|
||||
rm -f "pkgbuilds/${{ steps.prep.outputs.pkg_name }}"
|
||||
|
||||
- name: Create/Update Pull Request
|
||||
id: create-pr
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true' &&
|
||||
fromJson(steps.download.outputs.downloaded_files)[0]
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
add-paths: |
|
||||
pkgbuilds/*
|
||||
token: ${{ secrets.GH_BOT_TOKEN }}
|
||||
commit-message: "chore: Update ${{ github.repository }} to ${{ github.event.release.tag_name }}"
|
||||
branch: bot/bump-${{ github.repository }}-${{ github.event.release.tag_name }}
|
||||
delete-branch: true
|
||||
title: "chore: Update ${{ github.repository }} to ${{ github.event.release.tag_name }}"
|
||||
body: ${{ github.event.release.body }}
|
||||
labels: |
|
||||
auto-approve
|
||||
auto-merge
|
||||
|
||||
- name: Automerge PR
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
steps.check-release.outputs.isLatestRelease == 'true' &&
|
||||
fromJson(steps.download.outputs.downloaded_files)[0]
|
||||
run: |
|
||||
gh pr merge \
|
||||
--auto \
|
||||
--delete-branch \
|
||||
--squash \
|
||||
"${{ steps.create-pr.outputs.pull-request-number }}"
|
||||
71
.github/workflows/update-winget-release.yml
vendored
71
.github/workflows/update-winget-release.yml
vendored
@@ -1,71 +0,0 @@
|
||||
---
|
||||
# This workflow is centrally managed in https://github.com/<organization>/.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 release
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- released
|
||||
|
||||
concurrency:
|
||||
group: "${{ github.workflow }}-${{ github.event.release.tag_name }}"
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
update-winget-release:
|
||||
if: github.repository_owner == 'LizardByte'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check if Winget repo
|
||||
id: check-label
|
||||
env:
|
||||
TOPIC: winget-pkg
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const topic = process.env.TOPIC;
|
||||
console.log(`Checking if repo has topic: ${topic}`);
|
||||
|
||||
const repoTopics = await github.rest.repos.getAllTopics({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
console.log(`Repo topics: ${repoTopics.data.names}`);
|
||||
|
||||
const hasTopic = repoTopics.data.names.includes(topic);
|
||||
console.log(`Has topic: ${hasTopic}`);
|
||||
|
||||
core.setOutput('hasTopic', hasTopic);
|
||||
|
||||
- name: Download release asset
|
||||
id: download
|
||||
if: steps.check-label.outputs.hasTopic == 'true'
|
||||
uses: robinraju/release-downloader@v1.12
|
||||
with:
|
||||
repository: "${{ github.repository }}"
|
||||
tag: "${{ github.event.release.tag_name }}"
|
||||
fileName: "*.exe"
|
||||
tarBall: false
|
||||
zipBall: false
|
||||
out-file-path: "release_downloads"
|
||||
extract: false
|
||||
|
||||
- name: Release to WinGet
|
||||
if: >-
|
||||
steps.check-label.outputs.hasTopic == 'true' &&
|
||||
fromJson(steps.download.outputs.downloaded_files)[0]
|
||||
uses: vedantmgoyal2009/winget-releaser@v2
|
||||
with:
|
||||
identifier: "${{ github.repository_owner }}.${{ github.event.repository.name }}"
|
||||
release-tag: ${{ github.event.release.tag_name }}
|
||||
installers-regex: '\.exe$'
|
||||
token: ${{ secrets.GH_BOT_TOKEN }}
|
||||
@@ -27,6 +27,9 @@ endif()
|
||||
# set the module path, used for includes
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
# export compile_commands.json
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# set version info for this build
|
||||
include(${CMAKE_MODULE_PATH}/prep/build_version.cmake)
|
||||
|
||||
|
||||
@@ -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")
|
||||
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
|
||||
"${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/src/Input.h"
|
||||
"${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/src/Rtsp.h"
|
||||
|
||||
@@ -38,10 +38,17 @@ if(NOT DEFINED SUNSHINE_ICON_PATH)
|
||||
set(SUNSHINE_ICON_PATH "${CMAKE_SOURCE_DIR}/sunshine.ico")
|
||||
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
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/windows.rc"
|
||||
"${CMAKE_SOURCE_DIR}/src/platform/windows/publish.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/platform/windows/misc.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/platform/windows/misc.cpp"
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
# common cpack options
|
||||
set(CPACK_PACKAGE_NAME ${CMAKE_PROJECT_NAME})
|
||||
set(CPACK_PACKAGE_VENDOR "LizardByte")
|
||||
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_CONTACT "https://app.lizardbyte.dev")
|
||||
set(CPACK_PACKAGE_DESCRIPTION ${CMAKE_PROJECT_DESCRIPTION})
|
||||
|
||||
@@ -136,26 +136,13 @@ if(${SUNSHINE_TRAY} STREQUAL 1)
|
||||
endif()
|
||||
|
||||
# desktop file
|
||||
# todo - validate desktop files with `desktop-file-validate`
|
||||
if(NOT ${SUNSHINE_BUILD_FLATPAK})
|
||||
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()
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_FQDN}.desktop"
|
||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications")
|
||||
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")
|
||||
endif()
|
||||
|
||||
# metadata file
|
||||
# todo - validate file with `appstream-util validate-relax`
|
||||
if(NOT ${SUNSHINE_BUILD_FLATPAK})
|
||||
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()
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_FQDN}.metainfo.xml"
|
||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo")
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
# windows specific packaging
|
||||
|
||||
# see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.html
|
||||
install(TARGETS sunshine RUNTIME DESTINATION "." COMPONENT application)
|
||||
|
||||
# Hardening: include zlib1.dll (loaded via LoadLibrary() in openssl's libcrypto.a)
|
||||
@@ -52,79 +50,11 @@ cmake_path(CONVERT "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/assets/shaders"
|
||||
cmake_path(CONVERT "${CMAKE_BINARY_DIR}/assets/shaders" TO_NATIVE_PATH_LIST shaders_in_build_dest_native)
|
||||
execute_process(COMMAND cmd.exe /c mklink /J "${shaders_in_build_dest_native}" "${shaders_in_build_src_native}")
|
||||
|
||||
# set(CPACK_NSIS_MUI_HEADERIMAGE "") # TODO: image should be 150x57 bmp
|
||||
set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}\\\\sunshine.ico")
|
||||
set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\\\${PROJECT_EXE}")
|
||||
|
||||
# The name of the directory that will be created in C:/Program files/
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}")
|
||||
|
||||
# Extra install commands
|
||||
# Restores permissions on the install directory
|
||||
# Migrates config files from the root into the new config folder
|
||||
# Install service
|
||||
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS
|
||||
"${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}
|
||||
IfSilent +2 0
|
||||
ExecShell 'open' 'https://docs.lizardbyte.dev/projects/sunshine'
|
||||
nsExec::ExecToLog 'icacls \\\"$INSTDIR\\\" /reset'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\update-path.bat\\\" add'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\migrate-config.bat\\\"'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\add-firewall-rule.bat\\\"'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\install-gamepad.bat\\\"'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\install-service.bat\\\"'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\autostart-service.bat\\\"'
|
||||
NoController:
|
||||
")
|
||||
|
||||
# Extra uninstall commands
|
||||
# Uninstall service
|
||||
set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS
|
||||
"${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS}
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\delete-firewall-rule.bat\\\"'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\uninstall-service.bat\\\"'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe\\\" --restore-nvprefs-undo'
|
||||
MessageBox MB_YESNO|MB_ICONQUESTION \
|
||||
'Do you want to remove Virtual Gamepad?' \
|
||||
/SD IDNO IDNO NoGamepad
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\uninstall-gamepad.bat\\\"'; skipped if no
|
||||
NoGamepad:
|
||||
MessageBox MB_YESNO|MB_ICONQUESTION \
|
||||
'Do you want to remove $INSTDIR (this includes the configuration, cover images, and settings)?' \
|
||||
/SD IDNO IDNO NoDelete
|
||||
RMDir /r \\\"$INSTDIR\\\"; skipped if no
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\update-path.bat\\\" remove'
|
||||
NoDelete:
|
||||
")
|
||||
|
||||
# Adding an option for the start menu
|
||||
set(CPACK_NSIS_MODIFY_PATH OFF)
|
||||
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
||||
# This will be shown on the installed apps Windows settings
|
||||
set(CPACK_NSIS_INSTALLED_ICON_NAME "${CMAKE_PROJECT_NAME}.exe")
|
||||
set(CPACK_NSIS_CREATE_ICONS_EXTRA
|
||||
"${CPACK_NSIS_CREATE_ICONS_EXTRA}
|
||||
SetOutPath '\$INSTDIR'
|
||||
CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${CMAKE_PROJECT_NAME}.lnk' \
|
||||
'\$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe' '--shortcut'
|
||||
")
|
||||
set(CPACK_NSIS_DELETE_ICONS_EXTRA
|
||||
"${CPACK_NSIS_DELETE_ICONS_EXTRA}
|
||||
Delete '\$SMPROGRAMS\\\\$MUI_TEMP\\\\${CMAKE_PROJECT_NAME}.lnk'
|
||||
")
|
||||
|
||||
# Checking for previous installed versions
|
||||
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL "ON")
|
||||
|
||||
set(CPACK_NSIS_HELP_LINK "https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2getting__started.html")
|
||||
set(CPACK_NSIS_URL_INFO_ABOUT "${CMAKE_PROJECT_HOMEPAGE_URL}")
|
||||
set(CPACK_NSIS_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}/support")
|
||||
|
||||
set(CPACK_NSIS_MENU_LINKS
|
||||
"https://docs.lizardbyte.dev/projects/sunshine" "Sunshine documentation"
|
||||
"https://app.lizardbyte.dev" "LizardByte Web Site"
|
||||
"https://app.lizardbyte.dev/support" "LizardByte Support")
|
||||
set(CPACK_NSIS_MANIFEST_DPI_AWARE true)
|
||||
|
||||
# Setting components groups and dependencies
|
||||
set(CPACK_COMPONENT_GROUP_CORE_EXPANDED true)
|
||||
|
||||
@@ -165,3 +95,7 @@ set(CPACK_COMPONENT_FIREWALL_GROUP "Scripts")
|
||||
set(CPACK_COMPONENT_GAMEPAD_DISPLAY_NAME "Virtual Gamepad")
|
||||
set(CPACK_COMPONENT_GAMEPAD_DESCRIPTION "Scripts to install and uninstall Virtual Gamepad.")
|
||||
set(CPACK_COMPONENT_GAMEPAD_GROUP "Scripts")
|
||||
|
||||
# include specific packaging
|
||||
include(${CMAKE_MODULE_PATH}/packaging/windows_nsis.cmake)
|
||||
include(${CMAKE_MODULE_PATH}/packaging/windows_wix.cmake)
|
||||
|
||||
71
cmake/packaging/windows_nsis.cmake
Normal file
71
cmake/packaging/windows_nsis.cmake
Normal file
@@ -0,0 +1,71 @@
|
||||
# NSIS Packaging
|
||||
# see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.html
|
||||
|
||||
set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\\\${PROJECT_EXE}")
|
||||
|
||||
# Extra install commands
|
||||
# Restores permissions on the install directory
|
||||
# Migrates config files from the root into the new config folder
|
||||
# Install service
|
||||
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS
|
||||
"${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}
|
||||
IfSilent +2 0
|
||||
ExecShell 'open' 'https://docs.lizardbyte.dev/projects/sunshine'
|
||||
nsExec::ExecToLog 'icacls \\\"$INSTDIR\\\" /reset'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\update-path.bat\\\" add'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\migrate-config.bat\\\"'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\add-firewall-rule.bat\\\"'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\install-gamepad.bat\\\"'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\install-service.bat\\\"'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\autostart-service.bat\\\"'
|
||||
NoController:
|
||||
")
|
||||
|
||||
# Extra uninstall commands
|
||||
# Uninstall service
|
||||
set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS
|
||||
"${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS}
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\delete-firewall-rule.bat\\\"'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\uninstall-service.bat\\\"'
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe\\\" --restore-nvprefs-undo'
|
||||
MessageBox MB_YESNO|MB_ICONQUESTION \
|
||||
'Do you want to remove Virtual Gamepad?' \
|
||||
/SD IDNO IDNO NoGamepad
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\uninstall-gamepad.bat\\\"'; skipped if no
|
||||
NoGamepad:
|
||||
MessageBox MB_YESNO|MB_ICONQUESTION \
|
||||
'Do you want to remove $INSTDIR (this includes the configuration, cover images, and settings)?' \
|
||||
/SD IDNO IDNO NoDelete
|
||||
RMDir /r \\\"$INSTDIR\\\"; skipped if no
|
||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\update-path.bat\\\" remove'
|
||||
NoDelete:
|
||||
")
|
||||
|
||||
# Adding an option for the start menu
|
||||
set(CPACK_NSIS_MODIFY_PATH OFF)
|
||||
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
||||
# This will be shown on the installed apps Windows settings
|
||||
set(CPACK_NSIS_INSTALLED_ICON_NAME "${CMAKE_PROJECT_NAME}.exe")
|
||||
set(CPACK_NSIS_CREATE_ICONS_EXTRA
|
||||
"${CPACK_NSIS_CREATE_ICONS_EXTRA}
|
||||
SetOutPath '\$INSTDIR'
|
||||
CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${CMAKE_PROJECT_NAME}.lnk' \
|
||||
'\$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe' '--shortcut'
|
||||
")
|
||||
set(CPACK_NSIS_DELETE_ICONS_EXTRA
|
||||
"${CPACK_NSIS_DELETE_ICONS_EXTRA}
|
||||
Delete '\$SMPROGRAMS\\\\$MUI_TEMP\\\\${CMAKE_PROJECT_NAME}.lnk'
|
||||
")
|
||||
|
||||
# Checking for previous installed versions
|
||||
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL "ON")
|
||||
|
||||
set(CPACK_NSIS_HELP_LINK "https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2getting__started.html")
|
||||
set(CPACK_NSIS_URL_INFO_ABOUT "${CMAKE_PROJECT_HOMEPAGE_URL}")
|
||||
set(CPACK_NSIS_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}/support")
|
||||
|
||||
set(CPACK_NSIS_MENU_LINKS
|
||||
"https://docs.lizardbyte.dev/projects/sunshine" "Sunshine documentation"
|
||||
"https://app.lizardbyte.dev" "LizardByte Web Site"
|
||||
"https://app.lizardbyte.dev/support" "LizardByte Support")
|
||||
set(CPACK_NSIS_MANIFEST_DPI_AWARE true)
|
||||
72
cmake/packaging/windows_wix.cmake
Normal file
72
cmake/packaging/windows_wix.cmake
Normal file
@@ -0,0 +1,72 @@
|
||||
# WIX Packaging
|
||||
# see options at: https://cmake.org/cmake/help/latest/cpack_gen/wix.html
|
||||
|
||||
set(CPACK_WIX_VERSION 4)
|
||||
set(WIX_VERSION 4.0.4)
|
||||
set(WIX_UI_VERSION 4.0.4) # extension versioning is independent of the WiX version
|
||||
set(WIX_BUILD_PARENT_DIRECTORY "${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/win64")
|
||||
set(WIX_BUILD_DIRECTORY "${WIX_BUILD_PARENT_DIRECTORY}/WIX")
|
||||
|
||||
# Download and install WiX tools locally in the build directory
|
||||
set(WIX_TOOL_PATH "${CMAKE_BINARY_DIR}/.wix")
|
||||
file(MAKE_DIRECTORY ${WIX_TOOL_PATH})
|
||||
|
||||
# find dotnet
|
||||
find_program(DOTNET_EXECUTABLE dotnet REQUIRED HINTS "C:/Program Files/dotnet")
|
||||
|
||||
# Install WiX locally using dotnet
|
||||
execute_process(
|
||||
COMMAND ${DOTNET_EXECUTABLE} tool install --tool-path ${WIX_TOOL_PATH} wix --version ${WIX_VERSION}
|
||||
ERROR_VARIABLE WIX_INSTALL_OUTPUT
|
||||
RESULT_VARIABLE WIX_INSTALL_RESULT
|
||||
)
|
||||
|
||||
if(NOT WIX_INSTALL_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to install WiX tools locally.
|
||||
WiX packaging may not work correctly, error: ${WIX_INSTALL_OUTPUT}")
|
||||
endif()
|
||||
|
||||
# Install WiX UI Extension
|
||||
execute_process(
|
||||
COMMAND "${WIX_TOOL_PATH}/wix" extension add WixToolset.UI.wixext/${WIX_UI_VERSION}
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
ERROR_VARIABLE WIX_UI_INSTALL_OUTPUT
|
||||
RESULT_VARIABLE WIX_UI_INSTALL_RESULT
|
||||
)
|
||||
|
||||
if(NOT WIX_UI_INSTALL_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to install WiX UI extension, error: ${WIX_UI_INSTALL_OUTPUT}")
|
||||
endif()
|
||||
|
||||
# Set WiX-specific variables
|
||||
set(CPACK_WIX_ROOT "${WIX_TOOL_PATH}")
|
||||
set(CPACK_WIX_UPGRADE_GUID "512A3D1B-BE16-401B-A0D1-59BBA3942FB8")
|
||||
|
||||
# Help/Support URLs
|
||||
set(CPACK_WIX_HELP_LINK "https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2getting__started.html")
|
||||
set(CPACK_WIX_PRODUCT_URL "${CMAKE_PROJECT_HOMEPAGE_URL}")
|
||||
set(CPACK_WIX_PROGRAM_MENU_FOLDER "LizardByte")
|
||||
|
||||
set(CPACK_WIX_EXTENSIONS
|
||||
"WixToolset.UI.wixext"
|
||||
)
|
||||
|
||||
message(STATUS "cpack package directory: ${CPACK_PACKAGE_DIRECTORY}")
|
||||
|
||||
# copy custom wxs files to the build directory
|
||||
file(COPY "${CMAKE_CURRENT_LIST_DIR}/wix_resources/"
|
||||
DESTINATION "${WIX_BUILD_PARENT_DIRECTORY}/")
|
||||
|
||||
set(CPACK_WIX_EXTRA_SOURCES
|
||||
"${WIX_BUILD_PARENT_DIRECTORY}/custom-actions.wxs"
|
||||
"${WIX_BUILD_PARENT_DIRECTORY}/custom-shortcuts.wxs"
|
||||
)
|
||||
|
||||
# Copy root LICENSE and rename to have .txt extension
|
||||
file(COPY "${CMAKE_SOURCE_DIR}/LICENSE"
|
||||
DESTINATION "${CMAKE_BINARY_DIR}")
|
||||
file(RENAME "${CMAKE_BINARY_DIR}/LICENSE" "${CMAKE_BINARY_DIR}/LICENSE.txt")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_BINARY_DIR}/LICENSE.txt") # cpack will covert this to an RTF if it is txt
|
||||
|
||||
# https://cmake.org/cmake/help/latest/cpack_gen/wix.html#variable:CPACK_WIX_ARCHITECTURE
|
||||
set(CPACK_WIX_ARCHITECTURE "x64")
|
||||
100
cmake/packaging/wix_resources/custom-actions.wxs
Normal file
100
cmake/packaging/wix_resources/custom-actions.wxs
Normal file
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?include "WIX/cpack_variables.wxi"?>
|
||||
|
||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
|
||||
xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
|
||||
<Fragment Id="CustomActionsFragment">
|
||||
<CustomAction Id='InstallService'
|
||||
ExeCommand='cmd.exe /c "[INSTALL_ROOT]scripts\install-service.bat"'
|
||||
Directory='INSTALL_ROOT'
|
||||
Execute='deferred'
|
||||
Return='check'
|
||||
Impersonate='no' />
|
||||
|
||||
<CustomAction Id='ConfigFirewall'
|
||||
ExeCommand='cmd.exe /c "[INSTALL_ROOT]scripts\add-firewall-rule.bat"'
|
||||
Directory='INSTALL_ROOT'
|
||||
Execute='deferred'
|
||||
Return='check'
|
||||
Impersonate='no' />
|
||||
|
||||
<CustomAction Id='InstallGamepad'
|
||||
ExeCommand='cmd.exe /c "[INSTALL_ROOT]scripts\install-gamepad.bat"'
|
||||
Directory='INSTALL_ROOT'
|
||||
Execute='deferred'
|
||||
Return='check'
|
||||
Impersonate='no' />
|
||||
|
||||
<CustomAction Id='AutostartService'
|
||||
ExeCommand='cmd.exe /c "[INSTALL_ROOT]scripts\autostart-service.bat"'
|
||||
Directory='INSTALL_ROOT'
|
||||
Execute='deferred'
|
||||
Return='check'
|
||||
Impersonate='no' />
|
||||
|
||||
<CustomAction Id='MigrateConfig'
|
||||
ExeCommand='cmd.exe /c "[INSTALL_ROOT]scripts\migrate-config.bat"'
|
||||
Directory='INSTALL_ROOT'
|
||||
Execute='deferred'
|
||||
Return='check'
|
||||
Impersonate='no' />
|
||||
|
||||
<CustomAction Id='UpdatePath'
|
||||
ExeCommand='cmd.exe /c "[INSTALL_ROOT]scripts\update-path.bat add"'
|
||||
Directory='INSTALL_ROOT'
|
||||
Execute='deferred'
|
||||
Return='check'
|
||||
Impersonate='no' />
|
||||
|
||||
<CustomAction Id='ResetPermissions'
|
||||
ExeCommand='cmd.exe /c "icacls \"[INSTALL_ROOT]\" /reset"'
|
||||
Directory='INSTALL_ROOT'
|
||||
Execute='deferred'
|
||||
Return='check'
|
||||
Impersonate='no' />
|
||||
|
||||
<CustomAction Id='UninstallService'
|
||||
ExeCommand='cmd.exe /c "[INSTALL_ROOT]scripts\uninstall-service.bat"'
|
||||
Directory='INSTALL_ROOT'
|
||||
Execute='deferred'
|
||||
Return='check'
|
||||
Impersonate='no' />
|
||||
|
||||
<CustomAction Id='RemoveFirewall'
|
||||
ExeCommand='cmd.exe /c "[INSTALL_ROOT]scripts\delete-firewall-rule.bat"'
|
||||
Directory='INSTALL_ROOT'
|
||||
Execute='deferred'
|
||||
Return='check'
|
||||
Impersonate='no' />
|
||||
|
||||
<CustomAction Id='RestoreNvPrefs'
|
||||
ExeCommand='cmd.exe /c "[INSTALL_ROOT]$(var.CPACK_PACKAGE_NAME).exe --restore-nvprefs-undo"'
|
||||
Directory='INSTALL_ROOT'
|
||||
Execute='deferred'
|
||||
Return='check'
|
||||
Impersonate='no' />
|
||||
|
||||
<CustomAction Id='RemovePathUpdate'
|
||||
ExeCommand='cmd.exe /c "[INSTALL_ROOT]scripts\update-path.bat remove"'
|
||||
Directory='INSTALL_ROOT'
|
||||
Execute='deferred'
|
||||
Return='check'
|
||||
Impersonate='no' />
|
||||
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action='ResetPermissions' After='InstallFiles' Condition="NOT Installed" />
|
||||
<Custom Action='UpdatePath' After='ResetPermissions' Condition="NOT Installed" />
|
||||
<Custom Action='MigrateConfig' After='UpdatePath' Condition="NOT Installed" />
|
||||
<Custom Action='ConfigFirewall' After='MigrateConfig' Condition="NOT Installed" />
|
||||
<Custom Action='InstallGamepad' After='ConfigFirewall' Condition="NOT Installed" />
|
||||
<Custom Action='InstallService' After='InstallGamepad' Condition="NOT Installed" />
|
||||
<Custom Action='AutostartService' After='InstallService' Condition="NOT Installed" />
|
||||
|
||||
<Custom Action='RemoveFirewall' Before='RemoveFiles' Condition="REMOVE" />
|
||||
<Custom Action='UninstallService' Before='RemoveFiles' Condition="REMOVE" />
|
||||
<Custom Action='RestoreNvPrefs' Before='RemoveFiles' Condition="REMOVE" />
|
||||
<Custom Action='RemovePathUpdate' Before='RemoveFiles' Condition="REMOVE" />
|
||||
</InstallExecuteSequence>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
23
cmake/packaging/wix_resources/custom-shortcuts.wxs
Normal file
23
cmake/packaging/wix_resources/custom-shortcuts.wxs
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
|
||||
<?include "WIX/cpack_variables.wxi"?>
|
||||
|
||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||
<Fragment Id="CustomShortcutsFragment">
|
||||
<StandardDirectory Id='ProgramMenuFolder'>
|
||||
<Directory Id='ApplicationProgramsFolder' Name='$(var.CPACK_PACKAGE_VENDOR)'>
|
||||
<Component Id='ApplicationShortcut' Guid='*'>
|
||||
<Shortcut Id='ApplicationStartMenuShortcut'
|
||||
Name='$(var.CPACK_PACKAGE_NAME)'
|
||||
Description='Self-hosted game stream host for Moonlight'
|
||||
Target='[INSTALL_ROOT]$(var.CPACK_PACKAGE_NAME).exe'
|
||||
Arguments='--shortcut'
|
||||
WorkingDirectory='INSTALL_ROOT'/>
|
||||
<RemoveFolder Id='ApplicationProgramsFolder' On='uninstall'/>
|
||||
<RegistryValue Root='HKCU' Key='Software\\LizardByte\\$(var.CPACK_PACKAGE_NAME)'
|
||||
Name='installed' Type='integer' Value='1' KeyPath='yes'/>
|
||||
</Component>
|
||||
</Directory>
|
||||
</StandardDirectory>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
@@ -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
|
||||
if((DEFINED ENV{BRANCH}) AND (DEFINED ENV{BUILD_VERSION}) AND (DEFINED ENV{COMMIT})) # cmake-lint: disable=W0106
|
||||
if(($ENV{BRANCH} STREQUAL "master") AND (NOT $ENV{BUILD_VERSION} STREQUAL ""))
|
||||
# If BRANCH is "master" and BUILD_VERSION is not empty, then we are building a master branch
|
||||
MESSAGE("Got from CI master branch and version $ENV{BUILD_VERSION}")
|
||||
if((DEFINED ENV{BRANCH}) AND (DEFINED ENV{BUILD_VERSION})) # cmake-lint: disable=W0106
|
||||
if((DEFINED ENV{BRANCH}) AND (NOT $ENV{BUILD_VERSION} STREQUAL ""))
|
||||
# If BRANCH is defined and BUILD_VERSION is not empty, then we are building from CI
|
||||
# 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})
|
||||
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
|
||||
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()
|
||||
else()
|
||||
# Generate Sunshine Version based of the git tag
|
||||
# https://github.com/nocnokneo/cmake-git-versioning-example/blob/master/LICENSE
|
||||
else()
|
||||
find_package(Git)
|
||||
if(GIT_EXECUTABLE)
|
||||
MESSAGE("${CMAKE_SOURCE_DIR}")
|
||||
@@ -40,11 +56,11 @@ else()
|
||||
if(NOT GIT_DESCRIBE_ERROR_CODE)
|
||||
MESSAGE("Sunshine Branch: ${GIT_DESCRIBE_BRANCH}")
|
||||
if(NOT GIT_DESCRIBE_BRANCH STREQUAL "master")
|
||||
set(PROJECT_VERSION ${PROJECT_VERSION}.${GIT_DESCRIBE_VERSION})
|
||||
set(PROJECT_VERSION ${PROJECT_VERSION}-${GIT_DESCRIBE_VERSION})
|
||||
MESSAGE("Sunshine Version: ${GIT_DESCRIBE_VERSION}")
|
||||
endif()
|
||||
if(GIT_IS_DIRTY)
|
||||
set(PROJECT_VERSION ${PROJECT_VERSION}.dirty)
|
||||
set(PROJECT_VERSION ${PROJECT_VERSION}-dirty)
|
||||
MESSAGE("Git tree is dirty!")
|
||||
endif()
|
||||
else()
|
||||
@@ -54,3 +70,72 @@ else()
|
||||
MESSAGE(WARNING ": Git not found, cannot find git version")
|
||||
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}")
|
||||
|
||||
@@ -10,7 +10,6 @@ set(SUNSHINE_PUBLISHER_ISSUE_URL "https://app.lizardbyte.dev/support"
|
||||
option(BUILD_DOCS "Build documentation" ON)
|
||||
option(BUILD_TESTS "Build tests" ON)
|
||||
option(NPM_OFFLINE "Use offline npm packages. You must ensure packages are in your npm cache." OFF)
|
||||
option(TESTS_ENABLE_PYTHON_TESTS "Enable Python tests" ON)
|
||||
|
||||
option(BUILD_WERROR "Enable -Werror flag." OFF)
|
||||
|
||||
|
||||
@@ -12,19 +12,17 @@ elseif(UNIX)
|
||||
# configure the .desktop file
|
||||
set(SUNSHINE_DESKTOP_ICON "sunshine")
|
||||
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})
|
||||
set(SUNSHINE_DESKTOP_ICON "${PROJECT_FQDN}")
|
||||
configure_file(packaging/linux/flatpak/sunshine.desktop sunshine.desktop @ONLY)
|
||||
configure_file(packaging/linux/flatpak/${PROJECT_FQDN}.metainfo.xml
|
||||
${PROJECT_FQDN}.metainfo.xml @ONLY)
|
||||
configure_file(packaging/linux/flatpak/${PROJECT_FQDN}.desktop ${PROJECT_FQDN}.desktop @ONLY)
|
||||
else()
|
||||
configure_file(packaging/linux/sunshine.desktop sunshine.desktop @ONLY)
|
||||
configure_file(packaging/linux/sunshine_terminal.desktop sunshine_terminal.desktop @ONLY)
|
||||
configure_file(packaging/linux/${PROJECT_FQDN}.desktop ${PROJECT_FQDN}.desktop @ONLY)
|
||||
configure_file(packaging/linux/${PROJECT_FQDN}.terminal.desktop ${PROJECT_FQDN}.terminal.desktop @ONLY)
|
||||
endif()
|
||||
|
||||
# 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_file(packaging/linux/sunshine.service.in sunshine.service @ONLY)
|
||||
@@ -38,8 +36,6 @@ elseif(UNIX)
|
||||
# configure the flatpak manifest
|
||||
if(${SUNSHINE_CONFIGURE_FLATPAK_MAN})
|
||||
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/modules 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")
|
||||
find_library(ZLIB ZLIB1)
|
||||
list(APPEND SUNSHINE_EXTERNAL_LIBRARIES
|
||||
$<TARGET_OBJECTS:sunshine_rc_object>
|
||||
Windowsapp.lib
|
||||
Wtsapi32.lib)
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
"two_letters_code": {
|
||||
# map non-two letter codes here, left side is crowdin designation, right side is babel designation
|
||||
"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"
|
||||
|
||||
@@ -28,6 +28,7 @@ ARG CLONE_URL
|
||||
ENV BRANCH=${BRANCH}
|
||||
ENV BUILD_VERSION=${BUILD_VERSION}
|
||||
ENV COMMIT=${COMMIT}
|
||||
ENV CLONE_URL=${CLONE_URL}
|
||||
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
@@ -68,19 +69,16 @@ WORKDIR /build/sunshine/build
|
||||
RUN <<_MAKE
|
||||
#!/bin/bash
|
||||
set -e
|
||||
if [[ "${BUILD_VERSION}" == '' ]]; then
|
||||
|
||||
sub_version=""
|
||||
if [[ "${BRANCH}" != "master" ]]; then
|
||||
sub_version=".r${COMMIT}"
|
||||
else
|
||||
sub_version=""
|
||||
fi
|
||||
|
||||
cmake \
|
||||
-DSUNSHINE_CONFIGURE_ONLY=ON \
|
||||
-DSUNSHINE_CONFIGURE_PKGBUILD=ON \
|
||||
-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
|
||||
_MAKE
|
||||
|
||||
@@ -114,14 +112,13 @@ rm -f /build/sunshine/pkg/sunshine-debug*.pkg.tar.zst
|
||||
ls -a
|
||||
_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
|
||||
|
||||
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
|
||||
RUN <<_INSTALL_SUNSHINE
|
||||
|
||||
@@ -51,16 +51,17 @@ Xvfb ${DISPLAY} -screen 0 1024x768x24 &
|
||||
./test_sunshine --gtest_color=yes
|
||||
_TEST
|
||||
|
||||
FROM scratch AS artifacts
|
||||
FROM sunshine-base AS sunshine
|
||||
|
||||
ARG BASE
|
||||
ARG TAG
|
||||
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 --link --from=artifacts /sunshine*.deb /sunshine.deb
|
||||
COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /sunshine.deb
|
||||
|
||||
# install sunshine
|
||||
RUN <<_INSTALL_SUNSHINE
|
||||
|
||||
@@ -51,16 +51,17 @@ Xvfb ${DISPLAY} -screen 0 1024x768x24 &
|
||||
./test_sunshine --gtest_color=yes
|
||||
_TEST
|
||||
|
||||
FROM scratch AS artifacts
|
||||
FROM sunshine-base AS sunshine
|
||||
|
||||
ARG BASE
|
||||
ARG TAG
|
||||
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 --link --from=artifacts /sunshine*.deb /sunshine.deb
|
||||
COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /sunshine.deb
|
||||
|
||||
# install sunshine
|
||||
RUN <<_INSTALL_SUNSHINE
|
||||
|
||||
@@ -51,16 +51,17 @@ Xvfb ${DISPLAY} -screen 0 1024x768x24 &
|
||||
./test_sunshine --gtest_color=yes
|
||||
_TEST
|
||||
|
||||
FROM scratch AS artifacts
|
||||
FROM sunshine-base AS sunshine
|
||||
|
||||
ARG BASE
|
||||
ARG TAG
|
||||
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 --link --from=artifacts /sunshine*.deb /sunshine.deb
|
||||
COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /sunshine.deb
|
||||
|
||||
# install sunshine
|
||||
RUN <<_INSTALL_SUNSHINE
|
||||
|
||||
@@ -9,7 +9,7 @@ function generateExamples(endpoint, method, body = null) {
|
||||
}
|
||||
|
||||
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
|
||||
import requests
|
||||
from requests.auth import HTTPBasicAuth
|
||||
@@ -30,6 +30,7 @@ requests.${method.trim().toLowerCase()}(
|
||||
.then(data => console.log(data));`,
|
||||
PowerShell: `Invoke-RestMethod \`
|
||||
-SkipCertificateCheck \`
|
||||
-ContentType 'application/json' \`
|
||||
-Uri 'https://localhost:47990${endpoint.trim()}' \`
|
||||
-Method ${method.trim()} \`
|
||||
-Headers @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes('user:pass'))}
|
||||
|
||||
@@ -138,9 +138,12 @@ ninja -C build
|
||||
```}
|
||||
}}
|
||||
@tab{Windows | @tabs{
|
||||
@tab{Installer | ```bash
|
||||
@tab{NSIS Installer | ```bash
|
||||
cpack -G NSIS --config ./build/CPackConfig.cmake
|
||||
```}
|
||||
@tab{WiX Installer | ```bash
|
||||
cpack -G WIX --config ./build/CPackConfig.cmake
|
||||
```}
|
||||
@tab{Portable | ```bash
|
||||
cpack -G ZIP --config ./build/CPackConfig.cmake
|
||||
```}
|
||||
|
||||
@@ -57,10 +57,14 @@ editing the `conf` file in a text editor. Use the examples as reference.
|
||||
@endcode</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="18">Choices</td>
|
||||
<td rowspan="20">Choices</td>
|
||||
<td>bg</td>
|
||||
<td>Bulgarian</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>cs</td>
|
||||
<td>Czech</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>de</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>Chinese (Simplified)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>zh_TW</td>
|
||||
<td>Chinese (Traditional)</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### sunshine_name
|
||||
@@ -1363,35 +1371,6 @@ editing the `conf` file in a text editor. Use the examples as reference.
|
||||
</tr>
|
||||
</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
|
||||
|
||||
### upnp
|
||||
|
||||
@@ -5,8 +5,8 @@ Read our contribution guide in our organization level
|
||||
## Recommended Tools
|
||||
|
||||
| Tool | Description |
|
||||
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| <a href="https://www.jetbrains.com/clion/"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/CLion_icon.svg" width="30" height="30"></a><br>CLion | Recommended IDE for C++ development. Free licenses available for open source developers through the [JetBrains Open Source Program](https://www.jetbrains.com/community/opensource/). |
|
||||
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------|
|
||||
| <a href="https://www.jetbrains.com/clion/"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/CLion_icon.svg" width="30" height="30"></a><br>CLion | Recommended IDE for C and C++ development. Free for non-commercial use. |
|
||||
|
||||
## Project Patterns
|
||||
|
||||
|
||||
@@ -56,27 +56,28 @@ need to install CUDA.}
|
||||
</tr>
|
||||
<tr>
|
||||
<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>sunshine-debian-bookworm-{arch}.deb</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="1">12.5.1</td>
|
||||
<td>sunshine.pkg.tar.zst</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2">12.6.2</td>
|
||||
<td rowspan="2">560.35.03</td>
|
||||
<td>sunshine_{arch}.flatpak</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sunshine (copr - Fedora 40/41)</td>
|
||||
<td>Sunshine (copr - Fedora 41)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="1">12.8.1</td>
|
||||
<td rowspan="1">570.124.06</td>
|
||||
<td>Sunshine (copr - Fedora 42)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="1">12.9.1</td>
|
||||
<td rowspan="1">575.57.08</td>
|
||||
<td>sunshine.pkg.tar.zst</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
#### AppImage
|
||||
@@ -283,7 +284,7 @@ brew uninstall sunshine
|
||||
#### Installer (recommended)
|
||||
|
||||
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
|
||||
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!}
|
||||
|
||||
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
|
||||
3. Firewall rules
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 133 KiB |
@@ -465,6 +465,36 @@ ext-js:
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- New Nintendo 3DS -->
|
||||
<div class="col-md-6 col-lg-4 mb-5">
|
||||
<div class="card bg-dark text-white rounded-0">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="icon text-white">
|
||||
<img class="invert" src="https://cdn.jsdelivr.net/npm/simple-icons@v12/icons/nintendo3ds.svg" alt="3DS"/>
|
||||
</div>
|
||||
<div class="ms-3">
|
||||
<h5 class="fw-bolder mb-0">
|
||||
<a href="https://github.com/zoeyjodon/moonlight-N3DS" target="_blank" class="text-white text-decoration-none">
|
||||
New Nintendo 3DS
|
||||
</a>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="ms-auto">
|
||||
<span class="badge text-bg-warning rounded-pill">Community</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer p-3 px-4">
|
||||
<div class="pb-3">
|
||||
<a href="https://github.com/zoeyjodon/moonlight-N3DS" target="_blank" class="btn btn-info">
|
||||
<i class="fas fa-download"></i> Download
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- LG webOS TV -->
|
||||
<div class="col-md-6 col-lg-4 mb-5">
|
||||
<div class="card bg-dark text-white rounded-0">
|
||||
|
||||
12
package.json
12
package.json
@@ -8,15 +8,15 @@
|
||||
"serve": "serve ./tests/fixtures/http --no-port-switching"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lizardbyte/shared-web": "2025.326.11214",
|
||||
"vue": "3.5.13",
|
||||
"vue-i18n": "11.1.3"
|
||||
"@lizardbyte/shared-web": "2025.626.181239",
|
||||
"vue": "3.5.17",
|
||||
"vue-i18n": "11.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@codecov/vite-plugin": "1.9.0",
|
||||
"@codecov/vite-plugin": "1.9.1",
|
||||
"@vitejs/plugin-vue": "4.6.2",
|
||||
"serve": "14.2.3",
|
||||
"vite": "4.5.9",
|
||||
"serve": "14.2.4",
|
||||
"vite": "4.5.14",
|
||||
"vite-plugin-ejs": "1.6.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=@PROJECT_NAME@
|
||||
Exec=sunshine
|
||||
Version=1.0
|
||||
Categories=RemoteAccess;Network;
|
||||
Comment=@PROJECT_DESCRIPTION@
|
||||
Exec=sunshine
|
||||
Icon=sunshine
|
||||
Keywords=gamestream;stream;moonlight;remote play;
|
||||
Categories=AudioVideo;Network;RemoteAccess;
|
||||
Name=@PROJECT_NAME@
|
||||
Terminal=true
|
||||
Type=Application
|
||||
Version=1.0
|
||||
X-AppImage-Arch=x86_64
|
||||
X-AppImage-Name=sunshine
|
||||
X-AppImage-Version=@PROJECT_VERSION@
|
||||
X-AppImage-Arch=x86_64
|
||||
@@ -10,7 +10,7 @@ url=@PROJECT_HOMEPAGE_URL@
|
||||
license=('GPL-3.0-only')
|
||||
install=sunshine.install
|
||||
|
||||
_gcc_version=13
|
||||
_gcc_version=14
|
||||
|
||||
depends=(
|
||||
'avahi'
|
||||
@@ -36,7 +36,10 @@ depends=(
|
||||
)
|
||||
|
||||
makedepends=(
|
||||
'appstream'
|
||||
'appstream-glib'
|
||||
'cmake'
|
||||
'desktop-file-utils'
|
||||
'cuda'
|
||||
"gcc${_gcc_version}"
|
||||
'git'
|
||||
@@ -64,7 +67,7 @@ prepare() {
|
||||
|
||||
build() {
|
||||
export BRANCH="@GITHUB_BRANCH@"
|
||||
export BUILD_VERSION="@GITHUB_BUILD_VERSION@"
|
||||
export BUILD_VERSION="@BUILD_VERSION@"
|
||||
export COMMIT="@GITHUB_COMMIT@"
|
||||
|
||||
export CC="gcc-${_gcc_version}"
|
||||
@@ -86,6 +89,11 @@ build() {
|
||||
-D SUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' \
|
||||
-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
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=@PROJECT_NAME@
|
||||
Exec=/usr/bin/env systemctl start --u sunshine
|
||||
Version=1.0
|
||||
Actions=RunInTerminal;
|
||||
Categories=RemoteAccess;Network;
|
||||
Comment=@PROJECT_DESCRIPTION@
|
||||
Exec=/usr/bin/env systemctl start --u sunshine
|
||||
Icon=@SUNSHINE_DESKTOP_ICON@
|
||||
Keywords=gamestream;stream;moonlight;remote play;
|
||||
Categories=AudioVideo;Network;RemoteAccess;
|
||||
Actions=RunInTerminal;
|
||||
Name=@PROJECT_NAME@
|
||||
Type=Application
|
||||
Version=1.0
|
||||
|
||||
[Desktop Action RunInTerminal]
|
||||
Name=Run in Terminal
|
||||
Exec=gio launch @CMAKE_INSTALL_FULL_DATAROOTDIR@/applications/@PROJECT_FQDN@.terminal.desktop
|
||||
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"?>
|
||||
<component type="desktop-application">
|
||||
<component type="desktop">
|
||||
<id>@PROJECT_FQDN@</id>
|
||||
|
||||
<name>@CMAKE_PROJECT_NAME@</name>
|
||||
<name>@PROJECT_NAME@</name>
|
||||
<summary>@PROJECT_BRIEF_DESCRIPTION@</summary>
|
||||
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
@@ -15,39 +15,49 @@
|
||||
<control>gamepad</control>
|
||||
</supports>
|
||||
|
||||
<url type="bugtracker">https://github.com/LizardByte/Sunshine/issues</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="contact">https://app.lizardbyte.dev/support</url>
|
||||
<url type="translate">https://translate.lizardbyte.dev</url>
|
||||
<url type="contribute">https://docs.lizardbyte.dev</url>
|
||||
<url type="vcs-browser">https://github.com/LizardByte/Sunshine</url>
|
||||
<url type="contact">https://app.lizardbyte.dev/support</url>
|
||||
|
||||
<description>
|
||||
<p>
|
||||
@PROJECT_LONG_DESCRIPTION@
|
||||
</p>
|
||||
|
||||
<p>NOTE: Sunshine requires additional installation steps.</p>
|
||||
<p>NOTE: Sunshine requires additional installation steps (Flatpak).</p>
|
||||
<p>
|
||||
<code>flatpak run --command=additional-install.sh @PROJECT_FQDN@</code>
|
||||
</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>
|
||||
<code>sudo -i PULSE_SERVER=unix:/run/user/$(id -u $whoami)/pulse/native flatpak run @PROJECT_FQDN@</code>
|
||||
</p>
|
||||
</description>
|
||||
|
||||
<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>
|
||||
|
||||
<developer_name>LizardByte</developer_name>
|
||||
<developer id="dev.lizardbyte">
|
||||
<name>LizardByte</name>
|
||||
</developer>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>https://app.lizardbyte.dev/Sunshine/assets/img/banners/AdobeStock_305732536_1920x1280.jpg</image>
|
||||
<caption>Sunshine</caption>
|
||||
<image>https://app.lizardbyte.dev/Sunshine/assets/img/screenshots/01-sunshine-welcome-page.png</image>
|
||||
<caption>Sunshine welcome page</caption>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<content_rating type="oars-1.0">
|
||||
@@ -15,8 +15,11 @@ License: GPLv3-only
|
||||
URL: https://github.com/LizardByte/Sunshine
|
||||
Source0: tarball.tar.gz
|
||||
|
||||
BuildRequires: appstream
|
||||
# BuildRequires: boost-devel >= 1.86.0
|
||||
BuildRequires: cmake >= 3.25.0
|
||||
BuildRequires: desktop-file-utils
|
||||
BuildRequires: libappstream-glib
|
||||
BuildRequires: libayatana-appindicator3-devel
|
||||
BuildRequires: libcap-devel
|
||||
BuildRequires: libcurl-devel
|
||||
@@ -197,6 +200,11 @@ cmake "${cmake_args[@]}"
|
||||
make -j$(nproc) -C "%{_builddir}/Sunshine/build"
|
||||
|
||||
%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
|
||||
cd %{_builddir}/Sunshine/build
|
||||
xvfb-run ./tests/test_sunshine
|
||||
@@ -252,14 +260,14 @@ rm -f /usr/lib/modules-load.d/uhid.conf
|
||||
%{_modulesloaddir}/uhid.conf
|
||||
|
||||
# Desktop entries
|
||||
%{_datadir}/applications/sunshine*.desktop
|
||||
%{_datadir}/applications/*.desktop
|
||||
|
||||
# Icons
|
||||
%{_datadir}/icons/hicolor/scalable/apps/sunshine.svg
|
||||
%{_datadir}/icons/hicolor/scalable/status/sunshine*.svg
|
||||
|
||||
# Metainfo
|
||||
%{_datadir}/metainfo/sunshine.appdata.xml
|
||||
%{_datadir}/metainfo/*.metainfo.xml
|
||||
|
||||
# Assets
|
||||
%{_datadir}/sunshine/**
|
||||
|
||||
Submodule packaging/linux/flatpak/deps/flatpak-builder-tools updated: bf91cb0bee...903919f82f
Submodule packaging/linux/flatpak/deps/shared-modules updated: 1f8e591b26...8a98211689
@@ -1,5 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Categories=AudioVideo;Network;RemoteAccess;
|
||||
Categories=RemoteAccess;Network;
|
||||
Comment=@PROJECT_DESCRIPTION@
|
||||
Exec=sunshine.sh
|
||||
Icon=@SUNSHINE_DESKTOP_ICON@
|
||||
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"dev.lizardbyte.app.Sunshine": [
|
||||
"appstream-missing-screenshots",
|
||||
"appstream-external-screenshot-url",
|
||||
"appstream-screenshots-not-mirrored-in-ostree",
|
||||
"external-gitmodule-url-found",
|
||||
"finish-args-flatpak-spawn-access"
|
||||
"finish-args-flatpak-spawn-access",
|
||||
"finish-args-home-filesystem-access"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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@"
|
||||
url "@GITHUB_CLONE_URL@",
|
||||
tag: "@GITHUB_TAG@"
|
||||
version "@FORMULA_VERSION@"
|
||||
version "@BUILD_VERSION@"
|
||||
license all_of: ["GPL-3.0-only"]
|
||||
head "@GITHUB_CLONE_URL@", branch: "@GITHUB_DEFAULT_BRANCH@"
|
||||
|
||||
@@ -32,7 +32,6 @@ class @PROJECT_NAME@ < Formula
|
||||
depends_on "ninja" => :build
|
||||
depends_on "node" => :build
|
||||
depends_on "pkg-config" => :build
|
||||
depends_on "gcovr" => :test
|
||||
depends_on "curl"
|
||||
depends_on "miniupnpc"
|
||||
depends_on "openssl"
|
||||
@@ -320,31 +319,31 @@ index 5b3638d..aca9481 100644
|
||||
run [opt_bin/"sunshine", "~/.config/sunshine/sunshine.conf"]
|
||||
end
|
||||
|
||||
def caveats
|
||||
caveats_message = <<~EOS
|
||||
Thanks for installing @PROJECT_NAME@!
|
||||
|
||||
To get started, review the documentation at:
|
||||
https://docs.lizardbyte.dev/projects/sunshine
|
||||
EOS
|
||||
|
||||
def post_install
|
||||
if OS.linux?
|
||||
caveats_message += <<~EOS
|
||||
opoo <<~EOS
|
||||
ATTENTION: To complete installation, you must run the following command:
|
||||
`sudo #{bin}/postinst`
|
||||
EOS
|
||||
end
|
||||
|
||||
if OS.mac?
|
||||
caveats_message += <<~EOS
|
||||
opoo <<~EOS
|
||||
Sunshine can only access microphones on macOS due to system limitations.
|
||||
To stream system audio use "Soundflower" or "BlackHole".
|
||||
|
||||
Gamepads are not currently supported on macOS.
|
||||
EOS
|
||||
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
|
||||
|
||||
test do
|
||||
@@ -354,21 +353,5 @@ index 5b3638d..aca9481 100644
|
||||
# run the test suite
|
||||
system bin/"test_sunshine", "--gtest_color=yes", "--gtest_output=xml:test_results.xml"
|
||||
assert_path_exists testpath/"test_results.xml"
|
||||
|
||||
# create gcovr report
|
||||
if ENV["HOMEBREW_BUILDPATH"]
|
||||
|
||||
cd File.join(ENV["HOMEBREW_BUILDPATH"], "build") do
|
||||
system "gcovr", ".",
|
||||
"-r", "../src",
|
||||
"--exclude-noncode-lines",
|
||||
"--exclude-throw-branches",
|
||||
"--exclude-unreachable-branches",
|
||||
"--verbose",
|
||||
"--xml-pretty",
|
||||
"-o=coverage.xml"
|
||||
end
|
||||
assert_path_exists File.join(ENV["HOMEBREW_BUILDPATH"], "build", "coverage.xml")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,6 +25,7 @@ year = datetime.datetime.now().year
|
||||
# target locales
|
||||
target_locales = [
|
||||
'bg', # Bulgarian
|
||||
'cs', # Czech
|
||||
'de', # German
|
||||
'en', # English
|
||||
'en_GB', # English (United Kingdom)
|
||||
@@ -42,6 +43,7 @@ target_locales = [
|
||||
'tr', # Turkish
|
||||
'uk', # Ukrainian
|
||||
'zh', # Chinese
|
||||
'zh_TW', # Chinese (Traditional)
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -138,9 +138,12 @@ function add_arch_deps() {
|
||||
|
||||
function add_debian_based_deps() {
|
||||
dependencies+=(
|
||||
"appstream"
|
||||
"appstream-util"
|
||||
"bison" # required if we need to compile doxygen
|
||||
"build-essential"
|
||||
"cmake"
|
||||
"desktop-file-utils"
|
||||
"doxygen"
|
||||
"flex" # required if we need to compile doxygen
|
||||
"gcc-${gcc_version}"
|
||||
@@ -201,13 +204,16 @@ function add_ubuntu_deps() {
|
||||
|
||||
function add_fedora_deps() {
|
||||
dependencies+=(
|
||||
"appstream"
|
||||
"cmake"
|
||||
"desktop-file-utils"
|
||||
"doxygen"
|
||||
"gcc${gcc_version}"
|
||||
"gcc${gcc_version}-c++"
|
||||
"git"
|
||||
"graphviz"
|
||||
"libappindicator-gtk3-devel"
|
||||
"libappstream-glib"
|
||||
"libcap-devel"
|
||||
"libcurl-devel"
|
||||
"libdrm-devel"
|
||||
@@ -386,7 +392,7 @@ function run_install() {
|
||||
"gcc-ranlib"
|
||||
)
|
||||
|
||||
#set gcc version based on distros
|
||||
#set gcc version based on distros
|
||||
if [ "$distro" == "arch" ]; then
|
||||
export CC=gcc-14
|
||||
export CXX=g++-14
|
||||
@@ -460,6 +466,8 @@ function run_install() {
|
||||
install_cuda
|
||||
cmake_args+=("-DSUNSHINE_ENABLE_CUDA=ON")
|
||||
cmake_args+=("-DCMAKE_CUDA_COMPILER:PATH=$nvcc_path")
|
||||
else
|
||||
cmake_args+=("-DSUNSHINE_ENABLE_CUDA=OFF")
|
||||
fi
|
||||
|
||||
# Cmake stuff here
|
||||
@@ -467,6 +475,16 @@ function run_install() {
|
||||
echo "cmake args:"
|
||||
echo "${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"
|
||||
|
||||
# Create the package
|
||||
@@ -564,6 +582,15 @@ elif grep -q "Ubuntu 24.04" /etc/os-release; then
|
||||
cuda_build="520.61.05"
|
||||
gcc_version="11"
|
||||
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
|
||||
echo "Unsupported Distro or Version"
|
||||
exit 1
|
||||
|
||||
@@ -504,7 +504,6 @@ namespace config {
|
||||
{} // wa
|
||||
}, // display_device
|
||||
|
||||
1, // min_fps_factor
|
||||
0 // max_bitrate
|
||||
};
|
||||
|
||||
@@ -1143,7 +1142,6 @@ namespace config {
|
||||
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);
|
||||
|
||||
path_f(vars, "pkey", nvhttp.pkey);
|
||||
@@ -1240,6 +1238,7 @@ namespace config {
|
||||
|
||||
string_restricted_f(vars, "locale", config::sunshine.locale, {
|
||||
"bg"sv, // Bulgarian
|
||||
"cs"sv, // Czech
|
||||
"de"sv, // German
|
||||
"en"sv, // English
|
||||
"en_GB"sv, // English (UK)
|
||||
@@ -1257,6 +1256,7 @@ namespace config {
|
||||
"tr"sv, // Turkish
|
||||
"uk"sv, // Ukrainian
|
||||
"zh"sv, // Chinese
|
||||
"zh_TW"sv, // Chinese (Traditional)
|
||||
});
|
||||
|
||||
std::string log_level_string;
|
||||
|
||||
@@ -140,7 +140,6 @@ namespace config {
|
||||
workarounds_t wa;
|
||||
} 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
|
||||
};
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "process.h"
|
||||
#include "utility.h"
|
||||
#include "uuid.h"
|
||||
#include "version.h"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
@@ -81,7 +80,8 @@ namespace confighttp {
|
||||
void send_response(resp_https_t response, const nlohmann::json &output_tree) {
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -103,7 +103,9 @@ namespace confighttp {
|
||||
|
||||
const SimpleWeb::CaseInsensitiveMultimap headers {
|
||||
{"Content-Type", "application/json"},
|
||||
{"WWW-Authenticate", R"(Basic realm="Sunshine Gamestream Host", charset="UTF-8")"}
|
||||
{"WWW-Authenticate", R"(Basic realm="Sunshine Gamestream Host", charset="UTF-8")"},
|
||||
{"X-Frame-Options", "DENY"},
|
||||
{"Content-Security-Policy", "frame-ancestors 'none';"}
|
||||
};
|
||||
|
||||
response->write(code, tree.dump(), headers);
|
||||
@@ -119,7 +121,9 @@ namespace confighttp {
|
||||
auto address = net::addr_to_normalized_string(request->remote_endpoint().address());
|
||||
BOOST_LOG(info) << "Web UI: ["sv << address << "] -- not authorized"sv;
|
||||
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);
|
||||
}
|
||||
@@ -189,6 +193,8 @@ namespace confighttp {
|
||||
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
}
|
||||
@@ -209,10 +215,45 @@ namespace confighttp {
|
||||
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Validate the request content type and send bad request when mismatch.
|
||||
* @param response The HTTP response object.
|
||||
* @param request The HTTP request object.
|
||||
* @param contentType The expected content type
|
||||
*/
|
||||
bool check_content_type(resp_https_t response, req_https_t request, const std::string_view &contentType) {
|
||||
auto requestContentType = request->header.find("content-type");
|
||||
if (requestContentType == request->header.end()) {
|
||||
bad_request(response, request, "Content type not provided");
|
||||
return false;
|
||||
}
|
||||
// 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");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the index page.
|
||||
* @param response The HTTP response object.
|
||||
@@ -229,6 +270,8 @@ namespace confighttp {
|
||||
std::string content = file_handler::read_file(WEB_DIR "index.html");
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -247,6 +290,8 @@ namespace confighttp {
|
||||
std::string content = file_handler::read_file(WEB_DIR "pin.html");
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -265,6 +310,8 @@ namespace confighttp {
|
||||
std::string content = file_handler::read_file(WEB_DIR "apps.html");
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
headers.emplace("Content-Type", "text/html; charset=utf-8");
|
||||
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);
|
||||
}
|
||||
@@ -284,6 +331,8 @@ namespace confighttp {
|
||||
std::string content = file_handler::read_file(WEB_DIR "clients.html");
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -302,6 +351,8 @@ namespace confighttp {
|
||||
std::string content = file_handler::read_file(WEB_DIR "config.html");
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -320,6 +371,8 @@ namespace confighttp {
|
||||
std::string content = file_handler::read_file(WEB_DIR "password.html");
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -337,6 +390,8 @@ namespace confighttp {
|
||||
std::string content = file_handler::read_file(WEB_DIR "welcome.html");
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -355,6 +410,8 @@ namespace confighttp {
|
||||
std::string content = file_handler::read_file(WEB_DIR "troubleshooting.html");
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -371,6 +428,8 @@ namespace confighttp {
|
||||
std::ifstream in(WEB_DIR "images/sunshine.ico", std::ios::binary);
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -387,6 +446,8 @@ namespace confighttp {
|
||||
std::ifstream in(WEB_DIR "images/logo-sunshine-45.png", std::ios::binary);
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -438,6 +499,8 @@ namespace confighttp {
|
||||
// if it is, set the content type to the mime type
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
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);
|
||||
response->write(SimpleWeb::StatusCode::success_ok, in, headers);
|
||||
}
|
||||
@@ -535,6 +598,9 @@ namespace confighttp {
|
||||
* @api_examples{/api/apps| POST| {"name":"Hello, World!","index":-1}}
|
||||
*/
|
||||
void saveApp(resp_https_t response, req_https_t request) {
|
||||
if (!check_content_type(response, request, "application/json")) {
|
||||
return;
|
||||
}
|
||||
if (!authenticate(response, request)) {
|
||||
return;
|
||||
}
|
||||
@@ -602,6 +668,9 @@ namespace confighttp {
|
||||
* @api_examples{/api/apps/close| POST| null}
|
||||
*/
|
||||
void closeApp(resp_https_t response, req_https_t request) {
|
||||
if (!check_content_type(response, request, "application/json")) {
|
||||
return;
|
||||
}
|
||||
if (!authenticate(response, request)) {
|
||||
return;
|
||||
}
|
||||
@@ -623,6 +692,9 @@ namespace confighttp {
|
||||
* @api_examples{/api/apps/9999| DELETE| null}
|
||||
*/
|
||||
void deleteApp(resp_https_t response, req_https_t request) {
|
||||
if (!check_content_type(response, request, "application/json")) {
|
||||
return;
|
||||
}
|
||||
if (!authenticate(response, request)) {
|
||||
return;
|
||||
}
|
||||
@@ -703,6 +775,9 @@ namespace confighttp {
|
||||
* @api_examples{/api/unpair| POST| {"uuid":"1234"}}
|
||||
*/
|
||||
void unpair(resp_https_t response, req_https_t request) {
|
||||
if (!check_content_type(response, request, "application/json")) {
|
||||
return;
|
||||
}
|
||||
if (!authenticate(response, request)) {
|
||||
return;
|
||||
}
|
||||
@@ -733,6 +808,9 @@ namespace confighttp {
|
||||
* @api_examples{/api/clients/unpair-all| POST| null}
|
||||
*/
|
||||
void unpairAll(resp_https_t response, req_https_t request) {
|
||||
if (!check_content_type(response, request, "application/json")) {
|
||||
return;
|
||||
}
|
||||
if (!authenticate(response, request)) {
|
||||
return;
|
||||
}
|
||||
@@ -764,7 +842,7 @@ namespace confighttp {
|
||||
nlohmann::json output_tree;
|
||||
output_tree["status"] = true;
|
||||
output_tree["platform"] = SUNSHINE_PLATFORM;
|
||||
output_tree["version"] = PROJECT_VER;
|
||||
output_tree["version"] = PROJECT_VERSION;
|
||||
|
||||
auto vars = config::parse_config(file_handler::read_file(config::sunshine.config_file.c_str()));
|
||||
|
||||
@@ -809,6 +887,9 @@ namespace confighttp {
|
||||
* @api_examples{/api/config| POST| {"key":"value"}}
|
||||
*/
|
||||
void saveConfig(resp_https_t response, req_https_t request) {
|
||||
if (!check_content_type(response, request, "application/json")) {
|
||||
return;
|
||||
}
|
||||
if (!authenticate(response, request)) {
|
||||
return;
|
||||
}
|
||||
@@ -855,6 +936,9 @@ namespace confighttp {
|
||||
* @api_examples{/api/covers/upload| POST| {"key":"igdb_1234","url":"https://images.igdb.com/igdb/image/upload/t_cover_big_2x/abc123.png"}}
|
||||
*/
|
||||
void uploadCover(resp_https_t response, req_https_t request) {
|
||||
if (!check_content_type(response, request, "application/json")) {
|
||||
return;
|
||||
}
|
||||
if (!authenticate(response, request)) {
|
||||
return;
|
||||
}
|
||||
@@ -917,6 +1001,8 @@ namespace confighttp {
|
||||
std::string content = file_handler::read_file(config::sunshine.log_file.c_str());
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
headers.emplace("Content-Type", "text/plain");
|
||||
headers.emplace("X-Frame-Options", "DENY");
|
||||
headers.emplace("Content-Security-Policy", "frame-ancestors 'none';");
|
||||
response->write(SimpleWeb::StatusCode::success_ok, content, headers);
|
||||
}
|
||||
|
||||
@@ -938,6 +1024,9 @@ namespace confighttp {
|
||||
* @api_examples{/api/password| POST| {"currentUsername":"admin","currentPassword":"admin","newUsername":"admin","newPassword":"admin","confirmNewPassword":"admin"}}
|
||||
*/
|
||||
void savePassword(resp_https_t response, req_https_t request) {
|
||||
if (!check_content_type(response, request, "application/json")) {
|
||||
return;
|
||||
}
|
||||
if (!config::sunshine.username.empty() && !authenticate(response, request)) {
|
||||
return;
|
||||
}
|
||||
@@ -1008,6 +1097,9 @@ namespace confighttp {
|
||||
* @api_examples{/api/pin| POST| {"pin":"1234","name":"My PC"}}
|
||||
*/
|
||||
void savePin(resp_https_t response, req_https_t request) {
|
||||
if (!check_content_type(response, request, "application/json")) {
|
||||
return;
|
||||
}
|
||||
if (!authenticate(response, request)) {
|
||||
return;
|
||||
}
|
||||
@@ -1044,6 +1136,9 @@ namespace confighttp {
|
||||
* @api_examples{/api/reset-display-device-persistence| POST| null}
|
||||
*/
|
||||
void resetDisplayDevicePersistence(resp_https_t response, req_https_t request) {
|
||||
if (!check_content_type(response, request, "application/json")) {
|
||||
return;
|
||||
}
|
||||
if (!authenticate(response, request)) {
|
||||
return;
|
||||
}
|
||||
@@ -1063,6 +1158,9 @@ namespace confighttp {
|
||||
* @api_examples{/api/restart| POST| null}
|
||||
*/
|
||||
void restart(resp_https_t response, req_https_t request) {
|
||||
if (!check_content_type(response, request, "application/json")) {
|
||||
return;
|
||||
}
|
||||
if (!authenticate(response, request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "logging.h"
|
||||
#include "network.h"
|
||||
#include "platform/common.h"
|
||||
#include "version.h"
|
||||
|
||||
extern "C" {
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "process.h"
|
||||
#include "system_tray.h"
|
||||
#include "upnp.h"
|
||||
#include "version.h"
|
||||
#include "video.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -95,6 +94,10 @@ int main(int argc, char *argv[]) {
|
||||
task_pool_util::TaskPool::task_id_t force_shutdown = nullptr;
|
||||
|
||||
#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");
|
||||
#endif
|
||||
|
||||
@@ -119,7 +122,7 @@ int main(int argc, char *argv[]) {
|
||||
// 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
|
||||
// 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_data();
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
+ (NSString *)getDisplayName:(CGDirectDisplayID)displayID {
|
||||
for (NSScreen *screen in [NSScreen screens]) {
|
||||
if (screen.deviceDescription[@"NSScreenNumber"] == [NSNumber numberWithUnsignedInt:displayID]) {
|
||||
if ([screen.deviceDescription[@"NSScreenNumber"] isEqualToNumber:[NSNumber numberWithUnsignedInt:displayID]]) {
|
||||
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_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"
|
||||
#elif defined(__i386) || defined(_M_IX86)
|
||||
#define STEAM_DRIVER_SUBDIR L"x86"
|
||||
#else
|
||||
#warning No known Steam audio driver for this architecture
|
||||
#endif
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
/**
|
||||
* @file src/platform/windows/windows.rc.in
|
||||
* @brief Windows resource file template.
|
||||
* @note The final `windows.rc` is generated from this file during the CMake build.
|
||||
* @todo Use CMake definitions directly, instead of configuring this file.
|
||||
* @file src/platform/windows/windows.rc
|
||||
* @brief Windows resource file.
|
||||
*/
|
||||
#include "winver.h"
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
|
||||
PRODUCTVERSION @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
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
@@ -16,13 +18,13 @@ BEGIN
|
||||
BEGIN
|
||||
BLOCK "040904E4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "LizardByte\0"
|
||||
VALUE "FileDescription", "Sunshine\0"
|
||||
VALUE "FileVersion", "@PROJECT_VERSION@\0"
|
||||
VALUE "InternalName", "Sunshine\0"
|
||||
VALUE "LegalCopyright", "https://raw.githubusercontent.com/LizardByte/Sunshine/master/LICENSE\0"
|
||||
VALUE "ProductName", "Sunshine\0"
|
||||
VALUE "ProductVersion", "@PROJECT_VERSION@\0"
|
||||
VALUE "CompanyName", TOSTRING(PROJECT_VENDOR)
|
||||
VALUE "FileDescription", TOSTRING(PROJECT_NAME)
|
||||
VALUE "FileVersion", TOSTRING(PROJECT_VERSION)
|
||||
VALUE "InternalName", TOSTRING(PROJECT_NAME)
|
||||
VALUE "ProductName", TOSTRING(PROJECT_NAME)
|
||||
VALUE "ProductVersion", TOSTRING(PROJECT_VERSION)
|
||||
VALUE "LegalCopyright", "https://raw.githubusercontent.com/LizardByte/Sunshine/master/LICENSE"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -39,4 +41,4 @@ BEGIN
|
||||
|
||||
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 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
|
||||
#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.
|
||||
*/
|
||||
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")) {
|
||||
reed_solomon_new_fn = reed_solomon_new_avx512;
|
||||
reed_solomon_release_fn = reed_solomon_release_avx512;
|
||||
|
||||
@@ -1263,7 +1263,7 @@ namespace stream {
|
||||
void videoBroadcastThread(udp::socket &sock) {
|
||||
auto shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown);
|
||||
auto packets = mail::man->queue<video::packet_t>(mail::video_packets);
|
||||
auto timebase = boost::posix_time::microsec_clock::universal_time();
|
||||
auto video_epoch = std::chrono::steady_clock::now();
|
||||
|
||||
// Video traffic is sent on this thread
|
||||
platf::adjust_thread_priority(platf::thread_priority_e::high);
|
||||
@@ -1459,14 +1459,20 @@ namespace stream {
|
||||
|
||||
size_t next_shard_to_send = 0;
|
||||
|
||||
// RTP video timestamps use a 90 KHz clock and the frame_timestamp from when the frame was captured
|
||||
// When a timestamp isn't available (duplicate frames), the timestamp from rate control is used instead.
|
||||
bool frame_is_dupe = false;
|
||||
if (!packet->frame_timestamp) {
|
||||
packet->frame_timestamp = ratecontrol_next_frame_start;
|
||||
frame_is_dupe = true;
|
||||
}
|
||||
using rtp_tick = std::chrono::duration<uint32_t, std::ratio<1, 90000>>;
|
||||
uint32_t timestamp = std::chrono::round<rtp_tick>(*packet->frame_timestamp - video_epoch).count();
|
||||
|
||||
// set FEC info now that we know for sure what our percentage will be for this frame
|
||||
for (auto x = 0; x < shards.size(); ++x) {
|
||||
auto *inspect = (video_packet_raw_t *) shards.data(x);
|
||||
|
||||
// RTP video timestamps use a 90 KHz clock
|
||||
auto now = boost::posix_time::microsec_clock::universal_time();
|
||||
auto timestamp = (now - timebase).total_microseconds() / (1000 / 90);
|
||||
|
||||
inspect->packet.fecInfo =
|
||||
(x << 12 |
|
||||
shards.data_shards << 22 |
|
||||
@@ -1558,11 +1564,11 @@ namespace stream {
|
||||
|
||||
frame_network_latency_logger.second_point_now_and_log();
|
||||
|
||||
if (packet->is_idr()) {
|
||||
BOOST_LOG(verbose) << "Key Frame ["sv << packet->frame_index() << "] :: send ["sv << shards.size() << "] shards..."sv;
|
||||
} else {
|
||||
BOOST_LOG(verbose) << "Frame ["sv << packet->frame_index() << "] :: send ["sv << shards.size() << "] shards..."sv << std::endl;
|
||||
}
|
||||
BOOST_LOG(verbose) << "Sent Frame seq ["sv << packet->frame_index() << "] pts ["sv << timestamp
|
||||
<< "] shards ["sv << shards.size() << "/"sv << shards.percentage << "%]"sv
|
||||
<< (frame_is_dupe ? " Dupe" : "")
|
||||
<< (packet->is_idr() ? " Key" : "")
|
||||
<< (packet->after_ref_frame_invalidation ? " RFI" : "");
|
||||
|
||||
++blockIndex;
|
||||
lowseq += shards.size();
|
||||
@@ -1622,6 +1628,8 @@ namespace stream {
|
||||
break;
|
||||
}
|
||||
|
||||
BOOST_LOG(verbose) << "Audio [seq "sv << sequenceNumber << ", pts "sv << timestamp << "] :: send..."sv;
|
||||
|
||||
audio_packet.rtp.sequenceNumber = util::endian::big(sequenceNumber);
|
||||
audio_packet.rtp.timestamp = util::endian::big(timestamp);
|
||||
|
||||
@@ -1641,7 +1649,6 @@ namespace stream {
|
||||
session->localAddress,
|
||||
};
|
||||
platf::send(send_info);
|
||||
BOOST_LOG(verbose) << "Audio ["sv << sequenceNumber << "] :: send..."sv;
|
||||
|
||||
auto &fec_packet = session->audio.fec_packet;
|
||||
// initialize the FEC header at the beginning of the FEC block
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
#include "platform/common.h"
|
||||
#include "process.h"
|
||||
#include "src/entry_handler.h"
|
||||
#include "version.h"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
* @file src/upnp.cpp
|
||||
* @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
|
||||
#include <miniupnpc/miniupnpc.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@"
|
||||
@@ -1875,9 +1875,9 @@ namespace video {
|
||||
}
|
||||
});
|
||||
|
||||
// set minimum frame time, avoiding violation of client-requested target framerate
|
||||
auto minimum_frame_time = std::chrono::milliseconds(1000 / std::min(config.framerate, (config::video.min_fps_factor * 10)));
|
||||
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;
|
||||
// set minimum frame time based on client-requested target framerate
|
||||
std::chrono::duration<double, std::milli> minimum_frame_time {1000.0 / config.framerate};
|
||||
BOOST_LOG(info) << "Minimum frame time set to "sv << minimum_frame_time.count() << "ms, based on client-requested target framerate "sv << config.framerate << "."sv;
|
||||
|
||||
auto shutdown_event = mail->event<bool>(mail::shutdown);
|
||||
auto packets = mail::man->queue<packet_t>(mail::video_packets);
|
||||
|
||||
@@ -440,7 +440,12 @@
|
||||
"Are you sure to delete " + this.apps[id].name + "?"
|
||||
);
|
||||
if (resp) {
|
||||
fetch("./api/apps/" + id, { method: "DELETE" }).then((r) => {
|
||||
fetch("./api/apps/" + id, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
}).then((r) => {
|
||||
if (r.status === 200) document.location.reload();
|
||||
});
|
||||
}
|
||||
@@ -540,6 +545,9 @@
|
||||
this.coverFinderBusy = true;
|
||||
fetch("./api/covers/upload", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
key: cover.key,
|
||||
url: cover.saveUrl,
|
||||
@@ -555,6 +563,9 @@
|
||||
this.editForm["image-path"] = this.editForm["image-path"].toString().replace(/"/g, '');
|
||||
fetch("./api/apps", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(this.editForm),
|
||||
}).then((r) => {
|
||||
if (r.status === 200) document.location.reload();
|
||||
|
||||
@@ -178,7 +178,6 @@
|
||||
"dd_config_revert_on_disconnect": "disabled",
|
||||
"dd_mode_remapping": {"mixed": [], "resolution_only": [], "refresh_rate_only": []},
|
||||
"dd_wa_hdr_toggle_delay": 0,
|
||||
"min_fps_factor": 1,
|
||||
"max_bitrate": 0,
|
||||
},
|
||||
},
|
||||
@@ -371,6 +370,9 @@
|
||||
|
||||
return fetch("./api/config", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(config),
|
||||
}).then((r) => {
|
||||
if (r.status === 200) {
|
||||
@@ -393,7 +395,10 @@
|
||||
this.saved = this.restarted = false;
|
||||
}, 5000);
|
||||
fetch("./api/restart", {
|
||||
method: "POST"
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -32,6 +32,7 @@ function removeCmd(index) {
|
||||
<label for="locale" class="form-label">{{ $t('config.locale') }}</label>
|
||||
<select id="locale" class="form-select" v-model="config.locale">
|
||||
<option value="bg">Български (Bulgarian)</option>
|
||||
<option value="cs">Čeština (Czech)</option>
|
||||
<option value="de">Deutsch (German)</option>
|
||||
<option value="en">English</option>
|
||||
<option value="en_GB">English, UK</option>
|
||||
@@ -49,6 +50,7 @@ function removeCmd(index) {
|
||||
<option value="tr">Türkçe (Turkish)</option>
|
||||
<option value="uk">Українська (Ukranian)</option>
|
||||
<option value="zh">简体中文 (Chinese Simplified)</option>
|
||||
<option value="zh_TW">繁體中文 (Chinese Traditional)</option>
|
||||
</select>
|
||||
<div class="form-text">{{ $t('config.locale_desc') }}</div>
|
||||
</div>
|
||||
|
||||
@@ -11,13 +11,6 @@ const config = ref(props.config)
|
||||
</script>
|
||||
|
||||
<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-->
|
||||
<div class="mb-3">
|
||||
<label for="max_bitrate" class="form-label">{{ $t("config.max_bitrate") }}</label>
|
||||
|
||||
@@ -92,6 +92,9 @@
|
||||
this.error = null;
|
||||
fetch("./api/password", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(this.passwordData),
|
||||
}).then((r) => {
|
||||
if (r.status === 200) {
|
||||
|
||||
@@ -39,7 +39,13 @@
|
||||
let name = document.querySelector("#name-input").value;
|
||||
document.querySelector("#status").innerHTML = "";
|
||||
let b = JSON.stringify({pin: pin, name: name});
|
||||
fetch("./api/pin", {method: "POST", body: b})
|
||||
fetch("./api/pin", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: b
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((response) => {
|
||||
if (response.status === true) {
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
"cancel": "Отказ",
|
||||
"disabled": "Изключено",
|
||||
"disabled_def": "Изключено (по подразбиране)",
|
||||
"disabled_def_cbox": "По подразбиране: отметнато",
|
||||
"disabled_def_cbox": "По подразбиране: без отметка",
|
||||
"dismiss": "Отхвърляне",
|
||||
"do_cmd": "Команда преди стартиране",
|
||||
"elevated": "Изпълнение като администратор",
|
||||
"enabled": "Включено",
|
||||
"enabled_def": "Включено (по подразбиране)",
|
||||
"enabled_def_cbox": "По подразбиране: проверено",
|
||||
"enabled_def_cbox": "По подразбиране: с отметка",
|
||||
"error": "Грешка!",
|
||||
"note": "Забележка:",
|
||||
"password": "Парола",
|
||||
@@ -65,7 +65,7 @@
|
||||
"env_vars_desc": "Всички команди получават тези променливи на средата по подразбиране:",
|
||||
"env_xrandr_example": "Пример за автоматизиране на резолюцията чрез Xrandr:",
|
||||
"exit_timeout": "Време за изчакване при затваряне",
|
||||
"exit_timeout_desc": "Брой секунди за изчакване на всички процеси на приложението да завършат самостоятелно, когато бъде изпратена заявка за затваряне. Ако не е зададено, по подразбиране се изчаква до 5 секунди. Ако е зададено 0 или отрицателна стойност, приложението ще бъде прекратено незабавно.",
|
||||
"exit_timeout_desc": "Брой секунди за изчакване на всички процеси на приложението да завършат самостоятелно, когато бъде изпратена заявка за затваряне. Ако не е зададено, по подразбиране се изчаква до 5 секунди. Ако е зададена стойност 0, приложението ще бъде прекратено незабавно.",
|
||||
"find_cover": "Търсене на обложка",
|
||||
"global_prep_desc": "Включване/изключване на изпълнението на глобалните подготвителни команди за това приложение.",
|
||||
"global_prep_name": "Глобални команди за подготовка",
|
||||
@@ -152,43 +152,47 @@
|
||||
"controller_desc": "Позволява на клиентите да управляват отдалечения компютър с контролер",
|
||||
"credentials_file": "Файл с удостоверителни данни",
|
||||
"credentials_file_desc": "Съхраняване на потребителското име/парола отделно от файла за състоянието на Sunshine.",
|
||||
"dd_config_ensure_active": "Автоматично активиране на дисплея",
|
||||
"dd_config_ensure_only_display": "Деактивиране на други дисплеи и активиране само на посочения дисплей",
|
||||
"dd_config_ensure_primary": "Автоматично активиране на дисплея и превръщането му в основен дисплей",
|
||||
"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_verify_only": "Проверете дали дисплеят е включен (по подразбиране)",
|
||||
"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": "Полетата \"Requested\" могат да бъдат оставени празни, за да съответстват на всяка поискана стойност.",
|
||||
"dd_mode_remapping_desc_4_final_values_mixed": "Трябва да се посочи поне едно поле \"Final\". Непосочената разделителна способност или честота на опресняване няма да бъдат променени.",
|
||||
"dd_mode_remapping_desc_4_final_values_non_mixed": "Полето \"Final\" трябва да бъде посочено и не може да бъде празно.",
|
||||
"dd_mode_remapping_desc_5_sops_mixed_only": "Опцията \"Оптимизиране на настройките на играта\" трябва да е разрешена в клиента Moonlight, в противен случай се пропускат записи с посочени полета за разделителна способност.",
|
||||
"dd_mode_remapping_desc_5_sops_resolution_only": "Опцията \"Оптимизиране на настройките на играта\" трябва да е разрешена в клиента Moonlight, в противен случай мапингът се пропуска.",
|
||||
"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_mode_remapping_requested_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_refresh_rate_option_auto": "Използване на стойността за кадри/сек зададена от клиента (по подразбиране)",
|
||||
"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_desc": "Когато използвате виртуално дисплейно устройство за стрийминг, то може да покаже неправилен HDR цвят. С активирането на тази опция Sunshine ще се опита да смекчи този проблем.",
|
||||
"dd_wa_hdr_toggle": "Активиране на заобикаляне на висококонтрастния режим за HDR",
|
||||
"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": "Когато използвате виртуално екранно устройство за излъчването, е възможно цветовето на HDR да са неправилни. Sunshine може да се опита да смекчи този проблем, като изключи 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": "При принудително симулиране на контролер DualShock 4, да се симулира натискането на бутона Back/Select чрез натискане на сензорния панел",
|
||||
"encoder": "Принудително използване на определен метод на кодиране",
|
||||
@@ -229,7 +233,7 @@
|
||||
"key_repeat_delay_desc": "Колко бързо да започва повтарянето на симулираното натискане на клавишите, при задържането им в натиснато положение. Това е първоначалното закъснение в милисекунди преди да за почне повторението на клавишите.",
|
||||
"key_repeat_frequency": "Честота на повтаряне на клавишите",
|
||||
"key_repeat_frequency_desc": "Колко често да се извършват симулирани натискания на клавишите в секунда, при задържане на клавишите в натиснато положение. Стойността тук може да бъде и нецяло число.",
|
||||
"key_rightalt_to_key_win": "Карта на клавиш Alt вдясно към клавиш Windows",
|
||||
"key_rightalt_to_key_win": "Използване на десния Alt като заместител на клавиша Windows",
|
||||
"key_rightalt_to_key_win_desc": "Възможно е натискането на клавиша Windows да не може да бъде изпратено към сървъра от Moonlight. В тези случаи може да настроите Sunshine да мисли, че десният Alt е клавишът Windows.",
|
||||
"keyboard": "Управление чрез клавиатура",
|
||||
"keyboard_desc": "Позволява на клиентите да управляват отдалечения компютър с клавиатура",
|
||||
@@ -250,8 +254,8 @@
|
||||
"log_level_desc": "Минималното ниво на съобщения в журнала, извеждан на стандартния изход",
|
||||
"log_path": "Път до журналния файл",
|
||||
"log_path_desc": "Файлът, в който се запазва текущия журнал на Sunshine.",
|
||||
"min_fps_factor": "Коефициент на минимален брой кадри/сек",
|
||||
"min_fps_factor_desc": "Sunshine ще използва този коефициент за изчисляване на минималното време между кадрите. Лекото увеличаване на тази стойност може да помогне при излъчване на предимно статично съдържание. По-високите стойности ще създадат по-голям мрежов трафик.",
|
||||
"max_bitrate": "Максимална побитова скорост",
|
||||
"max_bitrate_desc": "Максималната побитова скорост (в Kbps), с която да се кодира потокът. Ако е зададена стойност 0, винаги ще се използва скоростта, поискана от Moonlight.",
|
||||
"min_threads": "Минимален брой нишки на процесора",
|
||||
"min_threads_desc": "Увеличаването на стойността леко намалява ефективността на кодирането, но компромисът обикновено си заслужава, тъй като ще се използват повече процесорни ядра за кодиране. Идеалната стойност е най-ниската възможна стойност, при която кодирането може да се извършва надеждно при желаните от настройки за излъчване и използваният хардуер.",
|
||||
"misc": "Други настройки",
|
||||
@@ -277,8 +281,6 @@
|
||||
"nvenc_realtime_hags_desc": "В момента драйверите на NVIDIA могат да засичат при кодиране, ако HAGS е включено, използва се реално-времеви приоритет и използването на видео паметта е близо до максимума. Изключването на тази опция понижава приоритета до „висок“, заобикаляйки засичането за сметка на намалена производителност на прихващане на екрана, когато графичният процесор е силно натоварен.",
|
||||
"nvenc_spatial_aq": "Пространствено AQ",
|
||||
"nvenc_spatial_aq_desc": "Използване на по-високи стойности на QP за по-простите области във видеото. Препоръчително е това да бъде включено, когато се излъчва с по-ниска побитова скорост.",
|
||||
"nvenc_spatial_aq_disabled": "Изключено (по-бързо, по подразбиране)",
|
||||
"nvenc_spatial_aq_enabled": "Включено (по-бавно)",
|
||||
"nvenc_twopass": "Режим на две преминавания",
|
||||
"nvenc_twopass_desc": "Добавя предварителна стъпка на кодиране. Това позволява да се открият повече вектори на движение, да се разпредели по-добре побитовата скорост в рамките на кадъра, както и да се спазват по-стриктно ограниченията на побитовата скорост. Изключването не се препоръчва, тъй като това може да доведе до периодично превишаване на зададената побитова скорост и последваща загуба на пакети.",
|
||||
"nvenc_twopass_disabled": "Изключено (най-бързо, не се препоръчва)",
|
||||
@@ -325,6 +327,8 @@
|
||||
"qsv_slow_hevc": "Разрешаване на бавното кодиране чрез HEVC",
|
||||
"qsv_slow_hevc_desc": "Това може да даде възможност за кодиране чрез HEVC при ползване на по-стари графични процесори на Intel, за сметка на по-голямо използване на графичния процесор и по-ниска производителност.",
|
||||
"restart_note": "Sunshine се рестартира, за да се приложат промените.",
|
||||
"stream_audio": "Предаване на звука към клиента",
|
||||
"stream_audio_desc": "Дали да предавате звука към клиента или не. Изключването на тази опция може да бъде полезно за излъчване към безжичен екран, когато се ползва като втори монитор.",
|
||||
"sunshine_name": "Име на Sunshine",
|
||||
"sunshine_name_desc": "Името, показвано в Moonlight за този сървър. Ако не е посочено, се използва името на компютъра.",
|
||||
"sw_preset": "Настройка на софтуерното кодиране",
|
||||
@@ -416,10 +420,10 @@
|
||||
"third_party_notice": "Забележка относно ползването на имената на трети страни"
|
||||
},
|
||||
"troubleshooting": {
|
||||
"dd_reset": "Нулиране на настройките на постоянното устройство за показване",
|
||||
"dd_reset_desc": "Ако Sunshine заседне при опит да възстанови променените настройки на устройството за показване, можете да нулирате настройките и да продължите да възстановявате състоянието на дисплея ръчно.",
|
||||
"dd_reset_error": "Грешка при нулиране на постоянството!",
|
||||
"dd_reset_success": "Успешно нулиране на постоянството!",
|
||||
"dd_reset": "Нулиране на зададените настройки за екранното устройство",
|
||||
"dd_reset_desc": "Ако Sunshine заседне опитвайки се да върне променените настройки на екранното устройство, можете да нулирате настройките и да възстановите състоянието на екрана ръчно.",
|
||||
"dd_reset_error": "Грешка при нулиране на настройките!",
|
||||
"dd_reset_success": "Успешно нулиране на настройките!",
|
||||
"force_close": "Принудително затваряне",
|
||||
"force_close_desc": "Ако Moonlight се оплаква, че дадено приложение работи в момента, принудителното затваряне на това приложение би трябвало да реши проблема.",
|
||||
"force_close_error": "Грешка при затваряне на приложението",
|
||||
|
||||
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."
|
||||
}
|
||||
}
|
||||
@@ -158,6 +158,8 @@
|
||||
"dd_config_label": "Gerätekonfiguration",
|
||||
"dd_config_revert_delay": "Zurücksetzungsverzögerung konfigurieren",
|
||||
"dd_config_revert_delay_desc": "Zusätzliche Verzögerung in Millisekunden, um zu warten, bevor die Konfiguration rückgängig gemacht wird, wenn die App geschlossen oder die letzte Sitzung beendet wurde. Hauptziel ist es, einen reibungsloseren Übergang beim schnellen Wechsel zwischen Apps zu ermöglichen.",
|
||||
"dd_config_revert_on_disconnect": "Zurücksetzen bei Trennung konfigurieren",
|
||||
"dd_config_revert_on_disconnect_desc": "Die Konfiguration beim Trennen aller Clients rückgängig machen, anstatt die App zu schließen oder die letzte Session zu beenden.",
|
||||
"dd_config_verify_only": "Überprüfen Sie, ob das Display aktiviert ist (Standard)",
|
||||
"dd_hdr_option": "HDR",
|
||||
"dd_hdr_option_auto": "Ein-/Ausschalten des HDR-Modus, wie vom Client gewünscht (Standard)",
|
||||
@@ -187,8 +189,10 @@
|
||||
"dd_resolution_option_manual": "Manuell eingegebene Auflösung verwenden",
|
||||
"dd_resolution_option_manual_desc": "Die zu verwendende Auflösung eingeben",
|
||||
"dd_resolution_option_ogs_desc": "Die Option \"Spieleinstellungen optimieren\" muss auf dem Moonlight-Client aktiviert sein, damit dies funktioniert.",
|
||||
"dd_wa_hdr_toggle_desc": "Wenn das virtuelle Display-Gerät als Streaming verwendet wird, könnte es eine falsche HDR-Farbe anzeigen. Wenn diese Option aktiviert ist, wird Sunshine versuchen, dieses Problem zu lindern.",
|
||||
"dd_wa_hdr_toggle": "Hochkontrast-Workaround für HDR aktivieren",
|
||||
"dd_wa_hdr_toggle_delay_desc_1": "Bei Verwendung des virtuellen Display-Geräts (VDD) zum Streamen kann es zu Fehlern bei der Anzeige der HDR-Farbe kommen. Sunshine kann versuchen, dieses Problem zu lindern, indem HDR ausgeschaltet und dann wieder eingeschaltet wird.",
|
||||
"dd_wa_hdr_toggle_delay_desc_2": "Wenn der Wert auf 0 gesetzt ist, ist die Workaround deaktiviert (Standard). Wenn der Wert zwischen 0 und 3000 Millisekunden liegt, schaltet Sonnenschein HDR, warten Sie auf die angegebene Zeit und schalten Sie HDR wieder ein. Die empfohlene Verzögerungszeit beträgt in den meisten Fällen etwa 500 Millisekunden.",
|
||||
"dd_wa_hdr_toggle_delay_desc_3": "Benutzen Sie diese Workaround nicht, es sei denn, Sie haben tatsächlich Probleme mit HDR, da sie direkt Auswirkungen auf die Startzeit des Streams hat!",
|
||||
"dd_wa_hdr_toggle_delay": "Workaround mit hohem Kontrast für HDR",
|
||||
"ds4_back_as_touchpad_click": "Zum Touchpad-Klick zurück/auswählen",
|
||||
"ds4_back_as_touchpad_click_desc": "Beim Erzwingen der DS4-Emulation zum Touchpad-Klick zurück/auswählen",
|
||||
"encoder": "Erzwinge einen bestimmten Encoder",
|
||||
@@ -250,8 +254,8 @@
|
||||
"log_level_desc": "Der minimale Log-Level wird auf Standard gedruckt",
|
||||
"log_path": "Logdateipfad",
|
||||
"log_path_desc": "Die Datei, in der die aktuellen Logs von Sunshine gespeichert werden.",
|
||||
"min_fps_factor": "Minimaler FPS Faktor",
|
||||
"min_fps_factor_desc": "Sonnenschein verwendet diesen Faktor, um die minimale Zeit zwischen den Frames zu berechnen. Die Erhöhung dieses Wertes kann helfen, wenn überwiegend statische Inhalte gestreamt werden. Höhere Werte verbrauchen mehr Bandbreite.",
|
||||
"max_bitrate": "Maximale Bitrate",
|
||||
"max_bitrate_desc": "Die maximale Bitrate (in Kbps), bei der Sunshine den Stream kodiert. Wenn sie auf 0 gesetzt ist, wird sie immer die Bitrate verwenden, die von Mononlight angefordert wird.",
|
||||
"min_threads": "Minimale CPU-Thread-Anzahl",
|
||||
"min_threads_desc": "Die Erhöhung des Wertes verringert die Encoding-Effizienz, aber der Abgleich lohnt sich in der Regel, mehr CPU-Kerne für die Kodierung zu verwenden. Der ideale Wert ist der niedrigste Wert, der zuverlässig an den gewünschten Streaming-Einstellungen auf Ihrer Hardware kodieren kann.",
|
||||
"misc": "Verschiedene Optionen",
|
||||
@@ -277,8 +281,6 @@
|
||||
"nvenc_realtime_hags_desc": "Derzeit können NVIDIA-Treiber im Encoder einfrieren, wenn HAGS aktiviert ist, Echtzeit-Priorität verwendet wird und die VRAM-Auslastung fast fast erreicht ist. Die Deaktivierung dieser Option senkt die Priorität auf hoch, indem das Einfrieren auf Kosten einer reduzierten Aufnahmeleistung umgangen wird, wenn die GPU stark belastet ist.",
|
||||
"nvenc_spatial_aq": "Spatial AQ",
|
||||
"nvenc_spatial_aq_desc": "Zuweisen von höheren QP-Werten zu flachen Regionen des Videos. Wird empfohlen zu aktivieren, wenn Streaming mit niedrigeren Bitraten.",
|
||||
"nvenc_spatial_aq_disabled": "Deaktiviert (schneller, Standard)",
|
||||
"nvenc_spatial_aq_enabled": "Aktiviert (langsamer)",
|
||||
"nvenc_twopass": "Zwei-Pass-Modus",
|
||||
"nvenc_twopass_desc": "Fügt vorläufige Kodierungen hinzu. Dies erlaubt es, mehr Bewegungsvektoren zu erkennen, eine bessere Verteilung der Bitrate über den Rahmen und strengere Einhaltung der Bitratengrenzen. Die Deaktivierung ist nicht empfehlenswert, da dies gelegentlich zu Bitraten-Overshoot und anschließendem Paketverlust führen kann.",
|
||||
"nvenc_twopass_disabled": "Deaktiviert (schnellste, nicht empfohlen)",
|
||||
@@ -325,6 +327,8 @@
|
||||
"qsv_slow_hevc": "Langsame HEVC Encodierung erlauben",
|
||||
"qsv_slow_hevc_desc": "Dies kann HEVC-Kodierung auf älteren Intel GPUs ermöglichen, auf Kosten einer höheren GPU-Nutzung und schlechteren Performance.",
|
||||
"restart_note": "Sunshine wird neu gestartet, um Änderungen anzuwenden.",
|
||||
"stream_audio": "Stream Audio",
|
||||
"stream_audio_desc": "Ob Audio gestrahlt werden soll oder nicht. Deaktivieren kann nützlich sein, um kopflose Displays als zweiten Monitor zu streamen.",
|
||||
"sunshine_name": "Sunshine Name",
|
||||
"sunshine_name_desc": "Der von Mononlight angezeigte Name, falls nicht angegeben, wird der Hostname des PCs verwendet",
|
||||
"sw_preset": "SW-Voreinstellungen",
|
||||
|
||||
@@ -256,8 +256,6 @@
|
||||
"log_path_desc": "The file where the current logs of Sunshine are stored.",
|
||||
"max_bitrate": "Maximum Bitrate",
|
||||
"max_bitrate_desc": "The maximum bitrate (in Kbps) that Sunshine will encode the stream at. If set to 0, it will always use the bitrate requested by Moonlight.",
|
||||
"min_fps_factor": "Minimum FPS Factor",
|
||||
"min_fps_factor_desc": "Sunshine 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_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",
|
||||
@@ -388,7 +386,7 @@
|
||||
"configuration": "Configuration",
|
||||
"home": "Home",
|
||||
"password": "Change Password",
|
||||
"pin": "Pin",
|
||||
"pin": "PIN",
|
||||
"theme_auto": "Auto",
|
||||
"theme_dark": "Dark",
|
||||
"theme_light": "Light",
|
||||
|
||||
@@ -158,6 +158,8 @@
|
||||
"dd_config_label": "Device configuration",
|
||||
"dd_config_revert_delay": "Config revert delay",
|
||||
"dd_config_revert_delay_desc": "Additional delay in milliseconds to wait before reverting configuration when the app has been closed or the last session terminated. Main purpose is to provide a smoother transition when quickly switching between apps.",
|
||||
"dd_config_revert_on_disconnect": "Config revert on disconnect",
|
||||
"dd_config_revert_on_disconnect_desc": "Revert configuration upon disconnect of all clients instead of app close or last session termination.",
|
||||
"dd_config_verify_only": "Verify that the display is enabled (default)",
|
||||
"dd_hdr_option": "HDR",
|
||||
"dd_hdr_option_auto": "Switch on/off the HDR mode as requested by the client (default)",
|
||||
@@ -187,8 +189,10 @@
|
||||
"dd_resolution_option_manual": "Use manually entered resolution",
|
||||
"dd_resolution_option_manual_desc": "Enter the resolution to be used",
|
||||
"dd_resolution_option_ogs_desc": "\"Optimize game settings\" option must be enabled on the Moonlight client for this to work.",
|
||||
"dd_wa_hdr_toggle_desc": "When using virtual display device as for streaming, it might display incorrect HDR color. With this option enabled, Sunshine will try to mitigate this issue.",
|
||||
"dd_wa_hdr_toggle": "Enable high-contrast workaround for HDR",
|
||||
"dd_wa_hdr_toggle_delay_desc_1": "When using virtual display device (VDD) for streaming, it might incorrectly display HDR color. Sunshine can try to mitigate this issue, by turning HDR off and then on again.",
|
||||
"dd_wa_hdr_toggle_delay_desc_2": "If the value is set to 0, the workaround is disabled (default). If the value is between 0 and 3000 milliseconds, Sunshine will turn off HDR, wait for the specified amount of time and then turn HDR on again. The recommended delay time is around 500 milliseconds in most cases.",
|
||||
"dd_wa_hdr_toggle_delay_desc_3": "DO NOT use this workaround unless you actually have issues with HDR as it directly impacts stream start time!",
|
||||
"dd_wa_hdr_toggle_delay": "High-contrast workaround for HDR",
|
||||
"ds4_back_as_touchpad_click": "Map Back/Select to Touchpad Click",
|
||||
"ds4_back_as_touchpad_click_desc": "When forcing DS4 emulation, map Back/Select to Touchpad Click",
|
||||
"encoder": "Force a Specific Encoder",
|
||||
@@ -250,8 +254,8 @@
|
||||
"log_level_desc": "The minimum log level printed to standard out",
|
||||
"log_path": "Logfile Path",
|
||||
"log_path_desc": "The file where the current logs of Sunshine are stored.",
|
||||
"min_fps_factor": "Minimum FPS Factor",
|
||||
"min_fps_factor_desc": "Sunshine 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.",
|
||||
"max_bitrate": "Maximum Bitrate",
|
||||
"max_bitrate_desc": "The maximum bitrate (in Kbps) that Sunshine will encode the stream at. If set to 0, it will always use the bitrate requested by Moonlight.",
|
||||
"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.",
|
||||
"misc": "Miscellaneous options",
|
||||
@@ -277,8 +281,6 @@
|
||||
"nvenc_realtime_hags_desc": "Currently NVIDIA drivers may freeze in encoder when HAGS is enabled, realtime priority is used and VRAM utilization is close to maximum. Disabling this option lowers the priority to high, sidestepping the freeze at the cost of reduced capture performance when the GPU is heavily loaded.",
|
||||
"nvenc_spatial_aq": "Spatial AQ",
|
||||
"nvenc_spatial_aq_desc": "Assign higher QP values to flat regions of the video. Recommended to enable when streaming at lower bitrates.",
|
||||
"nvenc_spatial_aq_disabled": "Disabled (faster, default)",
|
||||
"nvenc_spatial_aq_enabled": "Enabled (slower)",
|
||||
"nvenc_twopass": "Two-pass mode",
|
||||
"nvenc_twopass_desc": "Adds preliminary encoding pass. This allows to detect more motion vectors, better distribute bitrate across the frame and more strictly adhere to bitrate limits. Disabling it is not recommended since this can lead to occasional bitrate overshoot and subsequent packet loss.",
|
||||
"nvenc_twopass_disabled": "Disabled (fastest, not recommended)",
|
||||
@@ -325,6 +327,8 @@
|
||||
"qsv_slow_hevc": "Allow Slow HEVC Encoding",
|
||||
"qsv_slow_hevc_desc": "This can enable HEVC encoding on older Intel GPUs, at the cost of higher GPU usage and worse performance.",
|
||||
"restart_note": "Sunshine is restarting to apply changes.",
|
||||
"stream_audio": "Stream Audio",
|
||||
"stream_audio_desc": "Whether to stream audio or not. Disabling this can be useful for streaming headless displays as second monitors.",
|
||||
"sunshine_name": "Sunshine Name",
|
||||
"sunshine_name_desc": "The name displayed by Moonlight. If not specified, the PC's hostname is used",
|
||||
"sw_preset": "SW Presets",
|
||||
@@ -382,7 +386,7 @@
|
||||
"configuration": "Configuration",
|
||||
"home": "Home",
|
||||
"password": "Change Password",
|
||||
"pin": "Pin",
|
||||
"pin": "PIN",
|
||||
"theme_auto": "Auto",
|
||||
"theme_dark": "Dark",
|
||||
"theme_light": "Light",
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"env_vars_desc": "All commands get these environment variables by default:",
|
||||
"env_xrandr_example": "Example - Xrandr for Resolution Automation:",
|
||||
"exit_timeout": "Exit Timeout",
|
||||
"exit_timeout_desc": "Number of seconds to wait for all app processes to gracefully exit when requested to quit. If unset, the default is to wait up to 5 seconds. If set to zero or a negative value, the app will be immediately terminated.",
|
||||
"exit_timeout_desc": "Number of seconds to wait for all app processes to gracefully exit when requested to quit. If unset, the default is to wait up to 5 seconds. If set to 0, the app will be immediately terminated.",
|
||||
"find_cover": "Find Cover",
|
||||
"global_prep_desc": "Enable/Disable the execution of Global Prep Commands for this application.",
|
||||
"global_prep_name": "Global Prep Commands",
|
||||
@@ -158,7 +158,9 @@
|
||||
"dd_config_label": "Device configuration",
|
||||
"dd_config_revert_delay": "Config revert delay",
|
||||
"dd_config_revert_delay_desc": "Additional delay in milliseconds to wait before reverting configuration when the app has been closed or the last session terminated. Main purpose is to provide a smoother transition when quickly switching between apps.",
|
||||
"dd_config_verify_only": "Verify that the display is enabled (default)",
|
||||
"dd_config_revert_on_disconnect": "Config revert on disconnect",
|
||||
"dd_config_revert_on_disconnect_desc": "Revert configuration upon disconnect of all clients instead of app close or last session termination.",
|
||||
"dd_config_verify_only": "Verify that the display is enabled",
|
||||
"dd_hdr_option": "HDR",
|
||||
"dd_hdr_option_auto": "Switch on/off the HDR mode as requested by the client (default)",
|
||||
"dd_hdr_option_disabled": "Do not change HDR settings",
|
||||
@@ -187,8 +189,10 @@
|
||||
"dd_resolution_option_manual": "Use manually entered resolution",
|
||||
"dd_resolution_option_manual_desc": "Enter the resolution to be used",
|
||||
"dd_resolution_option_ogs_desc": "\"Optimize game settings\" option must be enabled on the Moonlight client for this to work.",
|
||||
"dd_wa_hdr_toggle_desc": "When using virtual display device as for streaming, it might display incorrect HDR color. With this option enabled, Sunshine will try to mitigate this issue.",
|
||||
"dd_wa_hdr_toggle": "Enable high-contrast workaround for HDR",
|
||||
"dd_wa_hdr_toggle_delay_desc_1": "When using virtual display device (VDD) for streaming, it might incorrectly display HDR color. Sunshine can try to mitigate this issue, by turning HDR off and then on again.",
|
||||
"dd_wa_hdr_toggle_delay_desc_2": "If the value is set to 0, the workaround is disabled (default). If the value is between 0 and 3000 milliseconds, Sunshine will turn off HDR, wait for the specified amount of time and then turn HDR on again. The recommended delay time is around 500 milliseconds in most cases.",
|
||||
"dd_wa_hdr_toggle_delay_desc_3": "DO NOT use this workaround unless you actually have issues with HDR as it directly impacts stream start time!",
|
||||
"dd_wa_hdr_toggle_delay": "High-contrast workaround for HDR",
|
||||
"ds4_back_as_touchpad_click": "Map Back/Select to Touchpad Click",
|
||||
"ds4_back_as_touchpad_click_desc": "When forcing DS4 emulation, map Back/Select to Touchpad Click",
|
||||
"encoder": "Force a Specific Encoder",
|
||||
@@ -250,8 +254,8 @@
|
||||
"log_level_desc": "The minimum log level printed to standard out",
|
||||
"log_path": "Logfile Path",
|
||||
"log_path_desc": "The file where the current logs of Sunshine are stored.",
|
||||
"min_fps_factor": "Minimum FPS Factor",
|
||||
"min_fps_factor_desc": "Sunshine 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.",
|
||||
"max_bitrate": "Maximum Bitrate",
|
||||
"max_bitrate_desc": "The maximum bitrate (in Kbps) that Sunshine will encode the stream at. If set to 0, it will always use the bitrate requested by Moonlight.",
|
||||
"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.",
|
||||
"misc": "Miscellaneous options",
|
||||
@@ -277,8 +281,6 @@
|
||||
"nvenc_realtime_hags_desc": "Currently NVIDIA drivers may freeze in encoder when HAGS is enabled, realtime priority is used and VRAM utilization is close to maximum. Disabling this option lowers the priority to high, sidestepping the freeze at the cost of reduced capture performance when the GPU is heavily loaded.",
|
||||
"nvenc_spatial_aq": "Spatial AQ",
|
||||
"nvenc_spatial_aq_desc": "Assign higher QP values to flat regions of the video. Recommended to enable when streaming at lower bitrates.",
|
||||
"nvenc_spatial_aq_disabled": "Disabled (faster, default)",
|
||||
"nvenc_spatial_aq_enabled": "Enabled (slower)",
|
||||
"nvenc_twopass": "Two-pass mode",
|
||||
"nvenc_twopass_desc": "Adds preliminary encoding pass. This allows to detect more motion vectors, better distribute bitrate across the frame and more strictly adhere to bitrate limits. Disabling it is not recommended since this can lead to occasional bitrate overshoot and subsequent packet loss.",
|
||||
"nvenc_twopass_disabled": "Disabled (fastest, not recommended)",
|
||||
@@ -325,6 +327,8 @@
|
||||
"qsv_slow_hevc": "Allow Slow HEVC Encoding",
|
||||
"qsv_slow_hevc_desc": "This can enable HEVC encoding on older Intel GPUs, at the cost of higher GPU usage and worse performance.",
|
||||
"restart_note": "Sunshine is restarting to apply changes.",
|
||||
"stream_audio": "Stream Audio",
|
||||
"stream_audio_desc": "Whether to stream audio or not. Disabling this can be useful for streaming headless displays as second monitors.",
|
||||
"sunshine_name": "Sunshine Name",
|
||||
"sunshine_name_desc": "The name displayed by Moonlight. If not specified, the PC's hostname is used",
|
||||
"sw_preset": "SW Presets",
|
||||
@@ -382,7 +386,7 @@
|
||||
"configuration": "Configuration",
|
||||
"home": "Home",
|
||||
"password": "Change Password",
|
||||
"pin": "Pin",
|
||||
"pin": "PIN",
|
||||
"theme_auto": "Auto",
|
||||
"theme_dark": "Dark",
|
||||
"theme_light": "Light",
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"elevated": "Elevado",
|
||||
"enabled": "Habilitado",
|
||||
"enabled_def": "Habilitado (por defecto)",
|
||||
"enabled_def_cbox": "Por defecto: comprobado",
|
||||
"enabled_def_cbox": "Por defecto: marcado",
|
||||
"error": "¡Error!",
|
||||
"note": "Nota:",
|
||||
"password": "Contraseña",
|
||||
@@ -65,7 +65,7 @@
|
||||
"env_vars_desc": "Todos los comandos obtienen estas variables de entorno de forma predeterminada:",
|
||||
"env_xrandr_example": "Ejemplo - Xrandr para Automatización de Resolución:",
|
||||
"exit_timeout": "Tiempo de espera de salida",
|
||||
"exit_timeout_desc": "Número de segundos a esperar a que todos los procesos de la aplicación salgan con gracia cuando se les solicite salir. Si no se activa, el valor predeterminado es esperar hasta 5 segundos. Si se establece a cero o un valor negativo, la aplicación se cerrará inmediatamente.",
|
||||
"exit_timeout_desc": "Segundos a esperar para que todos los procesos de la aplicación se cierren de manera ordenada cuando se solicite cerrar. Si no se establece, el valor predeterminado es esperar hasta 5 segundos. Si se establece en 0, la aplicación se cerrará inmediatamente.",
|
||||
"find_cover": "Encontrar portada",
|
||||
"global_prep_desc": "Activar/Desactivar la ejecución de Comandos de Preparación Global para esta aplicación.",
|
||||
"global_prep_name": "Comandos de preparación global",
|
||||
@@ -153,11 +153,13 @@
|
||||
"credentials_file": "Archivo de credenciales",
|
||||
"credentials_file_desc": "Guardar nombre de usuario/contraseña por separado del archivo de estado de Sunshine.",
|
||||
"dd_config_ensure_active": "Activar la pantalla automáticamente",
|
||||
"dd_config_ensure_only_display": "Desactivar otras pantallas y activar sólo la pantalla especificada",
|
||||
"dd_config_ensure_primary": "Activar la pantalla automáticamente y convertirla en una pantalla principal",
|
||||
"dd_config_ensure_only_display": "Desactivar otras pantallas y activar solo la pantalla especificada",
|
||||
"dd_config_ensure_primary": "Activar la pantalla automáticamente y convertirla en la pantalla principal",
|
||||
"dd_config_label": "Configuración del dispositivo",
|
||||
"dd_config_revert_delay": "Retraso de configuración",
|
||||
"dd_config_revert_delay_desc": "Retraso adicional en milisegundos a esperar antes de revertir la configuración cuando la aplicación ha sido cerrada o la última sesión ha terminado. El propósito principal es proporcionar una transición más suave cuando cambia rápidamente entre aplicaciones.",
|
||||
"dd_config_revert_delay": "Retardo para revertir la configuración",
|
||||
"dd_config_revert_delay_desc": "Retraso adicional en milisegundos a esperar antes de revertir la configuración cuando la app ha sido cerrada o la última sesión finalizada. El propósito principal es proporcionar una transición más suave al cambiar rápidamente entre aplicaciones.",
|
||||
"dd_config_revert_on_disconnect": "Revertir configuración al desconectar",
|
||||
"dd_config_revert_on_disconnect_desc": "Revertir la configuración al desconectar todos los clientes en lugar de cerrar la aplicación o terminar la última sesión.",
|
||||
"dd_config_verify_only": "Verificar que la pantalla está habilitada (por defecto)",
|
||||
"dd_hdr_option": "HDR",
|
||||
"dd_hdr_option_auto": "Encender/apagar el modo HDR tal como lo solicitó el cliente (por defecto)",
|
||||
@@ -187,8 +189,10 @@
|
||||
"dd_resolution_option_manual": "Usar resolución introducida manualmente",
|
||||
"dd_resolution_option_manual_desc": "Introduzca la resolución a usar",
|
||||
"dd_resolution_option_ogs_desc": "La opción \"Optimizar ajustes del juego\" debe estar habilitada en el cliente de luz lunar para que esto funcione.",
|
||||
"dd_wa_hdr_toggle_desc": "Cuando se utiliza el dispositivo de visualización virtual como para el streaming, puede mostrar un color HDR incorrecto. Con esta opción activada, Sunshine intentará mitigar este problema.",
|
||||
"dd_wa_hdr_toggle": "Habilitar solución de alto contraste para HDR",
|
||||
"dd_wa_hdr_toggle_delay_desc_1": "Cuando se utiliza un dispositivo de visualización virtual (VDD) para el streaming, podría mostrar incorrectamente el color HDR. Sunshine puede tratar de mitigar este problema, apagando el HDR y encendiendo de nuevo.",
|
||||
"dd_wa_hdr_toggle_delay_desc_2": "Si el valor se establece en 0, la solución temporal está deshabilitada (por defecto). Si el valor está entre 0 y 3000 milisegundos, Sunshine desactivará HDR, espera la cantidad de tiempo especificada y luego enciende HDR de nuevo. El retraso recomendado es de unos 500 milisegundos en la mayoría de los casos.",
|
||||
"dd_wa_hdr_toggle_delay_desc_3": "NO use esta solución a menos que realmente tenga problemas con HDR ya que afecta directamente el tiempo de inicio de la secuencia!",
|
||||
"dd_wa_hdr_toggle_delay": "Solución de alto contraste para HDR",
|
||||
"ds4_back_as_touchpad_click": "Mapa Atrás/Seleccionar a Touchpad Clic",
|
||||
"ds4_back_as_touchpad_click_desc": "Al forzar la emulación DS4, mapar Atrás/Seleccionar a Touchpad Clic",
|
||||
"encoder": "Forzar un codificador específico",
|
||||
@@ -250,8 +254,8 @@
|
||||
"log_level_desc": "El nivel mínimo de registro impreso a nivel estándar",
|
||||
"log_path": "Ruta del archivo de registro",
|
||||
"log_path_desc": "El archivo donde se almacenan los registros actuales de Sunshine.",
|
||||
"min_fps_factor": "Factor FPS Mínimo",
|
||||
"min_fps_factor_desc": "Sunshine usará este factor para calcular el tiempo mínimo entre fotogramas. Incrementar este valor ligeramente puede ayudar a la transmisión en su mayoría de contenido estático. Valores más altos consumirán más banda ancha.",
|
||||
"max_bitrate": "Tasa de bits máxima",
|
||||
"max_bitrate_desc": "La tasa de bits máxima (en Kbps) que Sunshine codificará la secuencia. Si se establece en 0, siempre utilizará la tasa de bits solicitada por la luz lunar.",
|
||||
"min_threads": "Recuento mínimo de hilos de CPU",
|
||||
"min_threads_desc": "Incrementar el valor reduce ligeramente la eficiencia de la codificación, pero la compensación suele valer la pena para obtener el uso de más núcleos de CPU para la codificación. El valor ideal es el valor más bajo que puede codificar de forma fiable en los ajustes de streaming deseados en su hardware.",
|
||||
"misc": "Opciones varias",
|
||||
@@ -277,8 +281,6 @@
|
||||
"nvenc_realtime_hags_desc": "Actualmente los controladores NVIDIA pueden congelarse en el codificador cuando HAGS está habilitado, se utiliza prioridad en tiempo real y la utilización de VRAM está cerca del máximo. Deshabilitar esta opción reduce la prioridad a alto, evitando la congelación a costa de un menor rendimiento de captura cuando la GPU está muy cargada.",
|
||||
"nvenc_spatial_aq": "Spatial AQ",
|
||||
"nvenc_spatial_aq_desc": "Asigne valores más altos de QP a regiones planas del vídeo. Recomendado para habilitar al transmitir a tasas de bits más bajas.",
|
||||
"nvenc_spatial_aq_disabled": "Desactivado (más rápido, por defecto)",
|
||||
"nvenc_spatial_aq_enabled": "Habilitado (más lento)",
|
||||
"nvenc_twopass": "Modo dos pases",
|
||||
"nvenc_twopass_desc": "Añade una tarjeta de codificación preliminar. Esto permite detectar más vectores de movimiento, distribuir mejor la tasa de bits a lo largo del fotograma y adherirse más estrictamente a los límites de la tasa de bits. Deshabilitar no es recomendable ya que esto puede llevar a un rebasamiento ocasional de la tasa de bits y a la pérdida posterior de paquetes.",
|
||||
"nvenc_twopass_disabled": "Desactivado (lo más rápido, no recomendado)",
|
||||
@@ -325,6 +327,8 @@
|
||||
"qsv_slow_hevc": "Permitir codificación HEVC lenta",
|
||||
"qsv_slow_hevc_desc": "Esto puede habilitar la codificación HEVC en GPU de Intel, a costa de un mayor uso de GPU y un peor rendimiento.",
|
||||
"restart_note": "Sunshine se está reiniciando para aplicar cambios.",
|
||||
"stream_audio": "Stream de audio",
|
||||
"stream_audio_desc": "Si transmitir o no audio, desactivar esto puede ser útil para transmitir pantallas sin cabeceras como segundo monitor.",
|
||||
"sunshine_name": "Nombre de Sunshine",
|
||||
"sunshine_name_desc": "El nombre mostrado por Moonlight. Si no se especifica, se utiliza el nombre de host del PC",
|
||||
"sw_preset": "Preajustes SW",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user