From 1520cb7bf93f9f55e373f84441775d7f7ea51034 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 27 Feb 2022 18:11:56 +0000 Subject: [PATCH 001/120] Bump actions/stale from 3 to 4.1.0 Bumps [actions/stale](https://github.com/actions/stale) from 3 to 4.1.0. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v3...v4.1.0) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/issues-stale.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/issues-stale.yml b/.github/workflows/issues-stale.yml index 02aa6ca820d..588dc6a6f75 100644 --- a/.github/workflows/issues-stale.yml +++ b/.github/workflows/issues-stale.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Stale - uses: actions/stale@v3 + uses: actions/stale@v4.1.0 with: stale-issue-message: > This issue is stale because it has been open for 30 days with no activity. @@ -30,7 +30,7 @@ jobs: days-before-close: 5 - name: Invalid Template - uses: actions/stale@v3 + uses: actions/stale@v4.1.0 with: stale-issue-message: > Invalid issues template. From 5e910b5fab6416b57820894ec4004c40d3e213ac Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sun, 27 Feb 2022 13:18:36 -0500 Subject: [PATCH 002/120] Update issues-stale.yml - Remove skip-stale-issue-message - Remove skip-stale-pr-message --- .github/workflows/issues-stale.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/issues-stale.yml b/.github/workflows/issues-stale.yml index 588dc6a6f75..ea11acbf8ad 100644 --- a/.github/workflows/issues-stale.yml +++ b/.github/workflows/issues-stale.yml @@ -37,14 +37,12 @@ jobs: close-issue-message: > This issue was closed because the the template was not completed after 5 days. stale-issue-label: 'invalid:template-incomplete' - skip-stale-issue-message: true stale-pr-message: > Invalid PR template. close-pr-message: > This PR was closed because the the template was not completed after 5 days. stale-pr-label: 'invalid:template-incomplete' exempt-pr-labels: 'status:in-progress' - skip-stale-pr-message: true only-labels: 'invalid:template-incomplete' days-before-stale: 0 days-before-close: 5 From 861331be1cdc52e4897cbca9d9288bbabf87adc6 Mon Sep 17 00:00:00 2001 From: Ryan Caezar Itang Date: Wed, 2 Mar 2022 11:19:05 +0800 Subject: [PATCH 003/120] Add TPCircularBuffer submodule --- sunshine/platform/macos/TPCircularBuffer | 1 + 1 file changed, 1 insertion(+) create mode 160000 sunshine/platform/macos/TPCircularBuffer diff --git a/sunshine/platform/macos/TPCircularBuffer b/sunshine/platform/macos/TPCircularBuffer new file mode 160000 index 00000000000..bce9170d9e8 --- /dev/null +++ b/sunshine/platform/macos/TPCircularBuffer @@ -0,0 +1 @@ +Subproject commit bce9170d9e8e566fb33d56136ec6e4b97f91ed2d From 8d4bd87ad2cc30c8f673fdc0836d89f133f8730f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 12:36:17 +0000 Subject: [PATCH 004/120] Bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/CI.yml | 10 +++++----- .github/workflows/clang.yml | 2 +- .github/workflows/pull-requests.yml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 82bbc3438f0..d36e4a7172f 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Verify Changelog id: verify_changelog @@ -37,7 +37,7 @@ jobs: # base_ref for pull request check, ref for push steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Check CMakeLists.txt Version run: | @@ -58,7 +58,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: recursive @@ -160,7 +160,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: recursive @@ -201,7 +201,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: recursive - name: MSYS2 Setup diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index 9ac9d06a1d5..3729968711d 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Clang format lint uses: DoozyX/clang-format-lint-action@v0.13 diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml index a322319e933..ad014e6d0c6 100644 --- a/.github/workflows/pull-requests.yml +++ b/.github/workflows/pull-requests.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Branch check if: ( github.head_ref == 'repo-sync/common-repo-files/default' && github.base_ref == 'master' ) || ( github.head_ref == 'nightly' && github.base_ref == 'master' ) From 4c7afc05c7ecbad3b5e722187415d96cb75eefd5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 21:55:46 +0000 Subject: [PATCH 005/120] Bump actions/stale from 4.1.0 to 5 Bumps [actions/stale](https://github.com/actions/stale) from 4.1.0 to 5. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v4.1.0...v5) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/issues-stale.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/issues-stale.yml b/.github/workflows/issues-stale.yml index ea11acbf8ad..1c40c45ddd6 100644 --- a/.github/workflows/issues-stale.yml +++ b/.github/workflows/issues-stale.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Stale - uses: actions/stale@v4.1.0 + uses: actions/stale@v5 with: stale-issue-message: > This issue is stale because it has been open for 30 days with no activity. @@ -30,7 +30,7 @@ jobs: days-before-close: 5 - name: Invalid Template - uses: actions/stale@v4.1.0 + uses: actions/stale@v5 with: stale-issue-message: > Invalid issues template. From 1f79f4ed1248cd32089709a7af8c5fc4ccd5c3fa Mon Sep 17 00:00:00 2001 From: Mathias Tillman Date: Wed, 9 Mar 2022 00:30:10 +0100 Subject: [PATCH 006/120] Fix rumble events causing hang because the received input events were not read properly. --- sunshine/platform/linux/input.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sunshine/platform/linux/input.cpp b/sunshine/platform/linux/input.cpp index fbdc8133961..3c92ba81b00 100644 --- a/sunshine/platform/linux/input.cpp +++ b/sunshine/platform/linux/input.cpp @@ -716,6 +716,15 @@ inline void rumbleIterate(std::vector &effects, std::vector return; } + // Copy over the received events + for (auto x = 0; x < polls_tmp.size(); ++x) { + for (auto y = 0; y < polls.size(); ++y) { + if (polls_tmp[x].fd == polls[y].el.fd) { + polls[y].el.revents = polls_tmp[x].revents; + } + } + } + for(int x = 0; x < polls.size(); ++x) { auto poll = std::begin(polls) + x; auto effect_it = std::begin(effects) + x; From a31c6c4cd029e31c132aa415e3c33bc3915aaf9e Mon Sep 17 00:00:00 2001 From: Mathias Tillman Date: Wed, 9 Mar 2022 16:20:51 +0100 Subject: [PATCH 007/120] Fix hwdevice being destroyed before context, causing a sigsegv because the context relies on the hwdevice still being active. --- sunshine/video.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sunshine/video.cpp b/sunshine/video.cpp index b2a8858b2be..f435d5073ca 100644 --- a/sunshine/video.cpp +++ b/sunshine/video.cpp @@ -324,7 +324,7 @@ struct encoder_t { class session_t { public: session_t() = default; - session_t(ctx_t &&ctx, std::shared_ptr &&device, int inject) : ctx { std::move(ctx) }, device { std::move(device) }, inject { inject } {} + session_t(ctx_t &&ctx, std::shared_ptr &&device, int inject) : device { std::move(device) }, ctx { std::move(ctx) }, inject { inject } {} session_t(session_t &&other) noexcept = default; @@ -341,8 +341,8 @@ class session_t { return *this; } - ctx_t ctx; std::shared_ptr device; + ctx_t ctx; std::vector replacements; From 9a2689692a32904f3208a8180bd7a8526ef0bca3 Mon Sep 17 00:00:00 2001 From: Mathias Tillman Date: Wed, 9 Mar 2022 16:40:39 +0100 Subject: [PATCH 008/120] Fix lint warning about code style. --- sunshine/platform/linux/input.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sunshine/platform/linux/input.cpp b/sunshine/platform/linux/input.cpp index 3c92ba81b00..1f9840fb08a 100644 --- a/sunshine/platform/linux/input.cpp +++ b/sunshine/platform/linux/input.cpp @@ -717,9 +717,10 @@ inline void rumbleIterate(std::vector &effects, std::vector } // Copy over the received events - for (auto x = 0; x < polls_tmp.size(); ++x) { - for (auto y = 0; y < polls.size(); ++y) { - if (polls_tmp[x].fd == polls[y].el.fd) { + for(auto x = 0; x < polls_tmp.size(); ++x) { + auto pfd = polls_tmp[x].fd; + for(auto y = 0; y < polls.size(); ++y) { + if (pfd == polls[y].el.fd) { polls[y].el.revents = polls_tmp[x].revents; } } From 80ebc9982edd3fa284385cf76b221a37cdd99c26 Mon Sep 17 00:00:00 2001 From: Mathias Tillman Date: Wed, 9 Mar 2022 17:27:42 +0100 Subject: [PATCH 009/120] Fix another lint warning. --- sunshine/platform/linux/input.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sunshine/platform/linux/input.cpp b/sunshine/platform/linux/input.cpp index 1f9840fb08a..c0222927bea 100644 --- a/sunshine/platform/linux/input.cpp +++ b/sunshine/platform/linux/input.cpp @@ -720,7 +720,7 @@ inline void rumbleIterate(std::vector &effects, std::vector for(auto x = 0; x < polls_tmp.size(); ++x) { auto pfd = polls_tmp[x].fd; for(auto y = 0; y < polls.size(); ++y) { - if (pfd == polls[y].el.fd) { + if(pfd == polls[y].el.fd) { polls[y].el.revents = polls_tmp[x].revents; } } From e61bbe87b4bd4c4554bf84843c830aaed9b0f182 Mon Sep 17 00:00:00 2001 From: Mathias Tillman Date: Wed, 9 Mar 2022 22:23:38 +0100 Subject: [PATCH 010/120] Read revents from the temporary pollfds instead of copying them over to the old vector. Decrement index for polls when erasing to make sure none of the events are skipped. --- sunshine/platform/linux/input.cpp | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/sunshine/platform/linux/input.cpp b/sunshine/platform/linux/input.cpp index c0222927bea..be923936135 100644 --- a/sunshine/platform/linux/input.cpp +++ b/sunshine/platform/linux/input.cpp @@ -696,13 +696,13 @@ struct input_raw_t { }; inline void rumbleIterate(std::vector &effects, std::vector &polls, std::chrono::milliseconds to) { - std::vector polls_tmp; - polls_tmp.reserve(polls.size()); + std::vector polls_recv; + polls_recv.reserve(polls.size()); for(auto &poll : polls) { - polls_tmp.emplace_back(poll.el); + polls_recv.emplace_back(poll.el); } - auto res = poll(polls_tmp.data(), polls.size(), to.count()); + auto res = poll(polls_recv.data(), polls_recv.size(), to.count()); // If timed out if(!res) { @@ -716,16 +716,6 @@ inline void rumbleIterate(std::vector &effects, std::vector return; } - // Copy over the received events - for(auto x = 0; x < polls_tmp.size(); ++x) { - auto pfd = polls_tmp[x].fd; - for(auto y = 0; y < polls.size(); ++y) { - if(pfd == polls[y].el.fd) { - polls[y].el.revents = polls_tmp[x].revents; - } - } - } - for(int x = 0; x < polls.size(); ++x) { auto poll = std::begin(polls) + x; auto effect_it = std::begin(effects) + x; @@ -735,16 +725,17 @@ inline void rumbleIterate(std::vector &effects, std::vector // TUPLE_2D_REF(dev, q, *dev_q_it); // on error - if((*poll)->revents & (POLLHUP | POLLRDHUP | POLLERR)) { + if(polls_recv[x].revents & (POLLHUP | POLLRDHUP | POLLERR)) { BOOST_LOG(warning) << "Gamepad ["sv << x << "] file discriptor closed unexpectedly"sv; polls.erase(poll); effects.erase(effect_it); + --x; continue; } - if(!((*poll)->revents & POLLIN)) { + if(!(polls_recv[x].revents & POLLIN)) { continue; } @@ -761,6 +752,7 @@ inline void rumbleIterate(std::vector &effects, std::vector polls.erase(poll); effects.erase(effect_it); + --x; continue; } From 6fca2c593ceb21dafe71600ad536af6edfd02c60 Mon Sep 17 00:00:00 2001 From: Mathias Tillman Date: Thu, 10 Mar 2022 09:09:24 +0100 Subject: [PATCH 011/120] Use session_t destructor to ensure the context and hwdevice are always destroyed in the correct order. --- sunshine/video.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sunshine/video.cpp b/sunshine/video.cpp index f435d5073ca..0f7eff35480 100644 --- a/sunshine/video.cpp +++ b/sunshine/video.cpp @@ -324,9 +324,14 @@ struct encoder_t { class session_t { public: session_t() = default; - session_t(ctx_t &&ctx, std::shared_ptr &&device, int inject) : device { std::move(device) }, ctx { std::move(ctx) }, inject { inject } {} + session_t(ctx_t &&ctx, std::shared_ptr &&device, int inject) : ctx { std::move(ctx) }, device { std::move(device) }, inject { inject } {} session_t(session_t &&other) noexcept = default; + ~session_t() { + // Order matters here because the context relies on the hwdevice still being valid + ctx.reset(); + device.reset(); + } // Ensure objects are destroyed in the correct order session_t &operator=(session_t &&other) { @@ -341,8 +346,8 @@ class session_t { return *this; } - std::shared_ptr device; ctx_t ctx; + std::shared_ptr device; std::vector replacements; From 045970bcc58ed88e6ff03451f3da9b5d40d49d18 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 11 Mar 2022 00:20:25 -0500 Subject: [PATCH 012/120] Create requirements.txt --- locale/requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 locale/requirements.txt diff --git a/locale/requirements.txt b/locale/requirements.txt new file mode 100644 index 00000000000..9d236e724ac --- /dev/null +++ b/locale/requirements.txt @@ -0,0 +1 @@ +Babel==2.9.1 From e28cc5e64597f81991b185dbebb5a95641b3421a Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 11 Mar 2022 00:21:12 -0500 Subject: [PATCH 013/120] Create _locale.py --- locale/_locale.py | 156 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 locale/_locale.py diff --git a/locale/_locale.py b/locale/_locale.py new file mode 100644 index 00000000000..4a2ec2c1852 --- /dev/null +++ b/locale/_locale.py @@ -0,0 +1,156 @@ +"""_locale.py + +Functions related to building, initializing, updating, and compiling localization translations. + +Borrowed from RetroArcher. +""" +# standard imports +import argparse +import datetime +import os +import subprocess + +project_name = 'Sunshine' + +script_dir = os.path.dirname(os.path.abspath(__file__)) +root_dir = os.path.dirname(script_dir) +locale_dir = os.path.join(root_dir, 'locale') +project_dir = os.path.join(root_dir, project_name.lower()) + +year = datetime.datetime.now().year + +# retroarcher target locales +target_locales = [ + 'de', # Deutsch + 'en', # English + 'en_GB', # English (United Kingdom) + 'en_US', # English (United States) + 'es', # español + 'fr', # français + 'it', # italiano + 'ru', # русский +] + + +def x_extract(): + """Executes `xgettext extraction` in subprocess.""" + + commands = [ + 'xgettext', + f'--default-domain={project_name.lower()}', + f'--output={os.path.join(locale_dir, project_name.lower() + ".pot")}', + '--language=C++', + '--boost', + '--from-code=utf-8', + '-F', + f'--msgid-bugs-address=github.com/{project_name.lower()}', + f'--copyright-holder={project_name}', + f'--package-name={project_name}', + '--package-version=v0' + ] + + pot_filepath = os.path.join(locale_dir, f'{project_name.lower()}.pot') + + extensions = ['cpp', 'h', 'm', 'mm'] + + # find input files + for root, dirs, files in os.walk(project_dir, topdown=True): + for name in files: + filename = os.path.join(root, name) + extension = filename.rsplit('.', 1)[-1] + if extension in extensions: # append input files + commands.append(filename) + + print(commands) + proc = subprocess.run(args=commands, cwd=root_dir) + + # fix header + body = "" + with open(file=pot_filepath, mode='r') as file: + for line in file.readlines(): + if line != '"Language: \\n"\n': # do not include this line + if line == '# SOME DESCRIPTIVE TITLE.\n': + body += f'# Translations template for {project_name}.\n' + elif line.startswith('#') and 'YEAR' in line: + body += line.replace('YEAR', str(year)) + elif line.startswith('#') and 'PACKAGE' in line: + body += line.replace('PACKAGE', project_name) + else: + body += line + + # rewrite pot file with updated header + with open(file=pot_filepath, mode='w+') as file: + file.write(body) + + +def babel_init(locale_code: str): + """Executes `pybabel init` in subprocess. + + :param locale_code: str - locale code + """ + commands = [ + 'pybabel', + 'init', + '-i', os.path.join(locale_dir, f'{project_name.lower()}.pot'), + '-d', locale_dir, + '-D', project_name.lower(), + '-l', locale_code + ] + + print(commands) + proc = subprocess.run(args=commands, cwd=root_dir) + + +def babel_update(): + """Executes `pybabel update` in subprocess.""" + commands = [ + 'pybabel', + 'update', + '-i', os.path.join(locale_dir, f'{project_name.lower()}.pot'), + '-d', locale_dir, + '-D', project_name.lower(), + '--update-header-comment' + ] + + print(commands) + proc = subprocess.run(args=commands, cwd=root_dir) + + +def babel_compile(): + """Executes `pybabel compile` in subprocess.""" + commands = [ + 'pybabel', + 'compile', + '-d', locale_dir, + '-D', project_name.lower() + ] + + print(commands) + proc = subprocess.run(args=commands, cwd=root_dir) + + +if __name__ == '__main__': + # Set up and gather command line arguments + parser = argparse.ArgumentParser( + description='Script helps update locale_id translations. Translations must be done manually.') + + parser.add_argument('--extract', action='store_true', help='Extract messages from c++ files.') + parser.add_argument('--init', action='store_true', help='Initialize any new locales specified in target locales.') + parser.add_argument('--update', action='store_true', help='Update existing locales.') + parser.add_argument('--compile', action='store_true', help='Compile translated locales.') + + args = parser.parse_args() + + if args.extract: + x_extract() + + if args.init: + for locale_id in target_locales: + if not os.path.isdir(os.path.join(locale_dir, locale_id)): + babel_init(locale_code=locale_id) + + if args.update: + babel_update() + + if args.compile: + babel_compile() From 3bd9f6b7103fb0c5faffd5a82ad5b38794445167 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 11 Mar 2022 00:22:29 -0500 Subject: [PATCH 014/120] Ignore translation templates and compilations --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 6fb681e7f23..39afd65aeba 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,7 @@ cmake-build* /assets/web/fonts/fontawesome-free-web/scss/ /assets/web/fonts/fontawesome-free-web/sprites/ /assets/web/fonts/fontawesome-free-web/svgs/ + +# Translations +*.mo +*.pot From b3cdadca8681f6934446ef1c3a01b6d41737e915 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 11 Mar 2022 00:26:53 -0500 Subject: [PATCH 015/120] Create localize.yml --- .github/workflows/localize.yml | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .github/workflows/localize.yml diff --git a/.github/workflows/localize.yml b/.github/workflows/localize.yml new file mode 100644 index 00000000000..e9407c087b4 --- /dev/null +++ b/.github/workflows/localize.yml @@ -0,0 +1,42 @@ +name: localize + +on: + push: + branches: [nightly] + workflow_dispatch: + +jobs: + localize: + name: Update Localization + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install Python 3.9 + uses: actions/setup-python@v3 # https://github.com/actions/setup-python + with: + python-version: '3.9' + + - name: Set up Python 3.9 Dependencies + run: | + cd ./locale + python -m pip install --upgrade pip setuptools + python -m pip install -r requirements.txt + + - name: Set up xgettext + run: | + sudo apt-get update -y && \ + sudo apt-get --reinstall install -y \ + gettext + + - name: Update Strings + run: | + python ./locale/_locale.py --extract --init --update + + - name: GitHub Commit & Push # push changes back into nightly + uses: actions-js/push@v1.2 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: nightly + message: localization updated by localize workflow From 88cf616a483462db86bf111c94e7a05573b652a2 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 11 Mar 2022 13:46:18 -0500 Subject: [PATCH 016/120] Move _locale.py and requirements --- {locale => scripts}/_locale.py | 0 {locale => scripts}/requirements.txt | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {locale => scripts}/_locale.py (100%) rename {locale => scripts}/requirements.txt (100%) diff --git a/locale/_locale.py b/scripts/_locale.py similarity index 100% rename from locale/_locale.py rename to scripts/_locale.py diff --git a/locale/requirements.txt b/scripts/requirements.txt similarity index 100% rename from locale/requirements.txt rename to scripts/requirements.txt From 01155ef4a3f31beab812fae1b0847c70e34f6172 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 11 Mar 2022 13:48:24 -0500 Subject: [PATCH 017/120] Update trigger events - Don't run if commits are all in 'locale' directory - Allows pushing changes back into nightly from this workflow without triggering and endless loop - Don't run job unless event is 'pull_request.merged' --- .github/workflows/localize.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/localize.yml b/.github/workflows/localize.yml index e9407c087b4..c587dcc96ee 100644 --- a/.github/workflows/localize.yml +++ b/.github/workflows/localize.yml @@ -3,11 +3,14 @@ name: localize on: push: branches: [nightly] + paths-ignore: + - 'locale/**' workflow_dispatch: jobs: localize: name: Update Localization + if: ${{ github.event.pull_request.merged }} runs-on: ubuntu-latest steps: - name: Checkout @@ -20,7 +23,7 @@ jobs: - name: Set up Python 3.9 Dependencies run: | - cd ./locale + cd ./scripts python -m pip install --upgrade pip setuptools python -m pip install -r requirements.txt @@ -32,7 +35,7 @@ jobs: - name: Update Strings run: | - python ./locale/_locale.py --extract --init --update + python ./scripts/_locale.py --extract --init --update - name: GitHub Commit & Push # push changes back into nightly uses: actions-js/push@v1.2 From f1d82a7d09d9f56b05b9a9a062095128972d8c2d Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 11 Mar 2022 14:00:23 -0500 Subject: [PATCH 018/120] Update trigger conditions - Only run when changes are made on files inside 'sunshine' directory - Prevents workflow from running again when this workflow pushes changes back into 'locale' directory - Should be cleaner than using 'paths-ignore' --- .github/workflows/localize.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/localize.yml b/.github/workflows/localize.yml index c587dcc96ee..b661983333b 100644 --- a/.github/workflows/localize.yml +++ b/.github/workflows/localize.yml @@ -3,8 +3,8 @@ name: localize on: push: branches: [nightly] - paths-ignore: - - 'locale/**' + paths: # prevents workflow from running again when this workflow pushes changes back into 'locale' directory + - 'sunshine/**' # only localizing files inside sunshine directory workflow_dispatch: jobs: From 84584c950b37ccc1498055c17bd317d3f6b2a9e8 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 11 Mar 2022 14:07:10 -0500 Subject: [PATCH 019/120] Update comment --- .github/workflows/localize.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/localize.yml b/.github/workflows/localize.yml index b661983333b..0ca9e62191b 100644 --- a/.github/workflows/localize.yml +++ b/.github/workflows/localize.yml @@ -3,7 +3,7 @@ name: localize on: push: branches: [nightly] - paths: # prevents workflow from running again when this workflow pushes changes back into 'locale' directory + paths: # prevents workflow from running unless files in these directories change - 'sunshine/**' # only localizing files inside sunshine directory workflow_dispatch: From a014391ae7e415256d47bec9925e93be9caf9922 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sun, 13 Mar 2022 16:29:51 -0400 Subject: [PATCH 020/120] Update for Crowdin Integration - Rename extracted template file to `sunshine.po` - Add `crowdin.yml` - Remove `--init` and `--update` from `localize.yml` - Crowdin will initialize new languages and update existing ones --- .github/workflows/localize.yml | 2 +- crowdin.yml | 17 +++++++++++++++++ scripts/_locale.py | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 crowdin.yml diff --git a/.github/workflows/localize.yml b/.github/workflows/localize.yml index 0ca9e62191b..eafc743009e 100644 --- a/.github/workflows/localize.yml +++ b/.github/workflows/localize.yml @@ -35,7 +35,7 @@ jobs: - name: Update Strings run: | - python ./scripts/_locale.py --extract --init --update + python ./scripts/_locale.py --extract - name: GitHub Commit & Push # push changes back into nightly uses: actions-js/push@v1.2 diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 00000000000..d014a00c283 --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,17 @@ +"base_path": "." +"base_url": "https://api.crowdin.com" # optional (for Crowdin Enterprise only) +"preserve_hierarchy": false # flatten tree on crowdin + +"files" : [ + { + "source" : "/locale/*.po", + "translation" : "/locale/%two_letters_code%/LC_MESSAGES/%original_file_name%", + "languages_mapping": { + "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" + } + } + } +] diff --git a/scripts/_locale.py b/scripts/_locale.py index 4a2ec2c1852..b26a059244e 100644 --- a/scripts/_locale.py +++ b/scripts/_locale.py @@ -38,7 +38,7 @@ def x_extract(): commands = [ 'xgettext', f'--default-domain={project_name.lower()}', - f'--output={os.path.join(locale_dir, project_name.lower() + ".pot")}', + f'--output={os.path.join(locale_dir, project_name.lower() + ".po")}', '--language=C++', '--boost', '--from-code=utf-8', From 907d0bfcd50855c2078e72846128881183e178c8 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sun, 13 Mar 2022 16:39:33 -0400 Subject: [PATCH 021/120] Fix `.po` file extension --- scripts/_locale.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/_locale.py b/scripts/_locale.py index b26a059244e..82e172cc772 100644 --- a/scripts/_locale.py +++ b/scripts/_locale.py @@ -49,7 +49,7 @@ def x_extract(): '--package-version=v0' ] - pot_filepath = os.path.join(locale_dir, f'{project_name.lower()}.pot') + pot_filepath = os.path.join(locale_dir, f'{project_name.lower()}.po') extensions = ['cpp', 'h', 'm', 'mm'] @@ -91,7 +91,7 @@ def babel_init(locale_code: str): commands = [ 'pybabel', 'init', - '-i', os.path.join(locale_dir, f'{project_name.lower()}.pot'), + '-i', os.path.join(locale_dir, f'{project_name.lower()}.po'), '-d', locale_dir, '-D', project_name.lower(), '-l', locale_code @@ -106,7 +106,7 @@ def babel_update(): commands = [ 'pybabel', 'update', - '-i', os.path.join(locale_dir, f'{project_name.lower()}.pot'), + '-i', os.path.join(locale_dir, f'{project_name.lower()}.po'), '-d', locale_dir, '-D', project_name.lower(), '--update-header-comment' From 04a2ecaff4fe555cfdd557905892001d23dee4ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 12:38:51 +0000 Subject: [PATCH 022/120] Bump actions-js/push from 1.2 to 1.3 Bumps [actions-js/push](https://github.com/actions-js/push) from 1.2 to 1.3. - [Release notes](https://github.com/actions-js/push/releases) - [Commits](https://github.com/actions-js/push/compare/v1.2...v1.3) --- updated-dependencies: - dependency-name: actions-js/push dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/localize.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/localize.yml b/.github/workflows/localize.yml index eafc743009e..57db544aef2 100644 --- a/.github/workflows/localize.yml +++ b/.github/workflows/localize.yml @@ -38,7 +38,7 @@ jobs: python ./scripts/_locale.py --extract - name: GitHub Commit & Push # push changes back into nightly - uses: actions-js/push@v1.2 + uses: actions-js/push@v1.3 with: github_token: ${{ secrets.GITHUB_TOKEN }} branch: nightly From 719f4cef595823964f3b372248116862f8d706fd Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 15 Mar 2022 19:17:06 -0400 Subject: [PATCH 023/120] Add pipefail and comments --- scripts/Dockerfile-ubuntu_20_04 | 6 ++++-- scripts/Dockerfile-ubuntu_21_04 | 4 ++-- scripts/Dockerfile-ubuntu_21_10 | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/scripts/Dockerfile-ubuntu_20_04 b/scripts/Dockerfile-ubuntu_20_04 index 5a633a10d6b..e65f91760e6 100644 --- a/scripts/Dockerfile-ubuntu_20_04 +++ b/scripts/Dockerfile-ubuntu_20_04 @@ -3,6 +3,7 @@ FROM ubuntu:20.04 AS sunshine-ubuntu_20_04 ARG DEBIAN_FRONTEND=noninteractive ARG TZ="Europe/London" +SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN apt-get update -y && \ apt-get install -y \ build-essential \ @@ -31,12 +32,13 @@ RUN apt-get update -y && \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* +# Update gcc alias RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 +# Install CuDA RUN wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run && chmod a+x /root/cuda.run RUN /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && rm /root/cuda.run +# Entrypoint COPY build-private.sh /root/build.sh - - ENTRYPOINT ["/root/build.sh"] diff --git a/scripts/Dockerfile-ubuntu_21_04 b/scripts/Dockerfile-ubuntu_21_04 index d5668df415a..c7c7a3d463e 100644 --- a/scripts/Dockerfile-ubuntu_21_04 +++ b/scripts/Dockerfile-ubuntu_21_04 @@ -3,6 +3,7 @@ FROM ubuntu:21.04 AS sunshine-ubuntu_21_04 ARG DEBIAN_FRONTEND=noninteractive ARG TZ="Europe/London" +SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN apt-get update -y && \ apt-get install -y \ build-essential \ @@ -31,7 +32,6 @@ RUN apt-get update -y && \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* +# Entrypoint COPY build-private.sh /root/build.sh - - ENTRYPOINT ["/root/build.sh"] diff --git a/scripts/Dockerfile-ubuntu_21_10 b/scripts/Dockerfile-ubuntu_21_10 index 14770625369..7b51da3d03e 100644 --- a/scripts/Dockerfile-ubuntu_21_10 +++ b/scripts/Dockerfile-ubuntu_21_10 @@ -3,6 +3,7 @@ FROM ubuntu:21.10 AS sunshine-ubuntu_21_10 ARG DEBIAN_FRONTEND=noninteractive ARG TZ="Europe/London" +SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN apt-get update -y && \ apt-get install -y \ build-essential \ @@ -31,7 +32,6 @@ RUN apt-get update -y && \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* +# Entrypoint COPY build-private.sh /root/build.sh - - ENTRYPOINT ["/root/build.sh"] From 3f309832f740204a3a72affa315150573243dffb Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 15 Mar 2022 19:17:22 -0400 Subject: [PATCH 024/120] Add comments --- scripts/Dockerfile-debian | 3 +-- scripts/Dockerfile-fedora_33 | 3 +-- scripts/Dockerfile-fedora_35 | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/scripts/Dockerfile-debian b/scripts/Dockerfile-debian index 15f0d65637b..809b20d333f 100644 --- a/scripts/Dockerfile-debian +++ b/scripts/Dockerfile-debian @@ -33,7 +33,6 @@ RUN apt-get update -y && \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* +# Entrypoint COPY build-private.sh /root/build.sh - - ENTRYPOINT ["/root/build.sh"] diff --git a/scripts/Dockerfile-fedora_33 b/scripts/Dockerfile-fedora_33 index ae7e49592ec..a2c8dfa4ed4 100644 --- a/scripts/Dockerfile-fedora_33 +++ b/scripts/Dockerfile-fedora_33 @@ -21,7 +21,6 @@ RUN dnf -y update && \ && dnf clean all \ && rm -rf /var/cache/yum +# Entrypoint COPY build-private.sh /root/build.sh - - ENTRYPOINT ["/root/build.sh"] diff --git a/scripts/Dockerfile-fedora_35 b/scripts/Dockerfile-fedora_35 index 0cde7aa4b09..ba7abac524e 100644 --- a/scripts/Dockerfile-fedora_35 +++ b/scripts/Dockerfile-fedora_35 @@ -26,7 +26,6 @@ RUN dnf -y update && \ && dnf clean all \ && rm -rf /var/cache/yum +# Entrypoint COPY build-private.sh /root/build.sh - - ENTRYPOINT ["/root/build.sh"] From 615f7e58750d312e341702e21c09389ea4f1a3fc Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 15 Mar 2022 19:18:23 -0400 Subject: [PATCH 025/120] Use correct version of boost and cmake --- scripts/Dockerfile-ubuntu_18_04 | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/scripts/Dockerfile-ubuntu_18_04 b/scripts/Dockerfile-ubuntu_18_04 index 5ee33ae3312..b6a05f6fb56 100644 --- a/scripts/Dockerfile-ubuntu_18_04 +++ b/scripts/Dockerfile-ubuntu_18_04 @@ -6,30 +6,24 @@ ARG TZ="Europe/London" SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN apt-get update -y && \ apt-get install -y \ - apt-transport-https \ - ca-certificates \ - gnupg \ software-properties-common \ - wget \ - && wget -qO - https://apt.kitware.com/keys/kitware-archive-latest.asc | apt-key add - && \ - add-apt-repository 'deb https://apt.kitware.com/ubuntu/ bionic main' && \ - add-apt-repository ppa:ubuntu-toolchain-r/test && \ - add-apt-repository ppa:savoury1/graphics && \ + && add-apt-repository ppa:savoury1/graphics && \ add-apt-repository ppa:savoury1/multimedia && \ add-apt-repository ppa:savoury1/ffmpeg4 && \ + add-apt-repository ppa:savoury1/boost-defaults-1.71 && \ + add-apt-repository ppa:ubuntu-toolchain-r/test && \ apt-get update -y && \ apt-get install -y \ build-essential \ cmake \ - ffmpeg \ gcc-10 \ git \ g++-10 \ libavdevice-dev \ - libboost-filesystem-dev \ - libboost-log-dev \ - libboost-regex-dev \ - libboost-thread-dev \ + libboost-filesystem1.71-dev \ + libboost-log1.71-dev \ + libboost-regex1.71-dev \ + libboost-thread1.71-dev \ libcap-dev \ libdrm-dev \ libevdev-dev \ @@ -44,15 +38,24 @@ RUN apt-get update -y && \ libxfixes-dev \ libxrandr-dev \ libxtst-dev \ + wget \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* +# Update gcc alias RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 +# Install CuDA RUN wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run && chmod a+x /root/cuda.run RUN /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && rm /root/cuda.run -COPY build-private.sh /root/build.sh - +# Install cmake +ADD https://cmake.org/files/v3.22/cmake-3.22.2-linux-x86_64.sh /cmake-3.22.2-linux-x86_64.sh +RUN mkdir /opt/cmake +RUN sh /cmake-3.22.2-linux-x86_64.sh --prefix=/opt/cmake --skip-license +RUN ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake +RUN cmake --version +# Entrypoint +COPY build-private.sh /root/build.sh ENTRYPOINT ["/root/build.sh"] From cbafe093960260be3e1a1f9570c1973ee9cf3e3b Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 15 Mar 2022 19:23:08 -0400 Subject: [PATCH 026/120] Add ubuntu 18.04 build and - Prepare for rpm packaging --- .github/workflows/CI.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d36e4a7172f..90557ec49df 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -150,13 +150,16 @@ jobs: strategy: fail-fast: true # false to test all, true to fail entire job if any fail matrix: - distro: [ debian, ubuntu_20_04, ubuntu_21_04, ubuntu_21_10 ] # removed ubuntu_18_04 for now + distro: [ debian, ubuntu_18_04, ubuntu_20_04, ubuntu_21_04, ubuntu_21_10 ] package: [ -p ] + extension: 'deb' include: # don't package these - distro: fedora_33 package: '' + extension: 'rpm' - distro: fedora_35 package: '' + extension: 'rpm' steps: - name: Checkout @@ -175,10 +178,10 @@ jobs: cd scripts sudo ./build-sunshine.sh ${{ matrix.package }} -u -n sunshine-${{ matrix.distro }} -s .. - name: Package Linux - if: ${{ matrix.package == '-p' }} + if: ${{ matrix.package != '' }} run: | cd scripts - sudo mv ./sunshine-${{ matrix.distro }}-build/sunshine-${{ matrix.distro }}.deb ../artifacts/ + sudo mv ./sunshine-${{ matrix.distro }}-build/sunshine-${{ matrix.distro }}.{matrix.extension} ../artifacts/ - name: Upload Artifacts if: ${{ matrix.package == '-p' && ( github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' ) }} uses: actions/upload-artifact@v2 From 7f22774e08f1e76afcb6797577d778a617915cb6 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 15 Mar 2022 19:29:12 -0400 Subject: [PATCH 027/120] Fix syntax error --- .github/workflows/CI.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 90557ec49df..77c746662ff 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -152,14 +152,14 @@ jobs: matrix: distro: [ debian, ubuntu_18_04, ubuntu_20_04, ubuntu_21_04, ubuntu_21_10 ] package: [ -p ] - extension: 'deb' + extension: [ deb ] include: # don't package these - distro: fedora_33 package: '' - extension: 'rpm' + extension: rpm - distro: fedora_35 package: '' - extension: 'rpm' + extension: rpm steps: - name: Checkout From 67762aa445d10cacc855e18f68e1622b777dfbe4 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 15 Mar 2022 19:39:21 -0400 Subject: [PATCH 028/120] Fix `matrix.extension` --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 77c746662ff..6da1c8620c8 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -181,7 +181,7 @@ jobs: if: ${{ matrix.package != '' }} run: | cd scripts - sudo mv ./sunshine-${{ matrix.distro }}-build/sunshine-${{ matrix.distro }}.{matrix.extension} ../artifacts/ + sudo mv ./sunshine-${{ matrix.distro }}-build/sunshine-${{ matrix.distro }}.${{ matrix.extension }} ../artifacts/ - name: Upload Artifacts if: ${{ matrix.package == '-p' && ( github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' ) }} uses: actions/upload-artifact@v2 From 2a7af03f9a0ba79299ef9eafbdec7e5cdb0ce16c Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 15 Mar 2022 22:02:16 -0400 Subject: [PATCH 029/120] Rename packages --- .github/workflows/CI.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6da1c8620c8..66a961547c9 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -121,9 +121,9 @@ jobs: rm -f "$CONFIG_DIR"/apps_windows.json mkdir -p ./"$HOME_DIR"/.config/"$CONFIG_DIR" cp ./"$CONFIG_DIR"/apps_linux.json ./"$HOME_DIR"/.config/"$CONFIG_DIR" - zip -r ./sunshine_linux.zip ./sunshine/* + zip -r ./sunshine-appimage.zip ./sunshine/* - mv sunshine_linux.zip ../artifacts/ + mv sunshine-appimage.zip ../artifacts/ - name: Verify AppImage run: | cd appimage_temp @@ -236,16 +236,16 @@ jobs: run: | cd sunshine-windows-build del ..\assets\apps_linux.json - 7z a Sunshine-Windows.zip ..\assets - 7z a Sunshine-Windows.zip sunshine.exe - 7z a Sunshine-Windows.zip tools\dxgi-info.exe - 7z a Sunshine-Windows.zip tools\audio-info.exe - 7z a Sunshine-Windows.zip tools\sunshinesvc.exe - 7z a Sunshine-Windows.zip ..\tools\install-service.bat - 7z a Sunshine-Windows.zip ..\tools\uninstall-service.bat + 7z a sunshine-windows.zip ..\assets + 7z a sunshine-windows.zip sunshine.exe + 7z a sunshine-windows.zip tools\dxgi-info.exe + 7z a sunshine-windows.zip tools\audio-info.exe + 7z a sunshine-windows.zip tools\sunshinesvc.exe + 7z a sunshine-windows.zip ..\tools\install-service.bat + 7z a sunshine-windows.zip ..\tools\uninstall-service.bat cd .. mkdir artifacts - move "sunshine-windows-build\Sunshine-Windows.zip" "artifacts" + move "sunshine-windows-build\sunshine-windows.zip" "artifacts" - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v2 From 0a9cc511ed0c0c7cff8800a1cc15facbb13688c8 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 15 Mar 2022 22:06:24 -0400 Subject: [PATCH 030/120] Update config.yml --- .github/ISSUE_TEMPLATE/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 64fadc7a523..c96ec16de2d 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,8 @@ blank_issues_enabled: false contact_links: + - name: AUR Package Issue + url: https://aur.archlinux.org/packages/sunshine + about: AUR Package Issues should be discussed on the AUR - name: Github Discussions url: https://github.com/SunshineStream/Sunshine/discussions about: General discussion, support, feature requests and more! From 20c0426acea5d9db8f2521f596422731ec579931 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 15 Mar 2022 22:11:44 -0400 Subject: [PATCH 031/120] Update pull_request_template.md --- .github/pull_request_template.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e3bcbfdce1d..6c3bab87f25 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,26 +1,22 @@ ## Description - -Please include a summary of the changes. + ### Screenshot - -Include screenshots if the changes are UI-related. + ### Issues Fixed or Closed - + - Fixes #(issue) ## Type of Change - -Please delete options that are not relevant. - + - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) ## Checklist - + - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas -- [ ] I have added or updated the documentation blocks for new or existing components +- [ ] I have added or updated the docstring/documentation-blocks for new or existing methods/components From 5bb197ccfcb7079047ff60771f582b54793ac61a Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 15 Mar 2022 22:30:01 -0400 Subject: [PATCH 032/120] Update sunshine.ico --- sunshine.ico | Bin 40454 -> 120760 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/sunshine.ico b/sunshine.ico index 8cfdfed9a006a46d7b4feb5c1955eccf9721d0fd..4d07b0852816e4d952accfca4e5703ca7c123412 100644 GIT binary patch literal 120760 zcmaHScR1VK`*5t7vA2p{qpjGZD5W-~c3Z?=r6@(M*lLE>ruNnvrKlBqmD;Ons}-|W z5XqZ9-{0SFuH@o`bDw*kdwl=^JODA^-wO}G3HYi30Qlg34+;6-T7U!(AfO2VC@KBl zS{VS)e})GT5&7S`oDTr-`-t1g`G0F_0D$v59)Owof9v<80Kni79)KG6{Xh6lgt+}v zcz_uFr|KXwRx;dCAWe-Y2LJy0??VE_{V;!1?(lErWuUGMsQ!6p7q=jEe60Hz0H}kL zqpgW>Yf=x5=UxB+WzWA4-hg|#9RQ%AuKDD#k)P#(1#zIU>IKHzBA^EO%lG_f@0W>& zGC=hqSr}0-zNS*&azLM@l0JPXufRR2-WgTz83v+fS@d-GDZ&v7dgl9WVcA z+x*tn#(R1jymG|%?%n0G?@^%R&rDe_Ao&0HdO+Ky|Je;_#UoC#n9(&~5~cF;TvD2z zYPQLnwKV$ecXg_xKm>UCyz8@v*>>v)$W2dju5r)y>4F{nIFR33-HW?XBB(C3U4n`V z?i!}NB1ON*x$izao>~)h_0TMRUD!DG-JZ;634TtJck=J|;RyrhU+ z6hLbg9aAPueQetr3T)2>Rxx3HrEkvV<>l8Ohq~GYj2E;J8VVNk?fC_kUfX2us(PwM z1XHun_=@h*da8T{v53;zIQ5F$Q3Gqn4p6&OYt`mNAq|7`gjgeD0g_~pFe0Ow95=nrfk`>oW`(|g+U z=X7NGxZAOjU$vB9&szmeLwO=m;NM$bSL$%;Z7vdLY6o#6=C0ap5=_U(b|WfyDcp*r z(Vt7Y@kiLXJ)|j7(rr%i5)fm2QNUD#ykCm)#4d$y-RT^nTFM=8D|k z+n@!n!_Ey?hXp5Pl8098tP#397Oo85{m`BDqXA@F=-h3P-%?f0O7Hu2VXgO^xry-{ zgY!`%BGX`L)brHp+hlOVEMnBEAuW^ed(FiMdHKIoV(*zK3YD}(lsMqq-Cc4l%}6CR z(h!@ggu<(o9Br?aM3uj+dJOcXdUhEQX#~J|;C8 zb`6sainAS=|G*yB$%YS?#}6n2ErfrwrU*!Q$SB^EVX4+{PYtOo5YG*U*WDmcr!%F1 z_Aq?(5V-I;r&EG3I(Tl9Szb@&*#68{FLs?JhU@*v-CnjZLn+K-X!8#`hvSy^T?@&o zfbEGVT~Xg5kuXTW&72Ao)IY$}{a~sPNb9@}3F z@+k{N>Zpj6rVW0yw)?E~7o;`lr&8;mv+CI~_eE5N2hJEPa`2Y(;rJ*5%AN=@a{L_o zJ~s?Hl#3w`qRySL@Jw({_!M?A9|ro?r|Uj3@22zEw}{J6iDA_%ilj1a9$6Rx{P3Q) z;BgLDK8-#Fh?l^Ve&ya-RA*5a%|3i|)Kg$qeS`EZb1;SaF^@tJS4Y`#)may_vwwcV ztpu^ZctzjJA(Uc_x6_|2>)IgH(4cwmf*r8xkK+5o);~3XNrF z$Agq%?RCNde<@u%i;Vf(=n^e!So*LDFb*{)1n*8bfw_VLsJqlbAW_WLgMrPJe~M{w zzUc);cV@E5d{)6@Du2SJlaAXL+B?ox= zZWpZhCnAH=6MRY})ZX!>M|4A!OxK1Z27={-$uBXh5nXc4;)ww?&J4o%@s*syF8tL)frIN zs1r2F(;R#0O_~`94%G*e@f8e8zT|Z7x6fcnS*ITAtHm*@oMSC8kS0n4&f)CpngiXL zZH5;r3i>um?DLh1dRhsBNqw zfI#f!czV1zegT(2UzwPclAiUw03j+WX}jXw1Q*VLTmE@!)7I-RCz;LI$6Sd?cuH3Y zkz9`VHeTdEXNperjAN)q>7|-?(O4GLQ^f?qE^V3aoJidsf&gA3f5YsP<(0tztXurx z$AWl}#$lu!uUV%#=&!JCookj zX1HnzJ(g<^Wpd`c_*(Y&*ed*9r^zPK6x4Js?U}Sy z_HX!}GPBL-yrE&6RlaZPrSEpw&4OO})D!M+N3o1$|08>xiDu^cYbQVu@pWC~CyANL zah;LD*Rm6*3M-X`loY~Ln3lUu@8$_ES_KfkR>8$=dTP-<02O><~i5uzT>k5M;p4mNx|JEp(Ykt*ldOa=XM zlFDEoeK-H1ThVYS@w>~Nm27}5rl+6w0orr{sR&OWHB0eZ+orUpHNo>g$!za&O#5Y2 zaKHaUOXLaA>aB5M4eB)Wfv9S0U#Rj*V#1D}6!-J6){JWG(g!(kP81@e$`d~l>egTH zsR73lUI}SVM0eNN*k;D@IWP)uJ4!W1pACxYOmJLI9bjZEzCD-wR-w#tC&gJgonOCy zypWzhqw4`gvQ@RS^tiDk8wQEQ-i=h`zTYrGCs)g)s7W;-(T`G``~-av7<1wV=ZJ+# zbxcC63_OT`EvooS(1sPT&x(e>JgShx6nw~4lF`kUupf=GqipF3bsyo(x%=(TeuaD% z0k1ZEokM92QhZ#NW#Ysnyd_KSb|xuc>U-LyU4tdL!vFq0o&;;`)N)gEdh0cEH9zEd z{D-R74@sG^N$+ow5>fD^o}dIJA<#$NnBdT=)7qzG^YFPhZ6aq=zd6ejn;L|@2c^%9 zv~5adr-AVhc=ORCblFg(oupuQO_V_#Dwx3mi0$9%(vKpwM86}RVqZjtizMfEzA2lx zh^L^?x)M#N5$JM1qfXoshYsZS7gccWpPMojHs`hFf;)4!j9gz;cMZA7Sc;|w&aWT- zFz=u^UH~i7!x&5|nM9jgd$2|-#&#c#S;7d&t~jnujLPfcPgT)$Lym)2b`2 zgO=ZdXHQb>e=BJE9z0&Cu}c0TvFS*hMeF@4ew(1<{cm0Q&{aF{g5wo~Ki+hz==Hw{ z4K>i;$n~0TvQzq>X`dAX1mJhWJQy5^(GTn)N+z_!`Bpi2Bne7_Cc6eYg*5YBx&1s) zniljI{lRE|u7$hkTb+Fe;r>3cJPtA}_>CCL3KG(*=g$fj_qB#X?HiqY?!;PFy2TDD ze+|)~jWk!wr-)Kp4MxO@z`2k}UH3EkrWJbIbdRo|sypTGJ@m2IOMNt*M&|NMCAB!L zeW1(Twe?jQS2wEdi3l#y*4+q0W3CR*SOpq;2hJ|PPM7MSn0MRG9JE_JBdPN%XX-CC znLscEkYMJMpM|mV9L0rZ8>9$5v7Q$r)PH?@Yk4tBZV;;3G+FouLIvA@RIRKw@CbCqxa;w!j8ZLM%GX<0oKs$z)~x4*KfG4AZo*yX!$b@LPQMV zP8XnjVp{O4En+HssN;2@cE|{YNF#!~* zgbgpROrN3QAD{8u(s!7g?oxI{{9OLy{+xu;mdzPH^t6t@@H3M}5}$xkNyhd)kTmyv zIJWC|+$RA{3_a#+mL+ukmVc(TR;s_l(;m>`a;9EAvV^2ah#)9lgZHvaF0aS&YR za_7nQTPS+$7%CJJ)T=oU<@$n|18yTFyP34!jGfw@SwR^(ro2Rkb-MBn1{7Wh%vWg- zoovpLYoz7xKiU)lD6@t_bV(B%qAv%DMxMAnsY^FNAN9S5PWqR9G(i=hnAYgT$xVq3 zZ_ypZi$9a+pM4v+gR{bvI)LE)z4_q#5&*G#`cbg#kF`Y#k?JbSCJvco=7mB|?~3}c z072*WiFL;j_uL-MF2msB6*t4Oz5$6qU-6& z!9%-wx@zaw-Zv{`Tlsk$yO$b-Q{YcHW%Y?&QhmY0`2Ba zR63_~qS_1bLf0fsD8M8;L?9dbrw!0z(;6hI5Q*URV~IxDw}FSaWgea3+pP?2YR6sPWnYIU zsad_&Z*izMgG+SI2dVU1Il(t7fQ37JB>Wb8N9_P!@@>?m1C2SQ(*!o>NC zaPI;?ZGya6hSEM$3K=2if|wsHM>W;I=^g|xB;E`5N_4p|IW;k*cmB=}e~O4nrZ4yX z(qIdapd`zKmrYv%>hN$|j=#Xz;1%VsY)kuDA zKq_^~7U9~0C$^f=C>}cjk%64|2m6BZdtof0Aa6c3@hzxDg|zbS)rJj5A8kxQ<*!8o#DRl@O21}M)WZcg(Knc_)uDIcFc#9D6s)5e?sHsjAJIQ=PZr^}tT&y_{l(*ly zZXV{jN&0Kq!oFxLMDzqnMUZxKt`$HACn=T*7anN;W)oaceAz#PYyz(GiBsMDa6GV< zm;XvO1-dm9V!PX?e5V^;D%@lESWv2|?3h}Ar>u4xYEdbd1^?i=+y2iAm^_HjUJn&kja_3Ltu!v%9bj`ZsDeX^bII8_x{!N^R z%ED8b9zh=_uh-}OIDJHzAU!tiLLUs4 zRn?EUcv{ygU>qLsfpS9qqjjg_)@Q~B8%coyhsG%A!S17lDv0n8NVmw0FXM~F9zVa$ zJKo4kL${Lx!((Bsh2!fog12#kOm{0|~HgN7f%HcdX=LeQ+IA3XvLj^NjoF!NytuTs4)-tg88QsD(cS8Uy`ESh1*%jBGO4;~T$w`uJ)XX=RoZvTfM1GzA??>Om7w6a zu}giAidD`giiwX)1XZa5Vz-E%FAZeCa=pg&F81SowejRul0h>D>e3Zba9SFE@K@li z^x~30!#7xLs4Rt>;V(_I;fR@ZYNN1{4~(vQ6M>wbi0V$aZxN7`W*Bgnx!l{i-~J>($`+#5C|1Hp&LiZuf_pq1$br^?vG2VB78lJ%=ksFQbP^+Yl8_mk@&e1;n@>X=k)JH z-8Z?*kdSPjhiR8;0(FXgkZ-r>&OG&})(U_xYU}nVG+#hFf) z1U@;75V|L~)VU|V2l|%JvOIN{KS!zGZH`@cVU&La6+qTH-}BCIlY)jy$?3IsKz@tD zYeUt*6+V=oR>Am&M)XdRCc&{Nv~|%?!c8B|lcRuW#u#d-=fWZ?Syv|I1pbL&P>>s} zG;axc3m?fAmPrS4US)Cj`Rg1V@wG$o_1v=GBtiM#I)u7y z=)qZe)`fpe>o22WV18~80nc;^GdO2CLi<;CK&^BiqIL_YW@vK7H+T^za_6c>4Hh6n z1A2N;}y-#EugkRNTEbL&N6AO-kp8lrN1GHu^HmNQRi+WJcn(M6A)lPrXn@}hao zcIXDQ_qi10-%!RNMg?*hoSR%IEF0bXLc$KK$d1EtTpq4eieBBQ&^`_m?4rDo&?Vl# z#TE-%G!|1$$TKX}cj0~|H1 zL=J?FM!u^h8aKwaCwK|UUsN9pvH_kmn(J9p7uXSIJ)U35y^G~4!dQ3f6)r?3hdA`b@Tkn-JJxt`JL6HB$BO7;AnDjRN zwsIa$Ot4gMk`Bh8tvvPIPVX;L7lQ#if{bGyDC|7T#SwMWXpNJ@crGk&9sXKMuG8I%>;?6py1CY>%)GXx++!ksE%N zo5f{B9>?wFAk+9Cm|};nbQm6LCigCadiJua_q-nzR1=%d*oTfu#_XpLmuXMVT? z`4quox#zd0^0DuD0(}r1@EoVx#N18RTWWCF$8k^!b@}lLe4b z!PO$aliyT&9vb-kln((4k=`A-M_}c9QK8fP3!*%P_Ikgh${O;A7Q1NZ=O-Z)R$#U` z(y6*<{W;!!ZXd^|2bF4d*&1wu*nK+*S*8U&)V;2$$amW4Bspm`u z`zNM)?FgqyK%mXCQ&_5=LKb`RZzj3g`WZU?>PB5EtBUX6FRI&Hs6XZ?`-%>I>Ea&A z)=_%#Xy~d&?jn5x>+f|eZg77|y(w~Y#HHiz-yfN= zN8cKUqk%TiR&T~nWTRH04_kmN?bSDcZGWIF;4kI?oDI@t6gYixuvKji8J*~G20W5v zD*AGJNnOf+VcKW5g9E@m=UePNV9+=3mL05od{sh&dZXpLd(e$@&I(dtFr zzavjos7&OatKXzi%P_OHs(jmxw3%V7k?T9O;eW&VkJl{};`#9f3fs;PeFYDyN; zB~gNRu_QA#{V$ABtqQ3)IHB#>G#9RA33$C*%P(n7P}^&4I}qpAhVTTq*lm2DrO$%B zM+E0@F4vi`y>C@)1cnsfx}F~3)N8xrx<>s`r%unV3uQ2wW1aayw$X-*>9(~FEMBNr z8W(@fM|+bf(Cp&m|wu!8Kq!xXx(qi5sPJ*8!hisAEYnE;_lG;cD!RJ*No^1 z-S&8@QE}Jw>PGgp(dNluUc$b%)JM#8I8i>6BGlv}9sH{l(DGY3Z7b`|9c_Z+qEm+_ zh9+2DE_UvkxJoj})g1u5|4GL3Bl4zl)$sx*q{|A8C2e+{OJZ;1HK+XMKamV=Xf};6 zxqeP~+&zNOlHY5iIZ46m7Z}DSVzqCpm;N$?EN88S=IQWY zh03btvDPW&Z2dndf??TpkuP+TM;%|Lh~76{Y&6<9?x2WWghz?=?QGJw#P!+55`>%q zwtxh6^$HfR3x0_9yyeN!vA%MrsPattSJD4zo!dQQeFP~%+OaOqG(I^0LSY*HS@1cB zFxz2-HV%_#K)}sMoL(0S_t0%Uadp(ol&ig5Nfy>yQdKOxqTi+U3pxXK7A0G$SwX)6 z+#|$Iakk8P15pkle_gyYSI40~j)xS%4fo&MEi|N={S-+>IZg+L`0!J3lfC$`* zK!I&83aMWV8pfA0ZA~l$N3xu;+QiOg9m>r7Q{k+C7GTU0y#DG?diW31pt zN+yTHN_WPk1`ke(Xyx00!54ei-EkijDtVBE%6gDE01laC?Lewd( zOIJB6v#P%}D6pUdLcG823W#A~bLLS$FQ~aj3U*3tMSV9zZ+U1Z*#Pjnfcnis-81yt0kI1xL!$yqbK3FDOleX1z-nebbYDZ> z;yTWt690GlKQ8r9bQ+jj>!q_r81ig*79j6VYYOHksj+$ty5z8qn29&-txZrTNjX%` zDVi96xpkgD;!6)eh3t!-FJYT!*{b zZb!>vCl8Ci%s#ugm*sN5L+lopDjAV@iTLwd;FW{k5$^tv{Za{PubYO`hY{7;`Vg#k zsXkCXO9FreS@tkq(Beu4iTPy2`e^8MgIvXn)F=Cp>87>a{2o>+<4KtA%bX*eB*kvi zZ7_%=VE%BfnC~jnAqR}$!@9Sa)^x=<6XA)IM#NO`49ZcbRh#>yEQ)FEO+YzyDS?ks zU&c0Wb97P#BY^AebJyLv93@km*weeysw_{2dI3hZcoq#`4*2~1>_B3TPsYyheZ&yc z4c}$$Xk!$WTd*rc+Z*l|9$Y(k4ZdVcecT46SOWooK~E?uTEYIclJ@s%p#fwy+cW+? zzzAp2lTTz<9vx!jZ)E0nCv22XnCgPsO{SK4FVasc{nao$)6$c-2wtCSJ>Pz}e^*AD zPCF*A8LLQCA`51gwyle<><#z_Ok5HWR}eNgK5Q8kt!_e%X3IuiF+V1#{ao5UHFw1|Iy) zCBYa+UB>bb_NbJefKPBN_n~w?9`i7yW8|&MUdiXOr(Uf38rl|aX;yRrf?%+7xG2WQ zUlIC2*i_tScJ@jmYe4U&5-94!nI7VtA3b=#9csg(*N53>M`1 z-RnRDtP(=snd&IEc=V*@*O&0=(AlCBs|IrLe!|g!ie~16iii}G9(k)d+zHa1%K-=yuVd3lUYLh9(#=FAAjm3C= zlkU{($&@2J^J-)LiuPKvr52;yAI*+9bR}uM4y;uoDiB11DVPtxVHLOOxi^YD+gDip z;1dJZ5QYSc|K{CQr|?k5i%|GM3Gz! zY_$Nep17*B;O!^Nzi@iMJI>1@Y$IXDsROU}0zI!Gfj-gb+>db10qM@7A?}RO^HF*8 z&)f{bg@S#L4CoQ8(Nv?K=10MgBAgRcb}`r;dR)qIZn}k;+PO6*?GPh4f#H--ML%)W zo3Fp+wZ>%1ex>&-d^J(?hP5WLOAUPMQ26$^;e%ebZ@)h9-cC3DaKB@JJQm+cBr1pX z?!4Z=J;IfBR6Vh9Zg%_{cs!PAerk&m7Z%DeFmJaAY8nEc7k9ishifD^Y?6;4>t59; z$eW9d6@GaU;?kIzDte${4qGT0o_UJQXH94tO^_J`KOzjk1{uBbClbav$N+3f^7TCm zEzb%Cx7ReRAzDVwueG!SljDP_okd0#gF*Z#kE`zGlZv8DUE$;$oEh`rZ=*46P35UP)lG*0-T7usUj$&72d zJu&&b(*p#z$VOdUWj^wtSyb@ZWatKm25U+Vz%X@Vlv+NEQ2Au6$BiE5TAC-a^bBS| zHDK3&!?rlZ=@h95Bx;r@S%w0!lP|BDhEw_z6*lP|?qDhn7J&C@_}FDI1;v_q^qVwP z705DZzd$VF;ypqnvhUG18A649XJx`KCrnGMQ=f1#DGncY^u4Yd2hP}o3NN?_NM=b@ zX(H!I3s{HMXvQy{F^DQ42K?a8n)iygdA?;InP~v21vaL*%3@X}=$^xqn)Y-FbJh^y zO38n%jy~Z{z$Dl4b-DJj)lV;Mk@aC0#u(LBv_pm%1kQjzoJ}uy1@3PDKmqI&kdm|xCy#yXh`6+_m0Uv_?`0G3CKcF;}8v`v5 zdOGvM+d?x#PjQL&804JaZcjFq7W&M{;CAmd#rvAJBJ$%L!=0Fn;G-IEmcxcJH+j2J z0EzvxB&2nTCTl2FV0&j8aX*?(d`nR-hvrQ~T#~_(bYJ8nn%IGRa#os*pB3y$rdSD> zZ(v8b2w3bq{b?WcLpydd#}xCHs|u(D#1}WGqt>%XXx%UIZvbcr`DLs?Bi$_yxQZJ@ zV{R^3Z_OX#HaD{^kl?q3xxbphB3sWIBv z>2r*$Uf{}|E;$FpgxMV329`7P>JCA@^R2ls5Z?m-=v8n*rMY9|cgIiU%r^r%5Tx?& z)qnBv_mwl7+* zN%IknR<;(djw~=0?6RIFKAO@f+K!+{>qnZct--?h)Z-S+N>+fh44;_{Z|P-OIiw6v zqk6uqmOV3gAIlbitzvs{v_d2buofj8(ACZcQ3FX9%+iQ!3i6s0F8(THF?ahRSlQ}= za=N##1O-#`bH?O~>9aJ&r*Q3oU3IAr_PWw7J8HsLLq25|{&%q|@m%?5dPjM!;hip8R#}dri(>GQ%J%mH!*t-HGo^=T8j9v^n_2sS!!+ zzspMHtAAo`>6&JukGz{)5>{|tK{WicVu5fUyX?wY{iAsWJd>8!=4vC}h)%*3aJcA( z*BRlP)__>`eycHPucLJ2n8&EkQVetEp*GK`bZ!g&+=4a<%}7SwQ;(-(!Ic|#^JF3q zZHj-@sLT)HYPd`e)EABENs1)t1g17I$bS1L3-Mj&R`p6!`S$y&{lxC8dbp9+Os7X!H6m6W+}*b5=6l;O)nte|%)$6+ z?Ff(u7T-4iGA1*+bUn*_=P__7c4!6RkC1IYU8r<=aDY>Yuj_hWF_U^Xw?aoYSdx*` zAm8zi7lB=G3B(I~-M-qJ5l{g8YgtW+$mjOg_mVkC!XnwS;KWTP+CJGEfv<(NUMA-% zvaLhP(q*iBlDis$>#i^swZs9K&EY`xj4ppzEQ}8{z_4}yvm=BHLERRJX1p%=bo6$q zH(szL)A3_<^e4VaI#ib0sxr&-M(9vcvUNwZE8D3L^2apRr`*7J-?RcT3w{yi^V?U84*cC#iaLscs~D!6^(pI(290(XGgPutF$)#O%t1OvTjn!qgg*=F$=*XN!5nEud zo+jgl4Ng>GRQ6b7}O&a*P4^QbPG=9)oy<6WFj#0qCSUZr*Px}vadNR zq4LD#^EZ)*?`Ujy%(bkJY22RK;6`CX3^wWc`zxMlo|EG5@;(K+<78}m`0^=}M??F)D);rMEj6ge}nOWdP|FNSsnt0uW~*E%_?N z`{x}$JY|1;!~|V4zaN3zfF9mEJ0MN^NEPx%)L^uK(fbN%*}G9_hZ>@Imi9ZCYw-x; zz+C;l=J*xaF$^~e{fS$zmtr`O+*q)tgkF6+ux!PfrkYql{lW{cP>||nsoxtr!iY2A z^7@rOs;g^1WXxUqQ~+4cRNMO&@p0YUKx@E0W0_4ai2tsd`ym%e6`J0PI{=%C^CyKm zHzjh%O)ax4LAs@vOc|o{Cg~e>Kz3s4VFPPtKy}oFQnBP zV`*`Q@H2DyD$6fLPoY66j#!dR`;)50g&wMY;fpsagNKjky-54=ew8CWUub)M!DWi8 z3Wi}S2lf)|8XXOly>I3~KUwYXD*=O8AIb_Oeu(T(TBX6rX4PkTs5D6x1wW>9Kz+{gD>>G<2@-somYF;K`dj=GHN#kD-FHVq%eCY9D7O3UkwNL^xuaR9 zIE^t;8gh-9?kvuN+To%{E&e82j>wY9ezgX&OYI|8jDr1nHA2~=OZHf{@pY1MsIV4= zKt2BR-kc>}7sTvV zcW0H7s8`MI51Mo9JrO)j-8$@`*`t+byaO+77fAqG6(Aj?N$fGE<|?KeLo~af&)iks zlGX0c?+CWIU1@*Ea{05CRxY5%-@+yfNB(NGLBfMTyuojo6jI2?hk{dC^+#^1lt;Kf zLU;L7WU;sbi`tLYJJ;z20Ut9jv&L@|J_osOEXxT-8LYVPs`Ue*FrE)q~HZkFvOfht6`8rHWAl>ug?hKP4<|O@oKg z2;p8g&AD^9zByK9$b0T8y=%unK2ur}BTmHj!=Hj+*>edEEQ%-Axy$CPFG3@jaZ1ce|A#`%bBF@Q2(~W|5sv-zCvi;thJheKjHmuJ zW4u)RE69Zyk&JA~uV9*3Busvn+E>i(2y1M)f0X`Uu$$5%#=4q#JfEJ2vyX$#6L*+1 zNm_-f1aQVr9nxtl0VHxgV;h<^=%V;M#q60^Ed8VY14uZG)C@{ih%53Jm8}Q2oYxp0 z=T(^2rp$E=pMUzQHnctX*9OeAAn5$|ovN=v7GPlTHxMo;@zpE zTLx(KFKuTq3EQmS*#-zZdd|t3V{l{P(%H)T5}e#U>CcE6&2=w-M_QKoT!1pStGdf* z-xd7a(Es5}>Vj-srd7NStoHyMO(e_Dm0SnM8;@B%>Ra|uXp0kTg1q$l;r%+T{(5~V z$*A6Q?alSTzPjGlEq^~(<~LWQv>#F zb}rzZ6kd0KiT;EyX#KeJ9)Y_xvi|1h>C*;Jj-3B1?fe{LTGV#7Od6&0CVI`-^y6Hg zHHTJRD^ZEy;NJK+1xT5}B;qwnIdFImKIkiGu37f!hldR#EU)L%A-YES>gDEbB#IL~ zvNsmoe;J%++wwEjOAF{oFmOFljE5RD4-4n3S&(fGW3v7$8Qhq0VPRNj3YIoBhiU(HQm1U_LF#jn>e?KyKb8{X+)w$l9Lw)(ik z@9Q>p@^@JM#`bKu<@~sJ?{j*rG|nBW#@yHsLvHOmqRg2odVgNL$%5F8YnrYGhS@m-ZN2{f<* z*Zt(76e!Chsqpct=eRC@xW|uL^9Piba04?Vv5_}z@y&hD)GqlFOdV|B{6>=FCR<9~ zd%igcNPQcv#mx{k7`i##F<-BSXV#oxQ>}X#MwidwQ97i1WI8?ySBMt&d`nkki|L_lj|>as15y zP{r1f>jmLX*yYGO7Y~b+B&FX53vWgO2r>;LAUro>opU4#!4dISuyGzwZI9snHvgRq z-^Y%)c35%F);(NqWWPdTa#eSk=M1!g1ZX}W?;>=q77|@NA7@P!6Xs;FzrFw1KmH8G zjlS>JpDeu4b-x7VE+*aQa7C&^wOEZV&Cv?6QrNNo$^sXUE;7HK&;~DDfMPYIz#BL0sOf}%qSU>9au_{!SR?YzJUNUn^ zE?#qZDz|~D=Oe63pBAG@3#slDuO`l5ijM~kx=3&^PM7|s6a0B{NAP8%w8!4-uXZEY z2euftQL6zb7(e~wLEZtqk66kT##ZB>*EgGOr7)F3+T|Hh8`+RpeB-d75_1=j+~&QX z)W1AQO#0^r!fF2mI_blf4~E_~vOTW&&ahp#4gd0oAM7X{i(szL>3$j|whnpuP7deU z7f!XU$NuI^G)|kvMWujDQ~f5+MNVVI!X8+M^47cun6Eqiq+g4}OF4psmxu*r@#A>E zmW5f9nUbBEV~3S3Dnc2GYXjUR?8lEh#6CVo7&M;ZrbXL%;UuWz>nU{w$$Cx(meIo%_h4D6Mu|kshnwqB--=zoauueZz~!08 ztKz;^!qHFXDsKF1{?(uH84q!4SGTCcA4*O2SzA!bwJ2ii{ z46X!OYAqfx#iGR7POu{s-JTDGrXcM9>awQmjC0|y#poyAXWtk7O2HcI$hrO|rn*k> z9i^B*q`l3&hGI(+Z$e%CclC`B{rA$TFiR)BCRnoJ^pIFjY{$PgD94E&ZD4u8E}8t8 zN51DCk=;k`yQDO|a!H%q&)qq#!~BSC=zEtKrFuUrZ_d+xc&`oFPVxF7`DAO?KGv|h zCML#GBOPlR#E;=2eMGylxJAdk6LPNGRJ)Dq6~SEi+IZ-j6sO)S^Pv)I${JALF-F!x z9u%O?xoYB-O+lNFF4Ek}yYKq`q*c4+)fzMRL)t!d@m@EHR)^nre zeQEskkCU7S&r)lg%BQ96i z${!xBvUL}d{?p-B6pdB_9(h%G656pMecDOQFH2ceYi&5ed?gW?%rSnkwf3F~=sYwc z@M*?C(b+RH(; zW)yTfR`;(iywPZaRe+=3coAV-veiJ{vY10utMF6Xxm-W3XK)>#6Ists_Wt7!=|)55 z6IA6VBV2iHggk%=omACPYYXU#{&npjrq`uEI1C%*@TWi)Z(qtI>Ai(gauw-L;uc{S zjqt2B3*Y+mtz?i!R&DhYqJU6_YT)`ppymn8PR+*3N0aF!F0*O-M8PZ0Hta1sUUcSsOsww&}u~I|`S$K1?8N5}3jFLy3upueZp1*FE)uz;;VyR`iA%4!-ps$^+KDCb4$yfM zD{JgvTUnDbw_bM53jS(p(VVA5wCpW;XRK7O1znGuw1WhLV1$nYyq_J2tO#xy2@(Wn z#$bIf&~&KNrx$dH7M0kqJRyVf~GL5xvXsU4mfls|V6>-9a)896ra@#@_Nd|!{*~)(ux(2#qK;290Vu47h&+0 zk98(oJ~xcG(v-ArKRPc~;Ln;<-{+uUXRY@(rS8ABs7*f%c}5?+<#nSRb7^07Nb&cY z0X*R~d3w-R?LJM!gN?IeLl`_w_k?9$c4FFr%=-?gvl&{4bAK9+?- zD581~d3GjxJAr~FeWg`e_s^s9tt$@u$6P2dWk-u=iK_#ZFBUyWd&x<_ZEmloUfmG9 z9Xr^TCCU-zTORX%3^zJ_&|_|h8^QRXkoC}RQB>S|BW~vQWe3uwIX5#o>h1Ry_PCMr z=A62}!558k*46TdB0(dTSR;0+(Vx?n5j5$F^}m7?qsje;Yirug;am9P+ijpQL1OP@ zJY`d!3mv!%v!&$RYV4}=9evZjm#5={i0sFard8E1JC5i*?$W0tm@>B<*p)A?p$6!= z6UV%%6>}Ow+#}-yv#!l$BD{Xl=HQil1!QSur_cooQQmr7$`Z9PnlLXs(dJiMi-vFQ z_cV#CA9)tIoDM(+N2dIW1chOCEbdvSHpO{${#Y6h9@}uCnMPqr^FwbEbA^O)=;Y zIsa%Mt@!lQxZO9q=+~Fa)_<^o*Su8_x^!scj!<7;a4;fL5p-+sn6tuZy>9Q*T+p;MY&~ zK($P5>D^`;7}^I}rB7omBR4o0GJ2?YJXzZ<#VlM9!JqO4F8Se8k$&-oxCaS7FO=S2 zAM*CEp}5D4RHUI$PS59<{r3ObI}iA%s`T&Q5EWDuaP6x^*Y3KCLJANFy{e$1s6ZxQ z?`>T>0a3A_C@slMASfzUz+Qn+q>}_t(f_Lgx@%ccL0k!%d*}WB?#vw~lbOk6GJya& zA0BS*+;+}$o^#IAk88n#X~X-UHfWziGDe&>t^bYFkG*>J-n~x#qv-SHS-s{JeYCFG zaa+eVUo!m5cJsa(-tW;{Pwt-Odh6T!Zr(S|v$5N>E(a_`JjqJPyFA6snga?c;mqZEAAWK z{r6V7|Hod)!^Lag`QOPaTIFrH_O?^^@l2c5^WW{pA6oJA#b=y6 zf5!91M+ciftzL7%Zv{WSIlk!$B{%i_*Kw_1DeF6@^M;iFe)n64YjaLKa9z)L2HkY< zUw`Y8wz22u#b@L!Xuo96;% z?7TaMHa-2qTMl}qUz2q&FFf_u6TIHO!*87O{?TWAa@5R5cWlmor=ahdOA1H+eDKPw z?@#v*nK3W>+&;}09DeZBFbCL5bB8uL z^PtgdPRJVBC8g6l_a2jb`itG~y6J!3qi%ZWoBp>Q`TMlL|CxTzyJL=ByWp2ErmWl6 z^s7;0n7m(9Lu{*XHd9=37QsC!#JG87%u^>+^W{Ii#P zfArAIrR$cQvF*?HZJK}cSw`bN`NdPN8C7<|jq_(5Kl8qya&CI%@9Q3XW?lZeSC5-r zwB^F2>~HR{?q9d`vB z4twp5&FvrSzv-91FDD=dA9Xjiz!T-5_ z)}&95Ic;iwk6*VgUpnvdo-N#|P22y!1>ZK!{H5iF_x8WpnEBjEcRe%MGx)ff|2xFm zSaEvW=?lyMcJI*2aAyZ^Pn9^JcT&nw5xxo*gPw;lAarVkA}`ks66r5V-g(=!&fIQY}1`~5KRtXJR7 z?=kdwz=& z|JUl7i~gK_`bTZ7FI>O2*f@>IiHrw2+<0tB{~_;O^6aB)Zzz8@@7pf7Y`NlwIj4R4 z)K^~}`~Br7@0&TaWcU$NzWrs$PnT`pwB#Qvemd;nALey`N2|kk*KeBg@+t5A@%6V` zk8OSPmLI-eo@xDfuysJi?3YtM*?RSWy*kgjsMTfjznwQVZOA|W{NIh!fBb3o$R@|V zyye+nZ_GODjkXp4IoQ0Q%~4l*4%(P^b>EwD*&X?BG%up z9QSnIqK}7UJbaSp+J_%IW6d2`9RAm)UH-h;T+r$I|J?Rl2X}}02Y)g0`x$+2e)Z?E zFTT|5s|!19O1`GcQ;+oh$8G;UsNV zzI?|@bIjl_^RkNP9x(B@!S}S!%)IpU<9klN|LWxz-_hiN`IlX5T=~-Q@-9d3d&rF8 z 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 literal 40454 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 Date: Tue, 15 Mar 2022 22:30:10 -0400 Subject: [PATCH 033/120] Delete gamepad.png --- gamepad.png | Bin 24804 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 gamepad.png diff --git a/gamepad.png b/gamepad.png deleted file mode 100644 index 274c7cede5d1740322b863990181d0a1810e3567..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24804 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 From 9930880ee6e08af75b8557f8a4d7b65b7a3d57f8 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 15 Mar 2022 22:30:23 -0400 Subject: [PATCH 034/120] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 72674eac740..d61b812c151 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -![Sunshine icon](gamepad.png "Sunshine") # Introduction Sunshine is a Gamestream host for Moonlight -[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/cgrtw2g3fq9b0b70/branch/master?svg=true)](https://ci.appveyor.com/project/loki-47-6F-64/sunshine/branch/master) -[![Downloads](https://img.shields.io/github/downloads/Loki-47-6F-64/sunshine/total)](https://github.com/Loki-47-6F-64/sunshine/releases) +[![CI](https://github.com/SunshineStream/Sunshine/actions/workflows/CI.yml/badge.svg?branch=master)](https://github.com/SunshineStream/Sunshine/actions/workflows/CI.yml) +[![Downloads](https://img.shields.io/github/downloads/sunshinestream/sunshine/total)](https://github.com/sunshinestream/sunshine/releases) +[![Crowdin](https://badges.crowdin.net/sunshinestream/localized.svg)](https://crowdin.com/project/sunshinestream) - [Building](README.md#building) - [Credits](README.md#credits) @@ -198,11 +198,11 @@ All shortcuts start with CTRL + ALT + SHIFT, just like Moonlight - CTRL + ALT + SHIFT + F1/F13 --> Switch to different monitor for Streaming ## Credits: +- [loki-47-6F-64/sunshine](https://github.com/loki-47-6F-64/sunshine) (For all the hard work put in to create sunshine in the first place!) - [Simple-Web-Server](https://gitlab.com/eidheim/Simple-Web-Server) - [Moonlight](https://github.com/moonlight-stream) - [Looking-Glass](https://github.com/gnif/LookingGlass) (For showing me how to properly capture frames on Windows, saving me a lot of time :) - [Eretik](http://eretik.omegahg.com/) (For creating PolicyConfig.h, allowing me to change the default audio device on Windows programmatically) -- [Twitter emoji](https://github.com/twitter/twemoji/blob/master/LICENSE-GRAPHICS) (Sunshine's icon is made of twemoji) ## Application List: **Note:** You can change the Application List in the "Apps" section of the User Interface `https://xxx.xxx.xxx.xxx:47990/` From 9c976a23de16c972e98dc155f3ff50d7e57bb25f Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 16 Mar 2022 18:34:43 -0400 Subject: [PATCH 035/120] Rename artifacts --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 66a961547c9..76d38cd0661 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -132,7 +132,7 @@ jobs: if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v2 with: - name: sunshine-AppImage + name: sunshine-appimage path: artifacts/ - name: Create Release if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} @@ -250,7 +250,7 @@ jobs: if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v2 with: - name: sunshine-${{ runner.os }} + name: sunshine-windows path: artifacts/ - name: Create Release if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} From a9b9d1bd09e9541d9d484ae48aeead8dec2ebae6 Mon Sep 17 00:00:00 2001 From: Mathias Tillman Date: Thu, 7 Apr 2022 08:20:47 +0200 Subject: [PATCH 036/120] Properly catch exceptions in stream broadcast handlers to prevent unhandled exception crash/termination. --- sunshine/stream.cpp | 130 ++++++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 59 deletions(-) diff --git a/sunshine/stream.cpp b/sunshine/stream.cpp index dd14e82963d..10e215b6eca 100644 --- a/sunshine/stream.cpp +++ b/sunshine/stream.cpp @@ -963,63 +963,69 @@ void videoBroadcastThread(udp::socket &sock) { fec_blocks[0] = payload; } - auto blockIndex = 0; - std::for_each(fec_blocks_begin, fec_blocks_end, [&](std::string_view ¤t_payload) { - auto packets = (current_payload.size() + (blocksize - 1)) / blocksize; + try { + auto blockIndex = 0; + std::for_each(fec_blocks_begin, fec_blocks_end, [&](std::string_view ¤t_payload) { + auto packets = (current_payload.size() + (blocksize - 1)) / blocksize; - for(int x = 0; x < packets; ++x) { - auto *inspect = (video_packet_raw_t *)¤t_payload[x * blocksize]; + for(int x = 0; x < packets; ++x) { + auto *inspect = (video_packet_raw_t *)¤t_payload[x * blocksize]; - inspect->packet.frameIndex = packet->pts; - inspect->packet.streamPacketIndex = ((uint32_t)lowseq + x) << 8; + inspect->packet.frameIndex = packet->pts; + inspect->packet.streamPacketIndex = ((uint32_t)lowseq + x) << 8; - // Match multiFecFlags with Moonlight - inspect->packet.multiFecFlags = 0x10; - inspect->packet.multiFecBlocks = (blockIndex << 4) | lastBlockIndex; + // Match multiFecFlags with Moonlight + inspect->packet.multiFecFlags = 0x10; + inspect->packet.multiFecBlocks = (blockIndex << 4) | lastBlockIndex; - if(x == 0) { - inspect->packet.flags |= FLAG_SOF; - } + if(x == 0) { + inspect->packet.flags |= FLAG_SOF; + } - if(x == packets - 1) { - inspect->packet.flags |= FLAG_EOF; + if(x == packets - 1) { + inspect->packet.flags |= FLAG_EOF; + } } - } - auto shards = fec::encode(current_payload, blocksize, fecPercentage, session->config.minRequiredFecPackets); + auto shards = fec::encode(current_payload, blocksize, fecPercentage, session->config.minRequiredFecPackets); - // 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); + // 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); - inspect->packet.fecInfo = - (x << 12 | - shards.data_shards << 22 | - shards.percentage << 4); + inspect->packet.fecInfo = + (x << 12 | + shards.data_shards << 22 | + shards.percentage << 4); - inspect->rtp.header = 0x80 | FLAG_EXTENSION; - inspect->rtp.sequenceNumber = util::endian::big(lowseq + x); + inspect->rtp.header = 0x80 | FLAG_EXTENSION; + inspect->rtp.sequenceNumber = util::endian::big(lowseq + x); - inspect->packet.multiFecBlocks = (blockIndex << 4) | lastBlockIndex; - inspect->packet.frameIndex = packet->pts; - } + inspect->packet.multiFecBlocks = (blockIndex << 4) | lastBlockIndex; + inspect->packet.frameIndex = packet->pts; + } - for(auto x = 0; x < shards.size(); ++x) { - sock.send_to(asio::buffer(shards[x]), session->video.peer); - } + for(auto x = 0; x < shards.size(); ++x) { + sock.send_to(asio::buffer(shards[x]), session->video.peer); + } - if(packet->flags & AV_PKT_FLAG_KEY) { - BOOST_LOG(verbose) << "Key Frame ["sv << packet->pts << "] :: send ["sv << shards.size() << "] shards..."sv; - } - else { - BOOST_LOG(verbose) << "Frame ["sv << packet->pts << "] :: send ["sv << shards.size() << "] shards..."sv << std::endl; - } + if(packet->flags & AV_PKT_FLAG_KEY) { + BOOST_LOG(verbose) << "Key Frame ["sv << packet->pts << "] :: send ["sv << shards.size() << "] shards..."sv; + } + else { + BOOST_LOG(verbose) << "Frame ["sv << packet->pts << "] :: send ["sv << shards.size() << "] shards..."sv << std::endl; + } - ++blockIndex; - lowseq += shards.size(); - }); + ++blockIndex; + lowseq += shards.size(); + }); - session->video.lowseq = lowseq; + session->video.lowseq = lowseq; + } + catch(const std::exception &e) { + BOOST_LOG(error) << "Broadcast video failed "sv << e.what(); + std::this_thread::sleep_for(100ms); + } } shutdown_event->raise(true); @@ -1077,30 +1083,36 @@ void audioBroadcastThread(udp::socket &sock) { auto &shards_p = session->audio.shards_p; std::copy_n(audio_packet->payload(), bytes, shards_p[sequenceNumber % RTPA_DATA_SHARDS]); - sock.send_to(asio::buffer((char *)audio_packet.get(), sizeof(audio_packet_raw_t) + bytes), session->audio.peer); + try { + sock.send_to(asio::buffer((char *)audio_packet.get(), sizeof(audio_packet_raw_t) + bytes), session->audio.peer); - BOOST_LOG(verbose) << "Audio ["sv << sequenceNumber << "] :: send..."sv; + 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 - if(sequenceNumber % RTPA_DATA_SHARDS == 0) { - fec_packet->fecHeader.baseSequenceNumber = util::endian::big(sequenceNumber); - fec_packet->fecHeader.baseTimestamp = util::endian::big(timestamp); - } + auto &fec_packet = session->audio.fec_packet; + // initialize the FEC header at the beginning of the FEC block + if(sequenceNumber % RTPA_DATA_SHARDS == 0) { + fec_packet->fecHeader.baseSequenceNumber = util::endian::big(sequenceNumber); + fec_packet->fecHeader.baseTimestamp = util::endian::big(timestamp); + } - // generate parity shards at the end of the FEC block - if((sequenceNumber + 1) % RTPA_DATA_SHARDS == 0) { - reed_solomon_encode(rs.get(), shards_p.begin(), RTPA_TOTAL_SHARDS, bytes); + // generate parity shards at the end of the FEC block + if((sequenceNumber + 1) % RTPA_DATA_SHARDS == 0) { + reed_solomon_encode(rs.get(), shards_p.begin(), RTPA_TOTAL_SHARDS, bytes); - for(auto x = 0; x < RTPA_FEC_SHARDS; ++x) { - fec_packet->rtp.sequenceNumber = util::endian::big(sequenceNumber + x + 1); - fec_packet->fecHeader.fecShardIndex = x; - memcpy(fec_packet->payload(), shards_p[RTPA_DATA_SHARDS + x], bytes); - sock.send_to(asio::buffer((char *)fec_packet.get(), sizeof(audio_fec_packet_raw_t) + bytes), session->audio.peer); - BOOST_LOG(verbose) << "Audio FEC ["sv << (sequenceNumber & ~(RTPA_DATA_SHARDS - 1)) << ' ' << x << "] :: send..."sv; + for(auto x = 0; x < RTPA_FEC_SHARDS; ++x) { + fec_packet->rtp.sequenceNumber = util::endian::big(sequenceNumber + x + 1); + fec_packet->fecHeader.fecShardIndex = x; + memcpy(fec_packet->payload(), shards_p[RTPA_DATA_SHARDS + x], bytes); + sock.send_to(asio::buffer((char *)fec_packet.get(), sizeof(audio_fec_packet_raw_t) + bytes), session->audio.peer); + BOOST_LOG(verbose) << "Audio FEC ["sv << (sequenceNumber & ~(RTPA_DATA_SHARDS - 1)) << ' ' << x << "] :: send..."sv; + } } } + catch(const std::exception &e) { + BOOST_LOG(error) << "Broadcast audio failed "sv << e.what(); + std::this_thread::sleep_for(100ms); + } } shutdown_event->raise(true); From b854807d40795c12b2104e7c56c90e1d596a4374 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Apr 2022 14:37:04 +0000 Subject: [PATCH 037/120] Bump actions/upload-artifact from 2 to 3 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/CI.yml | 6 +++--- .github/workflows/clang.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 76d38cd0661..56f1dab18d7 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -130,7 +130,7 @@ jobs: wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage && chmod +x appimagelint-x86_64.AppImage && ./appimagelint-x86_64.AppImage ./sunshine/sunshine.AppImage - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: sunshine-appimage path: artifacts/ @@ -184,7 +184,7 @@ jobs: sudo mv ./sunshine-${{ matrix.distro }}-build/sunshine-${{ matrix.distro }}.${{ matrix.extension }} ../artifacts/ - name: Upload Artifacts if: ${{ matrix.package == '-p' && ( github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' ) }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: sunshine-${{ matrix.distro }} path: artifacts/ @@ -248,7 +248,7 @@ jobs: move "sunshine-windows-build\sunshine-windows.zip" "artifacts" - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: sunshine-windows path: artifacts/ diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index 3729968711d..2ab2f600ac1 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -29,7 +29,7 @@ jobs: - name: Upload Artifacts if: ${{ matrix.inplace == true }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: sunshine path: sunshine/ From 1ad0c93ad80b207d0a5d8dbc50963da4e7905f78 Mon Sep 17 00:00:00 2001 From: Michael Rogers Date: Tue, 12 Apr 2022 16:13:05 -0500 Subject: [PATCH 038/120] Changed the video packet to contain AVPacket instead of extending it. --- sunshine/stream.cpp | 18 ++++++++++-------- sunshine/video.cpp | 18 ++++++++++-------- sunshine/video.h | 16 ++++------------ 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/sunshine/stream.cpp b/sunshine/stream.cpp index 10e215b6eca..27fbe85ab0b 100644 --- a/sunshine/stream.cpp +++ b/sunshine/stream.cpp @@ -895,7 +895,8 @@ void videoBroadcastThread(udp::socket &sock) { auto session = (session_t *)packet->channel_data; auto lowseq = session->video.lowseq; - std::string_view payload { (char *)packet->data, (size_t)packet->size }; + auto av_packet = packet->av_packet; + std::string_view payload { (char *)av_packet->data, (size_t)av_packet->size }; std::vector payload_new; auto nv_packet_header = "\0017charss"sv; @@ -904,7 +905,7 @@ void videoBroadcastThread(udp::socket &sock) { payload = { (char *)payload_new.data(), payload_new.size() }; - if(packet->flags & AV_PKT_FLAG_KEY) { + if(av_packet->flags & AV_PKT_FLAG_KEY) { for(auto &replacement : *packet->replacements) { auto frame_old = replacement.old; auto frame_new = replacement._new; @@ -969,9 +970,10 @@ void videoBroadcastThread(udp::socket &sock) { auto packets = (current_payload.size() + (blocksize - 1)) / blocksize; for(int x = 0; x < packets; ++x) { - auto *inspect = (video_packet_raw_t *)¤t_payload[x * blocksize]; + auto *inspect = (video_packet_raw_t *)¤t_payload[x * blocksize]; + auto av_packet = packet->av_packet; - inspect->packet.frameIndex = packet->pts; + inspect->packet.frameIndex = av_packet->pts; inspect->packet.streamPacketIndex = ((uint32_t)lowseq + x) << 8; // Match multiFecFlags with Moonlight @@ -1002,18 +1004,18 @@ void videoBroadcastThread(udp::socket &sock) { inspect->rtp.sequenceNumber = util::endian::big(lowseq + x); inspect->packet.multiFecBlocks = (blockIndex << 4) | lastBlockIndex; - inspect->packet.frameIndex = packet->pts; + inspect->packet.frameIndex = av_packet->pts; } for(auto x = 0; x < shards.size(); ++x) { sock.send_to(asio::buffer(shards[x]), session->video.peer); } - if(packet->flags & AV_PKT_FLAG_KEY) { - BOOST_LOG(verbose) << "Key Frame ["sv << packet->pts << "] :: send ["sv << shards.size() << "] shards..."sv; + if(av_packet->flags & AV_PKT_FLAG_KEY) { + BOOST_LOG(verbose) << "Key Frame ["sv << av_packet->pts << "] :: send ["sv << shards.size() << "] shards..."sv; } else { - BOOST_LOG(verbose) << "Frame ["sv << packet->pts << "] :: send ["sv << shards.size() << "] shards..."sv << std::endl; + BOOST_LOG(verbose) << "Frame ["sv << av_packet->pts << "] :: send ["sv << shards.size() << "] shards..."sv << std::endl; } ++blockIndex; diff --git a/sunshine/video.cpp b/sunshine/video.cpp index 0f7eff35480..f49cac95f99 100644 --- a/sunshine/video.cpp +++ b/sunshine/video.cpp @@ -776,9 +776,10 @@ int encode(int64_t frame_nr, session_t &session, frame_t::pointer frame, safe::m } while(ret >= 0) { - auto packet = std::make_unique(nullptr); + auto packet = std::make_unique(nullptr); + auto av_packet = packet.get()->av_packet; - ret = avcodec_receive_packet(ctx.get(), packet.get()); + ret = avcodec_receive_packet(ctx.get(), av_packet); if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { return 0; } @@ -788,12 +789,12 @@ int encode(int64_t frame_nr, session_t &session, frame_t::pointer frame, safe::m if(session.inject) { if(session.inject == 1) { - auto h264 = cbs::make_sps_h264(ctx.get(), packet.get()); + auto h264 = cbs::make_sps_h264(ctx.get(), av_packet); sps = std::move(h264.sps); } else { - auto hevc = cbs::make_sps_hevc(ctx.get(), packet.get()); + auto hevc = cbs::make_sps_hevc(ctx.get(), av_packet); sps = std::move(hevc.sps); vps = std::move(hevc.vps); @@ -1470,20 +1471,21 @@ int validate_config(std::shared_ptr &disp, const encoder_t &en } } - auto packet = packets->pop(); - if(!(packet->flags & AV_PKT_FLAG_KEY)) { + auto packet = packets->pop(); + auto av_packet = packet->av_packet; + if(!(av_packet->flags & AV_PKT_FLAG_KEY)) { BOOST_LOG(error) << "First packet type is not an IDR frame"sv; return -1; } int flag = 0; - if(cbs::validate_sps(&*packet, config.videoFormat ? AV_CODEC_ID_H265 : AV_CODEC_ID_H264)) { + if(cbs::validate_sps(&*av_packet, config.videoFormat ? AV_CODEC_ID_H265 : AV_CODEC_ID_H264)) { flag |= VUI_PARAMS; } auto nalu_prefix = config.videoFormat ? hevc_nalu : h264_nalu; - std::string_view payload { (char *)packet->data, (std::size_t)packet->size }; + std::string_view payload { (char *)av_packet->data, (std::size_t)av_packet->size }; if(std::search(std::begin(payload), std::end(payload), std::begin(nalu_prefix), std::end(nalu_prefix)) != std::end(payload)) { flag |= NALU_PREFIX_5b; } diff --git a/sunshine/video.h b/sunshine/video.h index fab4ff76837..05df4463d2b 100644 --- a/sunshine/video.h +++ b/sunshine/video.h @@ -16,17 +16,9 @@ extern "C" { struct AVPacket; namespace video { -struct packet_raw_t : public AVPacket { +struct packet_raw_t { void init_packet() { - pts = AV_NOPTS_VALUE; - dts = AV_NOPTS_VALUE; - pos = -1; - duration = 0; - flags = 0; - stream_index = 0; - buf = nullptr; - side_data = nullptr; - side_data_elems = 0; + this->av_packet = av_packet_alloc(); } template @@ -39,7 +31,7 @@ struct packet_raw_t : public AVPacket { } ~packet_raw_t() { - av_packet_unref(this); + av_packet_unref(this->av_packet); } struct replace_t { @@ -51,8 +43,8 @@ struct packet_raw_t : public AVPacket { replace_t(std::string_view old, std::string_view _new) noexcept : old { std::move(old) }, _new { std::move(_new) } {} }; + AVPacket *av_packet; std::vector *replacements; - void *channel_data; }; From a6921fffad2180cd237dbc4af11920a0d14de58f Mon Sep 17 00:00:00 2001 From: h <65380846+thatsysadmin@users.noreply.github.com> Date: Tue, 12 Apr 2022 20:29:08 -0700 Subject: [PATCH 039/120] Add initial support for RPM packaging (#121) - Add gen-rpm - Package rpm in CI testing and releases - Remove fedora 33 from testing (end of life) - Update arguments for `build_private.sh` and `build_sunshine.sh` Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- .github/workflows/CI.yml | 9 +- CMakeLists.txt | 1 + README.md | 45 +++++++- assets/85-sunshine-rules.rules | 1 + gen-rpm.in | 179 ++++++++++++++++++++++++++++++++ scripts/Dockerfile-debian | 2 +- scripts/Dockerfile-fedora_33 | 3 +- scripts/Dockerfile-fedora_35 | 3 +- scripts/Dockerfile-ubuntu_18_04 | 2 +- scripts/Dockerfile-ubuntu_20_04 | 2 +- scripts/Dockerfile-ubuntu_21_04 | 2 +- scripts/Dockerfile-ubuntu_21_10 | 2 +- scripts/build-private.sh | 15 ++- scripts/build-sunshine.sh | 25 ++++- 14 files changed, 271 insertions(+), 20 deletions(-) create mode 100644 assets/85-sunshine-rules.rules create mode 100755 gen-rpm.in diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 76d38cd0661..397ee3d8ef0 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -153,12 +153,9 @@ jobs: distro: [ debian, ubuntu_18_04, ubuntu_20_04, ubuntu_21_04, ubuntu_21_10 ] package: [ -p ] extension: [ deb ] - include: # don't package these - - distro: fedora_33 - package: '' - extension: rpm + include: # package these differently - distro: fedora_35 - package: '' + package: '-p' extension: rpm steps: @@ -176,7 +173,7 @@ jobs: - name: Build Linux run: | cd scripts - sudo ./build-sunshine.sh ${{ matrix.package }} -u -n sunshine-${{ matrix.distro }} -s .. + sudo ./build-sunshine.sh ${{ matrix.package }} -e ${{ matrix.extension }} -u -n sunshine-${{ matrix.distro }} -s .. - name: Package Linux if: ${{ matrix.package != '' }} run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index c3a1936e538..862e4f1ae3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -313,6 +313,7 @@ else() set(SUNSHINE_EXECUTABLE_PATH "sunshine") endif() configure_file(gen-deb.in gen-deb @ONLY) + configure_file(gen-rpm.in gen-rpm @ONLY) configure_file(sunshine.desktop.in sunshine.desktop @ONLY) configure_file(sunshine.service.in sunshine.service @ONLY) endif() diff --git a/README.md b/README.md index d61b812c151..f062769e394 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ They make use of docker to handle building Sunshine automatically ### Requirements: -Ubuntu 20.04: +#### Ubuntu 20.04: Install the following: #### Common @@ -52,15 +52,56 @@ On Ubuntu 20.04, the cuda compiler will fail since it's version is too old, it's sudo apt install nvidia-cuda-dev nvidia-cuda-toolkit ``` +#### Fedora 35: + +You will need some things in the RPMFusion repo, nost notably ffmpeg. +``` +sudo dnf install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm +``` +#### Development tools and libraries +``` +sudo dnf install \ + boost-devel \ + boost-static.x86_64 \ + cmake \ + ffmpeg-devel \ + gcc-c++ \ + libevdev-devel \ + libxcb-devel \ + libX11-devel \ + libXcursor-devel \ + libXfixes-devel \ + libXinerama-devel \ + libXi-devel \ + libXrandr-devel \ + libXtst-devel \ + mesa-libGL-devel \ + openssl-devel \ + opus-devel \ + pulseaudio-libs-devel +``` +#### If you need to build an RPM binary package: +``` +sudo dnf install rpmbuild +``` + #### Warning: You might require ffmpeg version >= 4.3. Check the troubleshooting section for more information. ### Compilation: -- `git clone https://github.com/loki-47-6F-64/sunshine.git --recurse-submodules` + +#### Ubuntu +- `git clone https://github.com/SunshineStream/Sunshine.git --recurse-submodules` - `cd sunshine && mkdir build && cd build` - `cmake -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 ..` - `make -j ${nproc}` +#### Fedora +- `git clone https://github.com/SunshineStream/Sunshine.git --recurse-submodules` +- `cd sunshine && mkdir build && cd build` +- `cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ ..` +- `make -j ${nproc}` + ### Setup: sunshine needs access to uinput to create mouse and gamepad events: diff --git a/assets/85-sunshine-rules.rules b/assets/85-sunshine-rules.rules new file mode 100644 index 00000000000..46a78a4a6da --- /dev/null +++ b/assets/85-sunshine-rules.rules @@ -0,0 +1 @@ +KERNEL=="uinput", GROUP="input", MODE="0660" \ No newline at end of file diff --git a/gen-rpm.in b/gen-rpm.in new file mode 100755 index 00000000000..e2bec8f43e7 --- /dev/null +++ b/gen-rpm.in @@ -0,0 +1,179 @@ +#!/bin/sh + +# Export filepaths +export BUILDDIR=@CMAKE_CURRENT_SOURCE_DIR@/build +export BUILDROOT=~/rpmbuild/ +export RPMSRC=~/rpmbuild/SOURCES +export RPMSPEC=~/rpmbuild/SPECS +export RPMBUILD=~/rpmbuild/BUILD + +# Check for Docker switch +if [ "$1" == "-d" ]; then + export DOCKERSTATUS=TRUE +else + export DOCKERSTATUS=FALSE +fi + +# Check if user's rpmbuild folder is there, if so, temoprairly rename it. +if [ -d ~/rpmbuild ]; then + echo "Backing up rpmbuild" + ~/rpmbuild ~/rpmbuild.bkp + export RPMBUILDEXISTS=TRUE +else + export RPMBUILDEXISTS=FALSE +fi + +# Create rpmbuild folder structure +mkdir ~/rpmbuild +mkdir ~/rpmbuild/BUILD +mkdir ~/rpmbuild/BUILDROOT +mkdir ~/rpmbuild/RPMS +mkdir ~/rpmbuild/SOURCES +mkdir ~/rpmbuild/SPECS +mkdir ~/rpmbuild/SRPMS + +# Create sunshine .spec file with preinstall and postinstall scripts +cat << 'EOF' > $RPMSPEC/sunshine.spec +Name: sunshine +Version: @PROJECT_VERSION@ +Release: 1%{?dist} +Summary: An NVIDIA Gamestream-compatible hosting server +BuildArch: x86_64 + +License: GPLv3 +URL: https://github.com/SunshineStream/Sunshine +Source0: sunshine-@PROJECT_VERSION@_bin.tar.gz + +Requires: systemd + +%description +An NVIDIA Gamestream-compatible hosting server + +%pre +#!/bin/sh + +# Sunshine Pre-Install Script +# Store backup for old config files to prevent it from being overwritten +if [ -f /etc/sunshine/sunshine.conf ]; then + cp /etc/sunshine/sunshine.conf /etc/sunshine/sunshine.conf.old +fi + +if [ -f /etc/sunshine/apps_linux.json ]; then + cp /etc/sunshine/apps_linux.json /etc/sunshine/apps_linux.json.old +fi + +%post +#!/bin/sh + +# Sunshine Post-Install Script +export GROUP_INPUT=input + +if [ -f /etc/group ]; then + if ! grep -q $GROUP_INPUT /etc/group; then + echo "Creating group $GROUP_INPUT" + + groupadd $GROUP_INPUT + fi +else + echo "Warning: /etc/group not found" +fi + +if [ -f /etc/sunshine/sunshine.conf.old ]; then + echo "Restoring old sunshine.conf" + mv /etc/sunshine/sunshine.conf.old /etc/sunshine/sunshine.conf +fi + +if [ -f /etc/sunshine/apps_linux.json.old ]; then + echo "Restoring old apps_linux.json" + mv /etc/sunshine/apps_linux.json.old /etc/sunshine/apps_linux.json +fi + +# Update permissions on config files for Web Manager +if [ -f /etc/sunshine/apps_linux.json ]; then + echo "chmod 666 /etc/sunshine/apps_linux.json" + chmod 666 /etc/sunshine/apps_linux.json +fi + +if [ -f /etc/sunshine/sunshine.conf ]; then + echo "chmod 666 /etc/sunshine/sunshine.conf" + chmod 666 /etc/sunshine/sunshine.conf +fi + +# Ensure Sunshine can grab images from KMS +path_to_setcap=$(which setcap) +if [ -x "$path_to_setcap" ] ; then + echo "$path_to_setcap cap_sys_admin+p /usr/bin/sunshine" + $path_to_setcap cap_sys_admin+p /usr/bin/sunshine +fi + +%prep +%setup -q + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT/%{_bindir} +mkdir -p $RPM_BUILD_ROOT/etc/sunshine +mkdir -p $RPM_BUILD_ROOT/usr/lib/systemd/user +mkdir -p $RPM_BUILD_ROOT/usr/share/applications +mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d + +cp sunshine $RPM_BUILD_ROOT/%{_bindir}/sunshine +cp sunshine.conf $RPM_BUILD_ROOT/etc/sunshine/sunshine.conf +cp apps_linux.json $RPM_BUILD_ROOT/etc/sunshine/apps_linux.json +cp sunshine.service $RPM_BUILD_ROOT/usr/lib/systemd/user/sunshine.service +cp sunshine.desktop $RPM_BUILD_ROOT/usr/share/applications/sunshine.desktop +cp 85-sunshine-rules.rules $RPM_BUILD_ROOT/etc/udev/rules.d/85-sunshine-rules.rules + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%{_bindir}/sunshine +/usr/lib/systemd/user/sunshine.service +/etc/sunshine/sunshine.conf +/etc/sunshine/apps_linux.json +/usr/share/applications/sunshine.desktop +/etc/udev/rules.d/85-sunshine-rules.rules + +%changelog +* Sat Mar 12 2022 h <65380846+thatsysadmin@users.noreply.github.com> +- Initial packaging of Sunshine. +EOF + +# Copy over sunshine binary and supplemental files into rpmbuild/BUILD/ +mkdir genrpm +mkdir genrpm/sunshine-@PROJECT_VERSION@ +cp sunshine-@PROJECT_VERSION@ genrpm/sunshine-@PROJECT_VERSION@/sunshine +cp sunshine.service genrpm/sunshine-@PROJECT_VERSION@/sunshine.service +cp sunshine.desktop genrpm/sunshine-@PROJECT_VERSION@/sunshine.desktop +cp @CMAKE_CURRENT_SOURCE_DIR@/assets/sunshine.conf genrpm/sunshine-@PROJECT_VERSION@/sunshine.conf +cp @CMAKE_CURRENT_SOURCE_DIR@/assets/apps_linux.json genrpm/sunshine-@PROJECT_VERSION@/apps_linux.json +cp @CMAKE_CURRENT_SOURCE_DIR@/assets/85-sunshine-rules.rules genrpm/sunshine-@PROJECT_VERSION@/85-sunshine-rules.rules +cd genrpm + +# tarball everything as if it was a source file for rpmbuild +tar --create --file sunshine-@PROJECT_VERSION@_bin.tar.gz sunshine-@PROJECT_VERSION@/ +cp sunshine-@PROJECT_VERSION@_bin.tar.gz ~/rpmbuild/SOURCES + +# Use rpmbuild to build the RPM package. +rpmbuild -bb $RPMSPEC/sunshine.spec + +# Check if running in a CT +if [ "$DOCKERSTATUS" == "FALSE" ]; then + # Move the completed RPM into the cmake build folder + mv ~/rpmbuild/RPMS/x86_64/sunshine-@PROJECT_VERSION@-1.fc*.x86_64.rpm @CMAKE_CURRENT_BINARY_DIR@/ + echo "Moving completed RPM package into CMake build folder." +elif [ "$DOCKERSTATUS" == "TRUE" ]; then + # Move into pickup location + mkdir -p /root/sunshine-build/package-rpm/ + mv ~/rpmbuild/RPMS/x86_64/sunshine-@PROJECT_VERSION@-1.fc*.x86_64.rpm /root/sunshine-build/package-rpm/sunshine.rpm + echo "Moving completed RPM package for pickup." +fi + +# Clean up; delete the rpmbuild folder we created and move back the original one +if [ "$RPMBUILDEXISTS" == "TRUE" ]; then + echo "Removing and replacing original rpmbuild folder." + rm -rf ~/rpmbuild + mv ~/rpmbuild.bkp ~/rpmbuild +fi +exit 0 diff --git a/scripts/Dockerfile-debian b/scripts/Dockerfile-debian index 809b20d333f..3a53fd9ff84 100644 --- a/scripts/Dockerfile-debian +++ b/scripts/Dockerfile-debian @@ -35,4 +35,4 @@ RUN apt-get update -y && \ # Entrypoint COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh"] +ENTRYPOINT ["/root/build.sh", "-deb"] diff --git a/scripts/Dockerfile-fedora_33 b/scripts/Dockerfile-fedora_33 index a2c8dfa4ed4..50a4e3dbbff 100644 --- a/scripts/Dockerfile-fedora_33 +++ b/scripts/Dockerfile-fedora_33 @@ -18,9 +18,10 @@ RUN dnf -y update && \ openssl-devel \ opus-devel \ pulseaudio-libs-devel \ + rpm-build \ && dnf clean all \ && rm -rf /var/cache/yum # Entrypoint COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh"] +ENTRYPOINT ["/root/build.sh", "-rpm"] diff --git a/scripts/Dockerfile-fedora_35 b/scripts/Dockerfile-fedora_35 index ba7abac524e..d4f5d843ba8 100644 --- a/scripts/Dockerfile-fedora_35 +++ b/scripts/Dockerfile-fedora_35 @@ -23,9 +23,10 @@ RUN dnf -y update && \ openssl-devel \ opus-devel \ pulseaudio-libs-devel \ + rpm-build \ && dnf clean all \ && rm -rf /var/cache/yum # Entrypoint COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh"] +ENTRYPOINT ["/root/build.sh", "-rpm"] diff --git a/scripts/Dockerfile-ubuntu_18_04 b/scripts/Dockerfile-ubuntu_18_04 index b6a05f6fb56..7225c0c72a3 100644 --- a/scripts/Dockerfile-ubuntu_18_04 +++ b/scripts/Dockerfile-ubuntu_18_04 @@ -58,4 +58,4 @@ RUN cmake --version # Entrypoint COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh"] +ENTRYPOINT ["/root/build.sh", "-deb"] diff --git a/scripts/Dockerfile-ubuntu_20_04 b/scripts/Dockerfile-ubuntu_20_04 index e65f91760e6..9ae7dfa913c 100644 --- a/scripts/Dockerfile-ubuntu_20_04 +++ b/scripts/Dockerfile-ubuntu_20_04 @@ -41,4 +41,4 @@ RUN /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-m # Entrypoint COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh"] +ENTRYPOINT ["/root/build.sh", "-deb"] diff --git a/scripts/Dockerfile-ubuntu_21_04 b/scripts/Dockerfile-ubuntu_21_04 index c7c7a3d463e..00801c55f9c 100644 --- a/scripts/Dockerfile-ubuntu_21_04 +++ b/scripts/Dockerfile-ubuntu_21_04 @@ -34,4 +34,4 @@ RUN apt-get update -y && \ # Entrypoint COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh"] +ENTRYPOINT ["/root/build.sh", "-deb"] diff --git a/scripts/Dockerfile-ubuntu_21_10 b/scripts/Dockerfile-ubuntu_21_10 index 7b51da3d03e..83b3e7f8a8b 100644 --- a/scripts/Dockerfile-ubuntu_21_10 +++ b/scripts/Dockerfile-ubuntu_21_10 @@ -34,4 +34,4 @@ RUN apt-get update -y && \ # Entrypoint COPY build-private.sh /root/build.sh -ENTRYPOINT ["/root/build.sh"] +ENTRYPOINT ["/root/build.sh", "-deb"] diff --git a/scripts/build-private.sh b/scripts/build-private.sh index 69446de6487..93d18748899 100755 --- a/scripts/build-private.sh +++ b/scripts/build-private.sh @@ -32,4 +32,17 @@ cmake "-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE" "-DSUNSHINE_EXECUTABLE_PATH=$SUNSHI make -j ${nproc} -./gen-deb +# Get preferred package format +if [ "$1" == "-rpm" ] +then + echo "Packaging in .rpm format." + ./gen-rpm -d +elif [ "$1" == "-deb" ] +then + echo "Packaging in .deb format." + ./gen-deb +else + echo "Preferred packaging not specified." + echo "Use -deb or -rpm to specify preferred package format." + exit 1 +fi diff --git a/scripts/build-sunshine.sh b/scripts/build-sunshine.sh index df21df3cb4b..5be8280823d 100755 --- a/scripts/build-sunshine.sh +++ b/scripts/build-sunshine.sh @@ -4,7 +4,8 @@ set -e usage() { echo "Usage: $0" echo " -d: Generate a debug build" - echo " -p: Generate a debian package" + echo " -p: Generate a linux package" + echo " -e: Extension of package... i.e. 'deb', 'rpm' --> default [deb]" echo " -u: The input device is not a TTY" echo " -n name: Docker container name --> default [sunshine]" echo " -s path/to/sources/sunshine: Use local sources instead of a git repository" @@ -26,13 +27,14 @@ absolute_path() { CMAKE_BUILD_TYPE="-e CMAKE_BUILD_TYPE=Release" SUNSHINE_PACKAGE_BUILD=OFF +SUNSHINE_PACKAGE_EXTENSION=deb SUNSHINE_GIT_URL=https://github.com/sunshinestream/sunshine.git CONTAINER_NAME=sunshine # Docker will fail if ctrl+c is passed through and the input is not a tty DOCKER_INTERACTIVE=-ti -while getopts ":dpuhc:s:n:" arg; do +while getopts ":dpuhc:e:s:n:" arg; do case ${arg} in u) echo "Input device is not a TTY" @@ -49,6 +51,21 @@ while getopts ":dpuhc:s:n:" arg; do SUNSHINE_ASSETS_DIR="-e SUNSHINE_ASSETS_DIR=/etc/sunshine" SUNSHINE_EXECUTABLE_PATH="-e SUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine" ;; + e) + echo "Defining package extension: $OPTARG" + if [ "$OPTARG" == "deb" ] + then + SUNSHINE_PACKAGE_EXTENSION=$OPTARG + echo "Package extension: deb" + elif [ "$OPTARG" == "rpm" ] + then + SUNSHINE_PACKAGE_EXTENSION=$OPTARG + echo "Package extension: rpm" + else + echo "Package extension not supported: $OPTARG" + echo "Falling back to default package extension: $SUNSHINE_PACKAGE_EXTENSION" + fi + ;; s) absolute_path "$OPTARG" OPTARG="$RETURN" @@ -98,8 +115,8 @@ then mkdir -p $BUILD_DIR case $SUNSHINE_PACKAGE_BUILD in ON) - echo "Downloading package to: $BUILD_DIR/$CONTAINER_NAME.deb" - docker cp $CONTAINER_NAME:/root/sunshine-build/package-deb/sunshine.deb "$BUILD_DIR/$CONTAINER_NAME.deb" + echo "Downloading package to: $BUILD_DIR/$CONTAINER_NAME.$SUNSHINE_PACKAGE_EXTENSION" + docker cp $CONTAINER_NAME:/root/sunshine-build/package-$SUNSHINE_PACKAGE_EXTENSION/sunshine.$SUNSHINE_PACKAGE_EXTENSION "$BUILD_DIR/$CONTAINER_NAME.$SUNSHINE_PACKAGE_EXTENSION" ;; *) echo "Downloading binary and assets to: $BUILD_DIR" From 536df759ae2033f7c383677249729199961be0db Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Mon, 18 Apr 2022 14:53:28 -0400 Subject: [PATCH 040/120] Initial version of sphinx documentation and... - remove ubuntu 21.04 from CI (end of life) - adjust matrix strategy for clang.yml - Use lessons learned from RetroArcher on localize.yml, crowdin.yml, and locale.py - Add end of life comments to Dockerfiles - Adjust dependency order in Dockerfiles --- .github/workflows/CI.yml | 2 +- .github/workflows/clang.yml | 8 +- .github/workflows/localize.yml | 45 +- .readthedocs.yaml | 26 + DOCKER_README.md | 113 ++ README.rst | 65 ++ assets/sunshine.conf | 319 +----- crowdin.yml | 4 + docs/Makefile | 20 + docs/make.bat | 35 + docs/source/about/advanced_usage.rst | 1087 ++++++++++++++++++++ docs/source/about/docker.rst | 5 + docs/source/about/installation.rst | 84 ++ docs/source/about/overview.rst | 1 + docs/source/about/third_party_packages.rst | 65 ++ docs/source/about/usage.rst | 163 +++ docs/source/building/build.rst | 31 + docs/source/building/linux.rst | 241 +++++ docs/source/building/macos.rst | 41 + docs/source/building/windows.rst | 22 + docs/source/conf.py | 88 ++ docs/source/contributing/contributing.rst | 32 + docs/source/contributing/localization.rst | 80 ++ docs/source/contributing/testing.rst | 42 + docs/source/index.rst | 7 + docs/source/toc.rst | 27 + scripts/Dockerfile-debian | 4 +- scripts/Dockerfile-fedora_33 | 3 + scripts/Dockerfile-fedora_35 | 4 +- scripts/Dockerfile-ubuntu_18_04 | 2 + scripts/Dockerfile-ubuntu_20_04 | 2 + scripts/Dockerfile-ubuntu_21_04 | 3 + scripts/Dockerfile-ubuntu_21_10 | 4 +- scripts/_locale.py | 14 +- scripts/requirements.txt | 3 + 35 files changed, 2350 insertions(+), 342 deletions(-) create mode 100644 .readthedocs.yaml create mode 100644 DOCKER_README.md create mode 100644 README.rst create mode 100644 docs/Makefile create mode 100644 docs/make.bat create mode 100644 docs/source/about/advanced_usage.rst create mode 100644 docs/source/about/docker.rst create mode 100644 docs/source/about/installation.rst create mode 100644 docs/source/about/overview.rst create mode 100644 docs/source/about/third_party_packages.rst create mode 100644 docs/source/about/usage.rst create mode 100644 docs/source/building/build.rst create mode 100644 docs/source/building/linux.rst create mode 100644 docs/source/building/macos.rst create mode 100644 docs/source/building/windows.rst create mode 100644 docs/source/conf.py create mode 100644 docs/source/contributing/contributing.rst create mode 100644 docs/source/contributing/localization.rst create mode 100644 docs/source/contributing/testing.rst create mode 100644 docs/source/index.rst create mode 100644 docs/source/toc.rst diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 60c91f8d137..da3cc6edcf8 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -150,7 +150,7 @@ jobs: strategy: fail-fast: true # false to test all, true to fail entire job if any fail matrix: - distro: [ debian, ubuntu_18_04, ubuntu_20_04, ubuntu_21_04, ubuntu_21_10 ] + distro: [ debian, ubuntu_18_04, ubuntu_20_04, ubuntu_21_10 ] package: [ -p ] extension: [ deb ] include: # package these differently diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index 2ab2f600ac1..f096c5f9f00 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -9,10 +9,6 @@ jobs: lint: name: Clang Format Lint runs-on: ubuntu-latest - strategy: - fail-fast: false # false to test all, true to fail entire job if any fail - matrix: - inplace: [ true, false ] # removed ubuntu_18_04 for now steps: - name: Checkout @@ -25,10 +21,10 @@ jobs: extensions: 'cpp,h,m,mm' clangFormatVersion: 13 style: file - inplace: ${{ matrix.inplace }} + inplace: false - name: Upload Artifacts - if: ${{ matrix.inplace == true }} + if: failure() uses: actions/upload-artifact@v3 with: name: sunshine diff --git a/.github/workflows/localize.yml b/.github/workflows/localize.yml index 57db544aef2..b860ad6439e 100644 --- a/.github/workflows/localize.yml +++ b/.github/workflows/localize.yml @@ -3,15 +3,16 @@ name: localize on: push: branches: [nightly] - paths: # prevents workflow from running unless files in these directories change - - 'sunshine/**' # only localizing files inside sunshine directory + paths: # prevents workflow from running unless these files change + - 'sunshine/**' + - 'locale/sunshine.po' workflow_dispatch: jobs: localize: name: Update Localization - if: ${{ github.event.pull_request.merged }} runs-on: ubuntu-latest + steps: - name: Checkout uses: actions/checkout@v3 @@ -37,9 +38,37 @@ jobs: run: | python ./scripts/_locale.py --extract - - name: GitHub Commit & Push # push changes back into nightly - uses: actions-js/push@v1.3 + - name: git diff + run: | + # print the git diff + git diff --exit-code locale/sunshine.po + + # set the variable with minimal output + OUTPUT=$(git diff --exit-code --numstat locale/sunshine.po) + echo "git_diff=${OUTPUT}" >> $GITHUB_ENV + + - name: git reset + if: ${{ env.git_diff != '1 1 locale/sunshine.po' }} # only run if more than 1 line changed + run: | + git reset --hard + + - name: Create/Update Pull Request + uses: peter-evans/create-pull-request@v4 with: - github_token: ${{ secrets.GITHUB_TOKEN }} - branch: nightly - message: localization updated by localize workflow + add-paths: | + locale/*.po + token: ${{ secrets.GH_PAT }} # must trigger PR tests + commit-message: New localization template + branch: localize/update + delete-branch: true + base: nightly + title: New Babel Updates + body: | + Update report + - Updated with *today's* date + - Auto-generated by [create-pull-request][1] + + [1]: https://github.com/peter-evans/create-pull-request + labels: | + babel + l10n diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000000..78c304f8fd9 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,26 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python +build: + os: ubuntu-20.04 + tools: + python: "3.9" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + builder: html + configuration: docs/source/conf.py + fail_on_warning: true + +# Using Sphinx, build docs in additional formats +formats: all + +python: + install: + - requirements: ./scripts/requirements.txt + system_packages: true diff --git a/DOCKER_README.md b/DOCKER_README.md new file mode 100644 index 00000000000..8691e01bf4e --- /dev/null +++ b/DOCKER_README.md @@ -0,0 +1,113 @@ +# Docker + +## Using docker run +Create and run the container (substitute your ``): + +```bash +docker run -d \ + --name=sunshine \ + --restart=unless-stopped + -v :/config \ + -e PUID= \ + -e PGID= \ + -e TZ= \ + -p 47990:47990 \ + -p 47984:47984 \ + -p 47989:47989 \ + -p 48010:48010 \ + -p 47998:47998 \ + -p 47999:47999 \ + -p 48000:48000 \ + -p 48002:48002 \ + -p 48010:48010 \ + sunshinestream/sunshine +``` + +To update the container it must be removed and recreated: + +```bash +# Stop the container +docker stop sunshine +# Remove the container +docker rm sunshine +# Pull the latest update +docker pull sunshinestream/sunshine +# Run the container with the same parameters as before +docker run -d ... +``` + +## Using docker-compose + +Create a `docker-compose.yml` file with the following contents (substitute your ``): + +```yaml +version: '3' +services: + retroarcher: + image: sunshinestream/sunshine + container_name: sunshine + restart: unless-stopped + volumes: + - :/config + environment: + - PUID= + - PGID= + - TZ= + ports: + - "47990:47990" + - "47984:47984" + - "47989:47989" + - "48010:48010" + - "47998:47998" + - "47999:47999" + - "48000:48000" + - "48002:48002" + - "48010:48010" +``` + +Create and start the container (run the command from the same folder as your `docker-compose.yml` file): + +```bash +docker-compose up -d +``` + +To update the container: +```bash +# Pull the latest update +docker-compose pull +# Update and restart the container +docker-compose up -d +``` + +## Parameters +You must substitute the `` with your own settings. + +Parameters are split into two halves separated by a colon. The left side represents the host and the right side the +container. + +**Example:** `-p external:internal` - This shows the port mapping from internal to external of the container. +Therefore `-p 47990:47990` would expose port `47990` from inside the container to be accessible from the host's IP on +port `47990` (e.g. `http://:47990`). The internal port must be `47990`, but the external port may be changed +(e.g. `-p 8080:47990`). + + +| Parameter | Function | Example Value | Required | +| --------------------------- | -------------------- | ------------------- | -------- | +| `-p :47990` | Web UI Port | `47990` | True | +| `-v :/config` | Volume mapping | `/home/sunshine` | True | +| `-e PUID=` | User ID | `1001` | False | +| `-e PGID=` | Group ID | `1001` | False | +| `-e TZ=` | Lookup TZ value [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) | `America/New_York` | True | + +### User / Group Identifiers: + +When using data volumes (-v flags) permissions issues can arise between the host OS and the container. To avoid this +issue you can specify the user PUID and group PGID. Ensure the data volume directory on the host is owned by the same +user you specify. + +In this instance `PUID=1001` and `PGID=1001`. To find yours use id user as below: + +```bash +$ id dockeruser +uid=1001(dockeruser) gid=1001(dockergroup) groups=1001(dockergroup) +``` diff --git a/README.rst b/README.rst new file mode 100644 index 00000000000..8fb29b6b355 --- /dev/null +++ b/README.rst @@ -0,0 +1,65 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/README.rst + +Overview +======== + +About +----- +Sunshine is a Game stream host for Moonlight. It is an open source version of GeForce Experience (GFE). + +These are the advantages of Sunshine over GFE. + + - FOSS (Free and Open Source Software) + - Multi-platform + + - Linux (deb, rpm, and AppImage packages) + - MacOS (Portfile) + - Windows (portable binary) + + - Pair over web ui + - Supports AMD and Nvidia GPUs for encoding + - Supports software encoding + - Supports streaming to multiple clients + - Web UI for configuration + +Integrations +------------ + +.. image:: https://img.shields.io/github/workflow/status/sunshinestream/sunshine/CI/master?label=CI%20build&logo=github&style=for-the-badge + :alt: GitHub Workflow Status (CI) + :target: https://github.com/SunshineStream/Sunshine/actions/workflows/CI.yml?query=branch%3Amaster + +.. image:: https://img.shields.io/github/workflow/status/sunshinestream/sunshine/localize/nightly?label=localize%20build&logo=github&style=for-the-badge + :alt: GitHub Workflow Status (localize) + :target: https://github.com/SunshineStream/Sunshine/actions/workflows/localize.yml?query=branch%3Anightly + +.. image:: https://img.shields.io/readthedocs/sunshinestream?label=Docs&style=for-the-badge&logo=readthedocs + :alt: Read the Docs + :target: http://sunshinestream.readthedocs.io/ + +.. image:: https://img.shields.io/badge/dynamic/json?color=blue&label=localized&style=for-the-badge&query=%24.progress..data.translationProgress&url=https%3A%2F%2Fbadges.awesome-crowdin.com%2Fstats-15178612-503956.json&logo=crowdin + :alt: CrowdIn + :target: https://crowdin.com/project/sunshinestream + +Support +--------- + +.. image:: https://img.shields.io/discord/938534566107418705?label=Discord&style=for-the-badge&color=blue&logo=discord + :alt: Discord + :target: https://sunshinestream.github.io/discord + +.. image:: https://img.shields.io/github/discussions/sunshinestream/sunshine?logo=github&style=for-the-badge + :alt: GitHub Discussions + :target: https://github.com/SunshineStream/Sunshine/discussions + +Downloads +--------- + +.. image:: https://img.shields.io/github/downloads/sunshinestream/sunshine/total?style=for-the-badge&logo=github + :alt: GitHub Releases + :target: https://github.com/SunshineStream/Sunshine/releases/latest + +.. comment + image:: https://img.shields.io/docker/pulls/sunshinestream/sunshine?style=for-the-badge&logo=docker + :alt: Docker + :target: https://hub.docker.com/r/sunshinestream/sunshine diff --git a/assets/sunshine.conf b/assets/sunshine.conf index a1e020f03c9..509ff52a283 100644 --- a/assets/sunshine.conf +++ b/assets/sunshine.conf @@ -1,318 +1 @@ -# If no external IP address is given, Sunshine will attempt to automatically detect external ip-address -# external_ip = 123.456.789.12 - -# Set the familly of ports used by Sunshine -# port = 47989 - -# The private key must be 2048 bits -# pkey = /dir/pkey.pem - -# The certificate must be signed with a 2048 bit key -# cert = /dir/cert.pem - -# The name displayed by Moonlight -# If not specified, the PC's hostname is used -# sunshine_name = Sunshine - -# The minimum log level printed to standard out -# -# none -> no logs are printed to standard out -# -# verbose = [0] -# debug = [1] -# info = [2] -# warning = [3] -# error = [4] -# fatal = [5] -# none = [6] -# -# min_log_level = info - -# The origin of the remote endpoint address that is not denied for HTTP method /pin -# Could be any of the following values: -# pc|lan|wan -# pc: Only localhost may access /pin -# lan: Only those in LAN may access /pin -# wan: Anyone may access /pin -# -# origin_pin_allowed = pc - -# The origin of the remote endpoint address that is not denied for HTTPS Web UI -# Could be any of the following values: -# pc|lan|wan -# pc: Only localhost may access the Web Manager -# lan: Only those in LAN may access the Web Manager -# wan: Anyone may access the Web Manager -# -# origin_web_ui_allowed = lan - -# If UPnP is enabled, Sunshine will attempt to open ports for streaming over the internet -# To enable it, uncomment the following line: -# upnp = on - -# The file where current state of Sunshine is stored -# file_state = sunshine_state.json - -# The file where user credentials for the UI are stored -# By default, credentials are stored in `file_state` -# credentials_file = sunshine_state.json - -# The display modes advertised by Sunshine -# -# Some versions of Moonlight, such as Moonlight-nx (Switch), -# rely on this list to ensure that the requested resolutions and fps -# are supported. -# -# fps = [10, 30, 60, 90, 120] -# resolutions = [ -# 352x240, -# 480x360, -# 858x480, -# 1280x720, -# 1920x1080, -# 2560x1080, -# 3440x1440, -# 1920x1200, -# 3860x2160, -# 3840x1600, -# ] - -# Sometimes it may be usefull to map keybindings. -# Wayland won't allow clients to capture the Win Key for example -# -# See https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes -# -# Note: -# keybindings needs to have a multiple of two elements -# keybindings = [ -# 0x10, 0xA0, -# 0x11, 0xA2, -# 0x12, 0xA4, -# 0x4A, 0x4B -# ] - -# It may be possible that you cannot send the Windows Key from Moonlight directly. -# In those cases it may be useful to make Sunshine think the Right Alt key is the Windows key -# key_rightalt_to_key_win = enabled - -# How long to wait in milliseconds for data from moonlight before shutting down the stream -# ping_timeout = 10000 - -# The file where configuration for the different applications that Sunshine can run during a stream -# file_apps = apps.json - -# Percentage of error correcting packets per data packet in each video frame -# Higher values can correct for more network packet loss, but at the cost of increasing bandwidth usage -# The default value of 20 is what GeForce Experience uses -# -# The value must be greater than 0 and lower than or equal to 255 -# fec_percentage = 20 - -# When multicasting, it could be usefull to have different configurations for each connected Client. -# For example: -# Clients connected through WAN and LAN have different bitrate contstraints. -# Decoders may require different settings for color -# -# Unlike simply broadcasting to multiple Client, this will generate distinct video streams. -# Note, CPU usage increases for each distinct video stream generated -# channels = 1 - -# The back/select button on the controller -# On the Shield, the home and powerbutton are not passed to Moonlight -# If, after the timeout, the back button is still pressed down, Home/Guide button press is emulated. -# If back_button_timeout < 0, then the Home/Guide button will not be emulated -# back_button_timeout = 2000 - -# !! Windows only !! -# Gamepads supported by Sunshine -# Possible values: -# x360 -- xbox 360 controller -# ds4 -- dualshock controller (PS4) -# gamepad = x360 - -# Control how fast keys will repeat themselves -# The initial delay in milliseconds before repeating keys -# key_repeat_delay = 500 -# -# How often keys repeat every second -# This configurable option supports decimals -# key_repeat_frequency = 24.9 - -# The name of the audio sink used for Audio Loopback -# If you do not specify this variable, pulseaudio will select the default monitor device. -# -# You can find the name of the audio sink using the following command: -# !! Linux only !! -# pacmd list-sinks | grep "name:" if running vanilla pulseaudio -# pPipewire: Use `pactl info | grep Source`. In some causes you'd need to use the `sink` device. Try `pactl info | grep Sink`, if _Source_ doesn't work -# audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo -# -# !! Windows only !! -# tools\audio-info.exe -# audio_sink = {0.0.0.00000000}.{FD47D9CC-4218-4135-9CE2-0C195C87405B} -# -# The virtual sink, is the audio device that's virtual (Like Steam Streaming Speakers), it allows Sunshine -# to stream audio, while muting the speakers. -# virtual_sink = {0.0.0.00000000}.{8edba70c-1125-467c-b89c-15da389bc1d4} - -# -# !! MacOS only !! -# audio_sink = BlackHole 2ch - -# !! Windows only !! -# You can select the video card you want to stream: -# The appropriate values can be found using the following command: -# tools\dxgi-info.exe -# adapter_name = Radeon RX 580 Series -# output_name = \\.\DISPLAY1 - -# !! Linux only !! -# Set the display number to stream. -# You can find them by the following command: -# xrandr --listmonitors -# Example output: "0: +HDMI-1 1920/518x1200/324+0+0 HDMI-1" -# ^ <-- You need this. -# output_name = 0 - -############################################### -# FFmpeg software encoding parameters -# Honestly, I have no idea what the optimal values would be. -# Play around with this :) - -# Quantitization Parameter -# Some devices don't support Constant Bit Rate. For those devices, QP is used instead -# Higher value means more compression, but less quality -# qp = 28 - -# Minimum number of threads used by ffmpeg to encode the video. -# Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually -# worth it to gain the use of more CPU cores for encoding. The ideal value is the lowest -# value that can reliably encode at your desired streaming settings on your hardware. -# min_threads = 1 - -# Allows the client to request HEVC Main or HEVC Main10 video streams. -# HEVC is more CPU-intensive to encode, so enabling this may reduce performance when using software encoding. -# If set to 0 (default), Sunshine will specify support for HEVC based on encoder -# If set to 1, Sunshine will not advertise support for HEVC -# If set to 2, Sunshine will advertise support for HEVC Main profile -# If set to 3, Sunshine will advertise support for HEVC Main and Main10 (HDR) profiles -# hevc_mode = 2 - -# Force a specific encoder, otherwise Sunshine will use the first encoder that is available -# supported encoders: -# nvenc -# amdvce # NOTE: alpha stage. The cursor is not yet displayed -# software -# -# encoder = nvenc -##################################### Software ##################################### -# See x264 --fullhelp for the different presets -# sw_preset = superfast -# sw_tune = zerolatency -# - -##################################### NVENC ##################################### -###### presets ########### -# default -# hp -- high performance -# hq -- high quality -# slow -- hq 2 passes -# medium -- hq 1 pass -# fast -- hp 1 pass -# bd -# ll -- low latency -# llhq -# llhp -# lossless -# losslesshp -########################## -# nv_preset = llhq -# -####### rate control ##### -# auto -- let ffmpeg decide rate control -# constqp -- constant QP mode -# vbr -- variable bitrate -# cbr -- constant bitrate -# cbr_hq -- cbr high quality -# cbr_ld_hq -- cbr low delay high quality -# vbr_hq -- vbr high quality -########################## -# nv_rc = auto - -###### h264 entropy ###### -# auto -- let ffmpeg nvenc decide the entropy encoding -# cabac -# cavlc -########################## -# nv_coder = auto - -##################################### AMD ##################################### -###### presets ########### -# default -# speed -# balanced -########################## -# amd_quality = balanced -# -####### rate control ##### -# auto -- let ffmpeg decide rate control -# constqp -- constant QP mode -# vbr_latency -- Latency Constrained Variable Bitrate -# vbr_peak -- Peak Contrained Variable Bitrate -# cbr -- constant bitrate -########################## -# amd_rc = auto - -###### h264 entropy ###### -# auto -- let ffmpeg nvenc decide the entropy encoding -# cabac -# cavlc -########################## -# amd_coder = auto - -#################################### VAAPI ################################### -####### adapter ########## -# Unlike with `amdvce` and `nvenc`, it doesn't matter if video encoding is done -# on a different GPU. -# Run the following commands: -# 1. ls /dev/dri/renderD* -# to find all devices capable of VAAPI -# 2. vainfo --display drm --device /dev/dri/renderD129 | grep -E "((VAProfileH264High|VAProfileHEVCMain|VAProfileHEVCMain10).*VAEntrypointEncSlice)|Driver version" -# Lists the name and capabilities of the device. -# To be supported by Sunshine, it needs to have at the very minimum: -# VAProfileH264High : VAEntrypointEncSlice -# adapter_name = /dev/dri/renderD128 - -################################# VideoToolbox ############################### -####### software encoding ########## -# Video Toolbox can be allowed/required to use software encoding instead of -# hardware accelerated encoding. -# auto -- let sunshine decide on encoding -# disabled -- disable software encoding -# allowed -- allow software encoding -# forced -- force software encoding -########################## -# vt_software = auto -# -####### realtime encoding ########## -# Disabling realtime encoding might result in a delayed frame encoding or frame drop -########################## -# vt_realtime = enabled -# -###### h264/hevc entropy ###### -# auto -- let ffmpeg decide the entropy encoding -# cabac -# cavlc -########################## -# vt_coder = auto - - -############################################## -# Some configurable parameters, are merely toggles for specific features -# The first occurrence turns it on, the second occurence turns it off, the third occurence turns it on again, etc, etc -# Here, you change the default state of any flag -# -# To set the initial state of flags -0 and -1 to on, set the following flags: -# flags = 012 -# -# See: sunshine --help for all options under the header: flags +# See our documentation at https://sunshinestream.readthedocs.io/en/latest/about/advanced_usage.html diff --git a/crowdin.yml b/crowdin.yml index d014a00c283..ca9c8c5c58b 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,6 +1,10 @@ "base_path": "." "base_url": "https://api.crowdin.com" # optional (for Crowdin Enterprise only) "preserve_hierarchy": false # flatten tree on crowdin +"pull_request_labels": [ + "crowdin", + "l10n" +] "files" : [ { diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000000..d0c3cbf1020 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000000..dc1312ab09c --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst new file mode 100644 index 00000000000..e01de0aa60f --- /dev/null +++ b/docs/source/about/advanced_usage.rst @@ -0,0 +1,1087 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/about/advanced_usage.rst + +Advanced Usage +============== +Sunshine will work with the default settings for most users. In some cases you may want to configure Sunshine further. + +Configuration +------------- +The default location for the configuration file is ``./assets/sunshine.conf``. You can use another location if you +choose, by passing in the full configuration file path as the first argument when you start Sunshine. + +** Default File Location** + +.. table:: + :widths: auto + + ======= =========== + Value Description + ======= =========== + Linux ./assets/sunshine.conf + MacOS /opt/local/etc/sunshine.conf + Windows ./assets/sunshine.conf + ======= =========== + +Example + .. code-block:: bash + + sunshine ~/sunshine_config.conf + +To manually configure sunshine you may edit the `conf` file in a text editor. Use the examples as reference. + +.. Note:: Some settings are not available within the web ui. + +General +------- + +sunshine_name +^^^^^^^^^^^^^ + +Description + The name displayed by Moonlight + +Default + PC hostname + +Example + .. code-block:: text + + sunshine_name = Sunshine + +min_log_level +^^^^^^^^^^^^^ + +Description + The minimum log level printed to standard out. + +**Choices** + +.. table:: + :widths: auto + + ======= =========== + Value Description + ======= =========== + verbose verbose logging + debug debug logging + info info logging + warning warning logging + error error logging + fatal fatal logging + none no logging + ======= =========== + +Default + ``info`` + +Example + .. code-block:: text + + min_log_level = info + +Controls +-------- + +gamepad +^^^^^^^ + +Description + The type of gamepad to emulate on the host. + + .. Caution:: Applies to Windows only. + +**Choices** + +.. table:: + :widths: auto + + ===== =========== + Value Description + ===== =========== + x360 xbox 360 controller + ds4 dualshock controller (PS4) + ===== =========== + +Default + ``x360`` + +Example + .. code-block:: text + + gamepad = x360 + +back_button_timeout +^^^^^^^^^^^^^^^^^^^ + +Description + If, after the timeout, the back/select button is still pressed down, Home/Guide button press is emulated. + + On Nvidia Shield, the home and power button are not passed to Moonlight. + + .. Tip:: If back_button_timeout < 0, then the Home/Guide button will not be emulated. + +Default + ``2000`` + +Example + .. code-block:: text + + back_button_timeout = 2000 + +key_repeat_delay +^^^^^^^^^^^^^^^^ + +Description + The initial delay in milliseconds before repeating keys. Controls how fast keys will repeat themselves. + +Default + ``500`` + +Example + .. code-block:: text + + key_repeat_delay = 500 + +key_repeat_frequency +^^^^^^^^^^^^^^^^^^^^ + +Description + How often keys repeat every second. + + .. Tip:: This configurable option supports decimals. + +Default + .. Todo:: Unknown + +Example + .. code-block:: text + + key_repeat_frequency = 24.9 + +keybindings +^^^^^^^^^^^ + +Description + Sometimes it may be useful to map keybindings. Wayland won't allow clients to capture the Win Key for example. + + .. Tip:: See `virtual key codes `_ + + .. Note:: keybindings needs to have a multiple of two elements. + +Default + None + +Example + .. code-block:: text + + keybindings = [ + 0x10, 0xA0, + 0x11, 0xA2, + 0x12, 0xA4, + 0x4A, 0x4B + ] + +key_rightalt_to_key_win +^^^^^^^^^^^^^^^^^^^^^^^ + +Description + It may be possible that you cannot send the Windows Key from Moonlight directly. In those cases it may be useful to + make Sunshine think the Right Alt key is the Windows key. + +Default + None + +Example + .. code-block:: text + + key_rightalt_to_key_win = enabled + +Display +------- + +adapter_name +^^^^^^^^^^^^ + +Description + Select the video card you want to stream. + + .. Tip:: To find the name of the appropriate values follow these instructions. + + Linux + VA-API + Unlike with `amdvce` and `nvenc`, it doesn't matter if video encoding is done on a different GPU. + + .. code-block:: bash + + ls /dev/dri/renderD* # to find all devices capable of VAAPI + + # replace ``renderD129`` with the device from above to lists the name and capabilities of the device + vainfo --display drm --device /dev/dri/renderD129 | \ + grep -E "((VAProfileH264High|VAProfileHEVCMain|VAProfileHEVCMain10).*VAEntrypointEncSlice)|Driver version" + + To be supported by Sunshine, it needs to have at the very minimum: + ``VAProfileH264High : VAEntrypointEncSlice`` + + .. Todo:: MacOS + + Windows + .. code-block:: batch + + tools\dxgi-info.exe + +Default + Sunshine will select the default video card. + +Examples + Linux + .. code-block:: text + + adapter_name = /dev/dri/renderD128 + + .. Todo:: MacOS + + Windows + .. code-block:: text + + adapter_name = Radeon RX 580 Series + +output_name +^^^^^^^^^^^ + +Description + Select the display number you want to stream. + + .. Tip:: To find the name of the appropriate values follow these instructions. + + Linux + .. code-block:: bash + + xrandr --listmonitors + + Example output: ``0: +HDMI-1 1920/518x1200/324+0+0 HDMI-1`` + + You need to use the value before the colon in the output, e.g. ``0``. + + .. Todo:: MacOS + + Windows + .. code-block:: batch + + tools\dxgi-info.exe + +Default + Sunshine will select the default display. + +Examples + Linux + .. code-block:: text + + output_name = 0 + + .. Todo:: MacOS + + Windows + .. code-block:: text + + output_name = \\.\DISPLAY1 + +fps +^^^ + +Description + The fps modes advertised by Sunshine. + + .. Note:: Some versions of Moonlight, such as Moonlight-nx (Switch), rely on this list to ensure that the requested + fps is supported. + +Default + .. Todo:: Unknown + +Example + .. code-block:: text + + fps = [10, 30, 60, 90, 120] + +resolutions +^^^^^^^^^^^ + +Description + The resolutions advertised by Sunshine. + + .. Note:: Some versions of Moonlight, such as Moonlight-nx (Switch), rely on this list to ensure that the requested + resolution is supported. + +Default + .. Todo:: Unknown + +Example + .. code-block:: text + + resolutions = [ + 352x240, + 480x360, + 858x480, + 1280x720, + 1920x1080, + 2560x1080, + 3440x1440, + 1920x1200, + 3860x2160, + 3840x1600, + ] + +Audio +----- + +audio_sink +^^^^^^^^^^ + +Description + The name of the audio sink used for audio loopback. + + .. Tip:: To find the name of the audio sink follow these instructions. + + Linux + pulseaudio + .. code-block:: bash + + pacmd list-sinks | grep "name:" + + Linux + pipewire + .. code-block:: bash + + pactl info | grep Source + # in some causes you'd need to use the `Sink` device, if `Source` doesn't work, so try: + pactl info | grep Sink + + MacOS + Sunshine can only access microphones on MacOS due to system limitations. To stream system audio use + `Soundflower `_ or + `BlackHole `_. + + Windows + .. code-block:: batch + + tools\audio-info.exe + +Default + Sunshine will select the default audio device. + +Examples + Linux + .. code-block:: text + + audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo + + MacOS + .. code-block:: text + + audio_sink = BlackHole 2ch + + Windows + .. code-block:: text + + audio_sink = {0.0.0.00000000}.{FD47D9CC-4218-4135-9CE2-0C195C87405B} + +virtual_sink +^^^^^^^^^^^^ + +Description + The audio device that's virtual, like Steam Streaming Speakers. This allows Sunshine to stream audio, while muting + the speakers. + + .. Tip:: See `audio_sink`_! + +Default + .. Todo:: Unknown + +Example + .. code-block:: text + + virtual_sink = {0.0.0.00000000}.{8edba70c-1125-467c-b89c-15da389bc1d4} + +Network +------- + +external_ip +^^^^^^^^^^^ + +Description + If no external IP address is given, Sunshine will attempt to automatically detect external ip-address. + +Default + Automatic + +Example + .. code-block:: text + + external_ip = 123.456.789.12 + +port +^^^^ + +Description + Set the family of ports used by Sunshine. + +Default + ``47989`` + +Example + .. code-block:: text + + port = 47989 + +pkey +^^^^ + +Description + The private key. This must be 2048 bits. + +Default + .. Todo:: Unknown + +Example + .. code-block:: text + + pkey = /dir/pkey.pem + +cert +^^^^ + +Description + The certificate. Must be signed with a 2048 bit key. + +Default + .. Todo:: Unknown + +Example + .. code-block:: text + + cert = /dir/cert.pem + +origin_pin_allowed +^^^^^^^^^^^^^^^^^^ + +Description + The origin of the remote endpoint address that is not denied for HTTP method /pin. + +**Choices** + +.. table:: + :widths: auto + + ===== =========== + Value Description + ===== =========== + pc Only localhost may access /pin + lan Only LAN devices may access /pin + wan Anyone may access /pin + ===== =========== + +Default + ``pc`` + +Example + .. code-block:: text + + origin_pin_allowed = pc + +origin_web_ui_allowed +^^^^^^^^^^^^^^^^^^^^^ + +Description + The origin of the remote endpoint address that is not denied for HTTPS Web UI. + +**Choices** + +.. table:: + :widths: auto + + ===== =========== + Value Description + ===== =========== + pc Only localhost may access the web ui + lan Only LAN devices may access the web ui + wan Anyone may access the web ui + ===== =========== + +Default + ``lan`` + +Example + .. code-block:: text + + origin_web_ui_allowed = lan + +upnp +^^^^ + +Description + Sunshine will attempt to open ports for streaming over the internet. + +**Choices** + +.. table:: + :widths: auto + + ===== =========== + Value Description + ===== =========== + on enable UPnP + off disable UPnP + ===== =========== + +Default + ``off`` + +Example + .. code-block:: text + + upnp = on + +ping_timeout +^^^^^^^^^^^^ + +Description + How long to wait in milliseconds for data from Moonlight before shutting down the stream. + +Default + ``10000`` + +Example + .. code-block:: text + + ping_timeout = 10000 + +Encoding +-------- + +channels +^^^^^^^^ + +Description + This will generate distinct video streams, unlike simply broadcasting to multiple Clients. + + When multicasting, it could be useful to have different configurations for each connected Client. + + For instance: + + - Clients connected through WAN and LAN have different bitrate constraints. + - Decoders may require different settings for color. + + .. Warning:: CPU usage increases for each distinct video stream generated. + +Default + ``1`` + +Example + .. code-block:: text + + channels = 1 + +fec_percentage +^^^^^^^^^^^^^^ + +Description + Percentage of error correcting packets per data packet in each video frame. + + .. Warning:: Higher values can correct for more network packet loss, but at the cost of increasing bandwidth usage. + +Default + ``20`` + +Range + ``1-255`` + +Example + .. code-block:: text + + fec_percentage = 20 + +qp +^^ + +Description + Quantitization Parameter. Some devices don't support Constant Bit Rate. For those devices, QP is used instead. + + .. Warning:: Higher value means more compression, but less quality. + +Default + ``28`` + +Example + .. code-block:: text + + qp = 28 + +min_threads +^^^^^^^^^^^ + +Description + Minimum number of threads used by ffmpeg to encode the video. + + .. Note:: Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually worth it to gain + the use of more CPU cores for encoding. The ideal value is the lowest value that can reliably encode at your + desired streaming settings on your hardware. + +Default + ``1`` + +Example + .. code-block:: text + + min_threads = 1 + +hevc_mode +^^^^^^^^^ + +Description + Allows the client to request HEVC Main or HEVC Main10 video streams. + + .. Warning:: HEVC is more CPU-intensive to encode, so enabling this may reduce performance when using software + encoding. + +**Choices** + +.. table:: + :widths: auto + + ===== =========== + Value Description + ===== =========== + 0 advertise support for HEVC based on encoder + 1 do not advertise support for HEVC + 2 advertise support for HEVC Main profile + 3 advertise support for HEVC Main and Main10 (HDR) profiles + ===== =========== + +Default + ``0`` + +Example + .. code-block:: text + + hevc_mode = 2 + +encoder +^^^^^^^ + +Description + Force a specific encoder. + +**Choices** + +.. table:: + :widths: auto + + ======== =========== + Value Description + ======== =========== + nvenc For Nvidia graphics cards + amdvce For AMD graphics cards + software Encoding occurs on the CPU + ======== =========== + +Default + Sunshine will use the first encoder that is available. + +Example + .. code-block:: text + + encoder = nvenc + +sw_preset +^^^^^^^^^ + +Description + The encoder preset to use. + + .. Note:: This option only applies when using software `encoder`_. + + .. Note:: From `FFmpeg `_. + + A preset is a collection of options that will provide a certain encoding speed to compression ratio. A slower + preset will provide better compression (compression is quality per filesize). This means that, for example, if + you target a certain file size or constant bit rate, you will achieve better quality with a slower preset. + Similarly, for constant quality encoding, you will simply save bitrate by choosing a slower preset. + + Use the slowest preset that you have patience for. + +**Choices** + +.. table:: + :widths: auto + + ========= =========== + Value Description + ========= =========== + ultrafast fastest + superfast + veryfast + superfast + faster + fast + medium + slow + slow + slower + veryslow slowest + ========= =========== + +Default + ``superfast`` + +Example + .. code-block:: text + + sw_preset = superfast + +sw_tune +^^^^^^^ + +Description + The tuning preset to use. + + .. Note:: This option only applies when using software `encoder`_. + + .. Note:: From `FFmpeg `_. + + You can optionally use -tune to change settings based upon the specifics of your input. + +**Choices** + +.. table:: + :widths: auto + + =========== =========== + Value Description + =========== =========== + film use for high quality movie content; lowers deblocking + animation good for cartoons; uses higher deblocking and more reference frames + grain preserves the grain structure in old, grainy film material + stillimage good for slideshow-like content + fastdecode allows faster decoding by disabling certain filters + zerolatency good for fast encoding and low-latency streaming + =========== =========== + +Default + ``zerolatency`` + +Example + .. code-block:: text + + sw_tune = zerolatency + +nv_preset +^^^^^^^^^ + +Description + The encoder preset to use. + + .. Note:: This option only applies when using nvenc `encoder`_. + +**Choices** + +.. table:: + :widths: auto + + ========== =========== + Value Description + ========== =========== + default let ffmpeg decide + hp high performance + hq high quality + slow high quality, 2 passes + medium high quality, 1 pass + fast high performance, 1 pass + bd + ll low latency + llhq low latency, high quality + llhp low latency, high performance + lossless lossless + losslesshp lossless, high performance + ========== =========== + +Default + ``llhq`` + +Example + .. code-block:: text + + nv_preset = llhq + +nv_rc +^^^^^ + +Description + The encoder rate control. + + .. Note:: This option only applies when using nvenc `encoder`_. + + .. Note:: Moonlight does not currently support variable bitrate, although it can still be selected here. + +**Choices** + +.. table:: + :widths: auto + + ========== =========== + Value Description + ========== =========== + auto let ffmpeg decide + constqp constant QP mode + cbr constant bitrate + cbr_hq constant bitrate, high quality + cbr_ld_hq constant bitrate, low delay, high quality + vbr variable bitrate + vbr_hq variable bitrate, high quality + ========== =========== + +Default + ``auto`` + +Example + .. code-block:: text + + nv_rc = auto + +nv_coder +^^^^^^^^ + +Description + The entropy encoding to use. + + .. Note:: This option only applies when using nvenc `encoder`_. + +**Choices** + +.. table:: + :widths: auto + + ========== =========== + Value Description + ========== =========== + auto let ffmpeg decide + cabac + cavlc + ========== =========== + +Default + ``auto`` + +Example + .. code-block:: text + + nv_coder = auto + +amd_quality +^^^^^^^^^^^ + +Description + The encoder preset to use. + + .. Note:: This option only applies when using amdvce `encoder`_. + +**Choices** + +.. table:: + :widths: auto + + ========== =========== + Value Description + ========== =========== + default let ffmpeg decide + speed fast + balanced balance performance and speed + ========== =========== + +Default + ``balanced`` + +Example + .. code-block:: text + + amd_quality = balanced + +amd_rc +^^^^^^ + +Description + The encoder rate control. + + .. Note:: This option only applies when using amdvce `encoder`_. + + .. Note:: Moonlight does not currently support variable bitrate, although it can still be selected here. + +**Choices** + +.. table:: + :widths: auto + + =========== =========== + Value Description + =========== =========== + auto let ffmpeg decide + constqp constant QP mode + cbr constant bitrate + vbr_latency variable bitrate, latency constrained + vbr_peak variable bitrate, peak constrained + =========== =========== + +Default + ``auto`` + +Example + .. code-block:: text + + amd_rc = auto + +amd_coder +^^^^^^^^^ + +Description + The entropy encoding to use. + + .. Note:: This option only applies when using nvenc `encoder`_. + +**Choices** + +.. table:: + :widths: auto + + ========== =========== + Value Description + ========== =========== + auto let ffmpeg decide + cabac + cavlc + ========== =========== + +Default + ``auto`` + +Example + .. code-block:: text + + amd_coder = auto + +vt_software +^^^^^^^^^^^ + +Description + Force Video Toolbox to use software encoding. + + .. Note:: This option only applies when using MacOS. + +**Choices** + +.. table:: + :widths: auto + + ========== =========== + Value Description + ========== =========== + auto let ffmpeg decide + disabled disable software encoding + allowed allow software encoding + forced force software encoding + ========== =========== + +Default + ``auto`` + +Example + .. code-block:: text + + vt_software = auto + +vt_realtime +^^^^^^^^^^^ + +Description + Realtime encoding. + + .. Note:: This option only applies when using MacOS. + + .. Warning:: Disabling realtime encoding might result in a delayed frame encoding or frame drop. + +Default + ``enabled`` + +Example + .. code-block:: text + + vt_realtime = enabled + +vt_coder +^^^^^^^^ + +Description + The entropy encoding to use. + + .. Note:: This option only applies when using MacOS. + +**Choices** + +.. table:: + :widths: auto + + ========== =========== + Value Description + ========== =========== + auto let ffmpeg decide + cabac + cavlc + ========== =========== + +Default + ``auto`` + +Example + .. code-block:: text + + vt_coder = auto + +Advanced +-------- + +file_apps +^^^^^^^^^ + +Description + The application configuration file path. The file contains a json formatted list of applications that can be started + by Moonlight. + +Default + OS dependent + +Example + .. code-block:: text + + file_apps = apps.json + +file_state +^^^^^^^^^^ + +Description + The file where current state of Sunshine is stored. + +Default + ``sunshine_state.json`` + +Example + .. code-block:: text + + file_state = sunshine_state.json + +credentials_file +^^^^^^^^^^^^^^^^ + +Description + The file where user credentials for the UI are stored. + +Default + ``sunshine_state.json`` + +Example + .. code-block:: text + + credentials_file = sunshine_state.json diff --git a/docs/source/about/docker.rst b/docs/source/about/docker.rst new file mode 100644 index 00000000000..f9afa251915 --- /dev/null +++ b/docs/source/about/docker.rst @@ -0,0 +1,5 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/DOCKER_README.md + +.. Todo:: This is a planned feature. Currently no Dockerfile or image exists for Sunshine. + +.. mdinclude:: ../../../DOCKER_README.md diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst new file mode 100644 index 00000000000..14ee37d2d12 --- /dev/null +++ b/docs/source/about/installation.rst @@ -0,0 +1,84 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/about/installation.rst + +Installation +============ +The recommended method for running Sunshine is to use the `binaries`_ bundled with the `latest release`_. + +Binaries +-------- +Binaries of Sunshine are created for each release. They are available for Linux, and Windows. +Binaries can be found in the `latest release`_. + +.. Todo:: Create binary package(s) for MacOS. See `here `_. + +.. Tip:: Some third party packages also exist. See + :ref:`Third Party Packages `. + +Docker +------ +.. Todo:: Docker images of Sunshine are planned to be included in the future. + They will be available on `Dockerhub.io`_ and `ghcr.io`_. + +Linux +----- + +AppImage +^^^^^^^^ +.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/pkg:appimage?logo=github&style=for-the-badge' + :alt: GitHub issues by-label + +#. Download and extract `sunshine-appimage.zip` + +Debian Packages +^^^^^^^^^^^^^^^ +.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:linux:debian?logo=github&style=for-the-badge' + :alt: GitHub issues by-label + +#. Download the corresponding `.deb` file, e.g. ``sunshine-ubuntu_20_04.deb`` +#. ``sudo apt install -f ``, e.g. ``sudo apt install -f ./sunshine-ubuntu_20_04.deb`` + +Red Hat Packages +^^^^^^^^^^^^^^^^ +.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:linux:fedora?logo=github&style=for-the-badge' + :alt: GitHub issues by-label + +#. Download the corresponding `.rpm` file, e.g. ``sunshine-fedora_35.rpm`` +#. ``sudo rpm -i ``, e.g. ``sudo rpm -i ./sunshine-fedora_35.rpm`` + +.. Note:: If this is the first time installing. + + .. code-block:: bash + + sudo usermod -a -G input $USER + sudo reboot now + +.. Tip:: Optionally, run Sunshine in the background. + + .. code-block:: bash + + systemctl --user start sunshine + +MacOS +----- +.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:macos?logo=github&style=for-the-badge' + :alt: GitHub issues by-label + +#. Install `MacPorts `_ +#. Download the `Portfile `_ from this repository to + ``/tmp`` +#. In a terminal run ``cd /tmp && sudo port install`` +#. The first time you start Sunshine, you will be asked to grant access to screen recording and your microphone. + +Windows +------- +.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:windows:10?logo=github&style=for-the-badge' + :alt: GitHub issues by-label + +.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:windows:11?logo=github&style=for-the-badge' + :alt: GitHub issues by-label + +#. Download and extract ``sunshine-windows.zip`` + +.. _latest release: https://github.com/SunshineStream/Sunshine/releases/latest +.. _Dockerhub.io: https://hub.docker.com/repository/docker/sunshinestream/sunshine +.. _ghcr.io: https://github.com/orgs/SunshineStream/packages?repo_name=sunshine diff --git a/docs/source/about/overview.rst b/docs/source/about/overview.rst new file mode 100644 index 00000000000..e4a3ad51c71 --- /dev/null +++ b/docs/source/about/overview.rst @@ -0,0 +1 @@ +.. include:: ../../../README.rst diff --git a/docs/source/about/third_party_packages.rst b/docs/source/about/third_party_packages.rst new file mode 100644 index 00000000000..4f349abefec --- /dev/null +++ b/docs/source/about/third_party_packages.rst @@ -0,0 +1,65 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/about/third_party_packages.rst + +Third Party Packages +==================== + +.. Warning:: These packages are not maintained by SunshineStream. Use at your own risk. + +AUR (Arch Linux User Repository) +-------------------------------- + +.. image:: https://img.shields.io/aur/version/sunshine?style=for-the-badge&logo=archlinux + :alt: AUR version + +.. image:: https://img.shields.io/aur/last-modified/sunshine?style=for-the-badge&logo=archlinux + :alt: AUR last modified + +.. image:: https://img.shields.io/aur/votes/sunshine?style=for-the-badge&logo=archlinux + :alt: AUR votes + +.. image:: https://img.shields.io/aur/maintainer/sunshine?style=for-the-badge&logo=archlinux + :alt: AUR maintainer + +.. image:: https://img.shields.io/static/v1?label=maintainer&message=hadogenes&color=blue&style=for-the-badge&logo=github + :alt: GitHub Maintainer + :target: https://github.com/hadogenes + +Chocolatey +---------- + +.. image:: https://img.shields.io/chocolatey/v/Sunshine?style=for-the-badge&logo=chocolatey + :alt: Chocolatey Version + +.. image:: https://img.shields.io/chocolatey/dt/sunshine?style=for-the-badge&logo=chocolatey + :alt: Chocolatey + +.. image:: https://img.shields.io/static/v1?label=maintainer&message=AeliusSaionji&color=blue&style=for-the-badge&logo=github + :alt: GitHub Maintainer + :target: https://github.com/AeliusSaionji + +Scoop +----- + +.. image:: https://img.shields.io/scoop/v/sunshine?bucket=extras&style=for-the-badge + :alt: Scoop Version (extras bucket) + +.. image:: https://img.shields.io/static/v1?label=maintainer&message=sitiom&color=blue&style=for-the-badge&logo=github + :alt: GitHub Maintainer + :target: https://github.com/sitiom + + +Legacy GitHub Repo +------------------ + +.. image:: https://img.shields.io/github/last-commit/loki-47-6F-64/sunshine?style=for-the-badge&logo=github + :alt: GitHub last commit + +.. image:: https://img.shields.io/github/release-date/loki-47-6F-64/sunshine?style=for-the-badge&logo=github + :alt: GitHub Release Date + +.. image:: https://img.shields.io/github/downloads/loki-47-6F-64/sunshine/total?style=for-the-badge&logo=github + :alt: GitHub Releases + +.. image:: https://img.shields.io/static/v1?label=maintainer&message=loki-47-6F-64&color=blue&style=for-the-badge&logo=github + :alt: GitHub Maintainer + :target: https://github.com/loki-47-6F-64 diff --git a/docs/source/about/usage.rst b/docs/source/about/usage.rst new file mode 100644 index 00000000000..6eafe4b9d7d --- /dev/null +++ b/docs/source/about/usage.rst @@ -0,0 +1,163 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/about/usage.rst + +Usage +===== +#. See the `setup`_ section for your specific OS. +#. Run ``sunshine /sunshine.conf``. + + .. Note:: The configuration file specified will be created if it doesn't exist. + + .. Tip:: If using the Linux AppImage, replace ``sunshine`` with ``./sunshine.AppImage`` + +#. Configure Sunshine in the web ui + The web ui is available on `https://localhost:47990 `_ by default. You may replace + `localhost` with your internal ip address. + + .. Tip:: Ignore any warning given by your browser about "insecure website". + + .. Caution:: If running for the first time, make sure to note the username and password Sunshine showed to you, + since you cannot get back later! + + Add games and applications. + This can be configured in the web ui. + + .. Note:: Additionally, apps can be configured manually. `assets/apps_.json` is an example of a list of + applications that are started just before running a stream. + + .. Note:: Application list is not fully supported on MacOS + +#. In Moonlight, you may need to add the PC manually. +#. When Moonlight request you insert the correct pin on sunshine: + + - Login to the web ui + - Go to "PIN" in the Header + - Type in your PIN and press Enter, you should get a Success Message + - In Moonlight, select one of the Applications listed + +Network +------- +Sunshine will be available on port 47990 by default. + +.. Warning:: Do not expose port 47990, or the web ui, to the internet! + +Arguments +--------- +To get a list of available arguments run the following: + + .. code-block:: bash + + sunshine --help + +Setup +----- + +Linux +^^^^^ +Sunshine needs access to `uinput` to create mouse and gamepad events. + +Add user to group `input`. + .. code-block:: bash + + usermod -a -G input $USER + +Create `udev` rules. + .. code-block:: bash + + nano /etc/udev/rules.d/85-sunshine-input.rules + + Input the following contents: + ``KERNEL=="uinput", GROUP="input", MODE="0660"`` + + Save the file and exit: + + #. ``CTRL+X`` to start exit. + #. ``Y`` to save modifications. + +Configure autostart service + `path/to/build/dir/sunshine.service` is used to start sunshine in the background. To use it, do the following: + + #. Copy it to the users systemd: ``cp sunshine.service ~/.config/systemd/user/`` + #. Starting + + - One time: ``systemctl --user start sunshine`` + - Always on boot: ``systemctl --user enable sunshine`` + +Additional Setup for KMS + .. Note:: ``cap_sys_admin`` may as well be root, except you don't need to be root to run it. + + It is necessary to allow Sunshine to use KMS: ``sudo setcap cap_sys_admin+p sunshine`` + +MacOS +^^^^^ +Sunshine can only access microphones on macOS due to system limitations. To stream system audio use +`Soundflower `_ or +`BlackHole `_ and +select their sink as audio device in `sunshine.conf`. + +.. Note:: Command Keys are not forwarded by Moonlight. Right Option-Key is mapped to CMD-Key. + +.. Caution:: Gamepads are not supported. + +Windows +^^^^^^^ +For gamepad support, install `ViGEmBus `_ + +Shortcuts +--------- +All shortcuts start with CTRL + ALT + SHIFT, just like Moonlight + + - ``CTRL + ALT + SHIFT + N`` - Hide/Unhide the cursor (This may be useful for Remote Desktop Mode for Moonlight) + - ``CTRL + ALT + SHIFT + F1/F13`` - Switch to different monitor for Streaming + +Application List +---------------- +- You can use Environment variables in place of values +- ``$(HOME)` will be replaced by the value of ``$HOME`` +- ``$$`` will be replaced by ``$``, e.g. ``$$(HOME)`` will be replaced by ``$(HOME)`` +- ``env`` - Adds or overwrites Environment variables for the commands/applications run by Sunshine +- ``"Variable name":"Variable value"`` +- ``apps`` - The list of applications +- Example application: + + .. code-block:: json + + { + "name":"An App", + "cmd":"command to open app", + "prep-cmd":[ + { + "do":"some-command", + "undo":"undo-that-command" + } + ], + "detached":[ + "some-command", + "another-command" + ] + } + + - ``name`` - The name of the application/game + - ``output`` - The file where the output of the command is stored + - ``detached`` - A list of commands to be run and forgotten about + - ``prep-cmd`` - A list of commands to be run before/after the application + + - If any of the prep-commands fail, starting the application is aborted + - ``do`` - Run before the application + + - If it fails, all ``undo`` commands of the previously succeeded ``do`` commands are run + + - ``undo`` - Run after the application has terminated + + - This should not fail considering it is supposed to undo the ``do`` commands + - If it fails, Sunshine is terminated + + - ``cmd`` - The main application + + - If not specified, a process is started that sleeps indefinitely + +Considerations +-------------- +- When an application is started, if there is an application already running, it will be terminated. +- When the application has been shutdown, the stream shuts down as well. +- In addition to the apps listed, one app "Desktop" is hardcoded into Sunshine. It does not start an application, + instead it simply starts a stream. diff --git a/docs/source/building/build.rst b/docs/source/building/build.rst new file mode 100644 index 00000000000..556725fcbcf --- /dev/null +++ b/docs/source/building/build.rst @@ -0,0 +1,31 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/building/build.rst + +Build +===== +Sunshine binaries are built using `CMake `_. Cross compilation is not +supported. That means the binaries must be built on the target operating system and architecture. + +Building Locally +---------------- + +Clone +^^^^^ +Ensure `git `_ is installed and run the following: + + .. code-block:: bash + + git clone https://github.com/sunshinestream/sunshine.git --recurse-submodules + cd sunshine && mkdir build && cd build + +Build +^^^^^ +See the section specific to your OS. + +Remote Build +------------ +It may be beneficial to build remotely in some cases. This will enable easier building on different operating systems. + +#. Fork the project +#. Activate workflows +#. Trigger the `CI` workflow manually +#. Download the artifacts/binaries from the workflow run summary diff --git a/docs/source/building/linux.rst b/docs/source/building/linux.rst new file mode 100644 index 00000000000..9f87d588694 --- /dev/null +++ b/docs/source/building/linux.rst @@ -0,0 +1,241 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/building/linux.rst + +Linux +===== + +Requirements +------------ +.. Warning:: Installing these dependencies may break your distribution. It is recommended to build in a virtual machine + or to use the Dockerfile builds located in the `./scripts` directory. + +Debian Bullseye +""""""""""""""" +End of Life: TBD + +Install Requirements + .. code-block:: bash + + sudo apt update && sudo apt install \ + build-essential \ + cmake \ + git \ + libavdevice-dev \ + libboost-filesystem-dev \ + libboost-log-dev \ + libboost-thread-dev \ + libcap-dev \ # KMS + libdrm-dev \ # KMS + libevdev-dev \ + libpulse-dev \ + libopus-dev \ + libssl-dev \ + libwayland-dev \ # Wayland + libx11-dev \ # X11 + libxcb-shm0-dev \ # X11 + libxcb-xfixes0-dev \ # X11 + libxcb1-dev \ # X11 + libxfixes-dev \ # X11 + libxrandr-dev \ # X11 + libxtst-dev \ # X11 + nvidia-cuda-dev \ # Cuda, NvFBC + nvidia-cuda-toolkit \ # Cuda, NvFBC + +Fedora 35 +""""""""" +End of Life: TBD + +Install Repositories + .. code-block:: bash + + sudo dnf update && \ + sudo dnf group install "Development Tools" && \ + sudo dnf install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm + +Install Requirements + .. code-block:: bash + + sudo dnf install \ + boost-devel \ + boost-static.x86_64 \ + cmake \ + ffmpeg-devel \ + gcc-c++ \ + libevdev-devel \ + libX11-devel \ # X11 + libxcb-devel \ # X11 + libXcursor-devel \ # X11 + libXfixes-devel \ # X11 + libXinerama-devel \ # X11 + libXi-devel \ # X11 + libXrandr-devel \ # X11 + libXtst-devel \ # X11 + mesa-libGL-devel \ + openssl-devel \ + opus-devel \ + pulseaudio-libs-devel \ + rpm-build \ # if you want to build an RPM binary package + +Ubuntu 18.04 +"""""""""""" +End of Life: April 2028 + +Install Repositories + .. code-block:: bash + + sudo apt update && sudo apt install \ + software-properties-common \ + && add-apt-repository ppa:savoury1/graphics && \ + add-apt-repository ppa:savoury1/multimedia && \ + add-apt-repository ppa:savoury1/ffmpeg4 && \ + add-apt-repository ppa:savoury1/boost-defaults-1.71 && \ + add-apt-repository ppa:ubuntu-toolchain-r/test && \ + +Install Requirements + .. code-block:: bash + + sudo apt install \ + build-essential \ + cmake \ + gcc-10 \ + git \ + g++-10 \ + libavdevice-dev \ + libboost-filesystem1.71-dev \ + libboost-log1.71-dev \ + libboost-regex1.71-dev \ + libboost-thread1.71-dev \ + libcap-dev \ # KMS + libdrm-dev \ # KMS + libevdev-dev \ + libpulse-dev \ + libopus-dev \ + libssl-dev \ + libwayland-dev \ # Wayland + libx11-dev \ # X11 + libxcb-shm0-dev \ # X11 + libxcb-xfixes0-dev \ # X11 + libxcb1-dev \ # X11 + libxfixes-dev \ # X11 + libxrandr-dev \ # X11 + libxtst-dev \ # X11 + wget \ + +Update gcc alias + .. code-block:: bash + + update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 + +Install CuDA + .. code-block:: bash + + wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O ./cuda.run && chmod a+x ./cuda.run + ./cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && rm ./cuda.run + +Install CMake + .. code-block:: bash + + wget https://cmake.org/files/v3.22/cmake-3.22.2-linux-x86_64.sh + mkdir /opt/cmake + sh /cmake-3.22.2-linux-x86_64.sh --prefix=/opt/cmake --skip-license + ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake + cmake --version + +Ubuntu 20.04 +"""""""""""" +End of Life: April 2030 + +Install Requirements + .. code-block:: bash + + sudo apt update && sudo apt install \ + build-essential \ + cmake \ + git \ + g++-10 \ + libavdevice-dev \ + libboost-filesystem-dev \ + libboost-log-dev \ + libboost-thread-dev \ + libcap-dev \ # KMS + libdrm-dev \ # KMS + libevdev-dev \ + libpulse-dev \ + libopus-dev \ + libssl-dev \ + libwayland-dev \ # Wayland + libx11-dev \ # X11 + libxcb-shm0-dev \ # X11 + libxcb-xfixes0-dev \ # X11 + libxcb1-dev \ # X11 + libxfixes-dev \ # X11 + libxrandr-dev \ # X11 + libxtst-dev \ # X11 + wget \ + +Update gcc alias + .. code-block:: bash + + update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 + +Install CuDA + .. code-block:: bash + + wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O ./cuda.run && chmod a+x ./cuda.run + ./cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && rm ./cuda.run + +Ubuntu 21.10 +"""""""""""" +End of Life: July 2022 + +Install Requirements + .. code-block:: bash + + sudo apt update && sudo apt install \ + build-essential \ + cmake \ + git \ + libavdevice-dev \ + libboost-filesystem-dev \ + libboost-log-dev \ + libboost-thread-dev \ + libcap-dev \ # KMS + libdrm-dev \ # KMS + libevdev-dev \ + libpulse-dev \ + libopus-dev \ + libssl-dev \ + libwayland-dev \ # Wayland + libx11-dev \ # X11 + libxcb-shm0-dev \ # X11 + libxcb-xfixes0-dev \ # X11 + libxcb1-dev \ # X11 + libxfixes-dev \ # X11 + libxrandr-dev \ # X11 + libxtst-dev \ # X11 + nvidia-cuda-dev \ # Cuda, NvFBC + nvidia-cuda-toolkit \ # Cuda, NvFBC + +Ubuntu 22.04 +"""""""""""" +End of Life: April 2027 + +.. Todo:: Create Ubuntu 22.04 Dockerfile and complete this documentation. + +Build +----- +.. Caution:: Ensure you are in the build directory created during the clone step earlier before continuing. + +Debian based OSes + .. code-block:: bash + + cmake -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 .. + +Red Hat based Oses + .. code-block:: bash + + cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ .. + +Finally + .. code-block:: bash + + make -j ${nproc} diff --git a/docs/source/building/macos.rst b/docs/source/building/macos.rst new file mode 100644 index 00000000000..c763ad12276 --- /dev/null +++ b/docs/source/building/macos.rst @@ -0,0 +1,41 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/building/macos.rst + +MacOS +===== + +Requirements +------------ +MacOS Big Sur and Xcode 12.5+ + +Use either `MacPorts `_ or `Homebrew `_ + +MacPorts +"""""""" +Install Requirements + .. code-block:: bash + + sudo port install cmake boost libopus ffmpeg + +Homebrew +"""""""" +Install Requirements + .. code-block:: bash + + brew install boost cmake ffmpeg libopusenc + # if there are issues with an SSL header that is not found: + cd /usr/local/include + ln -s ../opt/openssl/include/openssl . + +Build +----- +.. Caution:: Ensure you are in the build directory created during the clone step earlier before continuing. + + .. code-block:: bash + + cmake .. + make -j ${nproc} + +If cmake fails complaining to find Boost, try to set the path explicitly. + + ``cmake -DBOOST_ROOT=[boost path] ..``, e.g., ``cmake -DBOOST_ROOT=/opt/local/libexec/boost/1.76 ..`` + diff --git a/docs/source/building/windows.rst b/docs/source/building/windows.rst new file mode 100644 index 00000000000..6a7c1e16e24 --- /dev/null +++ b/docs/source/building/windows.rst @@ -0,0 +1,22 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/building/windows.rst + +Windows +======= + +Requirements +------------ +First you need to install `MSYS2 `_, then startup "MSYS2 MinGW 64-bit" and install the +following packages using: + +.. code-block:: batch + + pacman -S mingw-w64-x86_64-binutils mingw-w64-x86_64-openssl mingw-w64-x86_64-cmake mingw-w64-x86_64-toolchain mingw-w64-x86_64-opus mingw-w64-x86_64-x265 mingw-w64-x86_64-boost git mingw-w64-x86_64-make cmake make gcc + +Build +----- +.. Caution:: Ensure you are in the build directory created during the clone step earlier before continuing. + + .. code-block:: batch + + cmake -G"Unix Makefiles" .. + mingw32-make diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 00000000000..0375d42b6dc --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,88 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# standard imports +from datetime import datetime + + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +import os +# import sys + +script_dir = os.path.dirname(os.path.abspath(__file__)) # the directory of this file +source_dir = os.path.dirname(script_dir) # the source folder directory +root_dir = os.path.dirname(source_dir) # the root folder directory + +# -- Project information ----------------------------------------------------- +project = 'Sunshine' +copyright = f'{datetime.now ().year}, {project}' +author = 'ReenigneArcher' + +# The full version, including alpha/beta/rc tags +# version = '0.13.0' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'm2r2', # enable markdown files + 'sphinx.ext.autosectionlabel', + 'sphinx.ext.todo', # enable to-do sections + 'sphinx.ext.viewcode' # add links to view source code +] + +# Add any paths that contain templates here, relative to this directory. +# templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['toc.rst'] + +# Extensions to include. +source_suffix = ['.rst', '.md'] + + +# -- Options for HTML output ------------------------------------------------- + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +# html_static_path = ['_static'] + +html_logo = os.path.join(root_dir, 'sunshine.ico') + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'sphinx_rtd_theme' + +html_theme_options = { + # 'analytics_id': 'G-XXXXXXXXXX', # Provided by Google in your dashboard + # 'analytics_anonymize_ip': False, + 'logo_only': False, + 'display_version': False, + 'prev_next_buttons_location': 'bottom', + 'style_external_links': True, + 'vcs_pageview_mode': 'blob', + # 'style_nav_header_background': 'white', + # Toc options + 'collapse_navigation': True, + 'sticky_navigation': True, + 'navigation_depth': 4, + 'includehidden': True, + 'titles_only': False, +} + +# extension config options +autosectionlabel_prefix_document = True # Make sure the target is unique +todo_include_todos = True diff --git a/docs/source/contributing/contributing.rst b/docs/source/contributing/contributing.rst new file mode 100644 index 00000000000..d9f5106f398 --- /dev/null +++ b/docs/source/contributing/contributing.rst @@ -0,0 +1,32 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/contributing/contributing.rst + +Contributing +============ +#. Fork the repo on GitHub +#. Create a new branch for the feature you are adding or the issue you are fixing + + .. Tip:: Base the new branch off the `nightly` branch. It will make your life easier when you submit the PR! + +#. Make changes, push commits, etc. +#. Files should contain an empty line at the end. +#. Document your code! +#. Test your code! +#. When ready create a PR to this repo on the `nightly` branch. + + .. Hint:: If you accidentally make your PR against a different branch, a bot will comment letting you know it's on + the wrong branch. Don't worry. You can edit the PR to change the target branch. There is no reason to close the + PR! + + .. Note:: Draft PRs are also welcome as you work through issues. The benefit of creating a draft PR is that an + automated build can run in a github runner. + + .. Attention:: Do not expect partially complete PRs to be merged. These topics will be considered before merging. + + - Does the code follows the style guidelines of this project? + + .. Tip:: Look at examples of existing code in the project! + + - Is the code well commented? + - Were documentation blocks updated for new or modified components? + + .. Note:: Developers and maintainers will attempt to assist with challenging issues. diff --git a/docs/source/contributing/localization.rst b/docs/source/contributing/localization.rst new file mode 100644 index 00000000000..6d0f6556931 --- /dev/null +++ b/docs/source/contributing/localization.rst @@ -0,0 +1,80 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/contributing/localization.rst + +Localization +============ +Sunshine is being localized into various languages. The default language is `en` (English) and is highlighted green. + +.. image:: https://img.shields.io/badge/dynamic/json?color=blue&label=de&style=for-the-badge&query=%24.progress.0.data.translationProgress&url=https%3A%2F%2Fbadges.awesome-crowdin.com%2Fstats-15178612-503956.json +.. image:: https://img.shields.io/badge/dynamic/json?color=green&label=en&style=for-the-badge&query=%24.progress.1.data.translationProgress&url=https%3A%2F%2Fbadges.awesome-crowdin.com%2Fstats-15178612-503956.json +.. image:: https://img.shields.io/badge/dynamic/json?color=blue&label=en-GB&style=for-the-badge&query=%24.progress.2.data.translationProgress&url=https%3A%2F%2Fbadges.awesome-crowdin.com%2Fstats-15178612-503956.json +.. image:: https://img.shields.io/badge/dynamic/json?color=blue&label=en-US&style=for-the-badge&query=%24.progress.3.data.translationProgress&url=https%3A%2F%2Fbadges.awesome-crowdin.com%2Fstats-15178612-503956.json +.. image:: https://img.shields.io/badge/dynamic/json?color=blue&label=es-ES&style=for-the-badge&query=%24.progress.4.data.translationProgress&url=https%3A%2F%2Fbadges.awesome-crowdin.com%2Fstats-15178612-503956.json +.. image:: https://img.shields.io/badge/dynamic/json?color=blue&label=fr&style=for-the-badge&query=%24.progress.5.data.translationProgress&url=https%3A%2F%2Fbadges.awesome-crowdin.com%2Fstats-15178612-503956.json +.. image:: https://img.shields.io/badge/dynamic/json?color=blue&label=it&style=for-the-badge&query=%24.progress.6.data.translationProgress&url=https%3A%2F%2Fbadges.awesome-crowdin.com%2Fstats-15178612-503956.json +.. image:: https://img.shields.io/badge/dynamic/json?color=blue&label=ru&style=for-the-badge&query=%24.progress.7.data.translationProgress&url=https%3A%2F%2Fbadges.awesome-crowdin.com%2Fstats-15178612-503956.json + +Graph + .. image:: https://badges.awesome-crowdin.com/translation-15178612-503956.png + +CrowdIn +------- +The translations occur on +`CrowdIn `_. Feel free to contribute to localization there. +Only elements of the API are planned to be translated. + +.. Note:: The rest API has not yet been implemented. + +Translations Basics + - The brand names `SunshineStream` and `Sunshine` should never be translated. + - Other brand names should never be translated. + Examples: + + - AMD + - Nvidia + +CrowdIn Integration + How does it work? + + When a change is made to sunshine source code, a workflow generates new translation templates + that get pushed to CrowdIn automatically. + + When translations are updated on CrowdIn, a push gets made to the `l10n_nightly` branch and a PR is made against the + `nightly` branch. Once PR is merged, all updated translations are part of the project and will be included in the + next release. + +Extraction +---------- +There should be minimal cases where strings need to be extracted from source code; however it may be necessary in some +situations. For example if a system tray icon is added it should be localized as it is user interfacing. + + - Wrap the string to be extracted in a function as shown. + + .. code-block:: cpp + + #include + boost::locale::translate("Hello world!") + +.. Warning:: This is for information only. Contributors should never include manually updated template files, or + manually compiled language files in Pull Requests. + +Strings are automatically extracted from the code to the `locale/sunshine.po` template file. The generated file is +used by CrowdIn to generate language specific template files. The file is generated using the +`.github/workflows/localize.yml` workflow and is run on any push event into the `nightly` branch. Jobs are only run if +any of the following paths are modified. + + .. code-block:: yaml + + - 'sunshine/**' + +When testing locally it may be desirable to manually extract, initialize, update, and compile strings. Python is +required for this, along with the dependencies in the `./scripts/requirements.txt` file. + + Extract, initialize, and update + .. code-block:: bash + + python ./scripts/_locale.py --extract --init --update + + Compile + .. code-block:: bash + + python ./scripts/_locale.py --compile diff --git a/docs/source/contributing/testing.rst b/docs/source/contributing/testing.rst new file mode 100644 index 00000000000..a08c6f9c819 --- /dev/null +++ b/docs/source/contributing/testing.rst @@ -0,0 +1,42 @@ +:github_url: https://github.com/RetroArcher/RetroArcher/tree/nightly/docs/source/contributing/testing.rst + +Testing +======= + +Clang Format +------------ +Source code is tested against the `.clang-format` file for linting errors. The workflow file responsible for clang +format testing is `.github/workflows/clang.yml`. + +Test clang-format locally. + .. Todo:: This documentation needs to be improved. + + .. code-block:: bash + + clang-format ... + +Sphinx +------ +Sunshine uses `Sphinx `_ for documentation building. Sphinx is included +in the `./scripts/requirements.txt` file. Python is required to build sphinx docs. Installation and setup of python +will not be covered here. + +The config file for Sphinx is `docs/source/conf.py`. This is already included in the repo and should not be modified. + +Test with Sphinx + .. code-block:: bash + + cd docs + make html + + Alternatively + + .. code-block:: bash + + cd docs + sphinx-build -b html source build + +Unit Testing +------------ +.. Todo:: Sunshine does not currently have any unit tests. If you would like to help us improve please get in contact + with us, or make a PR with suggested changes. diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 00000000000..5384c8e2821 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,7 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/index.rst + +SunshineStream has this documentation hosted on `Read the Docs `_. + +Table of Contents +================= +.. include:: toc.rst diff --git a/docs/source/toc.rst b/docs/source/toc.rst new file mode 100644 index 00000000000..9c0989eedcf --- /dev/null +++ b/docs/source/toc.rst @@ -0,0 +1,27 @@ +.. toctree:: + :maxdepth: 2 + :caption: About + + about/overview + about/installation + about/docker + about/third_party_packages + about/usage + about/advanced_usage + +.. toctree:: + :maxdepth: 2 + :caption: Build + + building/build + building/linux + building/macos + building/windows + +.. toctree:: + :maxdepth: 2 + :caption: Contributing + + contributing/contributing + contributing/localization + contributing/testing diff --git a/scripts/Dockerfile-debian b/scripts/Dockerfile-debian index 3a53fd9ff84..fc77eb8e989 100644 --- a/scripts/Dockerfile-debian +++ b/scripts/Dockerfile-debian @@ -1,5 +1,7 @@ FROM debian:bullseye AS sunshine-debian +# Debian Bullseye end of life is TBD + ARG DEBIAN_FRONTEND=noninteractive ARG TZ="Europe/London" @@ -11,9 +13,9 @@ RUN apt-get update -y && \ cmake \ git \ libavdevice-dev \ - libboost-thread-dev \ libboost-filesystem-dev \ libboost-log-dev \ + libboost-thread-dev \ libcap-dev \ libdrm-dev \ libevdev-dev \ diff --git a/scripts/Dockerfile-fedora_33 b/scripts/Dockerfile-fedora_33 index 50a4e3dbbff..136058c3ec7 100644 --- a/scripts/Dockerfile-fedora_33 +++ b/scripts/Dockerfile-fedora_33 @@ -1,5 +1,8 @@ FROM fedora:33 AS sunshine-fedora_33 +# Fedora 33 end of life is November 2021 +# This file remains for reference only + SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN dnf -y update && \ dnf -y group install "Development Tools" && \ diff --git a/scripts/Dockerfile-fedora_35 b/scripts/Dockerfile-fedora_35 index d4f5d843ba8..18b04377c14 100644 --- a/scripts/Dockerfile-fedora_35 +++ b/scripts/Dockerfile-fedora_35 @@ -1,5 +1,7 @@ FROM fedora:35 AS sunshine-fedora_35 +# Fedora 35 end of life is TBD + SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN dnf -y update && \ dnf -y group install "Development Tools" && \ @@ -11,8 +13,8 @@ RUN dnf -y update && \ ffmpeg-devel \ gcc-c++ \ libevdev-devel \ - libxcb-devel \ libX11-devel \ + libxcb-devel \ libXcursor-devel \ libXfixes-devel \ libXinerama-devel \ diff --git a/scripts/Dockerfile-ubuntu_18_04 b/scripts/Dockerfile-ubuntu_18_04 index 7225c0c72a3..6ad3e8c02ad 100644 --- a/scripts/Dockerfile-ubuntu_18_04 +++ b/scripts/Dockerfile-ubuntu_18_04 @@ -1,5 +1,7 @@ FROM ubuntu:18.04 AS sunshine-ubuntu_18_04 +# Ubuntu 18.04 end of life is April 2028 + ARG DEBIAN_FRONTEND=noninteractive ARG TZ="Europe/London" diff --git a/scripts/Dockerfile-ubuntu_20_04 b/scripts/Dockerfile-ubuntu_20_04 index 9ae7dfa913c..44e897a7586 100644 --- a/scripts/Dockerfile-ubuntu_20_04 +++ b/scripts/Dockerfile-ubuntu_20_04 @@ -1,5 +1,7 @@ FROM ubuntu:20.04 AS sunshine-ubuntu_20_04 +# Ubuntu 20.04 end of life is April 2030 + ARG DEBIAN_FRONTEND=noninteractive ARG TZ="Europe/London" diff --git a/scripts/Dockerfile-ubuntu_21_04 b/scripts/Dockerfile-ubuntu_21_04 index 00801c55f9c..012845a5b69 100644 --- a/scripts/Dockerfile-ubuntu_21_04 +++ b/scripts/Dockerfile-ubuntu_21_04 @@ -1,5 +1,8 @@ FROM ubuntu:21.04 AS sunshine-ubuntu_21_04 +# Ubuntu 21.04 end of life is January 2022 +# This file remains for reference only + ARG DEBIAN_FRONTEND=noninteractive ARG TZ="Europe/London" diff --git a/scripts/Dockerfile-ubuntu_21_10 b/scripts/Dockerfile-ubuntu_21_10 index 83b3e7f8a8b..6be49dbe0cb 100644 --- a/scripts/Dockerfile-ubuntu_21_10 +++ b/scripts/Dockerfile-ubuntu_21_10 @@ -1,5 +1,7 @@ FROM ubuntu:21.10 AS sunshine-ubuntu_21_10 +# Ubuntu 21.10 end of life is July 2022 + ARG DEBIAN_FRONTEND=noninteractive ARG TZ="Europe/London" @@ -10,9 +12,9 @@ RUN apt-get update -y && \ cmake \ git \ libavdevice-dev \ - libboost-thread-dev \ libboost-filesystem-dev \ libboost-log-dev \ + libboost-thread-dev \ libcap-dev \ libdrm-dev \ libevdev-dev \ diff --git a/scripts/_locale.py b/scripts/_locale.py index 82e172cc772..e47887cc964 100644 --- a/scripts/_locale.py +++ b/scripts/_locale.py @@ -1,4 +1,6 @@ -"""_locale.py +""" +.. + _locale.py Functions related to building, initializing, updating, and compiling localization translations. @@ -62,7 +64,7 @@ def x_extract(): commands.append(filename) print(commands) - proc = subprocess.run(args=commands, cwd=root_dir) + subprocess.check_output(args=commands, cwd=root_dir) # fix header body = "" @@ -98,7 +100,7 @@ def babel_init(locale_code: str): ] print(commands) - proc = subprocess.run(args=commands, cwd=root_dir) + subprocess.check_output(args=commands, cwd=root_dir) def babel_update(): @@ -113,7 +115,7 @@ def babel_update(): ] print(commands) - proc = subprocess.run(args=commands, cwd=root_dir) + subprocess.check_output(args=commands, cwd=root_dir) def babel_compile(): @@ -126,13 +128,13 @@ def babel_compile(): ] print(commands) - proc = subprocess.run(args=commands, cwd=root_dir) + subprocess.check_output(args=commands, cwd=root_dir) if __name__ == '__main__': # Set up and gather command line arguments parser = argparse.ArgumentParser( - description='Script helps update locale_id translations. Translations must be done manually.') + description='Script helps update locale translations. Translations must be done manually.') parser.add_argument('--extract', action='store_true', help='Extract messages from c++ files.') parser.add_argument('--init', action='store_true', help='Initialize any new locales specified in target locales.') diff --git a/scripts/requirements.txt b/scripts/requirements.txt index 9d236e724ac..c089efd943c 100644 --- a/scripts/requirements.txt +++ b/scripts/requirements.txt @@ -1 +1,4 @@ Babel==2.9.1 +m2r2==0.3.2 +Sphinx==4.5.0 +sphinx-rtd-theme==1.0.0 From 293ee266afdb7a881b94c04c918b4a435a2ea19c Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Mon, 18 Apr 2022 15:26:53 -0400 Subject: [PATCH 041/120] Add docker file build instructions and... - Remove readme.md files --- README.md | 334 --------------------------------- docs/source/building/build.rst | 8 +- docs/source/building/linux.rst | 73 ++++++- scripts/README.md | 53 ------ 4 files changed, 72 insertions(+), 396 deletions(-) delete mode 100644 README.md delete mode 100644 scripts/README.md diff --git a/README.md b/README.md deleted file mode 100644 index f062769e394..00000000000 --- a/README.md +++ /dev/null @@ -1,334 +0,0 @@ -# Introduction -Sunshine is a Gamestream host for Moonlight - -[![CI](https://github.com/SunshineStream/Sunshine/actions/workflows/CI.yml/badge.svg?branch=master)](https://github.com/SunshineStream/Sunshine/actions/workflows/CI.yml) -[![Downloads](https://img.shields.io/github/downloads/sunshinestream/sunshine/total)](https://github.com/sunshinestream/sunshine/releases) -[![Crowdin](https://badges.crowdin.net/sunshinestream/localized.svg)](https://crowdin.com/project/sunshinestream) - -- [Building](README.md#building) -- [Credits](README.md#credits) - -# Building -- [Linux](README.md#linux) -- [MacOS](README.md#macos) -- [Windows](README.md#windows-10) - -## Linux - -If you do not wish to clutter your PC with development files, yet you want the very latest version... -You can use these [build scripts](scripts/README.md) -They make use of docker to handle building Sunshine automatically - -### Requirements: - -#### Ubuntu 20.04: -Install the following: - -#### Common -``` -sudo apt install cmake gcc-10 g++-10 libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libevdev-dev -``` -#### X11 -``` -sudo apt install libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev -``` - -#### KMS -This requires additional [setup](README.md#Setup). -``` -sudo apt install libdrm-dev libcap-dev -``` - -#### Wayland -This is for wlroots based compositores, such as Sway -``` -sudo apt install libwayland-dev -``` - -#### Cuda + NvFBC -This requires proprietary software -On Ubuntu 20.04, the cuda compiler will fail since it's version is too old, it's recommended you compile the sources with the [build scripts](scripts/README.md) -``` -sudo apt install nvidia-cuda-dev nvidia-cuda-toolkit -``` - -#### Fedora 35: - -You will need some things in the RPMFusion repo, nost notably ffmpeg. -``` -sudo dnf install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm -``` -#### Development tools and libraries -``` -sudo dnf install \ - boost-devel \ - boost-static.x86_64 \ - cmake \ - ffmpeg-devel \ - gcc-c++ \ - libevdev-devel \ - libxcb-devel \ - libX11-devel \ - libXcursor-devel \ - libXfixes-devel \ - libXinerama-devel \ - libXi-devel \ - libXrandr-devel \ - libXtst-devel \ - mesa-libGL-devel \ - openssl-devel \ - opus-devel \ - pulseaudio-libs-devel -``` -#### If you need to build an RPM binary package: -``` -sudo dnf install rpmbuild -``` - -#### Warning: -You might require ffmpeg version >= 4.3. Check the troubleshooting section for more information. - -### Compilation: - -#### Ubuntu -- `git clone https://github.com/SunshineStream/Sunshine.git --recurse-submodules` -- `cd sunshine && mkdir build && cd build` -- `cmake -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 ..` -- `make -j ${nproc}` - -#### Fedora -- `git clone https://github.com/SunshineStream/Sunshine.git --recurse-submodules` -- `cd sunshine && mkdir build && cd build` -- `cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ ..` -- `make -j ${nproc}` - -### Setup: -sunshine needs access to uinput to create mouse and gamepad events: - -- Add user to group 'input': - `usermod -a -G input $USER` -- Create udev rules: - - Run the following command: - `nano /etc/udev/rules.d/85-sunshine-input.rules` - - Input the following contents: - `KERNEL=="uinput", GROUP="input", MODE="0660"` - - Save the file and exit - 1. `CTRL+X` to start exit - 2. `Y` to save modifications -- `assets/sunshine.conf` is an example configuration file. Modify it as you see fit, then use it by running: - `sunshine path/to/sunshine.conf` -- Configure autostart service - `path/to/build/dir/sunshine.service` is used to start sunshine in the background. To use it, do the following: - 1. Copy it to the users systemd, `cp sunshine.service ~/.config/systemd/user/` - 2. Starting - - Onetime: - `systemctl --user start sunshine` - - Always on boot: - `systemctl --user enable sunshine` - -- `assets/apps.json` is an [example](README.md#application-list) of a list of applications that are started just before running a stream - -#### Additional Setup for KMS: -Please note that `cap_sys_admin` may as well be root, except you don't need to be root to run it. -It's necessary to allow Sunshine to use KMS -- `sudo setcap cap_sys_admin+p sunshine` - -### Trouleshooting: -- If you get "Could not create Sunshine Gamepad: Permission Denied", ensure you are part of the group "input": - - `groups $USER` - -- If Sunshine sends audio from the microphone instead of the speaker, try the following steps: - 1. Check whether you're using Pulseaudio or Pipewire - - Pulseaudio: Use `pacmd list-sources | grep "name:"` - - Pipewire: Use `pactl info | grep Source`. In some causes you'd need to use the `sink` device. Try `pactl info | grep Sink`, if _Source_ doesn't work. - 2. Copy the name to the configuration option "audio_sink" - 3. Restart sunshine - -- If you get "Error: Failed to create client: Daemon not running", ensure that your avahi-daemon is running: - - `systemctl status avahi-daemon` - -- If you use hardware acceleration on Linux using an Intel or an AMD GPU (with VAAPI), you will get tons of [graphical issues](https://github.com/loki-47-6F-64/sunshine/issues/228) if your ffmpeg version is < 4.3. If it is not available in your distribution's repositories, consider using a newer version of your distribution. - - Ubuntu started to ship ffmpeg 4.3 starting with groovy (20.10). If you're using an older version, you could use [this PPA](https://launchpad.net/%7Esavoury1/+archive/ubuntu/ffmpeg4) instead of upgrading. **Using PPAs is dangerous and may break your system. Use it at your own risk.** - -## macOS - -### Quickstart - -- Install [MacPorts](https://www.macports.org) -- Download the `Portfile` from this repository to `/tmp` -- In a Terminal run `cd /tmp && sudo port install` -- Sunshine configuration is in `/opt/local/etc` -- Run `sunshine` to start the Sunshine server -- You will be asked to grant access to screen recording and your microphone to be able to stream it - -### Manuel Build - -#### Requirements: -macOS Big Sur and Xcode 12.5+: - -Either, using [MacPorts](https://www.macports.org), install the following -``` -sudo port install cmake boost libopus ffmpeg -``` - -Or, using [Homebrew](https://brew.sh), install the follwoing: -``` -brew install boost cmake ffmpeg libopusenc -# if there are issues with an SSL header that is not found: -cd /usr/local/include -ln -s ../opt/openssl/include/openssl . -``` - -#### Compilation: -- `git clone https://github.com/SunshineStream/Sunshine.git --recurse-submodules` -- `cd sunshine && mkdir build && cd build` -- `cmake ..` -- `make -j ${nproc}` - -If cmake fails complaining to find Boost, try to set the path explicitly: `cmake -DBOOST_ROOT=[boost path] ..`, e.g., `cmake -DBOOST_ROOT=/opt/local/libexec/boost/1.76 ..` - -### Setup: -- Sunshine can only access microphones on macOS due to system limitations. To stream system audio use [Soundflower](https://github.com/mattingalls/Soundflower) or [BlackHole](https://github.com/ExistentialAudio/BlackHole) and select their sink as audio device in `sunshine.conf` -- `assets/sunshine.conf` is an example configuration file. Modify it as you see fit, then use it by running: - `sunshine path/to/sunshine.conf` -- `assets/apps.json` is an [example](README.md#application-list) of a list of applications that are started just before running a stream - -### Usage & Limitations: -- Command Keys are not forwarded by Moonlight. Right Option-Key is mapped to CMD-Key. -- Gamepads are not supported - -## Windows 10 - -### Requirements: - -First you need to install [MSYS2](https://www.msys2.org), then startup "MSYS2 MinGW 64-bit" and install the following packages using `pacman -S`: - - mingw-w64-x86_64-binutils mingw-w64-x86_64-openssl mingw-w64-x86_64-cmake mingw-w64-x86_64-toolchain mingw-w64-x86_64-opus mingw-w64-x86_64-x265 mingw-w64-x86_64-boost git mingw-w64-x86_64-make cmake make gcc - -### Compilation: -- `git clone https://github.com/loki-47-6F-64/sunshine.git --recursive` -- `cd sunshine && mkdir build && cd build` -- `cmake -G"Unix Makefiles" ..` -- `mingw32-make` - -### Setup: -- **OPTIONAL** Gamepad support: Download and run 'ViGEmBus_Setup_1.16.116.exe' from [https://github.com/ViGEm/ViGEmBus/releases] - - - -# Common - -## Usage: -- run "sunshine path/to/sunshine.conf" -- If running for the first time, make sure to note the username and password Sunshine showed to you, since you **cannot get back later**! -- In Moonlight: Add PC manually -- When Moonlight request you insert the correct pin on sunshine: - - Type in the URL bar of your browser: `https://xxx.xxx.xxx.xxx:47990` where `xxx.xxx.xxx.xxx` is the IP address of your computer - - Ignore any warning given by your browser about "insecure website" - - You should compile the next page with a new username and a password, needed to login into the next step - - Press "Save" and log in using the credentials given above - - Go to "PIN" in the Header - - Type in your PIN and press Enter, you should get a Success Message -- Click on one of the Applications listed -- Have fun :) - -## Shortcuts: - -All shortcuts start with CTRL + ALT + SHIFT, just like Moonlight -- CTRL + ALT + SHIFT + N --> Hide/Unhide the cursor (This may be usefull for Remote Desktop Mode for Moonlight) -- CTRL + ALT + SHIFT + F1/F13 --> Switch to different monitor for Streaming - -## Credits: -- [loki-47-6F-64/sunshine](https://github.com/loki-47-6F-64/sunshine) (For all the hard work put in to create sunshine in the first place!) -- [Simple-Web-Server](https://gitlab.com/eidheim/Simple-Web-Server) -- [Moonlight](https://github.com/moonlight-stream) -- [Looking-Glass](https://github.com/gnif/LookingGlass) (For showing me how to properly capture frames on Windows, saving me a lot of time :) -- [Eretik](http://eretik.omegahg.com/) (For creating PolicyConfig.h, allowing me to change the default audio device on Windows programmatically) - -## Application List: -**Note:** You can change the Application List in the "Apps" section of the User Interface `https://xxx.xxx.xxx.xxx:47990/` -- You can use Environment variables in place of values - - $(HOME) will be replaced by the value of $HOME - - $$ will be replaced by $ --> $$(HOME) will be replaced by $(HOME) -- env: Adds or overwrites Environment variables for the commands/applications run by Sunshine. - - "Variable name":"Variable value" -- apps: The list of applications - - Example: - ```json - { - "name":"An App", - "cmd":"command to open app", - "prep-cmd":[ - { - "do":"some-command", - "undo":"undo-that-command" - } - ], - "detached":[ - "some-command", - "another-command" - ] - } - ``` - - name: Self explanatory - - output : The file where the output of the command is stored - - If it is not specified, the output is ignored - - detached: A list of commands to be run and forgotten about - - prep-cmd: A list of commands to be run before/after the application - - If any of the prep-commands fail, starting the application is aborted - - do: Run before the application - - If it fails, all 'undo' commands of the previously succeeded 'do' commands are run - - undo : Run after the application has terminated - - This should not fail considering it is supposed to undo the 'do' commands. - - If it fails, Sunshine is terminated - - cmd : The main application - - If not specified, a processs is started that sleeps indefinitely - -1. When an application is started, if there is an application already running, it will be terminated. -2. When the application has been shutdown, the stream shuts down as well. -3. In addition to the apps listed, one app "Desktop" is hardcoded into Sunshine. It does not start an application, instead it simply starts a stream. - -Linux -```json -{ - "env":{ - "DISPLAY":":0", - "DRI_PRIME":"1", - "XAUTHORITY":"$(HOME)/.Xauthority", - "PATH":"$(PATH):$(HOME)/.local/bin" - }, - "apps":[ - { - "name":"Low Res Desktop", - "prep-cmd":[ - { "do":"xrandr --output HDMI-1 --mode 1920x1080", "undo":"xrandr --output HDMI-1 --mode 1920x1200" } - ] - }, - { - "name":"Steam BigPicture", - - "output":"steam.txt", - "cmd":"steam -bigpicture", - "prep-cmd":[] - } - ] -} -``` -Windows -```json -{ - "env":{ - "PATH":"$(PATH);C:\\Program Files (x86)\\Steam" - }, - "apps":[ - { - "name":"Steam BigPicture", - - "output":"steam.txt", - "prep-cmd":[ - {"do":"steam \"steam://open/bigpicture\""} - ] - } - ] -} -``` diff --git a/docs/source/building/build.rst b/docs/source/building/build.rst index 556725fcbcf..cd83cb14032 100644 --- a/docs/source/building/build.rst +++ b/docs/source/building/build.rst @@ -17,10 +17,14 @@ Ensure `git `_ is installed and run the following: git clone https://github.com/sunshinestream/sunshine.git --recurse-submodules cd sunshine && mkdir build && cd build -Build -^^^^^ +Compile +^^^^^^^ See the section specific to your OS. +- :ref:`Linux ` +- :ref:`MacOS ` +- :ref:`Windows ` + Remote Build ------------ It may be beneficial to build remotely in some cases. This will enable easier building on different operating systems. diff --git a/docs/source/building/linux.rst b/docs/source/building/linux.rst index 9f87d588694..15ff00014c4 100644 --- a/docs/source/building/linux.rst +++ b/docs/source/building/linux.rst @@ -6,10 +6,10 @@ Linux Requirements ------------ .. Warning:: Installing these dependencies may break your distribution. It is recommended to build in a virtual machine - or to use the Dockerfile builds located in the `./scripts` directory. + or to use the `Dockerfile builds`_ located in the `./scripts` directory. Debian Bullseye -""""""""""""""" +^^^^^^^^^^^^^^^ End of Life: TBD Install Requirements @@ -41,7 +41,7 @@ Install Requirements nvidia-cuda-toolkit \ # Cuda, NvFBC Fedora 35 -""""""""" +^^^^^^^^^ End of Life: TBD Install Repositories @@ -76,7 +76,7 @@ Install Requirements rpm-build \ # if you want to build an RPM binary package Ubuntu 18.04 -"""""""""""" +^^^^^^^^^^^^ End of Life: April 2028 Install Repositories @@ -141,7 +141,7 @@ Install CMake cmake --version Ubuntu 20.04 -"""""""""""" +^^^^^^^^^^^^ End of Life: April 2030 Install Requirements @@ -184,7 +184,7 @@ Install CuDA ./cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && rm ./cuda.run Ubuntu 21.10 -"""""""""""" +^^^^^^^^^^^^ End of Life: July 2022 Install Requirements @@ -216,7 +216,7 @@ Install Requirements nvidia-cuda-toolkit \ # Cuda, NvFBC Ubuntu 22.04 -"""""""""""" +^^^^^^^^^^^^ End of Life: April 2027 .. Todo:: Create Ubuntu 22.04 Dockerfile and complete this documentation. @@ -239,3 +239,62 @@ Finally .. code-block:: bash make -j ${nproc} + +Dockerfile Builds +----------------- +You may wish to simply build sunshine from source, without bloating your OS with development files. +There are scripts located in the ``./scripts`` directory that will create docker images that have the necessary +packages. As a result, removing the development files after you're done is a single command away. +These scripts use docker under the hood, as such, they can only be used to compile the Linux version + +.. Todo:: Publish the Dockerfiles to Dockerhub and ghcr. + +Requirements + Install `Docker `_ + +Instructions + #. :ref:`Clone `. Sunshine. + #. Select the desired Dockerfile from the ``./scripts`` directory. + + Available Files: + .. code-block:: text + + Dockerfile-debian + Dockerfile-fedora_33 # end of life + Dockerfile-fedora_35 + Dockerfile-ubuntu_18_04 + Dockerfile-ubuntu_20_04 + Dockerfile-ubuntu_21_04 # end of life + Dockerfile-ubuntu_21_10 + + #. Execute + + .. code-block:: bash + + cd scripts # move to the scripts directory + ./build-container.sh -f Dockerfile- # create the container (replace the "") + ./build-sunshine.sh -p -s .. # compile and build sunshine + + #. Updating + + .. code-block:: bash + + git pull # pull the latest changes from github + ./build-sunshine.sh -p -s .. # compile and build sunshine + + #. Optionally, delete the container + .. code-block:: bash + + ./build-container.sh -c delete + + #. Install the resulting package + + Debian + .. code-block:: bash + + sudo apt install -f sunshine-build/sunshine.deb + + Red Hat + .. code-block:: bash + + sudo rpm -i -f sunshine-build/sunshine.rpm diff --git a/scripts/README.md b/scripts/README.md deleted file mode 100644 index 16e99ac80e6..00000000000 --- a/scripts/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Introduction -Sunshine is a Gamestream host for Moonlight - -[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/cgrtw2g3fq9b0b70/branch/master?svg=true)](https://ci.appveyor.com/project/loki-47-6F-64/sunshine/branch/master) -[![Downloads](https://img.shields.io/github/downloads/Loki-47-6F-64/sunshine/total)](https://github.com/Loki-47-6F-64/sunshine/releases) - -You may wish to simply build sunshine from source, without bloating your OS with development files. -These scripts will create a docker images that have the necessary packages. As a result, removing the development files after you're done is a single command away. -These scripts use docker under the hood, as such, they can only be used to compile the Linux version - - -#### Requirements - -``` -sudo apt install docker -``` - -#### instructions - -You'll require one of the following Dockerfiles: -* Dockerfile-2004 --> Ubuntu 20.04 -* Dockerfile-2104 --> Ubuntu 21.04 -* Dockerfile-debian --> Debian Bullseye - -Depending on your system, the build-* scripts may need root privilleges - -First, the docker container needs to be created: -``` -cd scripts -./build-container.sh -f Dockerfile- -``` - -Then, the sources will be compiled and the debian package generated: -``` -./build-sunshine.sh -p -s .. -``` -You can run `build-sunshine -p -s ..` again as long as the docker container exists. - -``` -git pull -./build-sunshine.sh -p -s .. -``` - -Optionally, the docker container can be removed after you're finished: -``` -./build-container.sh -c delete -``` - -Finally install the resulting package: -``` -sudo apt install -f sunshine-build/sunshine.deb -``` - From 56cf3e4ede97006e1aff652c61d42a82586e7b62 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Mon, 18 Apr 2022 16:05:17 -0400 Subject: [PATCH 042/120] Update admonitions --- docs/source/about/advanced_usage.rst | 4 ++-- docs/source/about/installation.rst | 2 +- docs/source/about/third_party_packages.rst | 4 +++- docs/source/about/usage.rst | 10 ++++++---- docs/source/building/linux.rst | 4 ++-- docs/source/building/macos.rst | 2 +- docs/source/building/windows.rst | 2 +- docs/source/contributing/localization.rst | 2 +- 8 files changed, 17 insertions(+), 13 deletions(-) diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index e01de0aa60f..2a23e1bcb48 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -29,7 +29,7 @@ Example To manually configure sunshine you may edit the `conf` file in a text editor. Use the examples as reference. -.. Note:: Some settings are not available within the web ui. +.. Hint:: Some settings are not available within the web ui. General ------- @@ -166,7 +166,7 @@ Description .. Tip:: See `virtual key codes `_ - .. Note:: keybindings needs to have a multiple of two elements. + .. Hint:: keybindings needs to have a multiple of two elements. Default None diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index 14ee37d2d12..70fd28c2b8a 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -45,7 +45,7 @@ Red Hat Packages #. Download the corresponding `.rpm` file, e.g. ``sunshine-fedora_35.rpm`` #. ``sudo rpm -i ``, e.g. ``sudo rpm -i ./sunshine-fedora_35.rpm`` -.. Note:: If this is the first time installing. +.. Hint:: If this is the first time installing. .. code-block:: bash diff --git a/docs/source/about/third_party_packages.rst b/docs/source/about/third_party_packages.rst index 4f349abefec..6069258a505 100644 --- a/docs/source/about/third_party_packages.rst +++ b/docs/source/about/third_party_packages.rst @@ -3,7 +3,7 @@ Third Party Packages ==================== -.. Warning:: These packages are not maintained by SunshineStream. Use at your own risk. +.. Danger:: These packages are not maintained by SunshineStream. Use at your own risk. AUR (Arch Linux User Repository) -------------------------------- @@ -51,6 +51,8 @@ Scoop Legacy GitHub Repo ------------------ +.. Attention:: This repo is no longer maintained. Thank you to Loki for bringing this amazing project to life! + .. image:: https://img.shields.io/github/last-commit/loki-47-6F-64/sunshine?style=for-the-badge&logo=github :alt: GitHub last commit diff --git a/docs/source/about/usage.rst b/docs/source/about/usage.rst index 6eafe4b9d7d..4bb81bc5969 100644 --- a/docs/source/about/usage.rst +++ b/docs/source/about/usage.rst @@ -5,7 +5,9 @@ Usage #. See the `setup`_ section for your specific OS. #. Run ``sunshine /sunshine.conf``. - .. Note:: The configuration file specified will be created if it doesn't exist. + .. Note:: You do not need to specify a config file. If no config file is entered the default location will be used. + + .. Attention:: The configuration file specified will be created if it doesn't exist. .. Tip:: If using the Linux AppImage, replace ``sunshine`` with ``./sunshine.AppImage`` @@ -13,7 +15,7 @@ Usage The web ui is available on `https://localhost:47990 `_ by default. You may replace `localhost` with your internal ip address. - .. Tip:: Ignore any warning given by your browser about "insecure website". + .. Attention:: Ignore any warning given by your browser about "insecure website". .. Caution:: If running for the first time, make sure to note the username and password Sunshine showed to you, since you cannot get back later! @@ -24,7 +26,7 @@ Usage .. Note:: Additionally, apps can be configured manually. `assets/apps_.json` is an example of a list of applications that are started just before running a stream. - .. Note:: Application list is not fully supported on MacOS + .. Attention:: Application list is not fully supported on MacOS #. In Moonlight, you may need to add the PC manually. #. When Moonlight request you insert the correct pin on sunshine: @@ -38,7 +40,7 @@ Network ------- Sunshine will be available on port 47990 by default. -.. Warning:: Do not expose port 47990, or the web ui, to the internet! +.. Danger:: Do not expose port 47990, or the web ui, to the internet! Arguments --------- diff --git a/docs/source/building/linux.rst b/docs/source/building/linux.rst index 15ff00014c4..a519761a75c 100644 --- a/docs/source/building/linux.rst +++ b/docs/source/building/linux.rst @@ -5,7 +5,7 @@ Linux Requirements ------------ -.. Warning:: Installing these dependencies may break your distribution. It is recommended to build in a virtual machine +.. Danger:: Installing these dependencies may break your distribution. It is recommended to build in a virtual machine or to use the `Dockerfile builds`_ located in the `./scripts` directory. Debian Bullseye @@ -223,7 +223,7 @@ End of Life: April 2027 Build ----- -.. Caution:: Ensure you are in the build directory created during the clone step earlier before continuing. +.. Attention:: Ensure you are in the build directory created during the clone step earlier before continuing. Debian based OSes .. code-block:: bash diff --git a/docs/source/building/macos.rst b/docs/source/building/macos.rst index c763ad12276..97a58a239e9 100644 --- a/docs/source/building/macos.rst +++ b/docs/source/building/macos.rst @@ -28,7 +28,7 @@ Install Requirements Build ----- -.. Caution:: Ensure you are in the build directory created during the clone step earlier before continuing. +.. Attention:: Ensure you are in the build directory created during the clone step earlier before continuing. .. code-block:: bash diff --git a/docs/source/building/windows.rst b/docs/source/building/windows.rst index 6a7c1e16e24..36cea881697 100644 --- a/docs/source/building/windows.rst +++ b/docs/source/building/windows.rst @@ -14,7 +14,7 @@ following packages using: Build ----- -.. Caution:: Ensure you are in the build directory created during the clone step earlier before continuing. +.. Attention:: Ensure you are in the build directory created during the clone step earlier before continuing. .. code-block:: batch diff --git a/docs/source/contributing/localization.rst b/docs/source/contributing/localization.rst index 6d0f6556931..721ebc61c1e 100644 --- a/docs/source/contributing/localization.rst +++ b/docs/source/contributing/localization.rst @@ -22,7 +22,7 @@ The translations occur on `CrowdIn `_. Feel free to contribute to localization there. Only elements of the API are planned to be translated. -.. Note:: The rest API has not yet been implemented. +.. Attention:: The rest API has not yet been implemented. Translations Basics - The brand names `SunshineStream` and `Sunshine` should never be translated. From eacae3954e21eaf8a7349ddc8223cd117c117828 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Mon, 18 Apr 2022 16:21:05 -0400 Subject: [PATCH 043/120] Fix typos --- DOCKER_README.md | 2 +- docs/source/about/advanced_usage.rst | 2 +- docs/source/about/installation.rst | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/DOCKER_README.md b/DOCKER_README.md index 8691e01bf4e..aa2f1017a62 100644 --- a/DOCKER_README.md +++ b/DOCKER_README.md @@ -43,7 +43,7 @@ Create a `docker-compose.yml` file with the following contents (substitute your ```yaml version: '3' services: - retroarcher: + sunshine: image: sunshinestream/sunshine container_name: sunshine restart: unless-stopped diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index 2a23e1bcb48..4f427dcb253 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -9,7 +9,7 @@ Configuration The default location for the configuration file is ``./assets/sunshine.conf``. You can use another location if you choose, by passing in the full configuration file path as the first argument when you start Sunshine. -** Default File Location** +**Default File Location** .. table:: :widths: auto diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index 70fd28c2b8a..12813cef48b 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -24,14 +24,14 @@ Linux AppImage ^^^^^^^^ -.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/pkg:appimage?logo=github&style=for-the-badge' +.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/pkg:appimage?logo=github&style=for-the-badge :alt: GitHub issues by-label #. Download and extract `sunshine-appimage.zip` Debian Packages ^^^^^^^^^^^^^^^ -.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:linux:debian?logo=github&style=for-the-badge' +.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:linux:debian?logo=github&style=for-the-badge :alt: GitHub issues by-label #. Download the corresponding `.deb` file, e.g. ``sunshine-ubuntu_20_04.deb`` @@ -39,7 +39,7 @@ Debian Packages Red Hat Packages ^^^^^^^^^^^^^^^^ -.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:linux:fedora?logo=github&style=for-the-badge' +.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:linux:fedora?logo=github&style=for-the-badge :alt: GitHub issues by-label #. Download the corresponding `.rpm` file, e.g. ``sunshine-fedora_35.rpm`` @@ -60,7 +60,7 @@ Red Hat Packages MacOS ----- -.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:macos?logo=github&style=for-the-badge' +.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:macos?logo=github&style=for-the-badge :alt: GitHub issues by-label #. Install `MacPorts `_ @@ -71,10 +71,10 @@ MacOS Windows ------- -.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:windows:10?logo=github&style=for-the-badge' +.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:windows:10?logo=github&style=for-the-badge :alt: GitHub issues by-label -.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:windows:11?logo=github&style=for-the-badge' +.. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:windows:11?logo=github&style=for-the-badge :alt: GitHub issues by-label #. Download and extract ``sunshine-windows.zip`` From f36d81954baf724ea8d4f0b5f9d963ef03b971f9 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 19 Apr 2022 20:38:06 -0400 Subject: [PATCH 044/120] Update rpm install commands --- docs/source/about/installation.rst | 2 +- docs/source/building/linux.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index 12813cef48b..d2b9d877674 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -43,7 +43,7 @@ Red Hat Packages :alt: GitHub issues by-label #. Download the corresponding `.rpm` file, e.g. ``sunshine-fedora_35.rpm`` -#. ``sudo rpm -i ``, e.g. ``sudo rpm -i ./sunshine-fedora_35.rpm`` +#. ``sudo dnf install ``, e.g. ``sudo dnf install ./sunshine-fedora_35.rpm`` .. Hint:: If this is the first time installing. diff --git a/docs/source/building/linux.rst b/docs/source/building/linux.rst index a519761a75c..a6e7eefbd51 100644 --- a/docs/source/building/linux.rst +++ b/docs/source/building/linux.rst @@ -297,4 +297,4 @@ Instructions Red Hat .. code-block:: bash - sudo rpm -i -f sunshine-build/sunshine.rpm + sudo dnf install sunshine-build/sunshine.rpm From 7a1e5f43d9e4fb622585af9809d8acf8e05bacdc Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 23 Apr 2022 12:35:39 -0400 Subject: [PATCH 045/120] Workflow updates - Do not re-run PR tests on edited PRs - Close added/fixed issues on published release - Issues stale after 60 days instead of 30, close after 10 days instead of 5 - Use Vankka/pr-target-branch-action for checking that PR is made to proper branch - Add version number to sphinx config, must use cmake to configure the file - Add jobs to readthedocs.yaml configuration --- .github/workflows/CI.yml | 2 +- .github/workflows/clang.yml | 2 +- .github/workflows/issues-closer.yml | 21 ++++++++++++++++++ .github/workflows/issues-stale.yml | 4 ++-- .github/workflows/pull-requests.yml | 34 +++++++++-------------------- .readthedocs.yaml | 5 +++++ CMakeLists.txt | 1 + docs/source/{conf.py => conf.py.in} | 4 ++-- 8 files changed, 43 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/issues-closer.yml rename docs/source/{conf.py => conf.py.in} (97%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index da3cc6edcf8..b0be11308d8 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -3,7 +3,7 @@ name: CI on: pull_request: branches: [master, nightly] - types: [opened, synchronize, edited, reopened] + types: [opened, synchronize, reopened] push: branches: [master] workflow_dispatch: diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index f096c5f9f00..fd62d2611c2 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -3,7 +3,7 @@ name: clang-format-lint on: pull_request: branches: [master, nightly] - types: [opened, synchronize, edited, reopened] + types: [opened, synchronize, reopened] jobs: lint: diff --git a/.github/workflows/issues-closer.yml b/.github/workflows/issues-closer.yml new file mode 100644 index 00000000000..943bae37bf9 --- /dev/null +++ b/.github/workflows/issues-closer.yml @@ -0,0 +1,21 @@ +name: Close Added/Fixed Issues + +on: + release: + types: [published] + +jobs: + close_issues: + name: Check Issues / PRs + runs-on: ubuntu-latest + steps: + - name: Close Issues (added/fixed) + uses: actions/stale@v3 + with: + only-issues-labels: 'added,fixed' + close-issue-message: > + This is now available in the latest release. + close-issue-label: 'released' + days-before-issue-stale: 0 + days-before-issue-close: 0 + ignore-updates: true diff --git a/.github/workflows/issues-stale.yml b/.github/workflows/issues-stale.yml index 1c40c45ddd6..233582bd47c 100644 --- a/.github/workflows/issues-stale.yml +++ b/.github/workflows/issues-stale.yml @@ -26,8 +26,8 @@ jobs: This PR was closed because it has been stalled for 5 days with no activity. stale-pr-label: 'stale' exempt-pr-labels: 'status:in-progress' - days-before-stale: 30 - days-before-close: 5 + days-before-stale: 60 + days-before-close: 10 - name: Invalid Template uses: actions/stale@v5 diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml index ad014e6d0c6..36f597b909e 100644 --- a/.github/workflows/pull-requests.yml +++ b/.github/workflows/pull-requests.yml @@ -5,31 +5,17 @@ on: types: [opened, synchronize, edited, reopened] jobs: - check-branch: + check-pull-request: name: Check Pull Request runs-on: ubuntu-latest steps: - - name: Checkout Code - uses: actions/checkout@v3 - - - name: Branch check - if: ( github.head_ref == 'repo-sync/common-repo-files/default' && github.base_ref == 'master' ) || ( github.head_ref == 'nightly' && github.base_ref == 'master' ) - run: | - echo Base: "$GITHUB_BASE_REF" - echo Head: "$GITHUB_HEAD_REF" - echo "branch=True" >> $GITHUB_ENV - - - name: Comment on Pull Request - uses: mshick/add-pr-comment@v1 - if: github.base_ref != 'nightly' && env.branch != 'True' + - uses: Vankka/pr-target-branch-action@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - message: Pull requests must be made to the `nightly` branch. Thanks. - repo-token: ${{ secrets.GITHUB_TOKEN }} - repo-token-user-login: 'github-actions[bot]' - - - name: Fail Workflow - if: github.base_ref != 'nightly' && env.branch != 'True' - run: | - echo Base: "$GITHUB_BASE_REF" - echo Head: "$GITHUB_HEAD_REF" - exit 1 + target: master + exclude: nightly # Don't prevent going from nightly -> master + change-to: nightly + comment: | + Your PR was set to `master`, PRs should be sent to `nightly` + The base branch of this PR has been automatically changed to `nightly`, please check that there are no merge conflicts diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 78c304f8fd9..5f62d86b2d8 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -10,6 +10,11 @@ build: os: ubuntu-20.04 tools: python: "3.9" + jobs: + post_system_dependencies: + - apt-get install cmake + pre_create_environment: + - cmake .. # Build documentation in the docs/ directory with Sphinx sphinx: diff --git a/CMakeLists.txt b/CMakeLists.txt index 862e4f1ae3b..dcbd6942c0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -319,6 +319,7 @@ else() endif() configure_file(version.h.in version.h @ONLY) +configure_file(docs/source/conf.py.in "${CMAKE_CURRENT_SOURCE_DIR}/docs/source/conf.py" @ONLY) include_directories(${CMAKE_CURRENT_BINARY_DIR}) set(SUNSHINE_TARGET_FILES diff --git a/docs/source/conf.py b/docs/source/conf.py.in similarity index 97% rename from docs/source/conf.py rename to docs/source/conf.py.in index 0375d42b6dc..99ce714322c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py.in @@ -26,7 +26,7 @@ author = 'ReenigneArcher' # The full version, including alpha/beta/rc tags -# version = '0.13.0' +version = '@PROJECT_VERSION@' # -- General configuration --------------------------------------------------- @@ -60,7 +60,7 @@ # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] -html_logo = os.path.join(root_dir, 'sunshine.ico') +html_logo = os.path.join(root_dir, 'sunshine.png') # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. From 4cd1014bacdf7f147d77cca5de2ebd374992b7cd Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 23 Apr 2022 12:40:54 -0400 Subject: [PATCH 046/120] Use apt_packages to install cmake --- .readthedocs.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 5f62d86b2d8..c7d0ed50bfd 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -10,11 +10,11 @@ build: os: ubuntu-20.04 tools: python: "3.9" + apt_packages: + - cmake jobs: - post_system_dependencies: - - apt-get install cmake - pre_create_environment: - - cmake .. + pre_build: + - cmake -Wno-dev . # Build documentation in the docs/ directory with Sphinx sphinx: From b332633b074c9d7ec02b227438af7bcc2f4e4483 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 23 Apr 2022 13:09:18 -0400 Subject: [PATCH 047/120] Add submodules --- .readthedocs.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index c7d0ed50bfd..ad158de4b3c 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -14,7 +14,12 @@ build: - cmake jobs: pre_build: - - cmake -Wno-dev . + - cmake . + +# Include the submodules, required for cmake +submodules: + include: all + recursive: true # Build documentation in the docs/ directory with Sphinx sphinx: From 780339d91bddf923130ea80396fa8739307f369a Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 23 Apr 2022 13:16:21 -0400 Subject: [PATCH 048/120] Add boost dependencies --- .readthedocs.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index ad158de4b3c..8787039794a 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -12,6 +12,9 @@ build: python: "3.9" apt_packages: - cmake + - libboost-filesystem-dev + - libboost-log-dev + - libboost-thread-dev jobs: pre_build: - cmake . From 521335c387d68e58c85572278c95ed1798be0fe5 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 23 Apr 2022 16:20:06 -0400 Subject: [PATCH 049/120] Add ffmpeg dependency --- .readthedocs.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 8787039794a..a5997812d6e 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -12,6 +12,7 @@ build: python: "3.9" apt_packages: - cmake + - ffmpeg - libboost-filesystem-dev - libboost-log-dev - libboost-thread-dev From b286c061449715aef215ad8b47d895bfe612ef2e Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 23 Apr 2022 20:50:42 -0400 Subject: [PATCH 050/120] Fix localize `git diff` and `git reset` steps --- .github/workflows/localize.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/localize.yml b/.github/workflows/localize.yml index b860ad6439e..a017efab7ef 100644 --- a/.github/workflows/localize.yml +++ b/.github/workflows/localize.yml @@ -4,6 +4,7 @@ on: push: branches: [nightly] paths: # prevents workflow from running unless these files change + - '.github/workflows/localize.yml' - 'sunshine/**' - 'locale/sunshine.po' workflow_dispatch: @@ -40,15 +41,18 @@ jobs: - name: git diff run: | + # disable the pager + git config --global pager.diff false + # print the git diff - git diff --exit-code locale/sunshine.po + git diff locale/sunshine.po # set the variable with minimal output - OUTPUT=$(git diff --exit-code --numstat locale/sunshine.po) + OUTPUT=$(git diff --numstat locale/sunshine.po) echo "git_diff=${OUTPUT}" >> $GITHUB_ENV - name: git reset - if: ${{ env.git_diff != '1 1 locale/sunshine.po' }} # only run if more than 1 line changed + if: ${{ env.git_diff == '1 1 locale/sunshine.po' }} # only run if more than 1 line changed run: | git reset --hard From ef9abf2f159917c55e3f87ec54709351cdd77525 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Thu, 28 Apr 2022 18:06:55 -0400 Subject: [PATCH 051/120] Get version number from CMakeLists --- .github/workflows/issues-closer.yml | 21 ------------------- .readthedocs.yaml | 32 ++++++++++++++++------------- CMakeLists.txt | 1 - docs/source/{conf.py.in => conf.py} | 16 +++++++++++---- 4 files changed, 30 insertions(+), 40 deletions(-) delete mode 100644 .github/workflows/issues-closer.yml rename docs/source/{conf.py.in => conf.py} (84%) diff --git a/.github/workflows/issues-closer.yml b/.github/workflows/issues-closer.yml deleted file mode 100644 index 943bae37bf9..00000000000 --- a/.github/workflows/issues-closer.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Close Added/Fixed Issues - -on: - release: - types: [published] - -jobs: - close_issues: - name: Check Issues / PRs - runs-on: ubuntu-latest - steps: - - name: Close Issues (added/fixed) - uses: actions/stale@v3 - with: - only-issues-labels: 'added,fixed' - close-issue-message: > - This is now available in the latest release. - close-issue-label: 'released' - days-before-issue-stale: 0 - days-before-issue-close: 0 - ignore-updates: true diff --git a/.readthedocs.yaml b/.readthedocs.yaml index a5997812d6e..762371f85d7 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -10,20 +10,24 @@ build: os: ubuntu-20.04 tools: python: "3.9" - apt_packages: - - cmake - - ffmpeg - - libboost-filesystem-dev - - libboost-log-dev - - libboost-thread-dev - jobs: - pre_build: - - cmake . - -# Include the submodules, required for cmake -submodules: - include: all - recursive: true + +## apt packages required packages to run cmake on sunshine, note that additional packages are required +# apt_packages: +# - cmake +# - ffmpeg +# - libboost-filesystem-dev +# - libboost-log-dev +# - libboost-thread-dev + +## run cmake +# jobs: +# pre_build: +# - cmake . + +## Include the submodules, required for cmake +#submodules: +# include: all +# recursive: true # Build documentation in the docs/ directory with Sphinx sphinx: diff --git a/CMakeLists.txt b/CMakeLists.txt index dcbd6942c0d..862e4f1ae3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -319,7 +319,6 @@ else() endif() configure_file(version.h.in version.h @ONLY) -configure_file(docs/source/conf.py.in "${CMAKE_CURRENT_SOURCE_DIR}/docs/source/conf.py" @ONLY) include_directories(${CMAKE_CURRENT_BINARY_DIR}) set(SUNSHINE_TARGET_FILES diff --git a/docs/source/conf.py.in b/docs/source/conf.py similarity index 84% rename from docs/source/conf.py.in rename to docs/source/conf.py index 99ce714322c..86b7b805b5e 100644 --- a/docs/source/conf.py.in +++ b/docs/source/conf.py @@ -6,6 +6,8 @@ # standard imports from datetime import datetime +import os +import re # -- Path setup -------------------------------------------------------------- @@ -13,8 +15,6 @@ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -import os -# import sys script_dir = os.path.dirname(os.path.abspath(__file__)) # the directory of this file source_dir = os.path.dirname(script_dir) # the source folder directory @@ -26,8 +26,16 @@ author = 'ReenigneArcher' # The full version, including alpha/beta/rc tags -version = '@PROJECT_VERSION@' - +with open(os.path.join(root_dir, 'CMakeLists.txt'), 'r') as f: + version = re.search(r"project\(Sunshine VERSION ((\d+)\.(\d+)\.(\d+))\)", str(f.read())).group(1) +""" +To use cmake method for obtaining version instead of regex, +1. Within CMakeLists.txt add the following line without backticks: + ``configure_file(docs/source/conf.py.in "${CMAKE_CURRENT_SOURCE_DIR}/docs/source/conf.py" @ONLY)`` +2. Rename this file to ``conf.py.in`` +3. Uncomment the next line +""" +# version = '@PROJECT_VERSION@' # use this for cmake configure_file method # -- General configuration --------------------------------------------------- From 734400dc779de3ff8c2595e192b73d478f0e2289 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Thu, 28 Apr 2022 18:20:53 -0400 Subject: [PATCH 052/120] Remove white background from png logo --- sunshine.png | Bin 14699 -> 20640 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/sunshine.png b/sunshine.png index 77f4795673e5bc0e5c828e4b37f26a6d8c05105d..785bc479b9655ce9dd158be2f045c25d9e53f137 100644 GIT binary patch literal 20640 zcmZ5nRa{h08(vaa>29Q?Q@XpQyIVR0X;`|uOF&9eLZo5I1w^E!8Fffeb&267Yu@qSI1Li)3f9-=8zEzyrsxq!s{-J zz{bN%dkh<`6S_vg@9zBXk513ldxPvHyVlM&db>HV>#hrpg{g32hqgWce@JPIxw52A zdE2}wy~;g}gmy4yFgLS_jYZbY3jQU zn5gLqdN!sR`jObQdpp_?phtI{T1chVPf(u$@O39RX|yQ~xPwh|t@J3vaV53yi24<< z!rFTEnMF_OFHu-H0!3nnPe;9ADPzri4#slg|>5|xTD+BBs3jv`qqWNqemP%EWSkQcd!O-E5< zB+F7j>qP zCX%KcQCs00!1Fm093=7CAa&{67|K~y=}MqC{*9{#RYRF9iD0O;#xz_UZ>z1k<>(ix zB}=qlEyrWJAd`!FAZ~F2J|b`Y#?p7WQSDk^v**HO+(S*8h`gs5o+? z4LP$zbWLwpT5(K{_4n$b&W20#woUm+rKT)uF)~aF_>8=4z#BY%>&GHrEM14=FIAW` zOBH$QkGFaOO=!m7b;C#Z_M!oOni9S{+GR58qlHp*1faxFJmp+Jn!4I_3go;3HLc4q!v z3Z(uKGg{5oRKbzyLBiIaj8;@@($AvYUzxFW@r?oZ%acuksSd18UX<=HA7g3h@xYHY55> zeI88^`!NK>7A3*56vDbHAb=@@Xa9yA)0pB4h&4o>46aL&pcxt~x77dlJBKDlunwaL z+0lM_uIzXPxeee@J3VA{*Y{Y<@9=)%>*>t~M@)BNR zITd4A;RCo&wRu4w}^$F z6B4ZGg7cPh7N1>znBqN3Ne4mRkaf(BBIs;b6L9eZDt!(iz&=}O8{BG)Nq z+iRSK1&ion=35x(_4=cf_Qk)tjil4pm)7QL9ym&d>iq);vD1iSdr6 z`+Kv6%7j3Up93DH8&b4|PLQS61ww`NMx+bMT_<9}I%V+d3l?FQ6|)%5=78W5THqAJwH(82)nU`Tiw1=n=sT#de zTi-yILuucol8^bzh@p8%0xknpuu98puDde#d

Ham7aEv9?}_6 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 tMkvIoS9c?+KHU?(UL Date: Thu, 28 Apr 2022 17:38:20 -0700 Subject: [PATCH 053/120] Add RPMFusion/FFMPEG dependancy. --- gen-rpm.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen-rpm.in b/gen-rpm.in index e2bec8f43e7..792a3895573 100755 --- a/gen-rpm.in +++ b/gen-rpm.in @@ -44,7 +44,7 @@ License: GPLv3 URL: https://github.com/SunshineStream/Sunshine Source0: sunshine-@PROJECT_VERSION@_bin.tar.gz -Requires: systemd +Requires: systemd ffmpeg rpmfusion-free-release %description An NVIDIA Gamestream-compatible hosting server From 3d6611fd50d1eb95732ab6f4306cd57a572ab735 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Thu, 28 Apr 2022 22:51:02 -0400 Subject: [PATCH 054/120] Update help argument --- sunshine/main.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sunshine/main.cpp b/sunshine/main.cpp index bcab4b3bec9..c78c897f965 100644 --- a/sunshine/main.cpp +++ b/sunshine/main.cpp @@ -61,17 +61,19 @@ void print_help(const char *name) { std::cout << "Usage: "sv << name << " [options] [/path/to/configuration_file] [--cmd]"sv << std::endl << " Any configurable option can be overwritten with: \"name=value\""sv << std::endl + << std:endl + << " Note: The configuration will be created if it doesn't exist."sv << std::endl << std::endl << " --help | print help"sv << std::endl - << " --creds username password | set user credentials for the Web manager" << std::endl - << " --version | print the version of sunshine" << std::endl + << " --creds username password | set user credentials for the Web manager"sv << std::endl + << " --version | print the version of sunshine"sv << std::endl << std::endl << " flags"sv << std::endl << " -0 | Read PIN from stdin"sv << std::endl << " -1 | Do not load previously saved state and do retain any state after shutdown"sv << std::endl << " | Effectively starting as if for the first time without overwriting any pairings with your devices"sv << std::endl - << " -2 | Force replacement of headers in video stream" << std::endl - << " -p | Enable/Disable UPnP" << std::endl + << " -2 | Force replacement of headers in video stream"sv << std::endl + << " -p | Enable/Disable UPnP"sv << std::endl << std::endl; } From a9cf0ebf188095bac103adb12b3ed2d0acd1dbb4 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Thu, 28 Apr 2022 23:18:58 -0400 Subject: [PATCH 055/120] Remove unused `name` variable - Add documentation blocks --- sunshine/main.cpp | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/sunshine/main.cpp b/sunshine/main.cpp index c78c897f965..93bd40aa27c 100644 --- a/sunshine/main.cpp +++ b/sunshine/main.cpp @@ -57,11 +57,15 @@ struct NoDelete { BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int) -void print_help(const char *name) { +/** Print the help to stdout. + + This function prints output to stdout. +*/ +void print_help() { std::cout - << "Usage: "sv << name << " [options] [/path/to/configuration_file] [--cmd]"sv << std::endl + << "Usage: "sv << PROJECT_NAME << " [options] [/path/to/configuration_file] [--cmd]"sv << std::endl << " Any configurable option can be overwritten with: \"name=value\""sv << std::endl - << std:endl + << std::endl << " Note: The configuration will be created if it doesn't exist."sv << std::endl << std::endl << " --help | print help"sv << std::endl @@ -77,15 +81,23 @@ void print_help(const char *name) { << std::endl; } +/** Call the print_help function. + + Calls the print_help function and then exits. +*/ namespace help { -int entry(const char *name, int argc, char *argv[]) { - print_help(name); +int entry(int argc, char *argv[]) { + print_help(); return 0; } } // namespace help +/** Print the version details to stdout. + + This function prints the version details to stdout and then exits. +*/ namespace version { -int entry(const char *name, int argc, char *argv[]) { +int entry(int argc, char *argv[]) { std::cout << PROJECT_NAME << " version: v" << PROJECT_VER << std::endl; return 0; } @@ -108,9 +120,9 @@ void on_signal(int sig, FN &&fn) { } namespace gen_creds { -int entry(const char *name, int argc, char *argv[]) { +int entry(int argc, char *argv[]) { if(argc < 2 || argv[0] == "help"sv || argv[1] == "help"sv) { - print_help(name); + print_help(); return 0; } @@ -120,7 +132,7 @@ int entry(const char *name, int argc, char *argv[]) { } } // namespace gen_creds -std::map> cmd_to_func { +std::map> cmd_to_func { { "creds"sv, gen_creds::entry }, { "help"sv, help::entry }, { "version"sv, version::entry } @@ -328,4 +340,4 @@ int write_file(const char *path, const std::string_view &contents) { std::uint16_t map_port(int port) { return (std::uint16_t)((int)config::sunshine.port + port); -} \ No newline at end of file +} From ced0029abc479d49263f6de34b1a81b812d4631e Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Thu, 28 Apr 2022 23:47:05 -0400 Subject: [PATCH 056/120] Remove unused argument --- sunshine/config.cpp | 6 +++--- sunshine/main.cpp | 2 +- sunshine/main.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sunshine/config.cpp b/sunshine/config.cpp index 6aaeb3058e2..022df5e2c08 100644 --- a/sunshine/config.cpp +++ b/sunshine/config.cpp @@ -863,7 +863,7 @@ int parse(int argc, char *argv[]) { auto line = argv[x]; if(line == "--help"sv) { - print_help(*argv); + print_help(); return 1; } else if(*line == '-') { @@ -875,7 +875,7 @@ int parse(int argc, char *argv[]) { break; } if(apply_flags(line + 1)) { - print_help(*argv); + print_help(); return -1; } } @@ -889,7 +889,7 @@ int parse(int argc, char *argv[]) { else { TUPLE_EL(var, 1, parse_option(line, line_end)); if(!var) { - print_help(*argv); + print_help(); return -1; } diff --git a/sunshine/main.cpp b/sunshine/main.cpp index 93bd40aa27c..5a52f4aa23a 100644 --- a/sunshine/main.cpp +++ b/sunshine/main.cpp @@ -229,7 +229,7 @@ int main(int argc, char *argv[]) { return 7; } - return fn->second(argv[0], config::sunshine.cmd.argc, config::sunshine.cmd.argv); + return fn->second(config::sunshine.cmd.argc, config::sunshine.cmd.argv); } task_pool.start(1); diff --git a/sunshine/main.h b/sunshine/main.h index aa9558b3c32..48cbc62f81b 100644 --- a/sunshine/main.h +++ b/sunshine/main.h @@ -24,7 +24,7 @@ extern boost::log::sources::severity_logger fatal; void log_flush(); -void print_help(const char *name); +void print_help(); std::string read_file(const char *path); int write_file(const char *path, const std::string_view &contents); From e8ef7080347d452019e3b37d998e6cd3d0680771 Mon Sep 17 00:00:00 2001 From: Michael Rogers Date: Mon, 11 Apr 2022 18:09:51 -0500 Subject: [PATCH 057/120] Fix virtual sink overriding config sink. --- sunshine/audio.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sunshine/audio.cpp b/sunshine/audio.cpp index 4279eb4cbf3..3cc0e5e0cb6 100644 --- a/sunshine/audio.cpp +++ b/sunshine/audio.cpp @@ -135,9 +135,14 @@ void capture(safe::mail_t mail, config_t config, void *channel_data) { return; } - std::string *sink = - config::audio.sink.empty() ? &ref->sink.host : &config::audio.sink; - if(ref->sink.null) { + // Order of priorty: + // 1. Config + // 2. Virtual if available + // 3. Host + std::string *sink = &ref->sink.host; + if(!config::audio.sink.empty()) { + sink = &config::audio.sink; + } else if(ref->sink.null) { auto &null = *ref->sink.null; switch(stream->channelCount) { case 2: From 62ca9c31a07a7205c8b7d4af367a18cb2a80aff7 Mon Sep 17 00:00:00 2001 From: Michael Rogers Date: Mon, 11 Apr 2022 18:11:06 -0500 Subject: [PATCH 058/120] Updated the linux for better pulse behavior. --- sunshine/platform/linux/audio.cpp | 97 ++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 16 deletions(-) diff --git a/sunshine/platform/linux/audio.cpp b/sunshine/platform/linux/audio.cpp index c210da246b0..7b6f9c6ce48 100644 --- a/sunshine/platform/linux/audio.cpp +++ b/sunshine/platform/linux/audio.cpp @@ -65,7 +65,7 @@ struct mic_attr_t : public mic_t { } }; -std::unique_ptr microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) { +std::unique_ptr microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size, std::string source_name) { auto mic = std::make_unique(); pa_sample_spec ss { PA_SAMPLE_S16LE, sample_rate, (std::uint8_t)channels }; @@ -81,14 +81,9 @@ std::unique_ptr microphone(const std::uint8_t *mapping, int channels, std int status; - const char *audio_sink = "@DEFAULT_MONITOR@"; - if(!config::audio.sink.empty()) { - audio_sink = config::audio.sink.c_str(); - } - mic->mic.reset( pa_simple_new(nullptr, "sunshine", - pa_stream_direction_t::PA_STREAM_RECORD, audio_sink, + pa_stream_direction_t::PA_STREAM_RECORD, source_name.c_str(), "sunshine-record", &ss, &pa_map, &pa_attr, &status)); if(!mic->mic) { @@ -128,6 +123,18 @@ using loop_t = util::safe_ptr; using op_t = util::safe_ptr; using string_t = util::safe_ptr>; +template +using cb_simple_t = std::function i)>; + +template +void cb(ctx_t::pointer ctx, add_const_t i, void *userdata) { + auto &f = *(cb_simple_t *)userdata; + + // Cannot similarly filter on eol here. Unless reported otherwise assume + // we have no need for special filtering like cb? + f(ctx, i); +} + template using cb_t = std::function i, int eol)>; @@ -172,6 +179,7 @@ class server_t : public audio_control_t { public: loop_t loop; ctx_t ctx; + std::string requested_sink; struct { std::uint32_t stereo = PA_INVALID_INDEX; @@ -287,8 +295,6 @@ class server_t : public audio_control_t { sink_t sink; - // If hardware sink with more channels found, set that as host - int channels = 0; // Count of all virtual sinks that are created by us int nullcount = 0; @@ -304,11 +310,6 @@ class server_t : public audio_control_t { return; } - if(sink_info->active_port != nullptr) { - sink.host = sink_info->name; - channels = sink_info->channel_map.channels; - } - // Ensure Sunshine won't create a sink that already exists. if(!std::strcmp(sink_info->name, stereo)) { index.stereo = sink_info->owner_module; @@ -341,8 +342,11 @@ class server_t : public audio_control_t { return std::nullopt; } - if(!channels) { + auto sink_name = get_default_sink_name(); + if(sink_name.empty()) { BOOST_LOG(warning) << "Couldn't find an active sink"sv; + } else { + sink.host = sink_name; } if(index.stereo == PA_INVALID_INDEX) { @@ -382,13 +386,72 @@ class server_t : public audio_control_t { return std::make_optional(std::move(sink)); } + std::string get_default_sink_name() { + std::string sink_name = "@DEFAULT_SINK@"s; + auto alarm = safe::make_alarm(); + + cb_simple_t server_f = [&](ctx_t::pointer ctx, const pa_server_info *server_info) { + if(!server_info) { + BOOST_LOG(error) << "Couldn't get pulseaudio server info: "sv << pa_strerror(pa_context_errno(ctx)); + alarm->ring(-1); + } + + sink_name = server_info->default_sink_name; + alarm->ring(0); + }; + + op_t server_op { pa_context_get_server_info(ctx.get(), cb, &server_f) }; + alarm->wait(); + // No need to check status. If it failed just return default name. + return sink_name; + } + + std::string get_monitor_name(const std::string &sink_name) { + std::string monitor_name = "@DEFAULT_MONITOR@"s; + auto alarm = safe::make_alarm(); + + cb_t sink_f = [&](ctx_t::pointer ctx, const pa_sink_info *sink_info, int eol) { + if(!sink_info) { + if(!eol) { + BOOST_LOG(error) << "Couldn't get pulseaudio sink info for ["sv << sink_name + << "]: "sv << pa_strerror(pa_context_errno(ctx)); + alarm->ring(-1); + } + + alarm->ring(0); + return; + } + + monitor_name = sink_info->monitor_source_name; + }; + + op_t sink_op { pa_context_get_sink_info_by_name(ctx.get(), sink_name.c_str(), cb, &sink_f) }; + + alarm->wait(); + // No need to check status. If it failed just return default name. + BOOST_LOG(info) << "Found default monitor by name: "sv << monitor_name; + return monitor_name; + } + std::unique_ptr microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) override { - return ::platf::microphone(mapping, channels, sample_rate, frame_size); + // Sink choice priority: + // 1. Config sink + // 2. Last sink swapped to (Usually virtual in this case) + // 3. Default Sink + // An attempt was made to always use default to match the switching mechanic, + // but this happens right after the swap so the default returned by PA was not + // the new one just set! + auto sink_name = config::audio.sink; + if(sink_name.empty()) sink_name = requested_sink; + if(sink_name.empty()) sink_name = get_default_sink_name(); + + return ::platf::microphone(mapping, channels, sample_rate, frame_size, get_monitor_name(sink_name)); } int set_sink(const std::string &sink) override { auto alarm = safe::make_alarm(); + BOOST_LOG(info) << "Setting default sink to: ["sv << sink << "]"sv; op_t op { pa_context_set_default_sink( ctx.get(), sink.c_str(), success_cb, alarm.get()), @@ -406,6 +469,8 @@ class server_t : public audio_control_t { return -1; } + requested_sink = sink; + return 0; } From bd033f9e1515bda072d48c0006598f2b21521ab7 Mon Sep 17 00:00:00 2001 From: Michael Rogers Date: Mon, 11 Apr 2022 18:12:11 -0500 Subject: [PATCH 059/120] Fixed formatting. --- sunshine/platform/linux/audio.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sunshine/platform/linux/audio.cpp b/sunshine/platform/linux/audio.cpp index 7b6f9c6ce48..2770e515732 100644 --- a/sunshine/platform/linux/audio.cpp +++ b/sunshine/platform/linux/audio.cpp @@ -345,7 +345,8 @@ class server_t : public audio_control_t { auto sink_name = get_default_sink_name(); if(sink_name.empty()) { BOOST_LOG(warning) << "Couldn't find an active sink"sv; - } else { + } + else { sink.host = sink_name; } @@ -438,13 +439,13 @@ class server_t : public audio_control_t { // 1. Config sink // 2. Last sink swapped to (Usually virtual in this case) // 3. Default Sink - // An attempt was made to always use default to match the switching mechanic, - // but this happens right after the swap so the default returned by PA was not + // An attempt was made to always use default to match the switching mechanic, + // but this happens right after the swap so the default returned by PA was not // the new one just set! auto sink_name = config::audio.sink; if(sink_name.empty()) sink_name = requested_sink; if(sink_name.empty()) sink_name = get_default_sink_name(); - + return ::platf::microphone(mapping, channels, sample_rate, frame_size, get_monitor_name(sink_name)); } From 63a83cdf7a43a35c15c0556733ab43e4372e3a9e Mon Sep 17 00:00:00 2001 From: Michael Rogers Date: Mon, 11 Apr 2022 19:02:47 -0500 Subject: [PATCH 060/120] Fix formatting --- sunshine/audio.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sunshine/audio.cpp b/sunshine/audio.cpp index 3cc0e5e0cb6..2894d12884d 100644 --- a/sunshine/audio.cpp +++ b/sunshine/audio.cpp @@ -135,14 +135,15 @@ void capture(safe::mail_t mail, config_t config, void *channel_data) { return; } - // Order of priorty: + // Order of priorty: // 1. Config // 2. Virtual if available // 3. Host std::string *sink = &ref->sink.host; if(!config::audio.sink.empty()) { sink = &config::audio.sink; - } else if(ref->sink.null) { + } + else if(ref->sink.null) { auto &null = *ref->sink.null; switch(stream->channelCount) { case 2: From aa46b8e293f065946df84238c71b7347e347e7db Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 29 Apr 2022 12:52:09 -0400 Subject: [PATCH 061/120] Revert removing `name` argument from `print_help` function - The existing method is better because it uses the binary name instead of the project name `Sunshine`. --- sunshine/config.cpp | 6 +++--- sunshine/main.cpp | 18 +++++++++--------- sunshine/main.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/sunshine/config.cpp b/sunshine/config.cpp index 022df5e2c08..6aaeb3058e2 100644 --- a/sunshine/config.cpp +++ b/sunshine/config.cpp @@ -863,7 +863,7 @@ int parse(int argc, char *argv[]) { auto line = argv[x]; if(line == "--help"sv) { - print_help(); + print_help(*argv); return 1; } else if(*line == '-') { @@ -875,7 +875,7 @@ int parse(int argc, char *argv[]) { break; } if(apply_flags(line + 1)) { - print_help(); + print_help(*argv); return -1; } } @@ -889,7 +889,7 @@ int parse(int argc, char *argv[]) { else { TUPLE_EL(var, 1, parse_option(line, line_end)); if(!var) { - print_help(); + print_help(*argv); return -1; } diff --git a/sunshine/main.cpp b/sunshine/main.cpp index 5a52f4aa23a..0f5581d6f03 100644 --- a/sunshine/main.cpp +++ b/sunshine/main.cpp @@ -61,9 +61,9 @@ BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int) This function prints output to stdout. */ -void print_help() { +void print_help(const char *name) { std::cout - << "Usage: "sv << PROJECT_NAME << " [options] [/path/to/configuration_file] [--cmd]"sv << std::endl + << "Usage: "sv << name << " [options] [/path/to/configuration_file] [--cmd]"sv << std::endl << " Any configurable option can be overwritten with: \"name=value\""sv << std::endl << std::endl << " Note: The configuration will be created if it doesn't exist."sv << std::endl @@ -86,8 +86,8 @@ void print_help() { Calls the print_help function and then exits. */ namespace help { -int entry(int argc, char *argv[]) { - print_help(); +int entry(const char *name, int argc, char *argv[]) { + print_help(name); return 0; } } // namespace help @@ -97,7 +97,7 @@ int entry(int argc, char *argv[]) { This function prints the version details to stdout and then exits. */ namespace version { -int entry(int argc, char *argv[]) { +int entry(const char *name, int argc, char *argv[]) { std::cout << PROJECT_NAME << " version: v" << PROJECT_VER << std::endl; return 0; } @@ -120,9 +120,9 @@ void on_signal(int sig, FN &&fn) { } namespace gen_creds { -int entry(int argc, char *argv[]) { +int entry(const char *name, int argc, char *argv[]) { if(argc < 2 || argv[0] == "help"sv || argv[1] == "help"sv) { - print_help(); + print_help(name); return 0; } @@ -132,7 +132,7 @@ int entry(int argc, char *argv[]) { } } // namespace gen_creds -std::map> cmd_to_func { +std::map> cmd_to_func { { "creds"sv, gen_creds::entry }, { "help"sv, help::entry }, { "version"sv, version::entry } @@ -229,7 +229,7 @@ int main(int argc, char *argv[]) { return 7; } - return fn->second(config::sunshine.cmd.argc, config::sunshine.cmd.argv); + return fn->second(argv[0], config::sunshine.cmd.argc, config::sunshine.cmd.argv); } task_pool.start(1); diff --git a/sunshine/main.h b/sunshine/main.h index 48cbc62f81b..aa9558b3c32 100644 --- a/sunshine/main.h +++ b/sunshine/main.h @@ -24,7 +24,7 @@ extern boost::log::sources::severity_logger fatal; void log_flush(); -void print_help(); +void print_help(const char *name); std::string read_file(const char *path); int write_file(const char *path, const std::string_view &contents); From b0a02a5985828952c94eedfd8f7108e44d1b7aec Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 29 Apr 2022 19:02:10 -0400 Subject: [PATCH 062/120] Do not fail workflow if `sunshine.po` doesn't exist - Add proper keywords for boost::locale - Minor documentation updates about localization --- .github/workflows/localize.yml | 17 ++++++- docs/source/contributing/localization.rst | 6 ++- scripts/_locale.py | 56 ++++++++++++++--------- 3 files changed, 55 insertions(+), 24 deletions(-) diff --git a/.github/workflows/localize.yml b/.github/workflows/localize.yml index a017efab7ef..31f2299738b 100644 --- a/.github/workflows/localize.yml +++ b/.github/workflows/localize.yml @@ -9,6 +9,9 @@ on: - 'locale/sunshine.po' workflow_dispatch: +env: + file: ./locale/sunshine.po + jobs: localize: name: Update Localization @@ -37,9 +40,20 @@ jobs: - name: Update Strings run: | + # first, try to remove existing file as xgettext does not remove unused translations + if [ -f "${{ env.file }}" ]; + then + rm ${{ env.file }} + echo "new_file=false" >> $GITHUB_ENV + else + echo "new_file=true" >> $GITHUB_ENV + fi + + # extract the new strings python ./scripts/_locale.py --extract - name: git diff + if: ${{ env.new_file == 'false' }} run: | # disable the pager git config --global pager.diff false @@ -52,7 +66,8 @@ jobs: echo "git_diff=${OUTPUT}" >> $GITHUB_ENV - name: git reset - if: ${{ env.git_diff == '1 1 locale/sunshine.po' }} # only run if more than 1 line changed + # only run if a single line changed (date/time) and file already existed + if: ${{ env.git_diff == '1 1 locale/sunshine.po' && env.new_file == 'false' }} run: | git reset --hard diff --git a/docs/source/contributing/localization.rst b/docs/source/contributing/localization.rst index 721ebc61c1e..8127eda3d53 100644 --- a/docs/source/contributing/localization.rst +++ b/docs/source/contributing/localization.rst @@ -54,6 +54,9 @@ situations. For example if a system tray icon is added it should be localized as #include boost::locale::translate("Hello world!") + .. Tip:: More examples can be found in the documentation for + `boost locale `_. + .. Warning:: This is for information only. Contributors should never include manually updated template files, or manually compiled language files in Pull Requests. @@ -67,7 +70,8 @@ any of the following paths are modified. - 'sunshine/**' When testing locally it may be desirable to manually extract, initialize, update, and compile strings. Python is -required for this, along with the dependencies in the `./scripts/requirements.txt` file. +required for this, along with the python dependencies in the `./scripts/requirements.txt` file. Additionally, +`xgettext `_ must be installed. Extract, initialize, and update .. code-block:: bash diff --git a/scripts/_locale.py b/scripts/_locale.py index e47887cc964..339e2d4aea9 100644 --- a/scripts/_locale.py +++ b/scripts/_locale.py @@ -13,6 +13,7 @@ import subprocess project_name = 'Sunshine' +project_owner = 'SunshineStream' script_dir = os.path.dirname(os.path.abspath(__file__)) root_dir = os.path.dirname(script_dir) @@ -37,22 +38,30 @@ def x_extract(): """Executes `xgettext extraction` in subprocess.""" + pot_filepath = os.path.join(locale_dir, f'{project_name.lower()}.po') + commands = [ 'xgettext', + '--keyword=translate:1,1t', + '--keyword=translate:1c,2,2t', + '--keyword=translate:1,2,3t', + '--keyword=translate:1c,2,3,4t', + '--keyword=gettext:1', + '--keyword=pgettext:1c,2', + '--keyword=ngettext:1,2', + '--keyword=npgettext:1c,2,3', f'--default-domain={project_name.lower()}', - f'--output={os.path.join(locale_dir, project_name.lower() + ".po")}', + f'--output={pot_filepath}', '--language=C++', '--boost', '--from-code=utf-8', '-F', - f'--msgid-bugs-address=github.com/{project_name.lower()}', - f'--copyright-holder={project_name}', + f'--msgid-bugs-address=github.com/{project_owner.lower()}/{project_name.lower()}', + f'--copyright-holder={project_owner}', f'--package-name={project_name}', '--package-version=v0' ] - pot_filepath = os.path.join(locale_dir, f'{project_name.lower()}.po') - extensions = ['cpp', 'h', 'm', 'mm'] # find input files @@ -66,23 +75,26 @@ def x_extract(): print(commands) subprocess.check_output(args=commands, cwd=root_dir) - # fix header - body = "" - with open(file=pot_filepath, mode='r') as file: - for line in file.readlines(): - if line != '"Language: \\n"\n': # do not include this line - if line == '# SOME DESCRIPTIVE TITLE.\n': - body += f'# Translations template for {project_name}.\n' - elif line.startswith('#') and 'YEAR' in line: - body += line.replace('YEAR', str(year)) - elif line.startswith('#') and 'PACKAGE' in line: - body += line.replace('PACKAGE', project_name) - else: - body += line - - # rewrite pot file with updated header - with open(file=pot_filepath, mode='w+') as file: - file.write(body) + try: + # fix header + body = "" + with open(file=pot_filepath, mode='r') as file: + for line in file.readlines(): + if line != '"Language: \\n"\n': # do not include this line + if line == '# SOME DESCRIPTIVE TITLE.\n': + body += f'# Translations template for {project_name}.\n' + elif line.startswith('#') and 'YEAR' in line: + body += line.replace('YEAR', str(year)) + elif line.startswith('#') and 'PACKAGE' in line: + body += line.replace('PACKAGE', project_name) + else: + body += line + + # rewrite pot file with updated header + with open(file=pot_filepath, mode='w+') as file: + file.write(body) + except FileNotFoundError: + pass def babel_init(locale_code: str): From c4977b5393e6a266467bb9261b7866f6384cd798 Mon Sep 17 00:00:00 2001 From: ABeltramo Date: Sat, 23 Apr 2022 10:48:05 +0100 Subject: [PATCH 063/120] WIP: Moving to cpack in order to unify installers across all platforms --- CMakeLists.txt | 62 ++++++++++++- assets/linux-deb/conffiles | 2 + assets/linux-deb/postinst | 41 +++++++++ assets/linux-deb/preinst | 9 ++ gen-deb.in | 123 ------------------------- gen-rpm.in | 179 ------------------------------------- 6 files changed, 112 insertions(+), 304 deletions(-) create mode 100644 assets/linux-deb/conffiles create mode 100644 assets/linux-deb/postinst create mode 100644 assets/linux-deb/preinst delete mode 100755 gen-deb.in delete mode 100755 gen-rpm.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 862e4f1ae3b..291a6f2eb35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -312,8 +312,6 @@ else() if(NOT DEFINED SUNSHINE_EXECUTABLE_PATH) set(SUNSHINE_EXECUTABLE_PATH "sunshine") endif() - configure_file(gen-deb.in gen-deb @ONLY) - configure_file(gen-rpm.in gen-rpm @ONLY) configure_file(sunshine.desktop.in sunshine.desktop @ONLY) configure_file(sunshine.service.in sunshine.service @ONLY) endif() @@ -448,3 +446,63 @@ foreach(flag IN LISTS SUNSHINE_COMPILE_OPTIONS) endforeach() target_compile_options(sunshine PRIVATE $<$:${SUNSHINE_COMPILE_OPTIONS}>;$<$:${SUNSHINE_COMPILE_OPTIONS_CUDA};-std=c++17>) + +############# +# CPACK +#### + +# Add all assets dependencies +install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION ".") +install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION ".") +if(WIN32) # TODO: test + install(TARGETS sunshine RUNTIME DESTINATION ".") + + install(FILES "${SUNSHINE_ASSETS_DIR}/apps_windows.json" DESTINATION ".") + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/directx" DESTINATION "shaders") +endif() +if(APPLE) # TODO: test + install(TARGETS sunshine RUNTIME DESTINATION ".") + + install(FILES "${SUNSHINE_ASSETS_DIR}/apps_mac.json" DESTINATION ".") + # TODO: info.plist ?? +endif() +if(UNIX AND NOT APPLE) + install(FILES "${SUNSHINE_ASSETS_DIR}/apps_linux.json" DESTINATION ".") + install(FILES "${SUNSHINE_ASSETS_DIR}/85-sunshine-rules.rules" DESTINATION "/etc/udev/rules.d") + install(TARGETS sunshine RUNTIME DESTINATION "/usr/bin") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" DESTINATION "/usr/lib/systemd/user") + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/opengl" DESTINATION "shaders") + + # Pre and post install + set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA + "${SUNSHINE_ASSETS_DIR}/linux-deb/preinst;${SUNSHINE_ASSETS_DIR}/linux-deb/postinst;${SUNSHINE_ASSETS_DIR}/linux-deb/conffiles") + set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE "${SUNSHINE_ASSETS_DIR}/linux-deb/preinst") + set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${SUNSHINE_ASSETS_DIR}/linux-deb/postinst") +endif() + +# Common options +set(CPACK_PACKAGE_NAME "SunshineStream") +set(CPACK_PACKAGE_VENDOR "CMake.org") +set(CPACK_PACKAGE_CONTACT "https://github.com/SunshineStream/Sunshine") +set(CPACK_DEBIAN_PACKAGE_MAINTAINER "https://github.com/SunshineStream/Sunshine") +set(CPACK_PACKAGE_DESCRIPTION "Gamestream host for Moonlight") +set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/SunshineStream/Sunshine") +set(CPACK_RESOURCE_FILE_LICENSE ${PROJECT_SOURCE_DIR}/LICENSE) +set(CPACK_PACKAGE_ICON ${PROJECT_SOURCE_DIR}/sunshine.png) +set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") +set(CPACK_STRIP_FILES YES) + +# Installation destination dir +if(NOT WIN32) + set(CPACK_SET_DESTDIR true) +endif() +if(UNIX AND NOT APPLE) + set(CMAKE_INSTALL_PREFIX "/etc/sunshine") +endif() + +## DEB +set(CPACK_DEB_COMPONENT_INSTALL ON) +set(CPACK_DEBIAN_PACKAGE_DEPENDS "libssl1.1, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2") +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF) + +include(CPack) \ No newline at end of file diff --git a/assets/linux-deb/conffiles b/assets/linux-deb/conffiles new file mode 100644 index 00000000000..78176a81021 --- /dev/null +++ b/assets/linux-deb/conffiles @@ -0,0 +1,2 @@ +/etc/sunshine/sunshine.conf +/etc/sunshine/apps_linux.json diff --git a/assets/linux-deb/postinst b/assets/linux-deb/postinst new file mode 100644 index 00000000000..cf66231fd26 --- /dev/null +++ b/assets/linux-deb/postinst @@ -0,0 +1,41 @@ +#!/bin/sh + +export GROUP_INPUT=input + +if [ -f /etc/group ]; then + if ! grep -q $GROUP_INPUT /etc/group; then + echo "Creating group $GROUP_INPUT" + + groupadd $GROUP_INPUT + fi +else + echo "Warning: /etc/group not found" +fi + +if [ -f /etc/sunshine/sunshine.conf.old ]; then + echo "Restoring old sunshine.conf" + mv /etc/sunshine/sunshine.conf.old /etc/sunshine/sunshine.conf +fi + +if [ -f /etc/sunshine/apps_linux.json.old ]; then + echo "Restoring old apps_linux.json" + mv /etc/sunshine/apps_linux.json.old /etc/sunshine/apps_linux.json +fi + +# Update permissions on config files for Web Manager +if [ -f /etc/sunshine/apps_linux.json ]; then + echo "chmod 666 /etc/sunshine/apps_linux.json" + chmod 666 /etc/sunshine/apps_linux.json +fi + +if [ -f /etc/sunshine/sunshine.conf ]; then + echo "chmod 666 /etc/sunshine/sunshine.conf" + chmod 666 /etc/sunshine/sunshine.conf +fi + +# Ensure Sunshine can grab images from KMS +path_to_setcap=$(which setcap) +if [ -x "$path_to_setcap" ] ; then + echo "$path_to_setcap cap_sys_admin+p /usr/bin/sunshine" + $path_to_setcap cap_sys_admin+p $(readlink -f /usr/bin/sunshine) +fi diff --git a/assets/linux-deb/preinst b/assets/linux-deb/preinst new file mode 100644 index 00000000000..515d1a34ca5 --- /dev/null +++ b/assets/linux-deb/preinst @@ -0,0 +1,9 @@ +#!/bin/sh +#Store backup for old config files to prevent it from being overwritten +if [ -f /etc/sunshine/sunshine.conf ]; then + cp /etc/sunshine/sunshine.conf /etc/sunshine/sunshine.conf.old +fi + +if [ -f /etc/sunshine/apps_linux.json ]; then + cp /etc/sunshine/apps_linux.json /etc/sunshine/apps_linux.json.old +fi diff --git a/gen-deb.in b/gen-deb.in deleted file mode 100755 index 25ca36096f9..00000000000 --- a/gen-deb.in +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/sh - -if [ ! "@SUNSHINE_UNDEFINED_VARIABLE@" = "" ]; then - echo "Please run gen-deb generated by cmake inside the build directory" - exit 1 -fi - -if [ -d package-deb ]; then - echo "package-deb already exists: It will be replaced" - rm -rf package-deb -fi - -export DEBIAN=@CMAKE_CURRENT_BINARY_DIR@/package-deb/sunshine/DEBIAN -export RULES=@CMAKE_CURRENT_BINARY_DIR@/package-deb/sunshine/etc/udev/rules.d -export BIN=@CMAKE_CURRENT_BINARY_DIR@/package-deb/sunshine/usr/bin -export SERVICE=@CMAKE_CURRENT_BINARY_DIR@/package-deb/sunshine/usr/lib/systemd/user -export ASSETS=@CMAKE_CURRENT_BINARY_DIR@/package-deb/sunshine/etc/sunshine - -mkdir -p $DEBIAN -mkdir -p $RULES -mkdir -p $BIN -mkdir -p $ASSETS/shaders -mkdir -p $SERVICE - -if [ ! -f sunshine ]; then - echo "Error: Can't find sunshine" - exit 1 -fi - -cat << 'EOF' > $DEBIAN/conffiles -/etc/sunshine/sunshine.conf -/etc/sunshine/apps_linux.json -EOF - -cat << 'EOF' > $DEBIAN/control -Package: sunshine -Architecture: amd64 -Maintainer: @loki -Priority: optional -Version: @PROJECT_VERSION@ -Depends: libssl1.1, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2 -Description: Gamestream host for Moonlight -EOF - -cat << 'EOF' > $DEBIAN/preinst -#Store backup for old config files to prevent it from being overwritten -if [ -f /etc/sunshine/sunshine.conf ]; then - cp /etc/sunshine/sunshine.conf /etc/sunshine/sunshine.conf.old -fi - -if [ -f /etc/sunshine/apps_linux.json ]; then - cp /etc/sunshine/apps_linux.json /etc/sunshine/apps_linux.json.old -fi -EOF - -cat << 'EOF' > $DEBIAN/postinst -#!/bin/sh - -export GROUP_INPUT=input - -if [ -f /etc/group ]; then - if ! grep -q $GROUP_INPUT /etc/group; then - echo "Creating group $GROUP_INPUT" - - groupadd $GROUP_INPUT - fi -else - echo "Warning: /etc/group not found" -fi - -if [ -f /etc/sunshine/sunshine.conf.old ]; then - echo "Restoring old sunshine.conf" - mv /etc/sunshine/sunshine.conf.old /etc/sunshine/sunshine.conf -fi - -if [ -f /etc/sunshine/apps_linux.json.old ]; then - echo "Restoring old apps_linux.json" - mv /etc/sunshine/apps_linux.json.old /etc/sunshine/apps_linux.json -fi - -# Update permissions on config files for Web Manager -if [ -f /etc/sunshine/apps_linux.json ]; then - echo "chmod 666 /etc/sunshine/apps_linux.json" - chmod 666 /etc/sunshine/apps_linux.json -fi - -if [ -f /etc/sunshine/sunshine.conf ]; then - echo "chmod 666 /etc/sunshine/sunshine.conf" - chmod 666 /etc/sunshine/sunshine.conf -fi - -# Ensure Sunshine can grab images from KMS -path_to_setcap=$(which setcap) -if [ -x "$path_to_setcap" ] ; then - echo "$path_to_setcap cap_sys_admin+p /usr/bin/sunshine" - $path_to_setcap cap_sys_admin+p /usr/bin/sunshine -fi -EOF - -cat << 'EOF' > $RULES/85-sunshine-rules.rules -KERNEL=="uinput", GROUP="input", MODE="0660" -EOF - -cp sunshine $BIN/sunshine -cp @CMAKE_CURRENT_SOURCE_DIR@/assets/apps_linux.json $ASSETS/apps_linux.json -cp @CMAKE_CURRENT_SOURCE_DIR@/assets/sunshine.conf $ASSETS/sunshine.conf -cp @CMAKE_CURRENT_BINARY_DIR@/sunshine.service $SERVICE/sunshine.service -cp -r @CMAKE_CURRENT_SOURCE_DIR@/assets/web $ASSETS/web -cp -r @CMAKE_CURRENT_SOURCE_DIR@/assets/shaders/opengl $ASSETS/shaders/opengl - -chmod 755 $DEBIAN/postinst -chmod 755 $DEBIAN/preinst -chmod 755 $BIN/sunshine -chmod 644 $RULES/85-sunshine-rules.rules -chmod 666 $ASSETS/apps_linux.json -chmod 666 $ASSETS/sunshine.conf - -cd package-deb -if fakeroot dpkg-deb --build sunshine; then - echo "generated debian package: @CMAKE_CURRENT_BINARY_DIR@/package-deb/sunshine.deb" -fi -cd .. - diff --git a/gen-rpm.in b/gen-rpm.in deleted file mode 100755 index 792a3895573..00000000000 --- a/gen-rpm.in +++ /dev/null @@ -1,179 +0,0 @@ -#!/bin/sh - -# Export filepaths -export BUILDDIR=@CMAKE_CURRENT_SOURCE_DIR@/build -export BUILDROOT=~/rpmbuild/ -export RPMSRC=~/rpmbuild/SOURCES -export RPMSPEC=~/rpmbuild/SPECS -export RPMBUILD=~/rpmbuild/BUILD - -# Check for Docker switch -if [ "$1" == "-d" ]; then - export DOCKERSTATUS=TRUE -else - export DOCKERSTATUS=FALSE -fi - -# Check if user's rpmbuild folder is there, if so, temoprairly rename it. -if [ -d ~/rpmbuild ]; then - echo "Backing up rpmbuild" - ~/rpmbuild ~/rpmbuild.bkp - export RPMBUILDEXISTS=TRUE -else - export RPMBUILDEXISTS=FALSE -fi - -# Create rpmbuild folder structure -mkdir ~/rpmbuild -mkdir ~/rpmbuild/BUILD -mkdir ~/rpmbuild/BUILDROOT -mkdir ~/rpmbuild/RPMS -mkdir ~/rpmbuild/SOURCES -mkdir ~/rpmbuild/SPECS -mkdir ~/rpmbuild/SRPMS - -# Create sunshine .spec file with preinstall and postinstall scripts -cat << 'EOF' > $RPMSPEC/sunshine.spec -Name: sunshine -Version: @PROJECT_VERSION@ -Release: 1%{?dist} -Summary: An NVIDIA Gamestream-compatible hosting server -BuildArch: x86_64 - -License: GPLv3 -URL: https://github.com/SunshineStream/Sunshine -Source0: sunshine-@PROJECT_VERSION@_bin.tar.gz - -Requires: systemd ffmpeg rpmfusion-free-release - -%description -An NVIDIA Gamestream-compatible hosting server - -%pre -#!/bin/sh - -# Sunshine Pre-Install Script -# Store backup for old config files to prevent it from being overwritten -if [ -f /etc/sunshine/sunshine.conf ]; then - cp /etc/sunshine/sunshine.conf /etc/sunshine/sunshine.conf.old -fi - -if [ -f /etc/sunshine/apps_linux.json ]; then - cp /etc/sunshine/apps_linux.json /etc/sunshine/apps_linux.json.old -fi - -%post -#!/bin/sh - -# Sunshine Post-Install Script -export GROUP_INPUT=input - -if [ -f /etc/group ]; then - if ! grep -q $GROUP_INPUT /etc/group; then - echo "Creating group $GROUP_INPUT" - - groupadd $GROUP_INPUT - fi -else - echo "Warning: /etc/group not found" -fi - -if [ -f /etc/sunshine/sunshine.conf.old ]; then - echo "Restoring old sunshine.conf" - mv /etc/sunshine/sunshine.conf.old /etc/sunshine/sunshine.conf -fi - -if [ -f /etc/sunshine/apps_linux.json.old ]; then - echo "Restoring old apps_linux.json" - mv /etc/sunshine/apps_linux.json.old /etc/sunshine/apps_linux.json -fi - -# Update permissions on config files for Web Manager -if [ -f /etc/sunshine/apps_linux.json ]; then - echo "chmod 666 /etc/sunshine/apps_linux.json" - chmod 666 /etc/sunshine/apps_linux.json -fi - -if [ -f /etc/sunshine/sunshine.conf ]; then - echo "chmod 666 /etc/sunshine/sunshine.conf" - chmod 666 /etc/sunshine/sunshine.conf -fi - -# Ensure Sunshine can grab images from KMS -path_to_setcap=$(which setcap) -if [ -x "$path_to_setcap" ] ; then - echo "$path_to_setcap cap_sys_admin+p /usr/bin/sunshine" - $path_to_setcap cap_sys_admin+p /usr/bin/sunshine -fi - -%prep -%setup -q - -%install -rm -rf $RPM_BUILD_ROOT -mkdir -p $RPM_BUILD_ROOT/%{_bindir} -mkdir -p $RPM_BUILD_ROOT/etc/sunshine -mkdir -p $RPM_BUILD_ROOT/usr/lib/systemd/user -mkdir -p $RPM_BUILD_ROOT/usr/share/applications -mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d - -cp sunshine $RPM_BUILD_ROOT/%{_bindir}/sunshine -cp sunshine.conf $RPM_BUILD_ROOT/etc/sunshine/sunshine.conf -cp apps_linux.json $RPM_BUILD_ROOT/etc/sunshine/apps_linux.json -cp sunshine.service $RPM_BUILD_ROOT/usr/lib/systemd/user/sunshine.service -cp sunshine.desktop $RPM_BUILD_ROOT/usr/share/applications/sunshine.desktop -cp 85-sunshine-rules.rules $RPM_BUILD_ROOT/etc/udev/rules.d/85-sunshine-rules.rules - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -%{_bindir}/sunshine -/usr/lib/systemd/user/sunshine.service -/etc/sunshine/sunshine.conf -/etc/sunshine/apps_linux.json -/usr/share/applications/sunshine.desktop -/etc/udev/rules.d/85-sunshine-rules.rules - -%changelog -* Sat Mar 12 2022 h <65380846+thatsysadmin@users.noreply.github.com> -- Initial packaging of Sunshine. -EOF - -# Copy over sunshine binary and supplemental files into rpmbuild/BUILD/ -mkdir genrpm -mkdir genrpm/sunshine-@PROJECT_VERSION@ -cp sunshine-@PROJECT_VERSION@ genrpm/sunshine-@PROJECT_VERSION@/sunshine -cp sunshine.service genrpm/sunshine-@PROJECT_VERSION@/sunshine.service -cp sunshine.desktop genrpm/sunshine-@PROJECT_VERSION@/sunshine.desktop -cp @CMAKE_CURRENT_SOURCE_DIR@/assets/sunshine.conf genrpm/sunshine-@PROJECT_VERSION@/sunshine.conf -cp @CMAKE_CURRENT_SOURCE_DIR@/assets/apps_linux.json genrpm/sunshine-@PROJECT_VERSION@/apps_linux.json -cp @CMAKE_CURRENT_SOURCE_DIR@/assets/85-sunshine-rules.rules genrpm/sunshine-@PROJECT_VERSION@/85-sunshine-rules.rules -cd genrpm - -# tarball everything as if it was a source file for rpmbuild -tar --create --file sunshine-@PROJECT_VERSION@_bin.tar.gz sunshine-@PROJECT_VERSION@/ -cp sunshine-@PROJECT_VERSION@_bin.tar.gz ~/rpmbuild/SOURCES - -# Use rpmbuild to build the RPM package. -rpmbuild -bb $RPMSPEC/sunshine.spec - -# Check if running in a CT -if [ "$DOCKERSTATUS" == "FALSE" ]; then - # Move the completed RPM into the cmake build folder - mv ~/rpmbuild/RPMS/x86_64/sunshine-@PROJECT_VERSION@-1.fc*.x86_64.rpm @CMAKE_CURRENT_BINARY_DIR@/ - echo "Moving completed RPM package into CMake build folder." -elif [ "$DOCKERSTATUS" == "TRUE" ]; then - # Move into pickup location - mkdir -p /root/sunshine-build/package-rpm/ - mv ~/rpmbuild/RPMS/x86_64/sunshine-@PROJECT_VERSION@-1.fc*.x86_64.rpm /root/sunshine-build/package-rpm/sunshine.rpm - echo "Moving completed RPM package for pickup." -fi - -# Clean up; delete the rpmbuild folder we created and move back the original one -if [ "$RPMBUILDEXISTS" == "TRUE" ]; then - echo "Removing and replacing original rpmbuild folder." - rm -rf ~/rpmbuild - mv ~/rpmbuild.bkp ~/rpmbuild -fi -exit 0 From 2ea414d1d4d6f152650b41d826c2196b14a47d42 Mon Sep 17 00:00:00 2001 From: ABeltramo Date: Sat, 23 Apr 2022 11:04:00 +0100 Subject: [PATCH 064/120] testing RPM package dependencies --- CMakeLists.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 291a6f2eb35..859b544a9e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -478,6 +478,12 @@ if(UNIX AND NOT APPLE) "${SUNSHINE_ASSETS_DIR}/linux-deb/preinst;${SUNSHINE_ASSETS_DIR}/linux-deb/postinst;${SUNSHINE_ASSETS_DIR}/linux-deb/conffiles") set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE "${SUNSHINE_ASSETS_DIR}/linux-deb/preinst") set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${SUNSHINE_ASSETS_DIR}/linux-deb/postinst") + + # Dependencies + set(CPACK_DEB_COMPONENT_INSTALL ON) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "libssl1.1, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2") + set(CPACK_RPM_PACKAGE_REQUIRES "libssl==1.1, libavdevice>=58, libboost-thread>=1.67.0, libboost-filesystem>=1.67.0, libboost-log>=1.67.0, libpulse>=0, libopus>=0, libxcb-shm>=0, libxcb-xfixes>=0, libxtst>=0, libevdev>=2.0, libdrm>=2.0, libcap>=2.0") + set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF) # endif() # Common options @@ -500,9 +506,4 @@ if(UNIX AND NOT APPLE) set(CMAKE_INSTALL_PREFIX "/etc/sunshine") endif() -## DEB -set(CPACK_DEB_COMPONENT_INSTALL ON) -set(CPACK_DEBIAN_PACKAGE_DEPENDS "libssl1.1, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2") -set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF) - include(CPack) \ No newline at end of file From ffdcf0fea86bb046e329554d117510346c987d32 Mon Sep 17 00:00:00 2001 From: ABeltramo Date: Sat, 23 Apr 2022 15:13:27 +0100 Subject: [PATCH 065/120] feat: basic OSX .app generation added default brew link libraries path --- CMakeLists.txt | 40 ++++++++++++++++++++++++++-------------- sunshine.icns | Bin 0 -> 23711 bytes 2 files changed, 26 insertions(+), 14 deletions(-) create mode 100644 sunshine.icns diff --git a/CMakeLists.txt b/CMakeLists.txt index 859b544a9e1..d81bda12fb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,7 @@ if(WIN32) INPUT "${CMAKE_CURRENT_BINARY_DIR}/pre-compiled.zip" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/pre-compiled) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") - + if(NOT DEFINED SUNSHINE_PREPARED_BINARIES) set(SUNSHINE_PREPARED_BINARIES "${CMAKE_CURRENT_BINARY_DIR}/pre-compiled/windows") endif() @@ -127,8 +127,8 @@ if(WIN32) elseif(APPLE) add_compile_definitions(SUNSHINE_PLATFORM="macos") list(APPEND SUNSHINE_DEFINITIONS APPS_JSON="apps_mac.json") + link_directories(/opt/homebrew/lib/) # Default brew lib location link_directories(/opt/local/lib) - link_directories(/usr/local/lib) ADD_DEFINITIONS(-DBOOST_LOG_DYN_LINK) find_package(FFmpeg REQUIRED) @@ -296,14 +296,14 @@ else() third-party/glad/include/KHR/khrplatform.h third-party/glad/include/glad/gl.h third-party/glad/include/glad/egl.h) - + list(APPEND PLATFORM_LIBRARIES dl evdev pulse pulse-simple ) - + include_directories( /usr/include/libevdev-1.0 third-party/nv-codec-headers/include @@ -451,22 +451,36 @@ target_compile_options(sunshine PRIVATE $<$:${SUNSHINE_COM # CPACK #### -# Add all assets dependencies -install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION ".") -install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION ".") +# Add all assets dependencies if(WIN32) # TODO: test install(TARGETS sunshine RUNTIME DESTINATION ".") + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION ".") + install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION ".") install(FILES "${SUNSHINE_ASSETS_DIR}/apps_windows.json" DESTINATION ".") install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/directx" DESTINATION "shaders") endif() if(APPLE) # TODO: test - install(TARGETS sunshine RUNTIME DESTINATION ".") - install(FILES "${SUNSHINE_ASSETS_DIR}/apps_mac.json" DESTINATION ".") - # TODO: info.plist ?? + set(prefix "${CMAKE_PROJECT_NAME}.app/Contents") + set(INSTALL_RUNTIME_DIR "${prefix}/MacOS") + + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION "${INSTALL_RUNTIME_DIR}") + install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION "${INSTALL_RUNTIME_DIR}") + + install(TARGETS sunshine + BUNDLE DESTINATION . COMPONENT Runtime + RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} COMPONENT Runtime) + + # TODO: bundle doesn't produce a valid .app use cpack -G DragNDrop + # set(CPACK_BUNDLE_NAME "Sunshine") + # set(CPACK_BUNDLE_PLIST "${SUNSHINE_ASSETS_DIR}/info.plist") + # set(CPACK_BUNDLE_ICON "${PROJECT_SOURCE_DIR}/sunshine.icns") endif() if(UNIX AND NOT APPLE) + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION ".") + install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION ".") + install(FILES "${SUNSHINE_ASSETS_DIR}/apps_linux.json" DESTINATION ".") install(FILES "${SUNSHINE_ASSETS_DIR}/85-sunshine-rules.rules" DESTINATION "/etc/udev/rules.d") install(TARGETS sunshine RUNTIME DESTINATION "/usr/bin") @@ -474,7 +488,7 @@ if(UNIX AND NOT APPLE) install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/opengl" DESTINATION "shaders") # Pre and post install - set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA + set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${SUNSHINE_ASSETS_DIR}/linux-deb/preinst;${SUNSHINE_ASSETS_DIR}/linux-deb/postinst;${SUNSHINE_ASSETS_DIR}/linux-deb/conffiles") set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE "${SUNSHINE_ASSETS_DIR}/linux-deb/preinst") set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${SUNSHINE_ASSETS_DIR}/linux-deb/postinst") @@ -499,10 +513,8 @@ set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${VERSION}_${CPACK_DEBIAN_PAC set(CPACK_STRIP_FILES YES) # Installation destination dir -if(NOT WIN32) - set(CPACK_SET_DESTDIR true) -endif() if(UNIX AND NOT APPLE) + set(CPACK_SET_DESTDIR true) set(CMAKE_INSTALL_PREFIX "/etc/sunshine") endif() diff --git a/sunshine.icns b/sunshine.icns new file mode 100644 index 0000000000000000000000000000000000000000..0420582b244aa1599ebe86a9016d3113ef42c7cc GIT binary patch literal 23711 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 literal 0 HcmV?d00001 From e2bef750b4b3201be8ef6ee49a95263f025af05f Mon Sep 17 00:00:00 2001 From: ABeltramo Date: Wed, 27 Apr 2022 20:50:30 +0100 Subject: [PATCH 066/120] feat: created NSIS windows installer, fixed Linux packaging paths --- CMakeLists.txt | 99 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d81bda12fb3..4c19621ac45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -451,14 +451,71 @@ target_compile_options(sunshine PRIVATE $<$:${SUNSHINE_COM # CPACK #### -# Add all assets dependencies -if(WIN32) # TODO: test - install(TARGETS sunshine RUNTIME DESTINATION ".") - - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION ".") - install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION ".") - install(FILES "${SUNSHINE_ASSETS_DIR}/apps_windows.json" DESTINATION ".") - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/directx" DESTINATION "shaders") +# Common options +set(CPACK_PACKAGE_NAME "SunshineStream") +set(CPACK_PACKAGE_VENDOR "CMake.org") +set(CPACK_PACKAGE_CONTACT "https://github.com/SunshineStream/Sunshine") +set(CPACK_DEBIAN_PACKAGE_MAINTAINER "https://github.com/SunshineStream/Sunshine") +set(CPACK_PACKAGE_DESCRIPTION "Gamestream host for Moonlight") +set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/SunshineStream/Sunshine") +set(CPACK_RESOURCE_FILE_LICENSE ${PROJECT_SOURCE_DIR}/LICENSE) +set(CPACK_PACKAGE_ICON ${PROJECT_SOURCE_DIR}/sunshine.png) +set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") +set(CPACK_STRIP_FILES YES) + +# Platform specific options +if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.html + install(TARGETS sunshine RUNTIME DESTINATION "." COMPONENT application) + + # Adding tools + install(TARGETS dxgi-info RUNTIME DESTINATION "tools" COMPONENT dxgi) + install(TARGETS audio-info RUNTIME DESTINATION "tools" COMPONENT audio) + install(TARGETS sunshinesvc RUNTIME DESTINATION "tools" COMPONENT sunshinesvc) + + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT web) + install(FILES "${SUNSHINE_ASSETS_DIR}/apps_windows.json" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) + install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/directx" DESTINATION "${SUNSHINE_CONFIG_DIR}/shaders" COMPONENT assets) + + set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\sunshine.ico") + set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\\\${PROJECT_EXE}") + string(APPEND CPACK_NSIS_DEFINES "\n RequestExecutionLevel admin") # TODO: Not sure if this is needed but it took me a while to figure out where to put this option so I'm leaving it here + + # Sets permissions on the installed folder so that we can write in it + SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS + "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS} + ExecWait 'icacls \\\"$INSTDIR\\\" /grant:r Users:\\\(OI\\\)\\\(CI\\\)\\\(F\\\)' + ") + + # Adding an option for the start menu and PATH + set(CPACK_NSIS_MODIFY_PATH "OFF") # TODO: it asks to add it to the PATH but then it seems I can't just run it from powershell + set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") + set(CPACK_NSIS_MUI_FINISHPAGE_RUN "${PROJECT_NAME}.exe") + set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT_NAME}.exe") # This will be shown on the installed apps Windows settings + set(CPACK_NSIS_CREATE_ICONS "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${PROJECT_NAME}.lnk' '\$INSTDIR\\\\${PROJECT_NAME}.exe'") + + # Checking for previous installed versions + # set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL "ON") # TODO: doesn't work on my machine when Sunshine is already installed + + # Setting components groups and dependencies + set(CPACK_COMPONENT_APPLICATION_DISPLAY_NAME "Sunshine") + set(CPACK_COMPONENT_WEB_DISPLAY_NAME "Web interface") + set(CPACK_COMPONENT_ASSETS_DISPLAY_NAME "Extra assets files") + set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") + + set(CPACK_COMPONENT_APPLICATION_GROUP "Runtime") + set(CPACK_COMPONENT_WEB_GROUP "Runtime") + set(CPACK_COMPONENT_ASSETS_GROUP "Runtime") + + set(CPACK_COMPONENT_DXGI_DISPLAY_NAME "dxgi-info.exe") + set(CPACK_COMPONENT_AUDIO_DISPLAY_NAME "audio-info.exe") + set(CPACK_COMPONENT_SUNSHINESVC_DISPLAY_NAME "sunshinesvc.exe") + + set(CPACK_COMPONENT_DXGI_GROUP "Extra Tools") + set(CPACK_COMPONENT_AUDIO_GROUP "Extra Tools") + set(CPACK_COMPONENT_SUNSHINESVC_GROUP "Extra Tools") + + set(CPACK_COMPONENT_APPLICATION_DEPENDS web assets) endif() if(APPLE) # TODO: test @@ -478,14 +535,14 @@ if(APPLE) # TODO: test # set(CPACK_BUNDLE_ICON "${PROJECT_SOURCE_DIR}/sunshine.icns") endif() if(UNIX AND NOT APPLE) - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION ".") - install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION ".") + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION "${SUNSHINE_CONFIG_DIR}") + install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION "${SUNSHINE_CONFIG_DIR}") - install(FILES "${SUNSHINE_ASSETS_DIR}/apps_linux.json" DESTINATION ".") + install(FILES "${SUNSHINE_ASSETS_DIR}/apps_linux.json" DESTINATION "${SUNSHINE_CONFIG_DIR}") install(FILES "${SUNSHINE_ASSETS_DIR}/85-sunshine-rules.rules" DESTINATION "/etc/udev/rules.d") install(TARGETS sunshine RUNTIME DESTINATION "/usr/bin") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" DESTINATION "/usr/lib/systemd/user") - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/opengl" DESTINATION "shaders") + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/opengl" DESTINATION "${SUNSHINE_CONFIG_DIR}/shaders") # Pre and post install set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA @@ -497,23 +554,9 @@ if(UNIX AND NOT APPLE) set(CPACK_DEB_COMPONENT_INSTALL ON) set(CPACK_DEBIAN_PACKAGE_DEPENDS "libssl1.1, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2") set(CPACK_RPM_PACKAGE_REQUIRES "libssl==1.1, libavdevice>=58, libboost-thread>=1.67.0, libboost-filesystem>=1.67.0, libboost-log>=1.67.0, libpulse>=0, libopus>=0, libxcb-shm>=0, libxcb-xfixes>=0, libxtst>=0, libevdev>=2.0, libdrm>=2.0, libcap>=2.0") - set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF) # -endif() + set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF) # This should automatically figure out dependencies, doesn't work with the current config -# Common options -set(CPACK_PACKAGE_NAME "SunshineStream") -set(CPACK_PACKAGE_VENDOR "CMake.org") -set(CPACK_PACKAGE_CONTACT "https://github.com/SunshineStream/Sunshine") -set(CPACK_DEBIAN_PACKAGE_MAINTAINER "https://github.com/SunshineStream/Sunshine") -set(CPACK_PACKAGE_DESCRIPTION "Gamestream host for Moonlight") -set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/SunshineStream/Sunshine") -set(CPACK_RESOURCE_FILE_LICENSE ${PROJECT_SOURCE_DIR}/LICENSE) -set(CPACK_PACKAGE_ICON ${PROJECT_SOURCE_DIR}/sunshine.png) -set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") -set(CPACK_STRIP_FILES YES) - -# Installation destination dir -if(UNIX AND NOT APPLE) + # Installation destination dir set(CPACK_SET_DESTDIR true) set(CMAKE_INSTALL_PREFIX "/etc/sunshine") endif() From cc2d982cebee5cc19894ef2a23bf9fb29f88d638 Mon Sep 17 00:00:00 2001 From: ABeltramo Date: Wed, 27 Apr 2022 21:00:20 +0100 Subject: [PATCH 067/120] feat: testing out CI building for new packages --- .github/workflows/CI.yml | 56 ++++++++++++---------------------------- 1 file changed, 17 insertions(+), 39 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index b0be11308d8..e4a76c6e071 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -147,43 +147,29 @@ jobs: name: Linux runs-on: ubuntu-20.04 needs: check_changelog - strategy: - fail-fast: true # false to test all, true to fail entire job if any fail - matrix: - distro: [ debian, ubuntu_18_04, ubuntu_20_04, ubuntu_21_10 ] - package: [ -p ] - extension: [ deb ] - include: # package these differently - - distro: fedora_35 - package: '-p' - extension: rpm - steps: - name: Checkout uses: actions/checkout@v3 with: submodules: recursive - - name: Setup Container + - name: Build DEB and RPM run: | + mkdir -p build mkdir -p artifacts - - cd scripts - sudo ./build-container.sh -c build -f Dockerfile-${{ matrix.distro }} -n sunshine-${{ matrix.distro }} - - name: Build Linux - run: | - cd scripts - sudo ./build-sunshine.sh ${{ matrix.package }} -e ${{ matrix.extension }} -u -n sunshine-${{ matrix.distro }} -s .. - - name: Package Linux - if: ${{ matrix.package != '' }} - run: | - cd scripts - sudo mv ./sunshine-${{ matrix.distro }}-build/sunshine-${{ matrix.distro }}.${{ matrix.extension }} ../artifacts/ + cd build + + cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_CONFIG_DIR="." ../ + cpack -G DEB + cpack -G RPM + + cp Sunshine__.rpm ../artifacts/ + cp Sunshine__.deb ../artifacts/ - name: Upload Artifacts if: ${{ matrix.package == '-p' && ( github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' ) }} uses: actions/upload-artifact@v3 with: - name: sunshine-${{ matrix.distro }} + name: sunshine-linux path: artifacts/ - name: Create Release if: ${{ matrix.package == '-p' && github.event_name == 'push' && github.ref == 'refs/heads/master' }} @@ -218,6 +204,7 @@ jobs: mingw-w64-x86_64-opus mingw-w64-x86_64-x265 mingw-w64-x86_64-boost + mingw-w64-x86_64-nsis git yasm nasm @@ -226,23 +213,14 @@ jobs: - name: Build Windows shell: msys2 {0} run: | + mkdir artifacts + mkdir sunshine-windows-build && cd sunshine-windows-build cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=assets -G "MinGW Makefiles" .. mingw32-make -j2 - - name: Package Windows - run: | - cd sunshine-windows-build - del ..\assets\apps_linux.json - 7z a sunshine-windows.zip ..\assets - 7z a sunshine-windows.zip sunshine.exe - 7z a sunshine-windows.zip tools\dxgi-info.exe - 7z a sunshine-windows.zip tools\audio-info.exe - 7z a sunshine-windows.zip tools\sunshinesvc.exe - 7z a sunshine-windows.zip ..\tools\install-service.bat - 7z a sunshine-windows.zip ..\tools\uninstall-service.bat - cd .. - mkdir artifacts - move "sunshine-windows-build\sunshine-windows.zip" "artifacts" + cpack + + cp Sunshine__.exe ../artifacts - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 From 4e4a5c8df8c60dcf4fe2a409c4455c9786cc45ef Mon Sep 17 00:00:00 2001 From: ABeltramo Date: Fri, 29 Apr 2022 21:19:05 +0100 Subject: [PATCH 068/120] feat: testing out a better CI workflow --- .github/workflows/CI.yml | 162 ++++++++++++++++++++++++++------------- CMakeLists.txt | 2 +- 2 files changed, 110 insertions(+), 54 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index e4a76c6e071..b1503feb02d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -51,10 +51,60 @@ jobs: echo Within 'CMakeLists.txt' change "project(Sunshine VERSION $cmakelists_version)" to "project(Sunshine VERSION ${{ needs.check_changelog.outputs.next_version_bare }})" exit 1 + build_linux: + name: Build Sunshine on Linux + runs-on: ubuntu-20.04 + needs: check_changelog + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Cache Sunshine build + uses: actions/cache@v2 + with: + path: build + key: ${{ runner.os }}-sunshine-build + + - name: Setup Dependencies + run: | + mkdir -p artifacts + + sudo apt-get update -y && \ + sudo apt-get --reinstall install -y \ + git wget gcc-10 g++-10 build-essential cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev libwayland-dev + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 + sudo wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run && sudo chmod a+x /root/cuda.run + sudo /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && sudo rm /root/cuda.run + sudo add-apt-repository ppa:savoury1/graphics -y + sudo add-apt-repository ppa:savoury1/multimedia -y + sudo add-apt-repository ppa:savoury1/ffmpeg4 -y + sudo apt-get update -y + sudo apt-get upgrade -y && sudo apt-get dist-upgrade -y + sudo apt-get install ffmpeg -y + + - name: Build Sunshine + run: | + CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" + SUNSHINE_EXECUTABLE_PATH="${SUNSHINE_EXECUTABLE_PATH:-/usr/bin/sunshine}" + SUNSHINE_ASSETS_DIR="${SUNSHINE_ASSETS_DIR:-sunshine.AppImage.config}" + + SUNSHINE_ENABLE_WAYLAND=${SUNSHINE_ENABLE_WAYLAND:-ON} + SUNSHINE_ENABLE_X11=${SUNSHINE_ENABLE_X11:-ON} + SUNSHINE_ENABLE_DRM=${SUNSHINE_ENABLE_DRM:-ON} + SUNSHINE_ENABLE_CUDA=${SUNSHINE_ENABLE_CUDA:-ON} + + mkdir -p build + cd build + + cmake "-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE" "-DSUNSHINE_EXECUTABLE_PATH=$SUNSHINE_EXECUTABLE_PATH" "-DSUNSHINE_ASSETS_DIR=$SUNSHINE_ASSETS_DIR" "-DSUNSHINE_ENABLE_WAYLAND=$SUNSHINE_ENABLE_WAYLAND" "-DSUNSHINE_ENABLE_X11=$SUNSHINE_ENABLE_X11" "-DSUNSHINE_ENABLE_DRM=$SUNSHINE_ENABLE_DRM" "-DSUNSHINE_ENABLE_CUDA=$SUNSHINE_ENABLE_CUDA" "../" -DCMAKE_INSTALL_PREFIX=/usr + make -j ${nproc} DESTDIR=AppDir + build_appimage: name: AppImage runs-on: ubuntu-20.04 - needs: check_changelog + needs: build_linux steps: - name: Checkout @@ -62,38 +112,12 @@ jobs: with: submodules: recursive - - name: Setup Dependencies AppImage - run: | - mkdir -p artifacts - - sudo apt-get update -y && \ - sudo apt-get --reinstall install -y \ - git wget gcc-10 g++-10 build-essential cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev libwayland-dev - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 - sudo wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run && sudo chmod a+x /root/cuda.run - sudo /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && sudo rm /root/cuda.run - sudo add-apt-repository ppa:savoury1/graphics -y - sudo add-apt-repository ppa:savoury1/multimedia -y - sudo add-apt-repository ppa:savoury1/ffmpeg4 -y - sudo apt-get update -y - sudo apt-get upgrade -y && sudo apt-get dist-upgrade -y - sudo apt-get install ffmpeg -y - - name: Build AppImage - run: | - CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" - SUNSHINE_EXECUTABLE_PATH="${SUNSHINE_EXECUTABLE_PATH:-/usr/bin/sunshine}" - SUNSHINE_ASSETS_DIR="${SUNSHINE_ASSETS_DIR:-sunshine.AppImage.config}" - - SUNSHINE_ENABLE_WAYLAND=${SUNSHINE_ENABLE_WAYLAND:-ON} - SUNSHINE_ENABLE_X11=${SUNSHINE_ENABLE_X11:-ON} - SUNSHINE_ENABLE_DRM=${SUNSHINE_ENABLE_DRM:-ON} - SUNSHINE_ENABLE_CUDA=${SUNSHINE_ENABLE_CUDA:-ON} - - mkdir -p appimage-build && cd appimage-build - - cmake "-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE" "-DSUNSHINE_EXECUTABLE_PATH=$SUNSHINE_EXECUTABLE_PATH" "-DSUNSHINE_ASSETS_DIR=$SUNSHINE_ASSETS_DIR" "-DSUNSHINE_ENABLE_WAYLAND=$SUNSHINE_ENABLE_WAYLAND" "-DSUNSHINE_ENABLE_X11=$SUNSHINE_ENABLE_X11" "-DSUNSHINE_ENABLE_DRM=$SUNSHINE_ENABLE_DRM" "-DSUNSHINE_ENABLE_CUDA=$SUNSHINE_ENABLE_CUDA" "../" -DCMAKE_INSTALL_PREFIX=/usr + - name: Cache Sunshine build + uses: actions/cache@v2 + with: + path: build + key: ${{ runner.os }}-sunshine-build - make -j ${nproc} DESTDIR=AppDir - name: Set AppImage Version if: ${{ needs.check_changelog.outputs.next_version_bare != needs.check_changelog.outputs.latest_version }} run: | @@ -143,34 +167,44 @@ jobs: last_version: ${{ needs.check_changelog.outputs.last_version }} release_body: ${{ needs.check_changelog.outputs.release_body }} - build_linux: - name: Linux + build_deb_and_rpm: + name: Build DEB and RPM runs-on: ubuntu-20.04 - needs: check_changelog + needs: build_linux steps: - name: Checkout uses: actions/checkout@v3 with: submodules: recursive + - name: Cache Sunshine build + uses: actions/cache@v2 + with: + path: build + key: ${{ runner.os }}-sunshine-build + + - name: Extra dependencies + run: | + sudo apt-get update -y + sudo apt-get install -y cpack + - name: Build DEB and RPM run: | - mkdir -p build - mkdir -p artifacts cd build - - cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_CONFIG_DIR="." ../ cpack -G DEB cpack -G RPM - - cp Sunshine__.rpm ../artifacts/ - cp Sunshine__.deb ../artifacts/ - - name: Upload Artifacts + - name: Upload RPM if: ${{ matrix.package == '-p' && ( github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' ) }} uses: actions/upload-artifact@v3 with: - name: sunshine-linux - path: artifacts/ + name: sunshine-linux-rpm + path: build/Sunshine__.rpm + - name: Upload DEB + if: ${{ matrix.package == '-p' && ( github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' ) }} + uses: actions/upload-artifact@v3 + with: + name: sunshine-linux-deb + path: build/Sunshine__.deb - name: Create Release if: ${{ matrix.package == '-p' && github.event_name == 'push' && github.ref == 'refs/heads/master' }} uses: SunshineStream/actions/create_release@master @@ -212,21 +246,43 @@ jobs: make - name: Build Windows shell: msys2 {0} - run: | - mkdir artifacts - - mkdir sunshine-windows-build && cd sunshine-windows-build + run: | + mkdir sunshine-windows-build + cd sunshine-windows-build cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=assets -G "MinGW Makefiles" .. mingw32-make -j2 + - name: Create packages + shell: msys2 {0} + run: | + cd sunshine-windows-build cpack + + mkdir -p artifacts/standalone + mkdir -p artifacts/web + mkdir -p artifacts/shaders/directx + + # Installers + mv Sunshine__.exe artifacts/sunshine-windows-installer.exe - cp Sunshine__.exe ../artifacts - - name: Upload Artifacts + # Standalone + mv ../assets/web artifacts/web + mv tools artifacts/tools + mv ../assets/shaders/directx artifacts/shaders/directx + mv ../assets/apps_windows.json artifacts/apps_windows.json + mv ../assets/sunshine.conf artifacts/sunshine.conf + mv sunshine.exe artifacts/sunshine.exe + - name: Upload Sunshine Installer + if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} + uses: actions/upload-artifact@v3 + with: + name: sunshine-windows-installer + path: artifacts/sunshine-windows-installer.exe + - name: Upload Sunshine executable if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: - name: sunshine-windows - path: artifacts/ + name: sunshine-windows-standalone + path: artifacts/standalone - name: Create Release if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} uses: SunshineStream/actions/create_release@master diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c19621ac45..f34a86b03ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -457,7 +457,7 @@ set(CPACK_PACKAGE_VENDOR "CMake.org") set(CPACK_PACKAGE_CONTACT "https://github.com/SunshineStream/Sunshine") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "https://github.com/SunshineStream/Sunshine") set(CPACK_PACKAGE_DESCRIPTION "Gamestream host for Moonlight") -set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/SunshineStream/Sunshine") +set(CPACK_PACKAGE_HOMEPAGE_URL "https://sunshinestream.github.io") set(CPACK_RESOURCE_FILE_LICENSE ${PROJECT_SOURCE_DIR}/LICENSE) set(CPACK_PACKAGE_ICON ${PROJECT_SOURCE_DIR}/sunshine.png) set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") From af342c8cc98c1f9d5a29dff1dadbf1b3564f113b Mon Sep 17 00:00:00 2001 From: ABeltramo Date: Fri, 29 Apr 2022 21:21:37 +0100 Subject: [PATCH 069/120] fix: CI, better jobs dependencies --- .github/workflows/CI.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index b1503feb02d..082f1cd9947 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -32,7 +32,6 @@ jobs: check_versions: name: Check Versions runs-on: ubuntu-latest - needs: check_changelog if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }} # base_ref for pull request check, ref for push steps: @@ -54,7 +53,7 @@ jobs: build_linux: name: Build Sunshine on Linux runs-on: ubuntu-20.04 - needs: check_changelog + needs: [check_versions, check_changelog] steps: - name: Checkout uses: actions/checkout@v3 @@ -217,7 +216,7 @@ jobs: build_win: name: Windows runs-on: windows-2019 - needs: check_changelog + needs: [check_versions, check_changelog] steps: - name: Checkout From 6858f9c8d47a4e26fc25544aac25425c5b72db08 Mon Sep 17 00:00:00 2001 From: ABeltramo Date: Fri, 29 Apr 2022 23:10:27 +0100 Subject: [PATCH 070/120] fix: testing CI --- .github/workflows/CI.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 082f1cd9947..70d442d31bb 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -32,13 +32,12 @@ jobs: check_versions: name: Check Versions runs-on: ubuntu-latest - if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }} - # base_ref for pull request check, ref for push steps: - name: Checkout uses: actions/checkout@v3 - name: Check CMakeLists.txt Version + if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }} run: | version=$(grep -o -E '^project\(Sunshine VERSION [0-9]+\.[0-9]+\.[0-9]+\)' CMakeLists.txt | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+') echo "cmakelists_version=${version}" >> $GITHUB_ENV @@ -134,7 +133,7 @@ jobs: wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage && chmod +x linuxdeploy-x86_64.AppImage - ./linuxdeploy-x86_64.AppImage --appdir ../AppDir -e ../appimage-build/sunshine -i "../$ICON_FILE" -d "../appimage-build/$DESKTOP_FILE" --output appimage + ./linuxdeploy-x86_64.AppImage --appdir ../AppDir -e ../build/sunshine -i "../$ICON_FILE" -d "../build/$DESKTOP_FILE" --output appimage mv sunshine*.AppImage sunshine.AppImage mkdir sunshine && mv sunshine.AppImage sunshine/ @@ -185,7 +184,7 @@ jobs: - name: Extra dependencies run: | sudo apt-get update -y - sudo apt-get install -y cpack + sudo apt-get install -y cmake # will install cpack - name: Build DEB and RPM run: | @@ -256,32 +255,33 @@ jobs: cd sunshine-windows-build cpack - mkdir -p artifacts/standalone - mkdir -p artifacts/web - mkdir -p artifacts/shaders/directx + mkdir -p ../artifacts # Installers - mv Sunshine__.exe artifacts/sunshine-windows-installer.exe + mv Sunshine__.exe ../artifacts/sunshine-windows-installer.exe # Standalone - mv ../assets/web artifacts/web - mv tools artifacts/tools - mv ../assets/shaders/directx artifacts/shaders/directx - mv ../assets/apps_windows.json artifacts/apps_windows.json - mv ../assets/sunshine.conf artifacts/sunshine.conf - mv sunshine.exe artifacts/sunshine.exe + del ..\assets\apps_linux.json + 7z a sunshine-windows.zip ..\assets + 7z a sunshine-windows.zip sunshine.exe + 7z a sunshine-windows.zip tools\dxgi-info.exe + 7z a sunshine-windows.zip tools\audio-info.exe + 7z a sunshine-windows.zip tools\sunshinesvc.exe + 7z a sunshine-windows.zip ..\tools\install-service.bat + 7z a sunshine-windows.zip ..\tools\uninstall-service.bat + move "sunshine-windows.zip" "../artifacts" - name: Upload Sunshine Installer if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: - name: sunshine-windows-installer - path: artifacts/sunshine-windows-installer.exe + name: sunshine-windows + path: artifacts - name: Upload Sunshine executable if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: name: sunshine-windows-standalone - path: artifacts/standalone + path: sunshine-windows-build/artifacts/standalone - name: Create Release if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} uses: SunshineStream/actions/create_release@master From 5eb3e7c75f50426a9e4e5ca3eae0d55d167a90ce Mon Sep 17 00:00:00 2001 From: ABeltramo Date: Sat, 30 Apr 2022 09:45:33 +0100 Subject: [PATCH 071/120] CI: use cpack for windows 7Z, split back deb/rpm and appimage, moved release action at the end --- .github/workflows/CI.yml | 287 ++++++++++++++++++--------------------- 1 file changed, 130 insertions(+), 157 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 70d442d31bb..b85dfcd7408 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -5,7 +5,7 @@ on: branches: [master, nightly] types: [opened, synchronize, reopened] push: - branches: [master] + branches: [ master ] workflow_dispatch: jobs: @@ -13,62 +13,57 @@ jobs: name: Check Changelog runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Verify Changelog - id: verify_changelog - if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }} - # base_ref for pull request check, ref for push - uses: SunshineStream/actions/verify_changelog@master - with: - token: ${{ secrets.GITHUB_TOKEN }} + - name: Checkout + uses: actions/checkout@v3 + + - name: Verify Changelog + id: verify_changelog + if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }} + # base_ref for pull request check, ref for push + uses: SunshineStream/actions/verify_changelog@master + with: + token: ${{ secrets.GITHUB_TOKEN }} outputs: next_version: ${{ steps.verify_changelog.outputs.changelog_parser_version }} next_version_bare: ${{ steps.verify_changelog.outputs.changelog_parser_version_bare }} last_version: ${{ steps.verify_changelog.outputs.latest_release_tag_name }} - release_body: ${{ steps.verify_changelog.outputs.changelog_parser_description }} + release_body: ${{ steps.verify_changelog.outputs.changelog_parser_description }} check_versions: name: Check Versions runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - - name: Check CMakeLists.txt Version - if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }} - run: | - version=$(grep -o -E '^project\(Sunshine VERSION [0-9]+\.[0-9]+\.[0-9]+\)' CMakeLists.txt | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+') - echo "cmakelists_version=${version}" >> $GITHUB_ENV - - name: Compare CMakeList.txt Version - if: ${{ env.cmakelists_version != needs.check_changelog.outputs.next_version_bare }} - run: | - echo CMakeLists version: "$cmakelists_version" - echo Changelog version: "${{ needs.check_changelog.outputs.next_version_bare }}" - echo Within 'CMakeLists.txt' change "project(Sunshine VERSION $cmakelists_version)" to "project(Sunshine VERSION ${{ needs.check_changelog.outputs.next_version_bare }})" - exit 1 + - name: Check CMakeLists.txt Version + if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }} + run: | + version=$(grep -o -E '^project\(Sunshine VERSION [0-9]+\.[0-9]+\.[0-9]+\)' CMakeLists.txt | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+') + echo "cmakelists_version=${version}" >> $GITHUB_ENV - build_linux: - name: Build Sunshine on Linux + - name: Compare CMakeList.txt Version + if: ${{ env.cmakelists_version != needs.check_changelog.outputs.next_version_bare }} + run: | + echo CMakeLists version: "$cmakelists_version" + echo Changelog version: "${{ needs.check_changelog.outputs.next_version_bare }}" + echo Within 'CMakeLists.txt' change "project(Sunshine VERSION $cmakelists_version)" to "project(Sunshine VERSION ${{ needs.check_changelog.outputs.next_version_bare }})" + exit 1 + + build_appimage: + name: AppImage runs-on: ubuntu-20.04 - needs: [check_versions, check_changelog] + needs: check_changelog + steps: - name: Checkout uses: actions/checkout@v3 with: submodules: recursive - - name: Cache Sunshine build - uses: actions/cache@v2 - with: - path: build - key: ${{ runner.os }}-sunshine-build - - - name: Setup Dependencies + - name: Setup Dependencies AppImage run: | mkdir -p artifacts - sudo apt-get update -y && \ sudo apt-get --reinstall install -y \ git wget gcc-10 g++-10 build-essential cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev libwayland-dev @@ -82,146 +77,129 @@ jobs: sudo apt-get upgrade -y && sudo apt-get dist-upgrade -y sudo apt-get install ffmpeg -y - - name: Build Sunshine + - name: Build AppImage run: | CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" SUNSHINE_EXECUTABLE_PATH="${SUNSHINE_EXECUTABLE_PATH:-/usr/bin/sunshine}" SUNSHINE_ASSETS_DIR="${SUNSHINE_ASSETS_DIR:-sunshine.AppImage.config}" - SUNSHINE_ENABLE_WAYLAND=${SUNSHINE_ENABLE_WAYLAND:-ON} SUNSHINE_ENABLE_X11=${SUNSHINE_ENABLE_X11:-ON} SUNSHINE_ENABLE_DRM=${SUNSHINE_ENABLE_DRM:-ON} SUNSHINE_ENABLE_CUDA=${SUNSHINE_ENABLE_CUDA:-ON} - - mkdir -p build - cd build - + mkdir -p appimage-build && cd appimage-build cmake "-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE" "-DSUNSHINE_EXECUTABLE_PATH=$SUNSHINE_EXECUTABLE_PATH" "-DSUNSHINE_ASSETS_DIR=$SUNSHINE_ASSETS_DIR" "-DSUNSHINE_ENABLE_WAYLAND=$SUNSHINE_ENABLE_WAYLAND" "-DSUNSHINE_ENABLE_X11=$SUNSHINE_ENABLE_X11" "-DSUNSHINE_ENABLE_DRM=$SUNSHINE_ENABLE_DRM" "-DSUNSHINE_ENABLE_CUDA=$SUNSHINE_ENABLE_CUDA" "../" -DCMAKE_INSTALL_PREFIX=/usr make -j ${nproc} DESTDIR=AppDir - build_appimage: - name: AppImage - runs-on: ubuntu-20.04 - needs: build_linux - - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - submodules: recursive - - - name: Cache Sunshine build - uses: actions/cache@v2 - with: - path: build - key: ${{ runner.os }}-sunshine-build - - - name: Set AppImage Version - if: ${{ needs.check_changelog.outputs.next_version_bare != needs.check_changelog.outputs.latest_version }} - run: | - version=${{ needs.check_changelog.outputs.next_version_bare }} - echo "VERSION=${version}" >> $GITHUB_ENV - - name: Package AppImage - # https://docs.appimage.org/packaging-guide/index.html - run: | - mkdir -p appimage_temp && cd appimage_temp - - DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" - ICON_FILE="${ICON_FILE:-sunshine.png}" - CONFIG_DIR="${CONFIG_DIR:-sunshine/sunshine.AppImage.config/}" - HOME_DIR="${HOME_DIR:-sunshine/sunshine.AppImage.home/}" - - wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage && chmod +x linuxdeploy-x86_64.AppImage - - ./linuxdeploy-x86_64.AppImage --appdir ../AppDir -e ../build/sunshine -i "../$ICON_FILE" -d "../build/$DESKTOP_FILE" --output appimage + - name: Set AppImage Version + if: ${{ needs.check_changelog.outputs.next_version_bare != needs.check_changelog.outputs.latest_version }} + run: | + version=${{ needs.check_changelog.outputs.next_version_bare }} + echo "VERSION=${version}" >> $GITHUB_ENV + - name: Package AppImage + # https://docs.appimage.org/packaging-guide/index.html + run: | + mkdir -p appimage_temp && cd appimage_temp + DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" + ICON_FILE="${ICON_FILE:-sunshine.png}" + CONFIG_DIR="${CONFIG_DIR:-sunshine/sunshine.AppImage.config/}" + HOME_DIR="${HOME_DIR:-sunshine/sunshine.AppImage.home/}" + wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage && chmod +x linuxdeploy-x86_64.AppImage + ./linuxdeploy-x86_64.AppImage --appdir ../AppDir -e ../appimage-build/sunshine -i "../$ICON_FILE" -d "../appimage-build/$DESKTOP_FILE" --output appimage + mv sunshine*.AppImage sunshine.AppImage + mkdir sunshine && mv sunshine.AppImage sunshine/ + ./sunshine/sunshine.AppImage --appimage-portable-config + ./sunshine/sunshine.AppImage --appimage-portable-home + cp -r ../assets/* "$CONFIG_DIR" + rm -f "$CONFIG_DIR"/apps_windows.json + mkdir -p ./"$HOME_DIR"/.config/"$CONFIG_DIR" + cp ./"$CONFIG_DIR"/apps_linux.json ./"$HOME_DIR"/.config/"$CONFIG_DIR" + zip -r ./sunshine-appimage.zip ./sunshine/* + mv sunshine-appimage.zip ../artifacts/ - mv sunshine*.AppImage sunshine.AppImage - mkdir sunshine && mv sunshine.AppImage sunshine/ - ./sunshine/sunshine.AppImage --appimage-portable-config - ./sunshine/sunshine.AppImage --appimage-portable-home - cp -r ../assets/* "$CONFIG_DIR" - rm -f "$CONFIG_DIR"/apps_windows.json - mkdir -p ./"$HOME_DIR"/.config/"$CONFIG_DIR" - cp ./"$CONFIG_DIR"/apps_linux.json ./"$HOME_DIR"/.config/"$CONFIG_DIR" - zip -r ./sunshine-appimage.zip ./sunshine/* + - name: Verify AppImage + run: | + cd appimage_temp + wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage && chmod +x appimagelint-x86_64.AppImage && ./appimagelint-x86_64.AppImage ./sunshine/sunshine.AppImage - mv sunshine-appimage.zip ../artifacts/ - - name: Verify AppImage - run: | - cd appimage_temp - wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage && chmod +x appimagelint-x86_64.AppImage && ./appimagelint-x86_64.AppImage ./sunshine/sunshine.AppImage - - name: Upload Artifacts - if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} - uses: actions/upload-artifact@v3 - with: - name: sunshine-appimage - path: artifacts/ - - name: Create Release - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} - uses: SunshineStream/actions/create_release@master - with: - token: ${{ secrets.GITHUB_TOKEN }} - next_version: ${{ needs.check_changelog.outputs.next_version }} - last_version: ${{ needs.check_changelog.outputs.last_version }} - release_body: ${{ needs.check_changelog.outputs.release_body }} + - name: Upload Artifacts + if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} + uses: actions/upload-artifact@v3 + with: + name: sunshine-appimage + path: artifacts/ - build_deb_and_rpm: - name: Build DEB and RPM + build_linux: + name: Linux runs-on: ubuntu-20.04 - needs: build_linux + needs: check_changelog steps: - name: Checkout uses: actions/checkout@v3 with: submodules: recursive - - name: Cache Sunshine build - uses: actions/cache@v2 - with: - path: build - key: ${{ runner.os }}-sunshine-build - - - name: Extra dependencies + - name: Setup Dependencies AppImage run: | + mkdir -p artifacts + sudo apt-get update -y && \ + sudo apt-get --reinstall install -y \ + git wget gcc-10 g++-10 build-essential cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev libwayland-dev + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 + sudo wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run && sudo chmod a+x /root/cuda.run + sudo /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && sudo rm /root/cuda.run + sudo add-apt-repository ppa:savoury1/graphics -y + sudo add-apt-repository ppa:savoury1/multimedia -y + sudo add-apt-repository ppa:savoury1/ffmpeg4 -y sudo apt-get update -y - sudo apt-get install -y cmake # will install cpack + sudo apt-get upgrade -y && sudo apt-get dist-upgrade -y + sudo apt-get install ffmpeg -y - - name: Build DEB and RPM + - name: Build Sunshine + run: | + CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" + SUNSHINE_EXECUTABLE_PATH="${SUNSHINE_EXECUTABLE_PATH:-/usr/bin/sunshine}" + SUNSHINE_ENABLE_WAYLAND=${SUNSHINE_ENABLE_WAYLAND:-ON} + SUNSHINE_ENABLE_X11=${SUNSHINE_ENABLE_X11:-ON} + SUNSHINE_ENABLE_DRM=${SUNSHINE_ENABLE_DRM:-ON} + SUNSHINE_ENABLE_CUDA=${SUNSHINE_ENABLE_CUDA:-ON} + SUNSHINE_CONFIG_DIR=${SUNSHINE_CONFIG_DIR:-.} + + mkdir -p build + mkdir -p artifacts + + cd build + cmake "-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE" "-DSUNSHINE_CONFIG_DIR=$SUNSHINE_CONFIG_DIR" "-DSUNSHINE_EXECUTABLE_PATH=$SUNSHINE_EXECUTABLE_PATH" "-DSUNSHINE_ASSETS_DIR=$SUNSHINE_ASSETS_DIR" "-DSUNSHINE_ENABLE_WAYLAND=$SUNSHINE_ENABLE_WAYLAND" "-DSUNSHINE_ENABLE_X11=$SUNSHINE_ENABLE_X11" "-DSUNSHINE_ENABLE_DRM=$SUNSHINE_ENABLE_DRM" "-DSUNSHINE_ENABLE_CUDA=$SUNSHINE_ENABLE_CUDA" "../" -DCMAKE_INSTALL_PREFIX=/usr + + - name: Build DEB run: | cd build cpack -G DEB + mv Sunshine__.deb ../artifacts/ + + - name: Build RPM + run: | + cd build cpack -G RPM - - name: Upload RPM - if: ${{ matrix.package == '-p' && ( github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' ) }} - uses: actions/upload-artifact@v3 - with: - name: sunshine-linux-rpm - path: build/Sunshine__.rpm - - name: Upload DEB + mv Sunshine__.rpm ../artifacts/ + + - name: Upload Artifacts if: ${{ matrix.package == '-p' && ( github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' ) }} uses: actions/upload-artifact@v3 with: - name: sunshine-linux-deb - path: build/Sunshine__.deb - - name: Create Release - if: ${{ matrix.package == '-p' && github.event_name == 'push' && github.ref == 'refs/heads/master' }} - uses: SunshineStream/actions/create_release@master - with: - token: ${{ secrets.GITHUB_TOKEN }} - next_version: ${{ needs.check_changelog.outputs.next_version }} - last_version: ${{ needs.check_changelog.outputs.last_version }} - release_body: ${{ needs.check_changelog.outputs.release_body }} + name: sunshine-linux + path: artifacts/ build_win: name: Windows runs-on: windows-2019 - needs: [check_versions, check_changelog] + needs: [ check_versions, check_changelog ] steps: - name: Checkout uses: actions/checkout@v3 with: submodules: recursive + - name: MSYS2 Setup uses: msys2/setup-msys2@v2 with: @@ -242,46 +220,41 @@ jobs: nasm diffutils make + - name: Build Windows shell: msys2 {0} - run: | + run: | mkdir sunshine-windows-build cd sunshine-windows-build cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=assets -G "MinGW Makefiles" .. mingw32-make -j2 + - name: Create packages shell: msys2 {0} run: | cd sunshine-windows-build - cpack - + + cpack -G NSIS + cpack -G 7Z + mkdir -p ../artifacts # Installers mv Sunshine__.exe ../artifacts/sunshine-windows-installer.exe - - # Standalone - del ..\assets\apps_linux.json - 7z a sunshine-windows.zip ..\assets - 7z a sunshine-windows.zip sunshine.exe - 7z a sunshine-windows.zip tools\dxgi-info.exe - 7z a sunshine-windows.zip tools\audio-info.exe - 7z a sunshine-windows.zip tools\sunshinesvc.exe - 7z a sunshine-windows.zip ..\tools\install-service.bat - 7z a sunshine-windows.zip ..\tools\uninstall-service.bat - move "sunshine-windows.zip" "../artifacts" + mv Sunshine__.7z ../artifacts/sunshine-windows-standalone.7z + - name: Upload Sunshine Installer if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: name: sunshine-windows path: artifacts - - name: Upload Sunshine executable - if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} - uses: actions/upload-artifact@v3 - with: - name: sunshine-windows-standalone - path: sunshine-windows-build/artifacts/standalone + + release: + name: Create Release + runs-on: ubuntu-20.04 + needs: [ "build_win", "build_linux", "build_appimage" ] + steps: - name: Create Release if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} uses: SunshineStream/actions/create_release@master @@ -289,4 +262,4 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} next_version: ${{ needs.check_changelog.outputs.next_version }} last_version: ${{ needs.check_changelog.outputs.last_version }} - release_body: ${{ needs.check_changelog.outputs.release_body }} + release_body: ${{ needs.check_changelog.outputs.release_body }} \ No newline at end of file From dc4393a583c4dc2bb28838b993c0383b56cd3d97 Mon Sep 17 00:00:00 2001 From: ABeltramo Date: Sat, 30 Apr 2022 10:02:26 +0100 Subject: [PATCH 072/120] CI: windows build packaging to ZIP, split artifacts upload for different packages --- .github/workflows/CI.yml | 44 ++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index b85dfcd7408..f5cd2a6210b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -53,7 +53,7 @@ jobs: build_appimage: name: AppImage runs-on: ubuntu-20.04 - needs: check_changelog + needs: [ check_versions, check_changelog ] steps: - name: Checkout @@ -61,7 +61,7 @@ jobs: with: submodules: recursive - - name: Setup Dependencies AppImage + - name: Setup Dependencies run: | mkdir -p artifacts sudo apt-get update -y && \ @@ -131,14 +131,14 @@ jobs: build_linux: name: Linux runs-on: ubuntu-20.04 - needs: check_changelog + needs: [ check_versions, check_changelog ] steps: - name: Checkout uses: actions/checkout@v3 with: submodules: recursive - - name: Setup Dependencies AppImage + - name: Setup Dependencies run: | mkdir -p artifacts sudo apt-get update -y && \ @@ -174,20 +174,27 @@ jobs: run: | cd build cpack -G DEB - mv Sunshine__.deb ../artifacts/ + mv Sunshine__.deb ../artifacts/sunshine.deb - name: Build RPM run: | cd build cpack -G RPM - mv Sunshine__.rpm ../artifacts/ + mv Sunshine__.rpm ../artifacts/sunshine.rpm - - name: Upload Artifacts - if: ${{ matrix.package == '-p' && ( github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' ) }} + - name: Upload Sunshine DEB + if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: - name: sunshine-linux - path: artifacts/ + name: sunshine.deb + path: artifacts/sunshine.deb + + - name: Upload Sunshine RPM + if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} + uses: actions/upload-artifact@v3 + with: + name: sunshine.rpm + path: artifacts/sunshine.rpm build_win: name: Windows @@ -235,20 +242,27 @@ jobs: cd sunshine-windows-build cpack -G NSIS - cpack -G 7Z + cpack -G ZIP mkdir -p ../artifacts # Installers mv Sunshine__.exe ../artifacts/sunshine-windows-installer.exe - mv Sunshine__.7z ../artifacts/sunshine-windows-standalone.7z + mv Sunshine__.zip ../artifacts/sunshine-windows-standalone.zip + + - name: Upload Sunshine Windows Installer + if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} + uses: actions/upload-artifact@v3 + with: + name: sunshine-windows-installer + path: artifacts/sunshine-windows-installer.exe - - name: Upload Sunshine Installer + - name: Upload Sunshine Windows Standalone if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: - name: sunshine-windows - path: artifacts + name: sunshine-windows-installer + path: artifacts/sunshine-windows-standalone.zip release: name: Create Release From 31f7faa6a504cb284962240ec9ad070d3594bc54 Mon Sep 17 00:00:00 2001 From: ABeltramo Date: Sat, 30 Apr 2022 10:18:10 +0100 Subject: [PATCH 073/120] win: installation directory fix --- .github/workflows/CI.yml | 2 +- CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f5cd2a6210b..160fff7fa14 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -261,7 +261,7 @@ jobs: if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: - name: sunshine-windows-installer + name: sunshine-windows-standalone path: artifacts/sunshine-windows-standalone.zip release: diff --git a/CMakeLists.txt b/CMakeLists.txt index f34a86b03ea..cfe45ecae9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -479,6 +479,7 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\sunshine.ico") set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\\\${PROJECT_EXE}") + set(CPACK_PACKAGE_INSTALL_DIRECTORY "Sunshine") # The name of the directory that will be created in C:/Program files/ string(APPEND CPACK_NSIS_DEFINES "\n RequestExecutionLevel admin") # TODO: Not sure if this is needed but it took me a while to figure out where to put this option so I'm leaving it here # Sets permissions on the installed folder so that we can write in it From 2a69385aedbd1794c612d368aeff86186dddfd6a Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 30 Apr 2022 12:38:08 -0400 Subject: [PATCH 074/120] Revert workflow logic --- .github/workflows/CI.yml | 131 ++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 63 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 160fff7fa14..87a9d9fb48d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -5,7 +5,7 @@ on: branches: [master, nightly] types: [opened, synchronize, reopened] push: - branches: [ master ] + branches: [master] workflow_dispatch: jobs: @@ -32,12 +32,14 @@ jobs: check_versions: name: Check Versions runs-on: ubuntu-latest + needs: check_changelog + if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }} + # base_ref for pull request check, ref for push steps: - name: Checkout uses: actions/checkout@v3 - name: Check CMakeLists.txt Version - if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }} run: | version=$(grep -o -E '^project\(Sunshine VERSION [0-9]+\.[0-9]+\.[0-9]+\)' CMakeLists.txt | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+') echo "cmakelists_version=${version}" >> $GITHUB_ENV @@ -53,17 +55,15 @@ jobs: build_appimage: name: AppImage runs-on: ubuntu-20.04 - needs: [ check_versions, check_changelog ] - + needs: check_changelog steps: - name: Checkout uses: actions/checkout@v3 with: submodules: recursive - - name: Setup Dependencies + - name: Setup Dependencies AppImage run: | - mkdir -p artifacts sudo apt-get update -y && \ sudo apt-get --reinstall install -y \ git wget gcc-10 g++-10 build-essential cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev libwayland-dev @@ -82,11 +82,14 @@ jobs: CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" SUNSHINE_EXECUTABLE_PATH="${SUNSHINE_EXECUTABLE_PATH:-/usr/bin/sunshine}" SUNSHINE_ASSETS_DIR="${SUNSHINE_ASSETS_DIR:-sunshine.AppImage.config}" + SUNSHINE_ENABLE_WAYLAND=${SUNSHINE_ENABLE_WAYLAND:-ON} SUNSHINE_ENABLE_X11=${SUNSHINE_ENABLE_X11:-ON} SUNSHINE_ENABLE_DRM=${SUNSHINE_ENABLE_DRM:-ON} SUNSHINE_ENABLE_CUDA=${SUNSHINE_ENABLE_CUDA:-ON} + mkdir -p appimage-build && cd appimage-build + cmake "-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE" "-DSUNSHINE_EXECUTABLE_PATH=$SUNSHINE_EXECUTABLE_PATH" "-DSUNSHINE_ASSETS_DIR=$SUNSHINE_ASSETS_DIR" "-DSUNSHINE_ENABLE_WAYLAND=$SUNSHINE_ENABLE_WAYLAND" "-DSUNSHINE_ENABLE_X11=$SUNSHINE_ENABLE_X11" "-DSUNSHINE_ENABLE_DRM=$SUNSHINE_ENABLE_DRM" "-DSUNSHINE_ENABLE_CUDA=$SUNSHINE_ENABLE_CUDA" "../" -DCMAKE_INSTALL_PREFIX=/usr make -j ${nproc} DESTDIR=AppDir @@ -95,16 +98,21 @@ jobs: run: | version=${{ needs.check_changelog.outputs.next_version_bare }} echo "VERSION=${version}" >> $GITHUB_ENV + - name: Package AppImage # https://docs.appimage.org/packaging-guide/index.html run: | mkdir -p appimage_temp && cd appimage_temp + DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" ICON_FILE="${ICON_FILE:-sunshine.png}" CONFIG_DIR="${CONFIG_DIR:-sunshine/sunshine.AppImage.config/}" HOME_DIR="${HOME_DIR:-sunshine/sunshine.AppImage.home/}" + wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage && chmod +x linuxdeploy-x86_64.AppImage + ./linuxdeploy-x86_64.AppImage --appdir ../AppDir -e ../appimage-build/sunshine -i "../$ICON_FILE" -d "../appimage-build/$DESKTOP_FILE" --output appimage + mv sunshine*.AppImage sunshine.AppImage mkdir sunshine && mv sunshine.AppImage sunshine/ ./sunshine/sunshine.AppImage --appimage-portable-config @@ -114,6 +122,8 @@ jobs: mkdir -p ./"$HOME_DIR"/.config/"$CONFIG_DIR" cp ./"$CONFIG_DIR"/apps_linux.json ./"$HOME_DIR"/.config/"$CONFIG_DIR" zip -r ./sunshine-appimage.zip ./sunshine/* + + mkdir -p artifacts mv sunshine-appimage.zip ../artifacts/ - name: Verify AppImage @@ -128,17 +138,25 @@ jobs: name: sunshine-appimage path: artifacts/ + - name: Create Release + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + uses: SunshineStream/actions/create_release@master + with: + token: ${{ secrets.GITHUB_TOKEN }} + next_version: ${{ needs.check_changelog.outputs.next_version }} + last_version: ${{ needs.check_changelog.outputs.last_version }} + release_body: ${{ needs.check_changelog.outputs.release_body }} + build_linux: name: Linux runs-on: ubuntu-20.04 - needs: [ check_versions, check_changelog ] + needs: check_changelog steps: - name: Checkout uses: actions/checkout@v3 with: submodules: recursive - - - name: Setup Dependencies + - name: Setup Dependencies Linux run: | mkdir -p artifacts sudo apt-get update -y && \ @@ -154,7 +172,7 @@ jobs: sudo apt-get upgrade -y && sudo apt-get dist-upgrade -y sudo apt-get install ffmpeg -y - - name: Build Sunshine + - name: Build Linux run: | CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" SUNSHINE_EXECUTABLE_PATH="${SUNSHINE_EXECUTABLE_PATH:-/usr/bin/sunshine}" @@ -170,36 +188,37 @@ jobs: cd build cmake "-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE" "-DSUNSHINE_CONFIG_DIR=$SUNSHINE_CONFIG_DIR" "-DSUNSHINE_EXECUTABLE_PATH=$SUNSHINE_EXECUTABLE_PATH" "-DSUNSHINE_ASSETS_DIR=$SUNSHINE_ASSETS_DIR" "-DSUNSHINE_ENABLE_WAYLAND=$SUNSHINE_ENABLE_WAYLAND" "-DSUNSHINE_ENABLE_X11=$SUNSHINE_ENABLE_X11" "-DSUNSHINE_ENABLE_DRM=$SUNSHINE_ENABLE_DRM" "-DSUNSHINE_ENABLE_CUDA=$SUNSHINE_ENABLE_CUDA" "../" -DCMAKE_INSTALL_PREFIX=/usr - - name: Build DEB + - name: Package Linux run: | cd build - cpack -G DEB - mv Sunshine__.deb ../artifacts/sunshine.deb - - name: Build RPM - run: | - cd build + # package + cpack -G DEB cpack -G RPM + + # move + mv Sunshine__.deb ../artifacts/sunshine.deb mv Sunshine__.rpm ../artifacts/sunshine.rpm - - name: Upload Sunshine DEB - if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} + - name: Upload Artifacts + if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: - name: sunshine.deb - path: artifacts/sunshine.deb - - - name: Upload Sunshine RPM - if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} - uses: actions/upload-artifact@v3 + name: sunshine-linux + path: artifacts/ + - name: Create Release + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + uses: SunshineStream/actions/create_release@master with: - name: sunshine.rpm - path: artifacts/sunshine.rpm + token: ${{ secrets.GITHUB_TOKEN }} + next_version: ${{ needs.check_changelog.outputs.next_version }} + last_version: ${{ needs.check_changelog.outputs.last_version }} + release_body: ${{ needs.check_changelog.outputs.release_body }} build_win: name: Windows runs-on: windows-2019 - needs: [ check_versions, check_changelog ] + needs: check_changelog steps: - name: Checkout @@ -207,68 +226,54 @@ jobs: with: submodules: recursive - - name: MSYS2 Setup + - name: Setup Dependencies Windows uses: msys2/setup-msys2@v2 with: update: true install: >- base-devel + diffutils git + make mingw-w64-x86_64-binutils - mingw-w64-x86_64-openssl + mingw-w64-x86_64-boost mingw-w64-x86_64-cmake + mingw-w64-x86_64-nsis + mingw-w64-x86_64-openssl + mingw-w64-x86_64-opus mingw-w64-x86_64-toolchain - mingw-w64-x86_64-opus mingw-w64-x86_64-x265 - mingw-w64-x86_64-boost - mingw-w64-x86_64-nsis - git - yasm - nasm - diffutils - make + nasm + yasm - name: Build Windows shell: msys2 {0} run: | - mkdir sunshine-windows-build - cd sunshine-windows-build + mkdir build + cd build cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=assets -G "MinGW Makefiles" .. mingw32-make -j2 - - - name: Create packages + - name: Package Windows shell: msys2 {0} run: | - cd sunshine-windows-build - + mkdir -p artifacts + cd build + + # package cpack -G NSIS cpack -G ZIP - - mkdir -p ../artifacts - - # Installers + + # move mv Sunshine__.exe ../artifacts/sunshine-windows-installer.exe mv Sunshine__.zip ../artifacts/sunshine-windows-standalone.zip - - name: Upload Sunshine Windows Installer - if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} - uses: actions/upload-artifact@v3 - with: - name: sunshine-windows-installer - path: artifacts/sunshine-windows-installer.exe - - - name: Upload Sunshine Windows Standalone + - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: - name: sunshine-windows-standalone - path: artifacts/sunshine-windows-standalone.zip + name: sunshine-windows + path: artifacts/ - release: - name: Create Release - runs-on: ubuntu-20.04 - needs: [ "build_win", "build_linux", "build_appimage" ] - steps: - name: Create Release if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} uses: SunshineStream/actions/create_release@master @@ -276,4 +281,4 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} next_version: ${{ needs.check_changelog.outputs.next_version }} last_version: ${{ needs.check_changelog.outputs.last_version }} - release_body: ${{ needs.check_changelog.outputs.release_body }} \ No newline at end of file + release_body: ${{ needs.check_changelog.outputs.release_body }} From 369a941c48978f258eac26cc07ba959e3154d4b8 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 30 Apr 2022 17:51:14 -0400 Subject: [PATCH 075/120] Fix artifacts folder for AppImage --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 87a9d9fb48d..ff36850fa2a 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -102,6 +102,7 @@ jobs: - name: Package AppImage # https://docs.appimage.org/packaging-guide/index.html run: | + mkdir -p artifacts mkdir -p appimage_temp && cd appimage_temp DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" @@ -123,7 +124,6 @@ jobs: cp ./"$CONFIG_DIR"/apps_linux.json ./"$HOME_DIR"/.config/"$CONFIG_DIR" zip -r ./sunshine-appimage.zip ./sunshine/* - mkdir -p artifacts mv sunshine-appimage.zip ../artifacts/ - name: Verify AppImage From 6741997e59b739b0bb20b94e2f99af6e3f04604d Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 30 Apr 2022 18:22:17 -0400 Subject: [PATCH 076/120] Update documentation for cpack --- docs/source/about/installation.rst | 15 +++++++++++++++ docs/source/building/linux.rst | 2 ++ docs/source/building/windows.rst | 9 +++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index d2b9d877674..3900561a3c2 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -27,6 +27,21 @@ AppImage .. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/pkg:appimage?logo=github&style=for-the-badge :alt: GitHub issues by-label +The current compatibility of the AppImage is shown below. + + - [✖] Debian oldstable (buster) + - [✔] Debian stable (bullseye) + - [✔] Debian testing (bookworm) + - [✔] Debian unstable (sid) + - [✔] Ubuntu jammy + - [✔] Ubuntu impish + - [✔] Ubuntu focal + - [✖] Ubuntu bionic + - [✖] Ubuntu xenial + - [✖] Ubuntu trusty + - [✖] CentOS 7 + + #. Download and extract `sunshine-appimage.zip` Debian Packages diff --git a/docs/source/building/linux.rst b/docs/source/building/linux.rst index a6e7eefbd51..475e0c66969 100644 --- a/docs/source/building/linux.rst +++ b/docs/source/building/linux.rst @@ -239,6 +239,8 @@ Finally .. code-block:: bash make -j ${nproc} + cpack -G DEB # optionally, create a deb package + cpack -G RPM # optionally, create a rpm package Dockerfile Builds ----------------- diff --git a/docs/source/building/windows.rst b/docs/source/building/windows.rst index 36cea881697..7708da49b73 100644 --- a/docs/source/building/windows.rst +++ b/docs/source/building/windows.rst @@ -8,7 +8,7 @@ Requirements First you need to install `MSYS2 `_, then startup "MSYS2 MinGW 64-bit" and install the following packages using: -.. code-block:: batch +.. code-block:: bash pacman -S mingw-w64-x86_64-binutils mingw-w64-x86_64-openssl mingw-w64-x86_64-cmake mingw-w64-x86_64-toolchain mingw-w64-x86_64-opus mingw-w64-x86_64-x265 mingw-w64-x86_64-boost git mingw-w64-x86_64-make cmake make gcc @@ -16,7 +16,12 @@ Build ----- .. Attention:: Ensure you are in the build directory created during the clone step earlier before continuing. - .. code-block:: batch + .. code-block:: bash cmake -G"Unix Makefiles" .. + cmake -G"MinGW Makefiles" .. # alternatively + mingw32-make + + cpack -G NSIS # optionally, create a windows installer + cpack -G ZIP # optionally, create a windows standalone package From 12bf5cffc5b1bb8da40a9053b7e8e17ab7110d67 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 30 Apr 2022 19:06:19 -0400 Subject: [PATCH 077/120] Use `CMAKE_PROJECT_NAME` --- .github/workflows/CI.yml | 9 +++++---- CMakeLists.txt | 12 ++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ff36850fa2a..236d1602fec 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -197,8 +197,8 @@ jobs: cpack -G RPM # move - mv Sunshine__.deb ../artifacts/sunshine.deb - mv Sunshine__.rpm ../artifacts/sunshine.rpm + mv Sunshine.deb ../artifacts/sunshine.deb + mv Sunshine.rpm ../artifacts/sunshine.rpm - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} @@ -253,6 +253,7 @@ jobs: cd build cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=assets -G "MinGW Makefiles" .. mingw32-make -j2 + - name: Package Windows shell: msys2 {0} run: | @@ -264,8 +265,8 @@ jobs: cpack -G ZIP # move - mv Sunshine__.exe ../artifacts/sunshine-windows-installer.exe - mv Sunshine__.zip ../artifacts/sunshine-windows-standalone.zip + mv Sunshine.exe ../artifacts/sunshine-windows-installer.exe + mv Sunshine.zip ../artifacts/sunshine-windows-standalone.zip - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} diff --git a/CMakeLists.txt b/CMakeLists.txt index cfe45ecae9f..02a11376123 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -460,7 +460,7 @@ set(CPACK_PACKAGE_DESCRIPTION "Gamestream host for Moonlight") set(CPACK_PACKAGE_HOMEPAGE_URL "https://sunshinestream.github.io") set(CPACK_RESOURCE_FILE_LICENSE ${PROJECT_SOURCE_DIR}/LICENSE) set(CPACK_PACKAGE_ICON ${PROJECT_SOURCE_DIR}/sunshine.png) -set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") +set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}") set(CPACK_STRIP_FILES YES) # Platform specific options @@ -479,7 +479,7 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\sunshine.ico") set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\\\${PROJECT_EXE}") - set(CPACK_PACKAGE_INSTALL_DIRECTORY "Sunshine") # The name of the directory that will be created in C:/Program files/ + set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}") # The name of the directory that will be created in C:/Program files/ string(APPEND CPACK_NSIS_DEFINES "\n RequestExecutionLevel admin") # TODO: Not sure if this is needed but it took me a while to figure out where to put this option so I'm leaving it here # Sets permissions on the installed folder so that we can write in it @@ -491,15 +491,15 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h # Adding an option for the start menu and PATH set(CPACK_NSIS_MODIFY_PATH "OFF") # TODO: it asks to add it to the PATH but then it seems I can't just run it from powershell set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") - set(CPACK_NSIS_MUI_FINISHPAGE_RUN "${PROJECT_NAME}.exe") - set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT_NAME}.exe") # This will be shown on the installed apps Windows settings - set(CPACK_NSIS_CREATE_ICONS "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${PROJECT_NAME}.lnk' '\$INSTDIR\\\\${PROJECT_NAME}.exe'") + set(CPACK_NSIS_MUI_FINISHPAGE_RUN "${CMAKE_PROJECT_NAME}.exe") + set(CPACK_NSIS_INSTALLED_ICON_NAME "${CMAKE_PROJECT_NAME}.exe") # This will be shown on the installed apps Windows settings + set(CPACK_NSIS_CREATE_ICONS "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${CMAKE_PROJECT_NAME}.lnk' '\$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe'") # Checking for previous installed versions # set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL "ON") # TODO: doesn't work on my machine when Sunshine is already installed # Setting components groups and dependencies - set(CPACK_COMPONENT_APPLICATION_DISPLAY_NAME "Sunshine") + set(CPACK_COMPONENT_APPLICATION_DISPLAY_NAME "${CMAKE_PROJECT_NAME}") set(CPACK_COMPONENT_WEB_DISPLAY_NAME "Web interface") set(CPACK_COMPONENT_ASSETS_DISPLAY_NAME "Extra assets files") set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") From 639af4f08a86fe70f23267ab44186ec4b11c5336 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 30 Apr 2022 19:20:16 -0400 Subject: [PATCH 078/120] Add MacOS build --- .github/workflows/CI.yml | 58 ++++++++++++++++++++++++++++-- CMakeLists.txt | 8 ++--- docs/source/about/installation.rst | 20 +++++++---- docs/source/building/macos.rst | 6 ++-- 4 files changed, 78 insertions(+), 14 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 236d1602fec..44e75515c94 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -215,6 +215,60 @@ jobs: last_version: ${{ needs.check_changelog.outputs.last_version }} release_body: ${{ needs.check_changelog.outputs.release_body }} + build_mac: + name: MacOS + runs-on: macos-11 + needs: check_changelog + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Setup Dependencies MacOS + run: | + # install dependencies using homebrew + brew install boost cmake ffmpeg opus + + # fix openssl header not found + cd /usr/local/include + ln -s ../opt/openssl/include/openssl . + + - name: Build MacOS + run: | + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=assets .. + make -j ${nproc} + + - name: Package MacOS + run: | + mkdir -p artifacts + cd build + + # package + cpack -G DragNDrop + + # move + mv Sunshine.dmg ../artifacts/sunshine.dmg + + - name: Upload Artifacts + if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} + uses: actions/upload-artifact@v3 + with: + name: sunshine-macos + path: artifacts/ + + - name: Create Release + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + uses: SunshineStream/actions/create_release@master + with: + token: ${{ secrets.GITHUB_TOKEN }} + next_version: ${{ needs.check_changelog.outputs.next_version }} + last_version: ${{ needs.check_changelog.outputs.last_version }} + release_body: ${{ needs.check_changelog.outputs.release_body }} + build_win: name: Windows runs-on: windows-2019 @@ -265,8 +319,8 @@ jobs: cpack -G ZIP # move - mv Sunshine.exe ../artifacts/sunshine-windows-installer.exe - mv Sunshine.zip ../artifacts/sunshine-windows-standalone.zip + mv Sunshine.exe ../artifacts/sunshine-windows.exe + mv Sunshine.zip ../artifacts/sunshine-windows.zip - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 02a11376123..944bff644b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,8 +127,8 @@ if(WIN32) elseif(APPLE) add_compile_definitions(SUNSHINE_PLATFORM="macos") list(APPEND SUNSHINE_DEFINITIONS APPS_JSON="apps_mac.json") - link_directories(/opt/homebrew/lib/) # Default brew lib location link_directories(/opt/local/lib) + link_directories(/usr/local/lib) ADD_DEFINITIONS(-DBOOST_LOG_DYN_LINK) find_package(FFmpeg REQUIRED) @@ -531,9 +531,9 @@ if(APPLE) # TODO: test RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} COMPONENT Runtime) # TODO: bundle doesn't produce a valid .app use cpack -G DragNDrop - # set(CPACK_BUNDLE_NAME "Sunshine") - # set(CPACK_BUNDLE_PLIST "${SUNSHINE_ASSETS_DIR}/info.plist") - # set(CPACK_BUNDLE_ICON "${PROJECT_SOURCE_DIR}/sunshine.icns") + set(CPACK_BUNDLE_NAME "${CMAKE_PROJECT_NAME}") + set(CPACK_BUNDLE_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/assets/Info.plist") + set(CPACK_BUNDLE_ICON "${PROJECT_SOURCE_DIR}/sunshine.icns") endif() if(UNIX AND NOT APPLE) install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION "${SUNSHINE_CONFIG_DIR}") diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index 3900561a3c2..6634a714b2a 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -78,11 +78,15 @@ MacOS .. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:macos?logo=github&style=for-the-badge :alt: GitHub issues by-label -#. Install `MacPorts `_ -#. Download the `Portfile `_ from this repository to - ``/tmp`` -#. In a terminal run ``cd /tmp && sudo port install`` -#. The first time you start Sunshine, you will be asked to grant access to screen recording and your microphone. +Disk Image File option: + #. Download and install ``sunshine.dmg`` + +Portfile option: + #. Install `MacPorts `_ + #. Download the `Portfile `_ from this repository + to ``/tmp`` + #. In a terminal run ``cd /tmp && sudo port install`` + #. The first time you start Sunshine, you will be asked to grant access to screen recording and your microphone. Windows ------- @@ -92,7 +96,11 @@ Windows .. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:windows:11?logo=github&style=for-the-badge :alt: GitHub issues by-label -#. Download and extract ``sunshine-windows.zip`` +Installed option: + #. Download and install ``sunshine-windows.exe`` + +Standalone option: + #. Download and extract ``sunshine-windows.zip`` .. _latest release: https://github.com/SunshineStream/Sunshine/releases/latest .. _Dockerhub.io: https://hub.docker.com/repository/docker/sunshinestream/sunshine diff --git a/docs/source/building/macos.rst b/docs/source/building/macos.rst index 97a58a239e9..51ae6b1597a 100644 --- a/docs/source/building/macos.rst +++ b/docs/source/building/macos.rst @@ -14,14 +14,14 @@ MacPorts Install Requirements .. code-block:: bash - sudo port install cmake boost libopus ffmpeg + sudo port install cmake boost ffmpeg libopus Homebrew """""""" Install Requirements .. code-block:: bash - brew install boost cmake ffmpeg libopusenc + brew install boost cmake ffmpeg opus # if there are issues with an SSL header that is not found: cd /usr/local/include ln -s ../opt/openssl/include/openssl . @@ -35,6 +35,8 @@ Build cmake .. make -j ${nproc} + cpack -G DragNDrop # optionally, create a MacOS dmg package + If cmake fails complaining to find Boost, try to set the path explicitly. ``cmake -DBOOST_ROOT=[boost path] ..``, e.g., ``cmake -DBOOST_ROOT=/opt/local/libexec/boost/1.76 ..`` From e6d6d47be1a486a1d75248baaf20badd238245f3 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Thu, 5 May 2022 19:49:16 -0400 Subject: [PATCH 079/120] Create MacOS archive --- .github/workflows/CI.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 44e75515c94..791fe4eb994 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -249,9 +249,11 @@ jobs: # package cpack -G DragNDrop + cpack -G ZIP # move - mv Sunshine.dmg ../artifacts/sunshine.dmg + mv Sunshine.dmg ../artifacts/sunshine-macos.dmg + mv Sunshine.zip ../artifacts/sunshine-macos.zip - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} From 5135c16bdaee6e35be646f939ff1bd8557cef712 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Thu, 5 May 2022 21:05:57 -0400 Subject: [PATCH 080/120] Update Portfile and... - Upload Portfile as artifact during builds and releases - Update assets for cpack packages --- .github/workflows/CI.yml | 1 + CMakeLists.txt | 21 ++++++++++++++++----- Portfile => Portfile.in | 18 ++++++++++-------- docs/source/about/installation.rst | 10 ++++++++-- 4 files changed, 35 insertions(+), 15 deletions(-) rename Portfile => Portfile.in (76%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 791fe4eb994..0e71e2dee01 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -254,6 +254,7 @@ jobs: # move mv Sunshine.dmg ../artifacts/sunshine-macos.dmg mv Sunshine.zip ../artifacts/sunshine-macos.zip + mv Portfile ../artifacts/Portfile - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 944bff644b6..675a5725d5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -312,7 +312,6 @@ else() if(NOT DEFINED SUNSHINE_EXECUTABLE_PATH) set(SUNSHINE_EXECUTABLE_PATH "sunshine") endif() - configure_file(sunshine.desktop.in sunshine.desktop @ONLY) configure_file(sunshine.service.in sunshine.service @ONLY) endif() @@ -448,7 +447,7 @@ endforeach() target_compile_options(sunshine PRIVATE $<$:${SUNSHINE_COMPILE_OPTIONS}>;$<$:${SUNSHINE_COMPILE_OPTIONS_CUDA};-std=c++17>) ############# -# CPACK +# CPACK / Packaging #### # Common options @@ -474,6 +473,8 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT web) install(FILES "${SUNSHINE_ASSETS_DIR}/apps_windows.json" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) + install(FILES "${SUNSHINE_ASSETS_DIR}/box.png" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) + install(FILES "${SUNSHINE_ASSETS_DIR}/steam.png" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/directx" DESTINATION "${SUNSHINE_CONFIG_DIR}/shaders" COMPONENT assets) @@ -524,6 +525,8 @@ if(APPLE) # TODO: test set(INSTALL_RUNTIME_DIR "${prefix}/MacOS") install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION "${INSTALL_RUNTIME_DIR}") + install(FILES "${SUNSHINE_ASSETS_DIR}/apps_mac.json" DESTINATION "${INSTALL_RUNTIME_DIR}") + install(FILES "${SUNSHINE_ASSETS_DIR}/box.png" DESTINATION "${INSTALL_RUNTIME_DIR}") install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION "${INSTALL_RUNTIME_DIR}") install(TARGETS sunshine @@ -534,13 +537,18 @@ if(APPLE) # TODO: test set(CPACK_BUNDLE_NAME "${CMAKE_PROJECT_NAME}") set(CPACK_BUNDLE_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/assets/Info.plist") set(CPACK_BUNDLE_ICON "${PROJECT_SOURCE_DIR}/sunshine.icns") + + # Portfile + configure_file(Portfile.in Portfile @ONLY) endif() if(UNIX AND NOT APPLE) install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION "${SUNSHINE_CONFIG_DIR}") + install(FILES "${SUNSHINE_ASSETS_DIR}/85-sunshine-rules.rules" DESTINATION "/etc/udev/rules.d") + install(FILES "${SUNSHINE_ASSETS_DIR}/apps_linux.json" DESTINATION "${SUNSHINE_CONFIG_DIR}") + install(FILES "${SUNSHINE_ASSETS_DIR}/box.png" DESTINATION "${SUNSHINE_CONFIG_DIR}") + install(FILES "${SUNSHINE_ASSETS_DIR}/steam.png" DESTINATION "${SUNSHINE_CONFIG_DIR}") install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION "${SUNSHINE_CONFIG_DIR}") - install(FILES "${SUNSHINE_ASSETS_DIR}/apps_linux.json" DESTINATION "${SUNSHINE_CONFIG_DIR}") - install(FILES "${SUNSHINE_ASSETS_DIR}/85-sunshine-rules.rules" DESTINATION "/etc/udev/rules.d") install(TARGETS sunshine RUNTIME DESTINATION "/usr/bin") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" DESTINATION "/usr/lib/systemd/user") install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/opengl" DESTINATION "${SUNSHINE_CONFIG_DIR}/shaders") @@ -560,6 +568,9 @@ if(UNIX AND NOT APPLE) # Installation destination dir set(CPACK_SET_DESTDIR true) set(CMAKE_INSTALL_PREFIX "/etc/sunshine") + + # AppImage desktop file + configure_file(sunshine.desktop.in sunshine.desktop @ONLY) endif() -include(CPack) \ No newline at end of file +include(CPack) diff --git a/Portfile b/Portfile.in similarity index 76% rename from Portfile rename to Portfile.in index ea751ca8b33..6973ed40489 100644 --- a/Portfile +++ b/Portfile.in @@ -5,25 +5,27 @@ PortGroup cmake 1.1 PortGroup github 1.0 PortGroup boost 1.0 -github.setup abusse sunshine macos-dev -version 20220224 +github.setup sunshinestream sunshine master +version @PROJECT_VERSION@ +revision 1 categories multimedia +license GPL-3 +maintainers {sunshinestream @SunshineStream} {outlook.com:anselm.busse} platforms darwin -license GPL-2 -maintainers {outlook.com:anselm.busse} fetch.type git post-fetch { system -W ${worksrcpath} "${git.cmd} submodule update --init --recursive" } -description Sunshine is a Gamestream host for Moonlight -long_description Sunshine is a Gamestream host for Moonlight - +description Sunshine is a Gamestream host for Moonlight. +long_description {*}${description} homepage https://github.com/SunshineStream/Sunshine -depends_lib port:avahi port:ffmpeg port:libopus +depends_lib port:avahi \ + port:ffmpeg \ + port:libopus boost.version 1.76 diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index 6634a714b2a..d7e043a40d0 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -81,13 +81,19 @@ MacOS Disk Image File option: #. Download and install ``sunshine.dmg`` + .. Warning:: The Disk Image File is experimental. Limited support will be provided. + Portfile option: #. Install `MacPorts `_ - #. Download the `Portfile `_ from this repository - to ``/tmp`` + #. Download the ``Portfile`` to ``/tmp`` #. In a terminal run ``cd /tmp && sudo port install`` #. The first time you start Sunshine, you will be asked to grant access to screen recording and your microphone. +Standalone option: + #. Download and extract ``sunshine-macos.zip`` + + .. Warning:: The Standalone package is experimental. Limited support will be provided. + Windows ------- .. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:windows:10?logo=github&style=for-the-badge From 8b86abfcebbddb7963eca3abbb748ccbe3ed3283 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Thu, 5 May 2022 22:17:07 -0400 Subject: [PATCH 081/120] Reorganize assets --- .github/workflows/CI.yml | 35 +++++---- CMakeLists.txt | 38 ++++------ assets/{ => assets_common}/box.png | Bin assets/{ => assets_common}/steam.png | Bin assets/{ => assets_common}/sunshine.conf | 2 +- assets/{ => assets_common}/web/apps.html | 0 assets/{ => assets_common}/web/clients.html | 0 assets/{ => assets_common}/web/config.html | 0 .../fonts/fontawesome-free-web/LICENSE.txt | 0 .../fonts/fontawesome-free-web/attribution.js | 0 .../fontawesome-free-web/css/all.min.css | 0 .../fontawesome-free-web/css/brands.min.css | 0 .../css/fontawesome.min.css | 0 .../fontawesome-free-web/css/regular.min.css | 0 .../fontawesome-free-web/css/solid.min.css | 0 .../css/svg-with-js.min.css | 0 .../fontawesome-free-web/css/v4-shims.min.css | 0 .../webfonts/fa-brands-400.eot | Bin .../webfonts/fa-brands-400.svg | 0 .../webfonts/fa-brands-400.ttf | Bin .../webfonts/fa-brands-400.woff | Bin .../webfonts/fa-brands-400.woff2 | Bin .../webfonts/fa-regular-400.eot | Bin .../webfonts/fa-regular-400.svg | 0 .../webfonts/fa-regular-400.ttf | Bin .../webfonts/fa-regular-400.woff | Bin .../webfonts/fa-regular-400.woff2 | Bin .../webfonts/fa-solid-900.eot | Bin .../webfonts/fa-solid-900.svg | 0 .../webfonts/fa-solid-900.ttf | Bin .../webfonts/fa-solid-900.woff | Bin .../webfonts/fa-solid-900.woff2 | Bin .../web/header-no-nav.html | 0 assets/{ => assets_common}/web/header.html | 0 .../web/images/favicon.ico | Bin .../web/images/logo-sunshine-45.png | Bin assets/{ => assets_common}/web/index.html | 0 assets/{ => assets_common}/web/password.html | 0 assets/{ => assets_common}/web/pin.html | 0 .../web/third_party/bootstrap.bundle.min.js | 0 .../web/third_party/bootstrap.min.css | 0 .../web/third_party/vue.js | 0 .../web/troubleshooting.html | 0 assets/{ => assets_common}/web/welcome.html | 0 .../apps.json} | 0 .../shaders/opengl/ConvertUV.frag | 68 +++++++++--------- .../shaders/opengl/ConvertUV.vert | 52 +++++++------- .../shaders/opengl/ConvertY.frag | 50 ++++++------- .../shaders/opengl/Scene.frag | 26 +++---- .../shaders/opengl/Scene.vert | 42 +++++------ assets/{info.plist => assets_mac/Info.plist} | 0 .../{apps_mac.json => assets_mac/apps.json} | 0 .../apps.json} | 0 .../shaders/directx/ConvertUVPS.hlsl | 64 ++++++++--------- .../shaders/directx/ConvertUVVS.hlsl | 56 +++++++-------- .../shaders/directx/ConvertYPS.hlsl | 48 ++++++------- .../shaders/directx/ScenePS.hlsl | 26 +++---- .../shaders/directx/SceneVS.hlsl | 42 +++++------ .../{ => linux-misc}/85-sunshine-rules.rules | 0 59 files changed, 271 insertions(+), 278 deletions(-) rename assets/{ => assets_common}/box.png (100%) rename assets/{ => assets_common}/steam.png (100%) rename assets/{ => assets_common}/sunshine.conf (99%) rename assets/{ => assets_common}/web/apps.html (100%) rename assets/{ => assets_common}/web/clients.html (100%) rename assets/{ => assets_common}/web/config.html (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/LICENSE.txt (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/attribution.js (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/css/all.min.css (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/css/brands.min.css (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/css/fontawesome.min.css (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/css/regular.min.css (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/css/solid.min.css (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/css/svg-with-js.min.css (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/css/v4-shims.min.css (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.eot (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.svg (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.ttf (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff2 (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.eot (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.svg (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.ttf (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff2 (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.eot (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.svg (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.ttf (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff (100%) rename assets/{ => assets_common}/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff2 (100%) rename assets/{ => assets_common}/web/header-no-nav.html (100%) rename assets/{ => assets_common}/web/header.html (100%) rename assets/{ => assets_common}/web/images/favicon.ico (100%) rename assets/{ => assets_common}/web/images/logo-sunshine-45.png (100%) rename assets/{ => assets_common}/web/index.html (100%) rename assets/{ => assets_common}/web/password.html (100%) rename assets/{ => assets_common}/web/pin.html (100%) rename assets/{ => assets_common}/web/third_party/bootstrap.bundle.min.js (100%) rename assets/{ => assets_common}/web/third_party/bootstrap.min.css (100%) rename assets/{ => assets_common}/web/third_party/vue.js (100%) rename assets/{ => assets_common}/web/troubleshooting.html (100%) rename assets/{ => assets_common}/web/welcome.html (100%) rename assets/{apps_linux.json => assets_linux/apps.json} (100%) rename assets/{ => assets_linux}/shaders/opengl/ConvertUV.frag (96%) rename assets/{ => assets_linux}/shaders/opengl/ConvertUV.vert (95%) rename assets/{ => assets_linux}/shaders/opengl/ConvertY.frag (94%) rename assets/{ => assets_linux}/shaders/opengl/Scene.frag (93%) rename assets/{ => assets_linux}/shaders/opengl/Scene.vert (94%) rename assets/{info.plist => assets_mac/Info.plist} (100%) rename assets/{apps_mac.json => assets_mac/apps.json} (100%) rename assets/{apps_windows.json => assets_windows/apps.json} (100%) rename assets/{ => assets_windows}/shaders/directx/ConvertUVPS.hlsl (96%) rename assets/{ => assets_windows}/shaders/directx/ConvertUVVS.hlsl (96%) rename assets/{ => assets_windows}/shaders/directx/ConvertYPS.hlsl (95%) rename assets/{ => assets_windows}/shaders/directx/ScenePS.hlsl (95%) rename assets/{ => assets_windows}/shaders/directx/SceneVS.hlsl (95%) rename assets/{ => linux-misc}/85-sunshine-rules.rules (100%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 0e71e2dee01..504e706ff80 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -107,29 +107,34 @@ jobs: DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" ICON_FILE="${ICON_FILE:-sunshine.png}" - CONFIG_DIR="${CONFIG_DIR:-sunshine/sunshine.AppImage.config/}" - HOME_DIR="${HOME_DIR:-sunshine/sunshine.AppImage.home/}" + # CONFIG_DIR="${CONFIG_DIR:-sunshine/sunshine.AppImage.config/}" + # HOME_DIR="${HOME_DIR:-sunshine/sunshine.AppImage.home/}" wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage && chmod +x linuxdeploy-x86_64.AppImage ./linuxdeploy-x86_64.AppImage --appdir ../AppDir -e ../appimage-build/sunshine -i "../$ICON_FILE" -d "../appimage-build/$DESKTOP_FILE" --output appimage - mv sunshine*.AppImage sunshine.AppImage - mkdir sunshine && mv sunshine.AppImage sunshine/ - ./sunshine/sunshine.AppImage --appimage-portable-config - ./sunshine/sunshine.AppImage --appimage-portable-home - cp -r ../assets/* "$CONFIG_DIR" - rm -f "$CONFIG_DIR"/apps_windows.json - mkdir -p ./"$HOME_DIR"/.config/"$CONFIG_DIR" - cp ./"$CONFIG_DIR"/apps_linux.json ./"$HOME_DIR"/.config/"$CONFIG_DIR" - zip -r ./sunshine-appimage.zip ./sunshine/* + # mv sunshine*.AppImage sunshine.AppImage + # mkdir sunshine && mv sunshine.AppImage sunshine/ + # ./sunshine/sunshine.AppImage --appimage-portable-config + # ./sunshine/sunshine.AppImage --appimage-portable-home + # cp -r ../assets/assets_common/* "$CONFIG_DIR" + # cp -r ../assets/assets_linux/* "$CONFIG_DIR" - mv sunshine-appimage.zip ../artifacts/ + # mkdir -p ./"$HOME_DIR"/.config/"$CONFIG_DIR" + # cp ./"$CONFIG_DIR"/apps.json ./"$HOME_DIR"/.config/"$CONFIG_DIR" + # zip -r ./sunshine-appimage.zip ./sunshine/* + + # mv sunshine-appimage.zip ../artifacts/ + + mv sunshine*.AppImage ../artifacts/sunshine.AppImage + + # if testing succeeds, can remove commented lines - name: Verify AppImage run: | - cd appimage_temp - wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage && chmod +x appimagelint-x86_64.AppImage && ./appimagelint-x86_64.AppImage ./sunshine/sunshine.AppImage + # cd appimage_temp + 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: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} @@ -318,7 +323,7 @@ jobs: cd build # package - cpack -G NSIS + cpack -G NSIS cpack -G ZIP # move diff --git a/CMakeLists.txt b/CMakeLists.txt index 675a5725d5e..ec31a2a97b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,8 +66,6 @@ if(WIN32) add_compile_definitions(SUNSHINE_PLATFORM="windows") add_subdirectory(tools) #This is temporary, only tools for Windows are needed, for now - list(APPEND SUNSHINE_DEFINITIONS APPS_JSON="apps_windows.json") - include_directories(third-party/ViGEmClient/include) if(NOT DEFINED SUNSHINE_ICON_PATH) @@ -126,7 +124,6 @@ if(WIN32) set_source_files_properties(third-party/ViGEmClient/src/ViGEmClient.cpp PROPERTIES COMPILE_FLAGS "-Wno-unknown-pragmas -Wno-misleading-indentation -Wno-class-memaccess") elseif(APPLE) add_compile_definitions(SUNSHINE_PLATFORM="macos") - list(APPEND SUNSHINE_DEFINITIONS APPS_JSON="apps_mac.json") link_directories(/opt/local/lib) link_directories(/usr/local/lib) ADD_DEFINITIONS(-DBOOST_LOG_DYN_LINK) @@ -163,10 +160,9 @@ elseif(APPLE) sunshine/platform/macos/publish.cpp sunshine/platform/macos/TPCircularBuffer/TPCircularBuffer.c sunshine/platform/macos/TPCircularBuffer/TPCircularBuffer.h - ${CMAKE_CURRENT_SOURCE_DIR}/assets/Info.plist) + ${CMAKE_CURRENT_SOURCE_DIR}/assets/assets_mac/Info.plist) else() add_compile_definitions(SUNSHINE_PLATFORM="linux") - list(APPEND SUNSHINE_DEFINITIONS APPS_JSON="apps_linux.json") option(SUNSHINE_ENABLE_DRM "Enable KMS grab if available" ON) option(SUNSHINE_ENABLE_X11 "Enable X11 grab if available" ON) @@ -423,6 +419,7 @@ endif() list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_ASSETS_DIR="${SUNSHINE_ASSETS_DIR}") list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_CONFIG_DIR="${SUNSHINE_CONFIG_DIR}") list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_DEFAULT_DIR="${SUNSHINE_DEFAULT_DIR}") +list(APPEND SUNSHINE_DEFINITIONS APPS_JSON="apps.json") add_executable(sunshine ${SUNSHINE_TARGET_FILES}) target_link_libraries(sunshine ${SUNSHINE_EXTERNAL_LIBRARIES} ${EXTRA_LIBS}) target_compile_definitions(sunshine PUBLIC ${SUNSHINE_DEFINITIONS}) @@ -437,7 +434,7 @@ if(NOT DEFINED CMAKE_CUDA_STANDARD) endif() if(APPLE) - target_link_options(sunshine PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/assets/Info.plist) + target_link_options(sunshine PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/assets/assets_mac/Info.plist) endif() foreach(flag IN LISTS SUNSHINE_COMPILE_OPTIONS) @@ -471,12 +468,8 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h install(TARGETS audio-info RUNTIME DESTINATION "tools" COMPONENT audio) install(TARGETS sunshinesvc RUNTIME DESTINATION "tools" COMPONENT sunshinesvc) - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT web) - install(FILES "${SUNSHINE_ASSETS_DIR}/apps_windows.json" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) - install(FILES "${SUNSHINE_ASSETS_DIR}/box.png" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) - install(FILES "${SUNSHINE_ASSETS_DIR}/steam.png" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) - install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/directx" DESTINATION "${SUNSHINE_CONFIG_DIR}/shaders" COMPONENT assets) + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_common/" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_windows/" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\sunshine.ico") set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\\\${PROJECT_EXE}") @@ -517,17 +510,15 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h set(CPACK_COMPONENT_AUDIO_GROUP "Extra Tools") set(CPACK_COMPONENT_SUNSHINESVC_GROUP "Extra Tools") - set(CPACK_COMPONENT_APPLICATION_DEPENDS web assets) + set(CPACK_COMPONENT_APPLICATION_DEPENDS assets) endif() if(APPLE) # TODO: test set(prefix "${CMAKE_PROJECT_NAME}.app/Contents") set(INSTALL_RUNTIME_DIR "${prefix}/MacOS") - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION "${INSTALL_RUNTIME_DIR}") - install(FILES "${SUNSHINE_ASSETS_DIR}/apps_mac.json" DESTINATION "${INSTALL_RUNTIME_DIR}") - install(FILES "${SUNSHINE_ASSETS_DIR}/box.png" DESTINATION "${INSTALL_RUNTIME_DIR}") - install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION "${INSTALL_RUNTIME_DIR}") + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_common/" DESTINATION "${INSTALL_RUNTIME_DIR}") + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_mac/" DESTINATION "${INSTALL_RUNTIME_DIR}") install(TARGETS sunshine BUNDLE DESTINATION . COMPONENT Runtime @@ -535,23 +526,20 @@ if(APPLE) # TODO: test # TODO: bundle doesn't produce a valid .app use cpack -G DragNDrop set(CPACK_BUNDLE_NAME "${CMAKE_PROJECT_NAME}") - set(CPACK_BUNDLE_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/assets/Info.plist") + set(CPACK_BUNDLE_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/assets_mac/Info.plist") set(CPACK_BUNDLE_ICON "${PROJECT_SOURCE_DIR}/sunshine.icns") # Portfile configure_file(Portfile.in Portfile @ONLY) endif() if(UNIX AND NOT APPLE) - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION "${SUNSHINE_CONFIG_DIR}") - install(FILES "${SUNSHINE_ASSETS_DIR}/85-sunshine-rules.rules" DESTINATION "/etc/udev/rules.d") - install(FILES "${SUNSHINE_ASSETS_DIR}/apps_linux.json" DESTINATION "${SUNSHINE_CONFIG_DIR}") - install(FILES "${SUNSHINE_ASSETS_DIR}/box.png" DESTINATION "${SUNSHINE_CONFIG_DIR}") - install(FILES "${SUNSHINE_ASSETS_DIR}/steam.png" DESTINATION "${SUNSHINE_CONFIG_DIR}") - install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION "${SUNSHINE_CONFIG_DIR}") + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_common/" DESTINATION "${SUNSHINE_CONFIG_DIR}") + install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_linux/" DESTINATION "${SUNSHINE_CONFIG_DIR}") + + install(FILES "${SUNSHINE_ASSETS_DIR}/linux-misc/85-sunshine-rules.rules" DESTINATION "/etc/udev/rules.d") install(TARGETS sunshine RUNTIME DESTINATION "/usr/bin") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" DESTINATION "/usr/lib/systemd/user") - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/opengl" DESTINATION "${SUNSHINE_CONFIG_DIR}/shaders") # Pre and post install set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA diff --git a/assets/box.png b/assets/assets_common/box.png similarity index 100% rename from assets/box.png rename to assets/assets_common/box.png diff --git a/assets/steam.png b/assets/assets_common/steam.png similarity index 100% rename from assets/steam.png rename to assets/assets_common/steam.png diff --git a/assets/sunshine.conf b/assets/assets_common/sunshine.conf similarity index 99% rename from assets/sunshine.conf rename to assets/assets_common/sunshine.conf index 509ff52a283..04d51c2af1d 100644 --- a/assets/sunshine.conf +++ b/assets/assets_common/sunshine.conf @@ -1 +1 @@ -# See our documentation at https://sunshinestream.readthedocs.io/en/latest/about/advanced_usage.html +# See our documentation at https://sunshinestream.readthedocs.io/en/latest/about/advanced_usage.html diff --git a/assets/web/apps.html b/assets/assets_common/web/apps.html similarity index 100% rename from assets/web/apps.html rename to assets/assets_common/web/apps.html diff --git a/assets/web/clients.html b/assets/assets_common/web/clients.html similarity index 100% rename from assets/web/clients.html rename to assets/assets_common/web/clients.html diff --git a/assets/web/config.html b/assets/assets_common/web/config.html similarity index 100% rename from assets/web/config.html rename to assets/assets_common/web/config.html diff --git a/assets/web/fonts/fontawesome-free-web/LICENSE.txt b/assets/assets_common/web/fonts/fontawesome-free-web/LICENSE.txt similarity index 100% rename from assets/web/fonts/fontawesome-free-web/LICENSE.txt rename to assets/assets_common/web/fonts/fontawesome-free-web/LICENSE.txt diff --git a/assets/web/fonts/fontawesome-free-web/attribution.js b/assets/assets_common/web/fonts/fontawesome-free-web/attribution.js similarity index 100% rename from assets/web/fonts/fontawesome-free-web/attribution.js rename to assets/assets_common/web/fonts/fontawesome-free-web/attribution.js diff --git a/assets/web/fonts/fontawesome-free-web/css/all.min.css b/assets/assets_common/web/fonts/fontawesome-free-web/css/all.min.css similarity index 100% rename from assets/web/fonts/fontawesome-free-web/css/all.min.css rename to assets/assets_common/web/fonts/fontawesome-free-web/css/all.min.css diff --git a/assets/web/fonts/fontawesome-free-web/css/brands.min.css b/assets/assets_common/web/fonts/fontawesome-free-web/css/brands.min.css similarity index 100% rename from assets/web/fonts/fontawesome-free-web/css/brands.min.css rename to assets/assets_common/web/fonts/fontawesome-free-web/css/brands.min.css diff --git a/assets/web/fonts/fontawesome-free-web/css/fontawesome.min.css b/assets/assets_common/web/fonts/fontawesome-free-web/css/fontawesome.min.css similarity index 100% rename from assets/web/fonts/fontawesome-free-web/css/fontawesome.min.css rename to assets/assets_common/web/fonts/fontawesome-free-web/css/fontawesome.min.css diff --git a/assets/web/fonts/fontawesome-free-web/css/regular.min.css b/assets/assets_common/web/fonts/fontawesome-free-web/css/regular.min.css similarity index 100% rename from assets/web/fonts/fontawesome-free-web/css/regular.min.css rename to assets/assets_common/web/fonts/fontawesome-free-web/css/regular.min.css diff --git a/assets/web/fonts/fontawesome-free-web/css/solid.min.css b/assets/assets_common/web/fonts/fontawesome-free-web/css/solid.min.css similarity index 100% rename from assets/web/fonts/fontawesome-free-web/css/solid.min.css rename to assets/assets_common/web/fonts/fontawesome-free-web/css/solid.min.css diff --git a/assets/web/fonts/fontawesome-free-web/css/svg-with-js.min.css b/assets/assets_common/web/fonts/fontawesome-free-web/css/svg-with-js.min.css similarity index 100% rename from assets/web/fonts/fontawesome-free-web/css/svg-with-js.min.css rename to assets/assets_common/web/fonts/fontawesome-free-web/css/svg-with-js.min.css diff --git a/assets/web/fonts/fontawesome-free-web/css/v4-shims.min.css b/assets/assets_common/web/fonts/fontawesome-free-web/css/v4-shims.min.css similarity index 100% rename from assets/web/fonts/fontawesome-free-web/css/v4-shims.min.css rename to assets/assets_common/web/fonts/fontawesome-free-web/css/v4-shims.min.css diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.eot b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.eot similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.eot rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.eot diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.svg b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.svg similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.svg rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.svg diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.ttf b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.ttf similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.ttf rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.ttf diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff2 b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff2 similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff2 rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff2 diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.eot b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.eot similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.eot rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.eot diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.svg b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.svg similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.svg rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.svg diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.ttf b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.ttf similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.ttf rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.ttf diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff2 b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff2 similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff2 rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff2 diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.eot b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.eot similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.eot rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.eot diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.svg b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.svg similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.svg rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.svg diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.ttf b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.ttf similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.ttf rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.ttf diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff diff --git a/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff2 b/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff2 similarity index 100% rename from assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff2 rename to assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff2 diff --git a/assets/web/header-no-nav.html b/assets/assets_common/web/header-no-nav.html similarity index 100% rename from assets/web/header-no-nav.html rename to assets/assets_common/web/header-no-nav.html diff --git a/assets/web/header.html b/assets/assets_common/web/header.html similarity index 100% rename from assets/web/header.html rename to assets/assets_common/web/header.html diff --git a/assets/web/images/favicon.ico b/assets/assets_common/web/images/favicon.ico similarity index 100% rename from assets/web/images/favicon.ico rename to assets/assets_common/web/images/favicon.ico diff --git a/assets/web/images/logo-sunshine-45.png b/assets/assets_common/web/images/logo-sunshine-45.png similarity index 100% rename from assets/web/images/logo-sunshine-45.png rename to assets/assets_common/web/images/logo-sunshine-45.png diff --git a/assets/web/index.html b/assets/assets_common/web/index.html similarity index 100% rename from assets/web/index.html rename to assets/assets_common/web/index.html diff --git a/assets/web/password.html b/assets/assets_common/web/password.html similarity index 100% rename from assets/web/password.html rename to assets/assets_common/web/password.html diff --git a/assets/web/pin.html b/assets/assets_common/web/pin.html similarity index 100% rename from assets/web/pin.html rename to assets/assets_common/web/pin.html diff --git a/assets/web/third_party/bootstrap.bundle.min.js b/assets/assets_common/web/third_party/bootstrap.bundle.min.js similarity index 100% rename from assets/web/third_party/bootstrap.bundle.min.js rename to assets/assets_common/web/third_party/bootstrap.bundle.min.js diff --git a/assets/web/third_party/bootstrap.min.css b/assets/assets_common/web/third_party/bootstrap.min.css similarity index 100% rename from assets/web/third_party/bootstrap.min.css rename to assets/assets_common/web/third_party/bootstrap.min.css diff --git a/assets/web/third_party/vue.js b/assets/assets_common/web/third_party/vue.js similarity index 100% rename from assets/web/third_party/vue.js rename to assets/assets_common/web/third_party/vue.js diff --git a/assets/web/troubleshooting.html b/assets/assets_common/web/troubleshooting.html similarity index 100% rename from assets/web/troubleshooting.html rename to assets/assets_common/web/troubleshooting.html diff --git a/assets/web/welcome.html b/assets/assets_common/web/welcome.html similarity index 100% rename from assets/web/welcome.html rename to assets/assets_common/web/welcome.html diff --git a/assets/apps_linux.json b/assets/assets_linux/apps.json similarity index 100% rename from assets/apps_linux.json rename to assets/assets_linux/apps.json diff --git a/assets/shaders/opengl/ConvertUV.frag b/assets/assets_linux/shaders/opengl/ConvertUV.frag similarity index 96% rename from assets/shaders/opengl/ConvertUV.frag rename to assets/assets_linux/shaders/opengl/ConvertUV.frag index 416e1e8b2a7..4bd082870f5 100644 --- a/assets/shaders/opengl/ConvertUV.frag +++ b/assets/assets_linux/shaders/opengl/ConvertUV.frag @@ -1,35 +1,35 @@ -#version 300 es - -#ifdef GL_ES -precision lowp float; -#endif - -uniform sampler2D image; - -layout(shared) uniform ColorMatrix { - vec4 color_vec_y; - vec4 color_vec_u; - vec4 color_vec_v; - vec2 range_y; - vec2 range_uv; -}; - -in vec3 uuv; -layout(location = 0) out vec2 color; - -//-------------------------------------------------------------------------------------- -// Pixel Shader -//-------------------------------------------------------------------------------------- -void main() { - vec3 rgb_left = texture(image, uuv.xz).rgb; - vec3 rgb_right = texture(image, uuv.yz).rgb; - vec3 rgb = (rgb_left + rgb_right) * 0.5; - - float u = dot(color_vec_u.xyz, rgb) + color_vec_u.w; - float v = dot(color_vec_v.xyz, rgb) + color_vec_v.w; - - u = u * range_uv.x + range_uv.y; - v = v * range_uv.x + range_uv.y; - - color = vec2(u, v * 224.0f / 256.0f + 0.0625); +#version 300 es + +#ifdef GL_ES +precision lowp float; +#endif + +uniform sampler2D image; + +layout(shared) uniform ColorMatrix { + vec4 color_vec_y; + vec4 color_vec_u; + vec4 color_vec_v; + vec2 range_y; + vec2 range_uv; +}; + +in vec3 uuv; +layout(location = 0) out vec2 color; + +//-------------------------------------------------------------------------------------- +// Pixel Shader +//-------------------------------------------------------------------------------------- +void main() { + vec3 rgb_left = texture(image, uuv.xz).rgb; + vec3 rgb_right = texture(image, uuv.yz).rgb; + vec3 rgb = (rgb_left + rgb_right) * 0.5; + + float u = dot(color_vec_u.xyz, rgb) + color_vec_u.w; + float v = dot(color_vec_v.xyz, rgb) + color_vec_v.w; + + u = u * range_uv.x + range_uv.y; + v = v * range_uv.x + range_uv.y; + + color = vec2(u, v * 224.0f / 256.0f + 0.0625); } \ No newline at end of file diff --git a/assets/shaders/opengl/ConvertUV.vert b/assets/assets_linux/shaders/opengl/ConvertUV.vert similarity index 95% rename from assets/shaders/opengl/ConvertUV.vert rename to assets/assets_linux/shaders/opengl/ConvertUV.vert index a71fe58d1dd..70c14f4c231 100644 --- a/assets/shaders/opengl/ConvertUV.vert +++ b/assets/assets_linux/shaders/opengl/ConvertUV.vert @@ -1,27 +1,27 @@ -#version 300 es - -#ifdef GL_ES -precision mediump float; -#endif - -uniform float width_i; - -out vec3 uuv; -//-------------------------------------------------------------------------------------- -// Vertex Shader -//-------------------------------------------------------------------------------------- -void main() -{ - float idHigh = float(gl_VertexID >> 1); - float idLow = float(gl_VertexID & int(1)); - - float x = idHigh * 4.0 - 1.0; - float y = idLow * 4.0 - 1.0; - - float u_right = idHigh * 2.0; - float u_left = u_right - width_i; - float v = idLow * 2.0; - - uuv = vec3(u_left, u_right, v); - gl_Position = vec4(x, y, 0.0, 1.0); +#version 300 es + +#ifdef GL_ES +precision mediump float; +#endif + +uniform float width_i; + +out vec3 uuv; +//-------------------------------------------------------------------------------------- +// Vertex Shader +//-------------------------------------------------------------------------------------- +void main() +{ + float idHigh = float(gl_VertexID >> 1); + float idLow = float(gl_VertexID & int(1)); + + float x = idHigh * 4.0 - 1.0; + float y = idLow * 4.0 - 1.0; + + float u_right = idHigh * 2.0; + float u_left = u_right - width_i; + float v = idLow * 2.0; + + uuv = vec3(u_left, u_right, v); + gl_Position = vec4(x, y, 0.0, 1.0); } \ No newline at end of file diff --git a/assets/shaders/opengl/ConvertY.frag b/assets/assets_linux/shaders/opengl/ConvertY.frag similarity index 94% rename from assets/shaders/opengl/ConvertY.frag rename to assets/assets_linux/shaders/opengl/ConvertY.frag index 564fa25ab0a..dfd5774e9b4 100644 --- a/assets/shaders/opengl/ConvertY.frag +++ b/assets/assets_linux/shaders/opengl/ConvertY.frag @@ -1,26 +1,26 @@ -#version 300 es - -#ifdef GL_ES -precision lowp float; -#endif - -uniform sampler2D image; - -layout(shared) uniform ColorMatrix { - vec4 color_vec_y; - vec4 color_vec_u; - vec4 color_vec_v; - vec2 range_y; - vec2 range_uv; -}; - -in vec2 tex; -layout(location = 0) out float color; - -void main() -{ - vec3 rgb = texture(image, tex).rgb; - float y = dot(color_vec_y.xyz, rgb); - - color = y * range_y.x + range_y.y; +#version 300 es + +#ifdef GL_ES +precision lowp float; +#endif + +uniform sampler2D image; + +layout(shared) uniform ColorMatrix { + vec4 color_vec_y; + vec4 color_vec_u; + vec4 color_vec_v; + vec2 range_y; + vec2 range_uv; +}; + +in vec2 tex; +layout(location = 0) out float color; + +void main() +{ + vec3 rgb = texture(image, tex).rgb; + float y = dot(color_vec_y.xyz, rgb); + + color = y * range_y.x + range_y.y; } \ No newline at end of file diff --git a/assets/shaders/opengl/Scene.frag b/assets/assets_linux/shaders/opengl/Scene.frag similarity index 93% rename from assets/shaders/opengl/Scene.frag rename to assets/assets_linux/shaders/opengl/Scene.frag index 6375f1fd33c..ee4b36b99c2 100644 --- a/assets/shaders/opengl/Scene.frag +++ b/assets/assets_linux/shaders/opengl/Scene.frag @@ -1,14 +1,14 @@ -#version 300 es - -#ifdef GL_ES -precision lowp float; -#endif - -uniform sampler2D image; - -in vec2 tex; -layout(location = 0) out vec4 color; -void main() -{ - color = texture(image, tex); +#version 300 es + +#ifdef GL_ES +precision lowp float; +#endif + +uniform sampler2D image; + +in vec2 tex; +layout(location = 0) out vec4 color; +void main() +{ + color = texture(image, tex); } \ No newline at end of file diff --git a/assets/shaders/opengl/Scene.vert b/assets/assets_linux/shaders/opengl/Scene.vert similarity index 94% rename from assets/shaders/opengl/Scene.vert rename to assets/assets_linux/shaders/opengl/Scene.vert index 258878f434a..24c16bef1d5 100644 --- a/assets/shaders/opengl/Scene.vert +++ b/assets/assets_linux/shaders/opengl/Scene.vert @@ -1,22 +1,22 @@ -#version 300 es - -#ifdef GL_ES -precision mediump float; -#endif - -out vec2 tex; - -void main() -{ - float idHigh = float(gl_VertexID >> 1); - float idLow = float(gl_VertexID & int(1)); - - float x = idHigh * 4.0 - 1.0; - float y = idLow * 4.0 - 1.0; - - float u = idHigh * 2.0; - float v = idLow * 2.0; - - gl_Position = vec4(x, y, 0.0, 1.0); - tex = vec2(u, v); +#version 300 es + +#ifdef GL_ES +precision mediump float; +#endif + +out vec2 tex; + +void main() +{ + float idHigh = float(gl_VertexID >> 1); + float idLow = float(gl_VertexID & int(1)); + + float x = idHigh * 4.0 - 1.0; + float y = idLow * 4.0 - 1.0; + + float u = idHigh * 2.0; + float v = idLow * 2.0; + + gl_Position = vec4(x, y, 0.0, 1.0); + tex = vec2(u, v); } \ No newline at end of file diff --git a/assets/info.plist b/assets/assets_mac/Info.plist similarity index 100% rename from assets/info.plist rename to assets/assets_mac/Info.plist diff --git a/assets/apps_mac.json b/assets/assets_mac/apps.json similarity index 100% rename from assets/apps_mac.json rename to assets/assets_mac/apps.json diff --git a/assets/apps_windows.json b/assets/assets_windows/apps.json similarity index 100% rename from assets/apps_windows.json rename to assets/assets_windows/apps.json diff --git a/assets/shaders/directx/ConvertUVPS.hlsl b/assets/assets_windows/shaders/directx/ConvertUVPS.hlsl similarity index 96% rename from assets/shaders/directx/ConvertUVPS.hlsl rename to assets/assets_windows/shaders/directx/ConvertUVPS.hlsl index 2b72cddf43b..f9bf69df062 100644 --- a/assets/shaders/directx/ConvertUVPS.hlsl +++ b/assets/assets_windows/shaders/directx/ConvertUVPS.hlsl @@ -1,33 +1,33 @@ -Texture2D image : register(t0); - -SamplerState def_sampler : register(s0); - -struct FragTexWide { - float3 uuv : TEXCOORD0; -}; - -cbuffer ColorMatrix : register(b0) { - float4 color_vec_y; - float4 color_vec_u; - float4 color_vec_v; - float2 range_y; - float2 range_uv; -}; - -//-------------------------------------------------------------------------------------- -// Pixel Shader -//-------------------------------------------------------------------------------------- -float2 main_ps(FragTexWide input) : SV_Target -{ - float3 rgb_left = image.Sample(def_sampler, input.uuv.xz).rgb; - float3 rgb_right = image.Sample(def_sampler, input.uuv.yz).rgb; - float3 rgb = (rgb_left + rgb_right) * 0.5; - - float u = dot(color_vec_u.xyz, rgb) + color_vec_u.w; - float v = dot(color_vec_v.xyz, rgb) + color_vec_v.w; - - u = u * range_uv.x + range_uv.y; - v = v * range_uv.x + range_uv.y; - - return float2(u, v * 224.0f/256.0f + 0.0625); +Texture2D image : register(t0); + +SamplerState def_sampler : register(s0); + +struct FragTexWide { + float3 uuv : TEXCOORD0; +}; + +cbuffer ColorMatrix : register(b0) { + float4 color_vec_y; + float4 color_vec_u; + float4 color_vec_v; + float2 range_y; + float2 range_uv; +}; + +//-------------------------------------------------------------------------------------- +// Pixel Shader +//-------------------------------------------------------------------------------------- +float2 main_ps(FragTexWide input) : SV_Target +{ + float3 rgb_left = image.Sample(def_sampler, input.uuv.xz).rgb; + float3 rgb_right = image.Sample(def_sampler, input.uuv.yz).rgb; + float3 rgb = (rgb_left + rgb_right) * 0.5; + + float u = dot(color_vec_u.xyz, rgb) + color_vec_u.w; + float v = dot(color_vec_v.xyz, rgb) + color_vec_v.w; + + u = u * range_uv.x + range_uv.y; + v = v * range_uv.x + range_uv.y; + + return float2(u, v * 224.0f/256.0f + 0.0625); } \ No newline at end of file diff --git a/assets/shaders/directx/ConvertUVVS.hlsl b/assets/assets_windows/shaders/directx/ConvertUVVS.hlsl similarity index 96% rename from assets/shaders/directx/ConvertUVVS.hlsl rename to assets/assets_windows/shaders/directx/ConvertUVVS.hlsl index 66d97d4336f..77ff38d7deb 100644 --- a/assets/shaders/directx/ConvertUVVS.hlsl +++ b/assets/assets_windows/shaders/directx/ConvertUVVS.hlsl @@ -1,29 +1,29 @@ -struct VertTexPosWide { - float3 uuv : TEXCOORD; - float4 pos : SV_POSITION; -}; - -cbuffer info : register(b0) { - float width_i; -}; - -//-------------------------------------------------------------------------------------- -// Vertex Shader -//-------------------------------------------------------------------------------------- -VertTexPosWide main_vs(uint vI : SV_VERTEXID) -{ - float idHigh = float(vI >> 1); - float idLow = float(vI & uint(1)); - - float x = idHigh * 4.0 - 1.0; - float y = idLow * 4.0 - 1.0; - - float u_right = idHigh * 2.0; - float u_left = u_right - width_i; - float v = 1.0 - idLow * 2.0; - - VertTexPosWide vert_out; - vert_out.uuv = float3(u_left, u_right, v); - vert_out.pos = float4(x, y, 0.0, 1.0); - return vert_out; +struct VertTexPosWide { + float3 uuv : TEXCOORD; + float4 pos : SV_POSITION; +}; + +cbuffer info : register(b0) { + float width_i; +}; + +//-------------------------------------------------------------------------------------- +// Vertex Shader +//-------------------------------------------------------------------------------------- +VertTexPosWide main_vs(uint vI : SV_VERTEXID) +{ + float idHigh = float(vI >> 1); + float idLow = float(vI & uint(1)); + + float x = idHigh * 4.0 - 1.0; + float y = idLow * 4.0 - 1.0; + + float u_right = idHigh * 2.0; + float u_left = u_right - width_i; + float v = 1.0 - idLow * 2.0; + + VertTexPosWide vert_out; + vert_out.uuv = float3(u_left, u_right, v); + vert_out.pos = float4(x, y, 0.0, 1.0); + return vert_out; } \ No newline at end of file diff --git a/assets/shaders/directx/ConvertYPS.hlsl b/assets/assets_windows/shaders/directx/ConvertYPS.hlsl similarity index 95% rename from assets/shaders/directx/ConvertYPS.hlsl rename to assets/assets_windows/shaders/directx/ConvertYPS.hlsl index 386133c8393..c38d19c82ae 100644 --- a/assets/shaders/directx/ConvertYPS.hlsl +++ b/assets/assets_windows/shaders/directx/ConvertYPS.hlsl @@ -1,25 +1,25 @@ -Texture2D image : register(t0); - -SamplerState def_sampler : register(s0); - -cbuffer ColorMatrix : register(b0) { - float4 color_vec_y; - float4 color_vec_u; - float4 color_vec_v; - float2 range_y; - float2 range_uv; -}; - -struct PS_INPUT -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD; -}; - -float main_ps(PS_INPUT frag_in) : SV_Target -{ - float3 rgb = image.Sample(def_sampler, frag_in.tex, 0).rgb; - float y = dot(color_vec_y.xyz, rgb); - - return y * range_y.x + range_y.y; +Texture2D image : register(t0); + +SamplerState def_sampler : register(s0); + +cbuffer ColorMatrix : register(b0) { + float4 color_vec_y; + float4 color_vec_u; + float4 color_vec_v; + float2 range_y; + float2 range_uv; +}; + +struct PS_INPUT +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD; +}; + +float main_ps(PS_INPUT frag_in) : SV_Target +{ + float3 rgb = image.Sample(def_sampler, frag_in.tex, 0).rgb; + float y = dot(color_vec_y.xyz, rgb); + + return y * range_y.x + range_y.y; } \ No newline at end of file diff --git a/assets/shaders/directx/ScenePS.hlsl b/assets/assets_windows/shaders/directx/ScenePS.hlsl similarity index 95% rename from assets/shaders/directx/ScenePS.hlsl rename to assets/assets_windows/shaders/directx/ScenePS.hlsl index aa60123121a..53a9bc8dc2f 100644 --- a/assets/shaders/directx/ScenePS.hlsl +++ b/assets/assets_windows/shaders/directx/ScenePS.hlsl @@ -1,14 +1,14 @@ -Texture2D image : register(t0); - -SamplerState def_sampler : register(s0); - -struct PS_INPUT -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD; -}; - -float4 main_ps(PS_INPUT frag_in) : SV_Target -{ - return image.Sample(def_sampler, frag_in.tex, 0); +Texture2D image : register(t0); + +SamplerState def_sampler : register(s0); + +struct PS_INPUT +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD; +}; + +float4 main_ps(PS_INPUT frag_in) : SV_Target +{ + return image.Sample(def_sampler, frag_in.tex, 0); } \ No newline at end of file diff --git a/assets/shaders/directx/SceneVS.hlsl b/assets/assets_windows/shaders/directx/SceneVS.hlsl similarity index 95% rename from assets/shaders/directx/SceneVS.hlsl rename to assets/assets_windows/shaders/directx/SceneVS.hlsl index 51319ddb431..3afaffc60f9 100644 --- a/assets/shaders/directx/SceneVS.hlsl +++ b/assets/assets_windows/shaders/directx/SceneVS.hlsl @@ -1,22 +1,22 @@ -struct PS_INPUT -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD; -}; - -PS_INPUT main_vs(uint vI : SV_VERTEXID) -{ - float idHigh = float(vI >> 1); - float idLow = float(vI & uint(1)); - - float x = idHigh * 4.0 - 1.0; - float y = idLow * 4.0 - 1.0; - - float u = idHigh * 2.0; - float v = 1.0 - idLow * 2.0; - - PS_INPUT vert_out; - vert_out.pos = float4(x, y, 0.0, 1.0); - vert_out.tex = float2(u, v); - return vert_out; +struct PS_INPUT +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD; +}; + +PS_INPUT main_vs(uint vI : SV_VERTEXID) +{ + float idHigh = float(vI >> 1); + float idLow = float(vI & uint(1)); + + float x = idHigh * 4.0 - 1.0; + float y = idLow * 4.0 - 1.0; + + float u = idHigh * 2.0; + float v = 1.0 - idLow * 2.0; + + PS_INPUT vert_out; + vert_out.pos = float4(x, y, 0.0, 1.0); + vert_out.tex = float2(u, v); + return vert_out; } \ No newline at end of file diff --git a/assets/85-sunshine-rules.rules b/assets/linux-misc/85-sunshine-rules.rules similarity index 100% rename from assets/85-sunshine-rules.rules rename to assets/linux-misc/85-sunshine-rules.rules From ca6f02c953768520786f2d4221efe1919a16618d Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Thu, 5 May 2022 23:58:08 -0400 Subject: [PATCH 082/120] Modify windows installer --- CMakeLists.txt | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ec31a2a97b1..93ff2307d54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -471,8 +471,9 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_common/" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_windows/" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) - set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\sunshine.ico") - set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\\\${PROJECT_EXE}") + set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\sunshine.ico") + set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\\\${PROJECT_EXE}") + set(CPACK_NSIS_MUI_HEADERIMAGE "${CPACK_PACKAGE_ICON}") # Header image for installer set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}") # The name of the directory that will be created in C:/Program files/ string(APPEND CPACK_NSIS_DEFINES "\n RequestExecutionLevel admin") # TODO: Not sure if this is needed but it took me a while to figure out where to put this option so I'm leaving it here @@ -483,7 +484,7 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h ") # Adding an option for the start menu and PATH - set(CPACK_NSIS_MODIFY_PATH "OFF") # TODO: it asks to add it to the PATH but then it seems I can't just run it from powershell + set(CPACK_NSIS_MODIFY_PATH "ON") # TODO: it asks to add it to the PATH but then it seems I can't just run it from powershell set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") set(CPACK_NSIS_MUI_FINISHPAGE_RUN "${CMAKE_PROJECT_NAME}.exe") set(CPACK_NSIS_INSTALLED_ICON_NAME "${CMAKE_PROJECT_NAME}.exe") # This will be shown on the installed apps Windows settings @@ -493,22 +494,33 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h # set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL "ON") # TODO: doesn't work on my machine when Sunshine is already installed # Setting components groups and dependencies + # sunshine binary set(CPACK_COMPONENT_APPLICATION_DISPLAY_NAME "${CMAKE_PROJECT_NAME}") - set(CPACK_COMPONENT_WEB_DISPLAY_NAME "Web interface") - set(CPACK_COMPONENT_ASSETS_DISPLAY_NAME "Extra assets files") - set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") - - set(CPACK_COMPONENT_APPLICATION_GROUP "Runtime") - set(CPACK_COMPONENT_WEB_GROUP "Runtime") - set(CPACK_COMPONENT_ASSETS_GROUP "Runtime") + set(CPACK_COMPONENT_APPLICATION_DESCRIPTION "The main application.") + set(CPACK_COMPONENT_APPLICATION_GROUP "${CMAKE_PROJECT_NAME}") + set(CPACK_COMPONENT_APPLICATION_REQUIRED true) + + # assets + set(CPACK_COMPONENT_ASSETS_DISPLAY_NAME "Assets") + set(CPACK_COMPONENT_ASSETS_DESCRIPTION "Assets include the apps and configurations, shaders, default box art, and web ui.") + set(CPACK_COMPONENT_ASSETS_GROUP "${CMAKE_PROJECT_NAME}") + set(CPACK_COMPONENT_ASSETS_DEPENDS "${CMAKE_PROJECT_NAME}") + set(CPACK_COMPONENT_ASSETS_REQUIRED true) + + # audio tool + set(CPACK_COMPONENT_AUDIO_DISPLAY_NAME "audio-info.exe") + set(CPACK_COMPONENT_AUDIO_DESCRIPTION "CLI tool that allows you to get information about sound devices.") + set(CPACK_COMPONENT_AUDIO_GROUP "Tools") + # display tool set(CPACK_COMPONENT_DXGI_DISPLAY_NAME "dxgi-info.exe") - set(CPACK_COMPONENT_AUDIO_DISPLAY_NAME "audio-info.exe") - set(CPACK_COMPONENT_SUNSHINESVC_DISPLAY_NAME "sunshinesvc.exe") + set(CPACK_COMPONENT_DXGI_DESCRIPTION "CLI tool that allows you to get information about graphics cards and displays.") + set(CPACK_COMPONENT_DXGI_GROUP "Tools") - set(CPACK_COMPONENT_DXGI_GROUP "Extra Tools") - set(CPACK_COMPONENT_AUDIO_GROUP "Extra Tools") - set(CPACK_COMPONENT_SUNSHINESVC_GROUP "Extra Tools") + # service tool + set(CPACK_COMPONENT_SUNSHINESVC_DISPLAY_NAME "sunshinesvc.exe") + set(CPACK_COMPONENT_SUNSHINESVC_DESCRIPTION "CLI tool that allows you to enable/disable the Sunshine service.") + set(CPACK_COMPONENT_SUNSHINESVC_GROUP "Tools") set(CPACK_COMPONENT_APPLICATION_DEPENDS assets) endif() From 0d0496adf331670f6ea4f050af2c76b79d74b902 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 6 May 2022 10:04:29 -0400 Subject: [PATCH 083/120] Remove CPACK_NSIS_MUI_HEADERIMAGE --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 93ff2307d54..2c09a1cdd8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -471,9 +471,11 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_common/" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_windows/" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) + + # set(CPACK_NSIS_MUI_HEADERIMAGE "") # TODO: image should be 150x57 bmp + set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\sunshine.ico") set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\\\${PROJECT_EXE}") - set(CPACK_NSIS_MUI_HEADERIMAGE "${CPACK_PACKAGE_ICON}") # Header image for installer set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}") # The name of the directory that will be created in C:/Program files/ string(APPEND CPACK_NSIS_DEFINES "\n RequestExecutionLevel admin") # TODO: Not sure if this is needed but it took me a while to figure out where to put this option so I'm leaving it here From c4441db606d37c34a69d6dc5299a9955155156c0 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 6 May 2022 10:16:59 -0400 Subject: [PATCH 084/120] Remove CPACK_COMPONENT_APPLICATION_DEPENDS --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c09a1cdd8b..c12957b3f09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -524,7 +524,7 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h set(CPACK_COMPONENT_SUNSHINESVC_DESCRIPTION "CLI tool that allows you to enable/disable the Sunshine service.") set(CPACK_COMPONENT_SUNSHINESVC_GROUP "Tools") - set(CPACK_COMPONENT_APPLICATION_DEPENDS assets) + # set(CPACK_COMPONENT_APPLICATION_DEPENDS assets) endif() if(APPLE) # TODO: test From c409022df53d273c03e9f1812d6e1a4e6780e78f Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 6 May 2022 12:55:43 -0400 Subject: [PATCH 085/120] Combine AppImage and Linux build --- .github/workflows/CI.yml | 149 +++++++++------------------------------ CMakeLists.txt | 9 ++- 2 files changed, 36 insertions(+), 122 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 504e706ff80..e9d2a4bc1ef 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -52,8 +52,8 @@ jobs: echo Within 'CMakeLists.txt' change "project(Sunshine VERSION $cmakelists_version)" to "project(Sunshine VERSION ${{ needs.check_changelog.outputs.next_version_bare }})" exit 1 - build_appimage: - name: AppImage + build_linux: + name: Linux runs-on: ubuntu-20.04 needs: check_changelog steps: @@ -61,8 +61,7 @@ jobs: uses: actions/checkout@v3 with: submodules: recursive - - - name: Setup Dependencies AppImage + - name: Setup Dependencies Linux run: | sudo apt-get update -y && \ sudo apt-get --reinstall install -y \ @@ -77,21 +76,13 @@ jobs: sudo apt-get upgrade -y && sudo apt-get dist-upgrade -y sudo apt-get install ffmpeg -y - - name: Build AppImage + - name: Build Linux run: | - CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" - SUNSHINE_EXECUTABLE_PATH="${SUNSHINE_EXECUTABLE_PATH:-/usr/bin/sunshine}" - SUNSHINE_ASSETS_DIR="${SUNSHINE_ASSETS_DIR:-sunshine.AppImage.config}" - - SUNSHINE_ENABLE_WAYLAND=${SUNSHINE_ENABLE_WAYLAND:-ON} - SUNSHINE_ENABLE_X11=${SUNSHINE_ENABLE_X11:-ON} - SUNSHINE_ENABLE_DRM=${SUNSHINE_ENABLE_DRM:-ON} - SUNSHINE_ENABLE_CUDA=${SUNSHINE_ENABLE_CUDA:-ON} - - mkdir -p appimage-build && cd appimage-build - - cmake "-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE" "-DSUNSHINE_EXECUTABLE_PATH=$SUNSHINE_EXECUTABLE_PATH" "-DSUNSHINE_ASSETS_DIR=$SUNSHINE_ASSETS_DIR" "-DSUNSHINE_ENABLE_WAYLAND=$SUNSHINE_ENABLE_WAYLAND" "-DSUNSHINE_ENABLE_X11=$SUNSHINE_ENABLE_X11" "-DSUNSHINE_ENABLE_DRM=$SUNSHINE_ENABLE_DRM" "-DSUNSHINE_ENABLE_CUDA=$SUNSHINE_ENABLE_CUDA" "../" -DCMAKE_INSTALL_PREFIX=/usr - make -j ${nproc} DESTDIR=AppDir + mkdir -p build + + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_CONFIG_DIR=. -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine -DSUNSHINE_ENABLE_WAYLAND=ON -DSUNSHINE_ENABLE_X11=ON -DSUNSHINE_ENABLE_DRM=ON -DSUNSHINE_ENABLE_CUDA=ON "../" + make -j ${nproc} - name: Set AppImage Version if: ${{ needs.check_changelog.outputs.next_version_bare != needs.check_changelog.outputs.latest_version }} @@ -99,111 +90,35 @@ jobs: version=${{ needs.check_changelog.outputs.next_version_bare }} echo "VERSION=${version}" >> $GITHUB_ENV - - name: Package AppImage - # https://docs.appimage.org/packaging-guide/index.html + - name: Package Linux run: | mkdir -p artifacts - mkdir -p appimage_temp && cd appimage_temp - + cd build + + # variables DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" ICON_FILE="${ICON_FILE:-sunshine.png}" - # CONFIG_DIR="${CONFIG_DIR:-sunshine/sunshine.AppImage.config/}" - # HOME_DIR="${HOME_DIR:-sunshine/sunshine.AppImage.home/}" - + + # AppImage + # https://docs.appimage.org/packaging-guide/index.html wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage && chmod +x linuxdeploy-x86_64.AppImage + ./linuxdeploy-x86_64.AppImage --appdir . -e ./sunshine -i "../$ICON_FILE" -d "./$DESKTOP_FILE" --output appimage - ./linuxdeploy-x86_64.AppImage --appdir ../AppDir -e ../appimage-build/sunshine -i "../$ICON_FILE" -d "../appimage-build/$DESKTOP_FILE" --output appimage - - # mv sunshine*.AppImage sunshine.AppImage - # mkdir sunshine && mv sunshine.AppImage sunshine/ - # ./sunshine/sunshine.AppImage --appimage-portable-config - # ./sunshine/sunshine.AppImage --appimage-portable-home - # cp -r ../assets/assets_common/* "$CONFIG_DIR" - # cp -r ../assets/assets_linux/* "$CONFIG_DIR" - - # mkdir -p ./"$HOME_DIR"/.config/"$CONFIG_DIR" - # cp ./"$CONFIG_DIR"/apps.json ./"$HOME_DIR"/.config/"$CONFIG_DIR" - # zip -r ./sunshine-appimage.zip ./sunshine/* - - # mv sunshine-appimage.zip ../artifacts/ + # package + cpack -G DEB + cpack -G RPM + # move mv sunshine*.AppImage ../artifacts/sunshine.AppImage - - # if testing succeeds, can remove commented lines + mv ./cpack_artifacts/Sunshine.deb ../artifacts/sunshine.deb + mv ./cpack_artifacts/Sunshine.rpm ../artifacts/sunshine.rpm - name: Verify AppImage run: | - # cd appimage_temp - 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: Upload Artifacts - if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} - uses: actions/upload-artifact@v3 - with: - name: sunshine-appimage - path: artifacts/ - - - name: Create Release - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} - uses: SunshineStream/actions/create_release@master - with: - token: ${{ secrets.GITHUB_TOKEN }} - next_version: ${{ needs.check_changelog.outputs.next_version }} - last_version: ${{ needs.check_changelog.outputs.last_version }} - release_body: ${{ needs.check_changelog.outputs.release_body }} - - build_linux: - name: Linux - runs-on: ubuntu-20.04 - needs: check_changelog - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - submodules: recursive - - name: Setup Dependencies Linux - run: | - mkdir -p artifacts - sudo apt-get update -y && \ - sudo apt-get --reinstall install -y \ - git wget gcc-10 g++-10 build-essential cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev libwayland-dev - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 - sudo wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run && sudo chmod a+x /root/cuda.run - sudo /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && sudo rm /root/cuda.run - sudo add-apt-repository ppa:savoury1/graphics -y - sudo add-apt-repository ppa:savoury1/multimedia -y - sudo add-apt-repository ppa:savoury1/ffmpeg4 -y - sudo apt-get update -y - sudo apt-get upgrade -y && sudo apt-get dist-upgrade -y - sudo apt-get install ffmpeg -y - - - name: Build Linux - run: | - CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" - SUNSHINE_EXECUTABLE_PATH="${SUNSHINE_EXECUTABLE_PATH:-/usr/bin/sunshine}" - SUNSHINE_ENABLE_WAYLAND=${SUNSHINE_ENABLE_WAYLAND:-ON} - SUNSHINE_ENABLE_X11=${SUNSHINE_ENABLE_X11:-ON} - SUNSHINE_ENABLE_DRM=${SUNSHINE_ENABLE_DRM:-ON} - SUNSHINE_ENABLE_CUDA=${SUNSHINE_ENABLE_CUDA:-ON} - SUNSHINE_CONFIG_DIR=${SUNSHINE_CONFIG_DIR:-.} + wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage + chmod +x appimagelint-x86_64.AppImage - mkdir -p build - mkdir -p artifacts - - cd build - cmake "-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE" "-DSUNSHINE_CONFIG_DIR=$SUNSHINE_CONFIG_DIR" "-DSUNSHINE_EXECUTABLE_PATH=$SUNSHINE_EXECUTABLE_PATH" "-DSUNSHINE_ASSETS_DIR=$SUNSHINE_ASSETS_DIR" "-DSUNSHINE_ENABLE_WAYLAND=$SUNSHINE_ENABLE_WAYLAND" "-DSUNSHINE_ENABLE_X11=$SUNSHINE_ENABLE_X11" "-DSUNSHINE_ENABLE_DRM=$SUNSHINE_ENABLE_DRM" "-DSUNSHINE_ENABLE_CUDA=$SUNSHINE_ENABLE_CUDA" "../" -DCMAKE_INSTALL_PREFIX=/usr - - - name: Package Linux - run: | - cd build - - # package - cpack -G DEB - cpack -G RPM - - # move - mv Sunshine.deb ../artifacts/sunshine.deb - mv Sunshine.rpm ../artifacts/sunshine.rpm + ./appimagelint-x86_64.AppImage ./artifacts/sunshine.AppImage - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} @@ -244,7 +159,7 @@ jobs: run: | mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=assets .. + cmake -DCMAKE_BUILD_TYPE=Release .. make -j ${nproc} - name: Package MacOS @@ -257,9 +172,9 @@ jobs: cpack -G ZIP # move - mv Sunshine.dmg ../artifacts/sunshine-macos.dmg - mv Sunshine.zip ../artifacts/sunshine-macos.zip mv Portfile ../artifacts/Portfile + mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine-macos.dmg + mv ./cpack_artifacts/Sunshine.zip ../artifacts/sunshine-macos.zip - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} @@ -313,7 +228,7 @@ jobs: run: | mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=assets -G "MinGW Makefiles" .. + cmake -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles" .. mingw32-make -j2 - name: Package Windows @@ -327,8 +242,8 @@ jobs: cpack -G ZIP # move - mv Sunshine.exe ../artifacts/sunshine-windows.exe - mv Sunshine.zip ../artifacts/sunshine-windows.zip + mv ./cpack_artifacts/Sunshine.exe ../artifacts/sunshine-windows.exe + mv ./cpack_artifacts/Sunshine.zip ../artifacts/sunshine-windows.zip - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} diff --git a/CMakeLists.txt b/CMakeLists.txt index c12957b3f09..0640625ae65 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -449,7 +449,8 @@ target_compile_options(sunshine PRIVATE $<$:${SUNSHINE_COM # Common options set(CPACK_PACKAGE_NAME "SunshineStream") -set(CPACK_PACKAGE_VENDOR "CMake.org") +set(CPACK_PACKAGE_VENDOR "SunshineStream") +set(CPACK_PACKAGE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/cpack_artifacts) set(CPACK_PACKAGE_CONTACT "https://github.com/SunshineStream/Sunshine") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "https://github.com/SunshineStream/Sunshine") set(CPACK_PACKAGE_DESCRIPTION "Gamestream host for Moonlight") @@ -486,7 +487,7 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h ") # Adding an option for the start menu and PATH - set(CPACK_NSIS_MODIFY_PATH "ON") # TODO: it asks to add it to the PATH but then it seems I can't just run it from powershell + set(CPACK_NSIS_MODIFY_PATH "OFF") # TODO: it asks to add it to the PATH but is not working https://gitlab.kitware.com/cmake/cmake/-/issues/15635 set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") set(CPACK_NSIS_MUI_FINISHPAGE_RUN "${CMAKE_PROJECT_NAME}.exe") set(CPACK_NSIS_INSTALLED_ICON_NAME "${CMAKE_PROJECT_NAME}.exe") # This will be shown on the installed apps Windows settings @@ -501,12 +502,12 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h set(CPACK_COMPONENT_APPLICATION_DESCRIPTION "The main application.") set(CPACK_COMPONENT_APPLICATION_GROUP "${CMAKE_PROJECT_NAME}") set(CPACK_COMPONENT_APPLICATION_REQUIRED true) + set(CPACK_COMPONENT_APPLICATION_DEPENDS assets) # assets set(CPACK_COMPONENT_ASSETS_DISPLAY_NAME "Assets") set(CPACK_COMPONENT_ASSETS_DESCRIPTION "Assets include the apps and configurations, shaders, default box art, and web ui.") set(CPACK_COMPONENT_ASSETS_GROUP "${CMAKE_PROJECT_NAME}") - set(CPACK_COMPONENT_ASSETS_DEPENDS "${CMAKE_PROJECT_NAME}") set(CPACK_COMPONENT_ASSETS_REQUIRED true) # audio tool @@ -523,8 +524,6 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h set(CPACK_COMPONENT_SUNSHINESVC_DISPLAY_NAME "sunshinesvc.exe") set(CPACK_COMPONENT_SUNSHINESVC_DESCRIPTION "CLI tool that allows you to enable/disable the Sunshine service.") set(CPACK_COMPONENT_SUNSHINESVC_GROUP "Tools") - - # set(CPACK_COMPONENT_APPLICATION_DEPENDS assets) endif() if(APPLE) # TODO: test From 93aebf461a0b6e2c71b0f5efa292c22fde559e54 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 6 May 2022 13:21:47 -0400 Subject: [PATCH 086/120] Set assets dir for Windows --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index e9d2a4bc1ef..fe279f591b7 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -228,7 +228,7 @@ jobs: run: | mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles" .. + cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=assets -G "MinGW Makefiles" .. mingw32-make -j2 - name: Package Windows From 49bfd2ba1f1bc3d47b5935dbcf36e57febbc0087 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 6 May 2022 14:24:39 -0400 Subject: [PATCH 087/120] Rename apps.json files throughout project - Remove `appveyor.yml` - Add project description to CMakeLists.txt - Add project homepage url to CMakeLists.txt --- .github/workflows/CI.yml | 4 ++-- CMakeLists.txt | 9 +++++--- Portfile.in | 14 ++++++------ appveyor.yml | 44 -------------------------------------- assets/linux-deb/conffiles | 2 +- assets/linux-deb/postinst | 12 +++++------ assets/linux-deb/preinst | 4 ++-- docs/source/conf.py | 2 +- sunshine.desktop.in | 4 ++-- sunshine.service.in | 2 +- 10 files changed, 28 insertions(+), 69 deletions(-) delete mode 100644 appveyor.yml diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index fe279f591b7..5e854683e5c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -41,7 +41,7 @@ jobs: - name: Check CMakeLists.txt Version run: | - version=$(grep -o -E '^project\(Sunshine VERSION [0-9]+\.[0-9]+\.[0-9]+\)' CMakeLists.txt | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+') + version=$(grep -o -E '^project\(Sunshine \[VERSION [0-9]+\.[0-9]+\.[0-9]+\]' CMakeLists.txt | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+') echo "cmakelists_version=${version}" >> $GITHUB_ENV - name: Compare CMakeList.txt Version @@ -49,7 +49,7 @@ jobs: run: | echo CMakeLists version: "$cmakelists_version" echo Changelog version: "${{ needs.check_changelog.outputs.next_version_bare }}" - echo Within 'CMakeLists.txt' change "project(Sunshine VERSION $cmakelists_version)" to "project(Sunshine VERSION ${{ needs.check_changelog.outputs.next_version_bare }})" + echo Within 'CMakeLists.txt' change "project(Sunshine [VERSION $cmakelists_version]" to "project(Sunshine [VERSION ${{ needs.check_changelog.outputs.next_version_bare }}]" exit 1 build_linux: diff --git a/CMakeLists.txt b/CMakeLists.txt index 0640625ae65..8d9584d019d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 3.0) -project(Sunshine VERSION 0.13.0) +project(Sunshine [VERSION 0.13.0] + [DESCRIPTION Sunshine is a Gamestream host for Moonlight.] + [HOMEPAGE_URL https://sunshinestream.github.io] + ) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) @@ -453,8 +456,8 @@ set(CPACK_PACKAGE_VENDOR "SunshineStream") set(CPACK_PACKAGE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/cpack_artifacts) set(CPACK_PACKAGE_CONTACT "https://github.com/SunshineStream/Sunshine") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "https://github.com/SunshineStream/Sunshine") -set(CPACK_PACKAGE_DESCRIPTION "Gamestream host for Moonlight") -set(CPACK_PACKAGE_HOMEPAGE_URL "https://sunshinestream.github.io") +set(CPACK_PACKAGE_DESCRIPTION ${CMAKE_PROJECT_DESCRIPTION}) +set(CPACK_PACKAGE_HOMEPAGE_URL ${CMAKE_PROJECT_HOMEPAGE_URL}) set(CPACK_RESOURCE_FILE_LICENSE ${PROJECT_SOURCE_DIR}/LICENSE) set(CPACK_PACKAGE_ICON ${PROJECT_SOURCE_DIR}/sunshine.png) set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}") diff --git a/Portfile.in b/Portfile.in index 6973ed40489..60940cb41f5 100644 --- a/Portfile.in +++ b/Portfile.in @@ -19,9 +19,9 @@ post-fetch { system -W ${worksrcpath} "${git.cmd} submodule update --init --recursive" } -description Sunshine is a Gamestream host for Moonlight. +description @PROJECT_DESCRIPTION@ long_description {*}${description} -homepage https://github.com/SunshineStream/Sunshine +homepage @PROJECT_HOMEPAGE_URL@ depends_lib port:avahi \ port:ffmpeg \ @@ -37,14 +37,14 @@ cmake.out_of_source yes destroot { xinstall -d -m 755 ${destroot}${prefix}/etc/${name} - xinstall ${worksrcpath}/assets/apps_mac.json ${destroot}${prefix}/etc/${name} - xinstall ${worksrcpath}/assets/box.png ${destroot}${prefix}/etc/${name} - xinstall ${worksrcpath}/assets/sunshine.conf ${destroot}${prefix}/etc/${name} + xinstall ${worksrcpath}/assets/assets_mac/apps.json ${destroot}${prefix}/etc/${name} + xinstall ${worksrcpath}/assets/assets_common/box.png ${destroot}${prefix}/etc/${name} + xinstall ${worksrcpath}/assets/assets_common/sunshine.conf ${destroot}${prefix}/etc/${name} xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/web - xinstall {*}[glob ${worksrcpath}/assets/web/*.html] ${destroot}${prefix}/etc/${name}/web + xinstall {*}[glob ${worksrcpath}/assets/assets_common/web/*.html] ${destroot}${prefix}/etc/${name}/web xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/web/third_party - xinstall {*}[glob ${worksrcpath}/assets/web/third_party/*] ${destroot}${prefix}/etc/${name}/web/third_party + xinstall {*}[glob ${worksrcpath}/assets/assets_common/web/third_party/*] ${destroot}${prefix}/etc/${name}/web/third_party xinstall ${workpath}/build/${name} ${destroot}${prefix}/bin } diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 7fb08089e83..00000000000 --- a/appveyor.yml +++ /dev/null @@ -1,44 +0,0 @@ -services: - - docker - -environment: - matrix: - - APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004 - DOCKERFILE: Dockerfile-ubuntu_20_04 - - APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004 - DOCKERFILE: Dockerfile-ubuntu_21_04 - - APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004 - DOCKERFILE: Dockerfile-debian - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - BUILD_TYPE: Release - -install: - - cmd: C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -S mingw-w64-x86_64-binutils mingw-w64-x86_64-openssl mingw-w64-x86_64-cmake mingw-w64-x86_64-toolchain mingw-w64-x86_64-opus mingw-w64-x86_64-x265 mingw-w64-x86_64-boost git yasm nasm diffutils make" - -before_build: - - cmd: git submodule update --init --recursive - - cmd: mkdir build - - cmd: cd build - - sh: cd scripts - - sh: ./build-container.sh -f $DOCKERFILE - -build_script: - - cmd: set OLDPATH=%PATH% - - cmd: set PATH=C:\msys64\mingw64\bin - - cmd: cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSUNSHINE_ASSETS_DIR=assets -G "MinGW Makefiles" .. - - cmd: mingw32-make -j2 - - cmd: set PATH=%OLDPATH% - - sh: ./build-sunshine.sh -pu - -after_build: - - cmd: Del ..\assets\apps_linux.json - - cmd: 7z a Sunshine-Windows.zip ..\assets - - cmd: 7z a Sunshine-Windows.zip sunshine.exe - - cmd: 7z a Sunshine-Windows.zip tools\dxgi-info.exe - - cmd: 7z a Sunshine-Windows.zip tools\audio-info.exe - - cmd: 7z a Sunshine-Windows.zip tools\sunshinesvc.exe - - cmd: 7z a Sunshine-Windows.zip ..\tools\install-service.bat - - cmd: 7z a Sunshine-Windows.zip ..\tools\uninstall-service.bat - - cmd: appveyor PushArtifact Sunshine-Windows.zip - - sh: appveyor PushArtifact sunshine-build/sunshine.deb - diff --git a/assets/linux-deb/conffiles b/assets/linux-deb/conffiles index 78176a81021..cf2d2444378 100644 --- a/assets/linux-deb/conffiles +++ b/assets/linux-deb/conffiles @@ -1,2 +1,2 @@ /etc/sunshine/sunshine.conf -/etc/sunshine/apps_linux.json +/etc/sunshine/apps.json diff --git a/assets/linux-deb/postinst b/assets/linux-deb/postinst index cf66231fd26..d3195c6a4df 100644 --- a/assets/linux-deb/postinst +++ b/assets/linux-deb/postinst @@ -17,15 +17,15 @@ if [ -f /etc/sunshine/sunshine.conf.old ]; then mv /etc/sunshine/sunshine.conf.old /etc/sunshine/sunshine.conf fi -if [ -f /etc/sunshine/apps_linux.json.old ]; then - echo "Restoring old apps_linux.json" - mv /etc/sunshine/apps_linux.json.old /etc/sunshine/apps_linux.json +if [ -f /etc/sunshine/apps.json.old ]; then + echo "Restoring old apps.json" + mv /etc/sunshine/apps.json.old /etc/sunshine/apps.json fi # Update permissions on config files for Web Manager -if [ -f /etc/sunshine/apps_linux.json ]; then - echo "chmod 666 /etc/sunshine/apps_linux.json" - chmod 666 /etc/sunshine/apps_linux.json +if [ -f /etc/sunshine/apps.json ]; then + echo "chmod 666 /etc/sunshine/apps.json" + chmod 666 /etc/sunshine/apps.json fi if [ -f /etc/sunshine/sunshine.conf ]; then diff --git a/assets/linux-deb/preinst b/assets/linux-deb/preinst index 515d1a34ca5..ec56e883c48 100644 --- a/assets/linux-deb/preinst +++ b/assets/linux-deb/preinst @@ -4,6 +4,6 @@ if [ -f /etc/sunshine/sunshine.conf ]; then cp /etc/sunshine/sunshine.conf /etc/sunshine/sunshine.conf.old fi -if [ -f /etc/sunshine/apps_linux.json ]; then - cp /etc/sunshine/apps_linux.json /etc/sunshine/apps_linux.json.old +if [ -f /etc/sunshine/apps.json ]; then + cp /etc/sunshine/apps.json /etc/sunshine/apps.json.old fi diff --git a/docs/source/conf.py b/docs/source/conf.py index 86b7b805b5e..360db8f6952 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -27,7 +27,7 @@ # The full version, including alpha/beta/rc tags with open(os.path.join(root_dir, 'CMakeLists.txt'), 'r') as f: - version = re.search(r"project\(Sunshine VERSION ((\d+)\.(\d+)\.(\d+))\)", str(f.read())).group(1) + version = re.search(r"project\(Sunshine \[VERSION ((\d+)\.(\d+)\.(\d+))\]", str(f.read())).group(1) """ To use cmake method for obtaining version instead of regex, 1. Within CMakeLists.txt add the following line without backticks: diff --git a/sunshine.desktop.in b/sunshine.desktop.in index 195bade32fb..a345e5dc467 100644 --- a/sunshine.desktop.in +++ b/sunshine.desktop.in @@ -1,9 +1,9 @@ [Desktop Entry] Type=Application -Name=sunshine +Name=@PROJECT_NAME@ Exec=sunshine Version=1.0 -Comment=Host for Moonlight Streaming Client +Comment=@PROJECT_DESCRIPTION@ Icon=sunshine Categories=Utility; Terminal=true diff --git a/sunshine.service.in b/sunshine.service.in index c0c38289c57..157b3a4dce3 100644 --- a/sunshine.service.in +++ b/sunshine.service.in @@ -1,5 +1,5 @@ [Unit] -Description=Sunshine Gamestream Server for Moonlight +Description=@PROJECT_DESCRIPTION@ [Service] ExecStart=@SUNSHINE_EXECUTABLE_PATH@ From a3e3da3136d4007ecb15bc66f66d735fc4d7314d Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 6 May 2022 14:39:26 -0400 Subject: [PATCH 088/120] Fix cmake project parameters --- .github/workflows/CI.yml | 2 +- CMakeLists.txt | 6 +++--- docs/source/conf.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 5e854683e5c..97d90219435 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -41,7 +41,7 @@ jobs: - name: Check CMakeLists.txt Version run: | - version=$(grep -o -E '^project\(Sunshine \[VERSION [0-9]+\.[0-9]+\.[0-9]+\]' CMakeLists.txt | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+') + version=$(grep -o -E '^project\(Sunshine VERSION [0-9]+\.[0-9]+\.[0-9]+' CMakeLists.txt | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+') echo "cmakelists_version=${version}" >> $GITHUB_ENV - name: Compare CMakeList.txt Version diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d9584d019d..b5c388862f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required(VERSION 3.0) -project(Sunshine [VERSION 0.13.0] - [DESCRIPTION Sunshine is a Gamestream host for Moonlight.] - [HOMEPAGE_URL https://sunshinestream.github.io] +project(Sunshine VERSION 0.13.0 + DESCRIPTION "Sunshine is a Gamestream host for Moonlight." + HOMEPAGE_URL "https://sunshinestream.github.io" ) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) diff --git a/docs/source/conf.py b/docs/source/conf.py index 360db8f6952..f609783ce9f 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -27,7 +27,7 @@ # The full version, including alpha/beta/rc tags with open(os.path.join(root_dir, 'CMakeLists.txt'), 'r') as f: - version = re.search(r"project\(Sunshine \[VERSION ((\d+)\.(\d+)\.(\d+))\]", str(f.read())).group(1) + version = re.search(r"project\(Sunshine VERSION ((\d+)\.(\d+)\.(\d+))", str(f.read())).group(1) """ To use cmake method for obtaining version instead of regex, 1. Within CMakeLists.txt add the following line without backticks: From fff419a7ff19c11b029054181db35f578aced4f1 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 6 May 2022 15:19:11 -0400 Subject: [PATCH 089/120] Fix AppImage source filename --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 97d90219435..3f8e04e67f1 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -109,7 +109,7 @@ jobs: cpack -G RPM # move - mv sunshine*.AppImage ../artifacts/sunshine.AppImage + mv Sunshine*.AppImage ../artifacts/sunshine.AppImage mv ./cpack_artifacts/Sunshine.deb ../artifacts/sunshine.deb mv ./cpack_artifacts/Sunshine.rpm ../artifacts/sunshine.rpm From 6c04065ba780b2d34633eb5e5493d209ca3bbb98 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sun, 8 May 2022 21:39:10 -0400 Subject: [PATCH 090/120] Set DEFAULT_SUNSHINE_DIR for CI builds - Add libssl3.0 as CPACK_DEBIAN_PACKAGE_DEPENDS --- .github/workflows/CI.yml | 4 ++-- CMakeLists.txt | 2 +- Portfile.in | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3f8e04e67f1..3aed4d1ea85 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -81,7 +81,7 @@ jobs: mkdir -p build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_CONFIG_DIR=. -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine -DSUNSHINE_ENABLE_WAYLAND=ON -DSUNSHINE_ENABLE_X11=ON -DSUNSHINE_ENABLE_DRM=ON -DSUNSHINE_ENABLE_CUDA=ON "../" + cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_CONFIG_DIR=. -DSUNSHINE_DEFAULT_DIR=/etc/sunshine -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine -DSUNSHINE_ENABLE_WAYLAND=ON -DSUNSHINE_ENABLE_X11=ON -DSUNSHINE_ENABLE_DRM=ON -DSUNSHINE_ENABLE_CUDA=ON "../" make -j ${nproc} - name: Set AppImage Version @@ -159,7 +159,7 @@ jobs: run: | mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release .. + cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_DEFAULT_DIR=/etc/sunshine .. make -j ${nproc} - name: Package MacOS diff --git a/CMakeLists.txt b/CMakeLists.txt index b5c388862f2..f58e0439392 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -565,7 +565,7 @@ if(UNIX AND NOT APPLE) # Dependencies set(CPACK_DEB_COMPONENT_INSTALL ON) - set(CPACK_DEBIAN_PACKAGE_DEPENDS "libssl1.1, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2") + set(CPACK_DEBIAN_PACKAGE_DEPENDS "libssl1.1 | libssl3.0, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2") set(CPACK_RPM_PACKAGE_REQUIRES "libssl==1.1, libavdevice>=58, libboost-thread>=1.67.0, libboost-filesystem>=1.67.0, libboost-log>=1.67.0, libpulse>=0, libopus>=0, libxcb-shm>=0, libxcb-xfixes>=0, libxtst>=0, libevdev>=2.0, libdrm>=2.0, libcap>=2.0") set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF) # This should automatically figure out dependencies, doesn't work with the current config diff --git a/Portfile.in b/Portfile.in index 60940cb41f5..c784c3b05b0 100644 --- a/Portfile.in +++ b/Portfile.in @@ -31,7 +31,8 @@ depends_lib port:avahi \ boost.version 1.76 configure.args -DBOOST_ROOT=[boost::install_area] \ - -DSUNSHINE_ASSETS_DIR=${prefix}/etc/sunshine + -DSUNSHINE_ASSETS_DIR=${worksrcpath}/assets + -DSUNSHINE_DEFAULT_DIR=${prefix}/etc/sunshine cmake.out_of_source yes From 496e51d93a60988066735e50c9e9c58f96a7cfcc Mon Sep 17 00:00:00 2001 From: Caz zoo Date: Sat, 7 May 2022 17:32:42 +0200 Subject: [PATCH 091/120] Fixes #8 and relates #146 Adding required missing dependencies for Arch base distro --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index b0be11308d8..a020205ec11 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -111,7 +111,7 @@ jobs: wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage && chmod +x linuxdeploy-x86_64.AppImage - ./linuxdeploy-x86_64.AppImage --appdir ../AppDir -e ../appimage-build/sunshine -i "../$ICON_FILE" -d "../appimage-build/$DESKTOP_FILE" --output appimage + ./linuxdeploy-x86_64.AppImage --appdir ../AppDir -e ../appimage-build/sunshine -i "../$ICON_FILE" -d "../appimage-build/$DESKTOP_FILE" -l /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0 -l /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 -l /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 --output appimage mv sunshine*.AppImage sunshine.AppImage mkdir sunshine && mv sunshine.AppImage sunshine/ From c2752262e5635f138ce1758c136ba27fef2e7a18 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 10 May 2022 18:54:50 -0400 Subject: [PATCH 092/120] Add missing AppImage libraries --- .github/workflows/CI.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3aed4d1ea85..6f44197ccae 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -101,8 +101,17 @@ jobs: # AppImage # https://docs.appimage.org/packaging-guide/index.html - wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage && chmod +x linuxdeploy-x86_64.AppImage - ./linuxdeploy-x86_64.AppImage --appdir . -e ./sunshine -i "../$ICON_FILE" -d "./$DESKTOP_FILE" --output appimage + wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + chmod +x linuxdeploy-x86_64.AppImage + ./linuxdeploy-x86_64.AppImage \ + --appdir . \ + -e ./sunshine \ + -i "../$ICON_FILE" \ + -d "./$DESKTOP_FILE" \ + -l /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0 \ + -l /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 \ + -l /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 \ + --output appimage # package cpack -G DEB From 88925c705f38b14ad4018589968c05d176ccb137 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 10 May 2022 19:19:16 -0400 Subject: [PATCH 093/120] Add gtk plugin for linuxdeploy / AppImage --- .github/workflows/CI.yml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6f44197ccae..2e2b72a2b1b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -103,14 +103,22 @@ jobs: # https://docs.appimage.org/packaging-guide/index.html wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage chmod +x linuxdeploy-x86_64.AppImage + + # https://github.com/linuxdeploy/linuxdeploy-plugin-gtk + sudo apt-get install libgtk-3-dev librsvg2-dev -y + wget https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh + chmod +x linuxdeploy-plugin-gtk.sh + export DEPLOY_GTK_VERSION=3 + ./linuxdeploy-x86_64.AppImage \ --appdir . \ - -e ./sunshine \ - -i "../$ICON_FILE" \ - -d "./$DESKTOP_FILE" \ - -l /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0 \ - -l /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 \ - -l /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 \ + --plugin gtk \ + --executable ./sunshine \ + --icon-file "../$ICON_FILE" \ + --desktop-file "./$DESKTOP_FILE" \ + --library /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0 \ + --library /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 \ + --library /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 \ --output appimage # package From ca00949851dba872373b8bebde42d16a2f315930 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 10 May 2022 21:18:37 -0400 Subject: [PATCH 094/120] Refactor build_linux job --- .github/workflows/CI.yml | 84 ++++++++++++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 2e2b72a2b1b..a1b091b91d2 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -63,18 +63,67 @@ jobs: submodules: recursive - name: Setup Dependencies Linux run: | - sudo apt-get update -y && \ - sudo apt-get --reinstall install -y \ - git wget gcc-10 g++-10 build-essential cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev libwayland-dev - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 - sudo wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run && sudo chmod a+x /root/cuda.run - sudo /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && sudo rm /root/cuda.run - sudo add-apt-repository ppa:savoury1/graphics -y - sudo add-apt-repository ppa:savoury1/multimedia -y sudo add-apt-repository ppa:savoury1/ffmpeg4 -y + # sudo add-apt-repository ppa:savoury1/boost-defaults-1.71 -y + sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y + sudo apt-get update -y - sudo apt-get upgrade -y && sudo apt-get dist-upgrade -y - sudo apt-get install ffmpeg -y + sudo apt-get install -y \ + build-essential \ + cmake \ + gcc-10 \ + git \ + g++-10 \ + libavdevice-dev \ + libboost-filesystem-dev \ + libboost-log-dev \ + libboost-thread-dev \ + libcap-dev \ + libdrm-dev \ + libevdev-dev \ + libpulse-dev \ + libopus-dev \ + libssl-dev \ + libwayland-dev \ + libx11-dev \ + libxcb-shm0-dev \ + libxcb-xfixes0-dev \ + libxcb1-dev \ + libxfixes-dev \ + libxrandr-dev \ + libxtst-dev \ + wget + # # Ubuntu 20.04+ packages + # libboost-filesystem-dev + # libboost-log-dev + # libboost-thread-dev + + # # Ubuntu 18.04 packages + # libboost-filesystem1.71-dev \ + # libboost-log1.71-dev \ + # libboost-regex1.71-dev \ + # libboost-thread1.71-dev \ + + # clean apt cache + sudo apt-get clean + sudo rm -rf /var/lib/apt/lists/* + + # Update gcc alias + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 + + # Install CuDA + sudo wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run + sudo chmod a+x /root/cuda.run + sudo /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm + sudo rm /root/cuda.run + + # # Install cmake (necessary for 18.04) + # wget https://cmake.org/files/v3.22/cmake-3.22.2-linux-x86_64.sh + # chmod +x cmake-3.22.2-linux-x86_64.sh + # mkdir /opt/cmake + # ./cmake-3.22.2-linux-x86_64.sh --prefix=/opt/cmake --skip-license + # ln --force --symbolic /opt/cmake/bin/cmake /usr/local/bin/cmake + # cmake --version - name: Build Linux run: | @@ -104,15 +153,14 @@ jobs: wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage chmod +x linuxdeploy-x86_64.AppImage - # https://github.com/linuxdeploy/linuxdeploy-plugin-gtk - sudo apt-get install libgtk-3-dev librsvg2-dev -y - wget https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh - chmod +x linuxdeploy-plugin-gtk.sh - export DEPLOY_GTK_VERSION=3 + # # https://github.com/linuxdeploy/linuxdeploy-plugin-gtk + # sudo apt-get install libgtk-3-dev librsvg2-dev -y + # wget https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh + # chmod +x linuxdeploy-plugin-gtk.sh + # export DEPLOY_GTK_VERSION=3 ./linuxdeploy-x86_64.AppImage \ --appdir . \ - --plugin gtk \ --executable ./sunshine \ --icon-file "../$ICON_FILE" \ --desktop-file "./$DESKTOP_FILE" \ @@ -120,6 +168,8 @@ jobs: --library /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 \ --library /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 \ --output appimage + # # add this argument back if using gtk plugin + # --plugin gtk \ # package cpack -G DEB @@ -135,6 +185,8 @@ jobs: wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage chmod +x appimagelint-x86_64.AppImage + # rm -rf ~/.cache/appimagelint/ + ./appimagelint-x86_64.AppImage ./artifacts/sunshine.AppImage - name: Upload Artifacts From 68ba1db24ab66df63fd525d15f95b95bc958beac Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 11 May 2022 21:31:31 -0400 Subject: [PATCH 095/120] Refactor assets and config directory --- .github/workflows/CI.yml | 6 +- .gitignore | 16 ++--- CMakeLists.txt | 65 +++++++++++------- Portfile.in | 20 +++--- assets/linux-deb/conffiles | 2 - assets/linux-deb/preinst | 9 --- docs/source/about/advanced_usage.rst | 12 ++-- docs/source/about/installation.rst | 2 +- .../common/assets}/box.png | Bin .../common/assets}/steam.png | Bin .../common/assets}/web/apps.html | 0 .../common/assets}/web/clients.html | 0 .../common/assets}/web/config.html | 0 .../fonts/fontawesome-free-web/LICENSE.txt | 0 .../fonts/fontawesome-free-web/attribution.js | 0 .../fontawesome-free-web/css/all.min.css | 0 .../fontawesome-free-web/css/brands.min.css | 0 .../css/fontawesome.min.css | 0 .../fontawesome-free-web/css/regular.min.css | 0 .../fontawesome-free-web/css/solid.min.css | 0 .../css/svg-with-js.min.css | 0 .../fontawesome-free-web/css/v4-shims.min.css | 0 .../webfonts/fa-brands-400.eot | Bin .../webfonts/fa-brands-400.svg | 0 .../webfonts/fa-brands-400.ttf | Bin .../webfonts/fa-brands-400.woff | Bin .../webfonts/fa-brands-400.woff2 | Bin .../webfonts/fa-regular-400.eot | Bin .../webfonts/fa-regular-400.svg | 0 .../webfonts/fa-regular-400.ttf | Bin .../webfonts/fa-regular-400.woff | Bin .../webfonts/fa-regular-400.woff2 | Bin .../webfonts/fa-solid-900.eot | Bin .../webfonts/fa-solid-900.svg | 0 .../webfonts/fa-solid-900.ttf | Bin .../webfonts/fa-solid-900.woff | Bin .../webfonts/fa-solid-900.woff2 | Bin .../common/assets}/web/header-no-nav.html | 0 .../common/assets}/web/header.html | 0 .../common/assets}/web/images/favicon.ico | Bin .../assets}/web/images/logo-sunshine-45.png | Bin .../common/assets}/web/index.html | 0 .../common/assets}/web/password.html | 0 .../common/assets}/web/pin.html | 0 .../web/third_party/bootstrap.bundle.min.js | 0 .../assets}/web/third_party/bootstrap.min.css | 0 .../common/assets}/web/third_party/vue.js | 0 .../common/assets}/web/troubleshooting.html | 0 .../common/assets}/web/welcome.html | 0 .../common/config}/sunshine.conf | 0 .../assets}/shaders/opengl/ConvertUV.frag | 0 .../assets}/shaders/opengl/ConvertUV.vert | 0 .../assets}/shaders/opengl/ConvertY.frag | 0 .../linux/assets}/shaders/opengl/Scene.frag | 0 .../linux/assets}/shaders/opengl/Scene.vert | 0 .../linux/config}/apps.json | 0 src_assets/linux/deb/conffiles | 2 + .../linux/deb}/postinst | 16 ++--- src_assets/linux/deb/preinst | 9 +++ .../linux/misc}/85-sunshine-rules.rules | 0 .../macos/assets}/Info.plist | 0 .../macos/config}/apps.json | 0 .../assets}/shaders/directx/ConvertUVPS.hlsl | 0 .../assets}/shaders/directx/ConvertUVVS.hlsl | 0 .../assets}/shaders/directx/ConvertYPS.hlsl | 0 .../assets}/shaders/directx/ScenePS.hlsl | 0 .../assets}/shaders/directx/SceneVS.hlsl | 0 .../windows/config}/apps.json | 0 sunshine/config.cpp | 6 +- 69 files changed, 90 insertions(+), 75 deletions(-) delete mode 100644 assets/linux-deb/conffiles delete mode 100644 assets/linux-deb/preinst rename {assets/assets_common => src_assets/common/assets}/box.png (100%) rename {assets/assets_common => src_assets/common/assets}/steam.png (100%) rename {assets/assets_common => src_assets/common/assets}/web/apps.html (100%) rename {assets/assets_common => src_assets/common/assets}/web/clients.html (100%) rename {assets/assets_common => src_assets/common/assets}/web/config.html (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/LICENSE.txt (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/attribution.js (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/css/all.min.css (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/css/brands.min.css (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/css/fontawesome.min.css (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/css/regular.min.css (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/css/solid.min.css (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/css/svg-with-js.min.css (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/css/v4-shims.min.css (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.eot (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.svg (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.ttf (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff2 (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.eot (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.svg (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.ttf (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff2 (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.eot (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.svg (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.ttf (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff (100%) rename {assets/assets_common => src_assets/common/assets}/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff2 (100%) rename {assets/assets_common => src_assets/common/assets}/web/header-no-nav.html (100%) rename {assets/assets_common => src_assets/common/assets}/web/header.html (100%) rename {assets/assets_common => src_assets/common/assets}/web/images/favicon.ico (100%) rename {assets/assets_common => src_assets/common/assets}/web/images/logo-sunshine-45.png (100%) rename {assets/assets_common => src_assets/common/assets}/web/index.html (100%) rename {assets/assets_common => src_assets/common/assets}/web/password.html (100%) rename {assets/assets_common => src_assets/common/assets}/web/pin.html (100%) rename {assets/assets_common => src_assets/common/assets}/web/third_party/bootstrap.bundle.min.js (100%) rename {assets/assets_common => src_assets/common/assets}/web/third_party/bootstrap.min.css (100%) rename {assets/assets_common => src_assets/common/assets}/web/third_party/vue.js (100%) rename {assets/assets_common => src_assets/common/assets}/web/troubleshooting.html (100%) rename {assets/assets_common => src_assets/common/assets}/web/welcome.html (100%) rename {assets/assets_common => src_assets/common/config}/sunshine.conf (100%) rename {assets/assets_linux => src_assets/linux/assets}/shaders/opengl/ConvertUV.frag (100%) rename {assets/assets_linux => src_assets/linux/assets}/shaders/opengl/ConvertUV.vert (100%) rename {assets/assets_linux => src_assets/linux/assets}/shaders/opengl/ConvertY.frag (100%) rename {assets/assets_linux => src_assets/linux/assets}/shaders/opengl/Scene.frag (100%) rename {assets/assets_linux => src_assets/linux/assets}/shaders/opengl/Scene.vert (100%) rename {assets/assets_linux => src_assets/linux/config}/apps.json (100%) create mode 100644 src_assets/linux/deb/conffiles rename {assets/linux-deb => src_assets/linux/deb}/postinst (59%) create mode 100644 src_assets/linux/deb/preinst rename {assets/linux-misc => src_assets/linux/misc}/85-sunshine-rules.rules (100%) rename {assets/assets_mac => src_assets/macos/assets}/Info.plist (100%) rename {assets/assets_mac => src_assets/macos/config}/apps.json (100%) rename {assets/assets_windows => src_assets/windows/assets}/shaders/directx/ConvertUVPS.hlsl (100%) rename {assets/assets_windows => src_assets/windows/assets}/shaders/directx/ConvertUVVS.hlsl (100%) rename {assets/assets_windows => src_assets/windows/assets}/shaders/directx/ConvertYPS.hlsl (100%) rename {assets/assets_windows => src_assets/windows/assets}/shaders/directx/ScenePS.hlsl (100%) rename {assets/assets_windows => src_assets/windows/assets}/shaders/directx/SceneVS.hlsl (100%) rename {assets/assets_windows => src_assets/windows/config}/apps.json (100%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index a1b091b91d2..dac856ed1c6 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -130,7 +130,7 @@ jobs: mkdir -p build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_CONFIG_DIR=. -DSUNSHINE_DEFAULT_DIR=/etc/sunshine -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine -DSUNSHINE_ENABLE_WAYLAND=ON -DSUNSHINE_ENABLE_X11=ON -DSUNSHINE_ENABLE_DRM=ON -DSUNSHINE_ENABLE_CUDA=ON "../" + cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=/usr/local/sunshine/.assets -DSUNSHINE_CONFIG_DIR=/usr/local/sunshine/config -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine -DSUNSHINE_ENABLE_WAYLAND=ON -DSUNSHINE_ENABLE_X11=ON -DSUNSHINE_ENABLE_DRM=ON -DSUNSHINE_ENABLE_CUDA=ON .. make -j ${nproc} - name: Set AppImage Version @@ -228,7 +228,7 @@ jobs: run: | mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_DEFAULT_DIR=/etc/sunshine .. + cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=/usr/local/sunshine/.assets -DSUNSHINE_CONFIG_DIR=/usr/local/sunshine/config .. make -j ${nproc} - name: Package MacOS @@ -297,7 +297,7 @@ jobs: run: | mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=assets -G "MinGW Makefiles" .. + cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=assets -DSUNSHINE_CONFIG_DIR=config -G "MinGW Makefiles" .. mingw32-make -j2 - name: Package Windows diff --git a/.gitignore b/.gitignore index 39afd65aeba..6c44c5bc23e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,14 +10,14 @@ cmake-build* .idea # Extra FontAwesome files -/assets/web/fonts/fontawesome-free-web/css/*.css -!/assets/web/fonts/fontawesome-free-web/css/*min.css -/assets/web/fonts/fontawesome-free-web/js/ -/assets/web/fonts/fontawesome-free-web/less/ -/assets/web/fonts/fontawesome-free-web/metadata/ -/assets/web/fonts/fontawesome-free-web/scss/ -/assets/web/fonts/fontawesome-free-web/sprites/ -/assets/web/fonts/fontawesome-free-web/svgs/ +/src_assets/common/assets/web/fonts/fontawesome-free-web/css/*.css +!/src_assets/common/assets/web/fonts/fontawesome-free-web/css/*min.css +/src_assets/common/assets/web/fonts/fontawesome-free-web/js/ +/src_assets/common/assets/web/fonts/fontawesome-free-web/less/ +/src_assets/common/assets/web/fonts/fontawesome-free-web/metadata/ +/src_assets/common/assets/web/fonts/fontawesome-free-web/scss/ +/src_assets/common/assets/web/fonts/fontawesome-free-web/sprites/ +/src_assets/common/assets/web/fonts/fontawesome-free-web/svgs/ # Translations *.mo diff --git a/CMakeLists.txt b/CMakeLists.txt index f58e0439392..68035d547d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ project(Sunshine VERSION 0.13.0 ) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +set(SUNSHINE_SOURCE_ASSETS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src_assets") if(WIN32) # Ugly hack to compile with #include @@ -147,6 +148,8 @@ elseif(APPLE) set(PLATFORM_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) + set(APPLE_PLIST_FILE ${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/Info.plist) + set(PLATFORM_TARGET_FILES sunshine/platform/macos/av_audio.h sunshine/platform/macos/av_audio.m @@ -163,7 +166,7 @@ elseif(APPLE) sunshine/platform/macos/publish.cpp sunshine/platform/macos/TPCircularBuffer/TPCircularBuffer.c sunshine/platform/macos/TPCircularBuffer/TPCircularBuffer.h - ${CMAKE_CURRENT_SOURCE_DIR}/assets/assets_mac/Info.plist) + ${APPLE_PLIST_FILE}) else() add_compile_definitions(SUNSHINE_PLATFORM="linux") @@ -390,15 +393,11 @@ else() endif() if(NOT SUNSHINE_ASSETS_DIR) - set(SUNSHINE_ASSETS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/assets") + set(SUNSHINE_ASSETS_DIR "${CMAKE_CURRENT_BINARY_DIR}/.assets") endif() if(NOT SUNSHINE_CONFIG_DIR) - set(SUNSHINE_CONFIG_DIR "${SUNSHINE_ASSETS_DIR}") -endif() - -if(NOT SUNSHINE_DEFAULT_DIR) - set(SUNSHINE_DEFAULT_DIR "${SUNSHINE_ASSETS_DIR}") + set(SUNSHINE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}/config") endif() list(APPEND CBS_EXTERNAL_LIBRARIES @@ -421,8 +420,6 @@ endif() list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_ASSETS_DIR="${SUNSHINE_ASSETS_DIR}") list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_CONFIG_DIR="${SUNSHINE_CONFIG_DIR}") -list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_DEFAULT_DIR="${SUNSHINE_DEFAULT_DIR}") -list(APPEND SUNSHINE_DEFINITIONS APPS_JSON="apps.json") add_executable(sunshine ${SUNSHINE_TARGET_FILES}) target_link_libraries(sunshine ${SUNSHINE_EXTERNAL_LIBRARIES} ${EXTRA_LIBS}) target_compile_definitions(sunshine PUBLIC ${SUNSHINE_DEFINITIONS}) @@ -437,7 +434,7 @@ if(NOT DEFINED CMAKE_CUDA_STANDARD) endif() if(APPLE) - target_link_options(sunshine PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/assets/assets_mac/Info.plist) + target_link_options(sunshine PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,${APPLE_PLIST_FILE}) endif() foreach(flag IN LISTS SUNSHINE_COMPILE_OPTIONS) @@ -472,8 +469,11 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h install(TARGETS audio-info RUNTIME DESTINATION "tools" COMPONENT audio) install(TARGETS sunshinesvc RUNTIME DESTINATION "tools" COMPONENT sunshinesvc) - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_common/" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_windows/" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT assets) + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}" COMPONENT assets) + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}" COMPONENT assets) + + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/common/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT config) + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}" COMPONENT config) # set(CPACK_NSIS_MUI_HEADERIMAGE "") # TODO: image should be 150x57 bmp @@ -509,10 +509,16 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h # assets set(CPACK_COMPONENT_ASSETS_DISPLAY_NAME "Assets") - set(CPACK_COMPONENT_ASSETS_DESCRIPTION "Assets include the apps and configurations, shaders, default box art, and web ui.") + set(CPACK_COMPONENT_ASSETS_DESCRIPTION "Shaders, default box art, and web ui.") set(CPACK_COMPONENT_ASSETS_GROUP "${CMAKE_PROJECT_NAME}") set(CPACK_COMPONENT_ASSETS_REQUIRED true) + # config + set(CPACK_COMPONENT_CONFIG_DISPLAY_NAME "Config") + set(CPACK_COMPONENT_CONFIG_DESCRIPTION "Default config and apps.json files.") + set(CPACK_COMPONENT_CONFIG_GROUP "${CMAKE_PROJECT_NAME}") + set(CPACK_COMPONENT_CONFIG_REQUIRED true) + # audio tool set(CPACK_COMPONENT_AUDIO_DISPLAY_NAME "audio-info.exe") set(CPACK_COMPONENT_AUDIO_DESCRIPTION "CLI tool that allows you to get information about sound devices.") @@ -528,13 +534,23 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h set(CPACK_COMPONENT_SUNSHINESVC_DESCRIPTION "CLI tool that allows you to enable/disable the Sunshine service.") set(CPACK_COMPONENT_SUNSHINESVC_GROUP "Tools") endif() +if(UNIX) + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}") + + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/common/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}") + + # Installation destination dir + set(CPACK_SET_DESTDIR true) + set(CMAKE_INSTALL_PREFIX "/usr/local/sunshine/") +endif() if(APPLE) # TODO: test set(prefix "${CMAKE_PROJECT_NAME}.app/Contents") set(INSTALL_RUNTIME_DIR "${prefix}/MacOS") - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_common/" DESTINATION "${INSTALL_RUNTIME_DIR}") - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_mac/" DESTINATION "${INSTALL_RUNTIME_DIR}") + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}") + + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}") install(TARGETS sunshine BUNDLE DESTINATION . COMPONENT Runtime @@ -542,26 +558,27 @@ if(APPLE) # TODO: test # TODO: bundle doesn't produce a valid .app use cpack -G DragNDrop set(CPACK_BUNDLE_NAME "${CMAKE_PROJECT_NAME}") - set(CPACK_BUNDLE_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/assets_mac/Info.plist") + set(CPACK_BUNDLE_PLIST "${APPLE_PLIST_FILE}") set(CPACK_BUNDLE_ICON "${PROJECT_SOURCE_DIR}/sunshine.icns") # Portfile configure_file(Portfile.in Portfile @ONLY) endif() if(UNIX AND NOT APPLE) - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_common/" DESTINATION "${SUNSHINE_CONFIG_DIR}") - install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/assets_linux/" DESTINATION "${SUNSHINE_CONFIG_DIR}") + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}") + + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}") - install(FILES "${SUNSHINE_ASSETS_DIR}/linux-misc/85-sunshine-rules.rules" DESTINATION "/etc/udev/rules.d") + install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/85-sunshine-rules.rules" DESTINATION "/etc/udev/rules.d") install(TARGETS sunshine RUNTIME DESTINATION "/usr/bin") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" DESTINATION "/usr/lib/systemd/user") # Pre and post install set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA - "${SUNSHINE_ASSETS_DIR}/linux-deb/preinst;${SUNSHINE_ASSETS_DIR}/linux-deb/postinst;${SUNSHINE_ASSETS_DIR}/linux-deb/conffiles") - set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE "${SUNSHINE_ASSETS_DIR}/linux-deb/preinst") - set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${SUNSHINE_ASSETS_DIR}/linux-deb/postinst") + "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/deb/preinst;${SUNSHINE_SOURCE_ASSETS_DIR}/linux/deb/postinst;${SUNSHINE_SOURCE_ASSETS_DIR}/linux/deb/conffiles") + set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/deb/preinst") + set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/deb/postinst") # Dependencies set(CPACK_DEB_COMPONENT_INSTALL ON) @@ -569,10 +586,6 @@ if(UNIX AND NOT APPLE) set(CPACK_RPM_PACKAGE_REQUIRES "libssl==1.1, libavdevice>=58, libboost-thread>=1.67.0, libboost-filesystem>=1.67.0, libboost-log>=1.67.0, libpulse>=0, libopus>=0, libxcb-shm>=0, libxcb-xfixes>=0, libxtst>=0, libevdev>=2.0, libdrm>=2.0, libcap>=2.0") set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF) # This should automatically figure out dependencies, doesn't work with the current config - # Installation destination dir - set(CPACK_SET_DESTDIR true) - set(CMAKE_INSTALL_PREFIX "/etc/sunshine") - # AppImage desktop file configure_file(sunshine.desktop.in sunshine.desktop @ONLY) endif() diff --git a/Portfile.in b/Portfile.in index c784c3b05b0..2cb3546681e 100644 --- a/Portfile.in +++ b/Portfile.in @@ -31,21 +31,19 @@ depends_lib port:avahi \ boost.version 1.76 configure.args -DBOOST_ROOT=[boost::install_area] \ - -DSUNSHINE_ASSETS_DIR=${worksrcpath}/assets - -DSUNSHINE_DEFAULT_DIR=${prefix}/etc/sunshine + -DSUNSHINE_ASSETS_DIR=${prefix}/usr/local/sunshine/.assets + -DSUNSHINE_CONFIG_DIR=${prefix}/usr/local/sunshine/config cmake.out_of_source yes destroot { - xinstall -d -m 755 ${destroot}${prefix}/etc/${name} - xinstall ${worksrcpath}/assets/assets_mac/apps.json ${destroot}${prefix}/etc/${name} - xinstall ${worksrcpath}/assets/assets_common/box.png ${destroot}${prefix}/etc/${name} - xinstall ${worksrcpath}/assets/assets_common/sunshine.conf ${destroot}${prefix}/etc/${name} - - xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/web - xinstall {*}[glob ${worksrcpath}/assets/assets_common/web/*.html] ${destroot}${prefix}/etc/${name}/web - xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/web/third_party - xinstall {*}[glob ${worksrcpath}/assets/assets_common/web/third_party/*] ${destroot}${prefix}/etc/${name}/web/third_party + xinstall -d -m 755 ${destroot}${prefix}/usr/local/${name}/.assets + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/*] ${destroot}${prefix}/usr/local/${name}/.assets + xinstall {*}[glob ${worksrcpath}/src_assets/macos/assets/*] ${destroot}${prefix}/usr/local/${name}/.assets + + xinstall -d -m 755 ${destroot}${prefix}/usr/local/${name}/config + xinstall {*}[glob ${worksrcpath}/src_assets/common/config/*] ${destroot}${prefix}/usr/local/${name}/config + xinstall {*}[glob ${worksrcpath}/src_assets/macos/config/*] ${destroot}${prefix}/usr/local/${name}/config xinstall ${workpath}/build/${name} ${destroot}${prefix}/bin } diff --git a/assets/linux-deb/conffiles b/assets/linux-deb/conffiles deleted file mode 100644 index cf2d2444378..00000000000 --- a/assets/linux-deb/conffiles +++ /dev/null @@ -1,2 +0,0 @@ -/etc/sunshine/sunshine.conf -/etc/sunshine/apps.json diff --git a/assets/linux-deb/preinst b/assets/linux-deb/preinst deleted file mode 100644 index ec56e883c48..00000000000 --- a/assets/linux-deb/preinst +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -#Store backup for old config files to prevent it from being overwritten -if [ -f /etc/sunshine/sunshine.conf ]; then - cp /etc/sunshine/sunshine.conf /etc/sunshine/sunshine.conf.old -fi - -if [ -f /etc/sunshine/apps.json ]; then - cp /etc/sunshine/apps.json /etc/sunshine/apps.json.old -fi diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index 4f427dcb253..7699232c8e1 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -6,9 +6,12 @@ Sunshine will work with the default settings for most users. In some cases you m Configuration ------------- -The default location for the configuration file is ``./assets/sunshine.conf``. You can use another location if you +The default location for the configuration file is listed below. You can use another location if you choose, by passing in the full configuration file path as the first argument when you start Sunshine. +The default location of the ``apps.json`` is the same as the configuration file. You can use a custom +location by modifying the configuration file. + **Default File Location** .. table:: @@ -17,9 +20,10 @@ choose, by passing in the full configuration file path as the first argument whe ======= =========== Value Description ======= =========== - Linux ./assets/sunshine.conf - MacOS /opt/local/etc/sunshine.conf - Windows ./assets/sunshine.conf + Docker /config/ + Linux /usr/local/sunshine/config/ + MacOS /usr/local/sunshine/config/ + Windows ./config/ ======= =========== Example diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index d7e043a40d0..40eecd209c0 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -27,7 +27,7 @@ AppImage .. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/pkg:appimage?logo=github&style=for-the-badge :alt: GitHub issues by-label -The current compatibility of the AppImage is shown below. +The current known compatibility of the AppImage is shown below. - [✖] Debian oldstable (buster) - [✔] Debian stable (bullseye) diff --git a/assets/assets_common/box.png b/src_assets/common/assets/box.png similarity index 100% rename from assets/assets_common/box.png rename to src_assets/common/assets/box.png diff --git a/assets/assets_common/steam.png b/src_assets/common/assets/steam.png similarity index 100% rename from assets/assets_common/steam.png rename to src_assets/common/assets/steam.png diff --git a/assets/assets_common/web/apps.html b/src_assets/common/assets/web/apps.html similarity index 100% rename from assets/assets_common/web/apps.html rename to src_assets/common/assets/web/apps.html diff --git a/assets/assets_common/web/clients.html b/src_assets/common/assets/web/clients.html similarity index 100% rename from assets/assets_common/web/clients.html rename to src_assets/common/assets/web/clients.html diff --git a/assets/assets_common/web/config.html b/src_assets/common/assets/web/config.html similarity index 100% rename from assets/assets_common/web/config.html rename to src_assets/common/assets/web/config.html diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/LICENSE.txt b/src_assets/common/assets/web/fonts/fontawesome-free-web/LICENSE.txt similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/LICENSE.txt rename to src_assets/common/assets/web/fonts/fontawesome-free-web/LICENSE.txt diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/attribution.js b/src_assets/common/assets/web/fonts/fontawesome-free-web/attribution.js similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/attribution.js rename to src_assets/common/assets/web/fonts/fontawesome-free-web/attribution.js diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/css/all.min.css b/src_assets/common/assets/web/fonts/fontawesome-free-web/css/all.min.css similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/css/all.min.css rename to src_assets/common/assets/web/fonts/fontawesome-free-web/css/all.min.css diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/css/brands.min.css b/src_assets/common/assets/web/fonts/fontawesome-free-web/css/brands.min.css similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/css/brands.min.css rename to src_assets/common/assets/web/fonts/fontawesome-free-web/css/brands.min.css diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/css/fontawesome.min.css b/src_assets/common/assets/web/fonts/fontawesome-free-web/css/fontawesome.min.css similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/css/fontawesome.min.css rename to src_assets/common/assets/web/fonts/fontawesome-free-web/css/fontawesome.min.css diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/css/regular.min.css b/src_assets/common/assets/web/fonts/fontawesome-free-web/css/regular.min.css similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/css/regular.min.css rename to src_assets/common/assets/web/fonts/fontawesome-free-web/css/regular.min.css diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/css/solid.min.css b/src_assets/common/assets/web/fonts/fontawesome-free-web/css/solid.min.css similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/css/solid.min.css rename to src_assets/common/assets/web/fonts/fontawesome-free-web/css/solid.min.css diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/css/svg-with-js.min.css b/src_assets/common/assets/web/fonts/fontawesome-free-web/css/svg-with-js.min.css similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/css/svg-with-js.min.css rename to src_assets/common/assets/web/fonts/fontawesome-free-web/css/svg-with-js.min.css diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/css/v4-shims.min.css b/src_assets/common/assets/web/fonts/fontawesome-free-web/css/v4-shims.min.css similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/css/v4-shims.min.css rename to src_assets/common/assets/web/fonts/fontawesome-free-web/css/v4-shims.min.css diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.eot b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.eot similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.eot rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.eot diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.svg b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.svg similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.svg rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.svg diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.ttf b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.ttf similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.ttf rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.ttf diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff2 b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff2 similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff2 rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-brands-400.woff2 diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.eot b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.eot similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.eot rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.eot diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.svg b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.svg similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.svg rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.svg diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.ttf b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.ttf similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.ttf rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.ttf diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff2 b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff2 similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff2 rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-regular-400.woff2 diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.eot b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.eot similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.eot rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.eot diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.svg b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.svg similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.svg rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.svg diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.ttf b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.ttf similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.ttf rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.ttf diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff diff --git a/assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff2 b/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff2 similarity index 100% rename from assets/assets_common/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff2 rename to src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/fa-solid-900.woff2 diff --git a/assets/assets_common/web/header-no-nav.html b/src_assets/common/assets/web/header-no-nav.html similarity index 100% rename from assets/assets_common/web/header-no-nav.html rename to src_assets/common/assets/web/header-no-nav.html diff --git a/assets/assets_common/web/header.html b/src_assets/common/assets/web/header.html similarity index 100% rename from assets/assets_common/web/header.html rename to src_assets/common/assets/web/header.html diff --git a/assets/assets_common/web/images/favicon.ico b/src_assets/common/assets/web/images/favicon.ico similarity index 100% rename from assets/assets_common/web/images/favicon.ico rename to src_assets/common/assets/web/images/favicon.ico diff --git a/assets/assets_common/web/images/logo-sunshine-45.png b/src_assets/common/assets/web/images/logo-sunshine-45.png similarity index 100% rename from assets/assets_common/web/images/logo-sunshine-45.png rename to src_assets/common/assets/web/images/logo-sunshine-45.png diff --git a/assets/assets_common/web/index.html b/src_assets/common/assets/web/index.html similarity index 100% rename from assets/assets_common/web/index.html rename to src_assets/common/assets/web/index.html diff --git a/assets/assets_common/web/password.html b/src_assets/common/assets/web/password.html similarity index 100% rename from assets/assets_common/web/password.html rename to src_assets/common/assets/web/password.html diff --git a/assets/assets_common/web/pin.html b/src_assets/common/assets/web/pin.html similarity index 100% rename from assets/assets_common/web/pin.html rename to src_assets/common/assets/web/pin.html diff --git a/assets/assets_common/web/third_party/bootstrap.bundle.min.js b/src_assets/common/assets/web/third_party/bootstrap.bundle.min.js similarity index 100% rename from assets/assets_common/web/third_party/bootstrap.bundle.min.js rename to src_assets/common/assets/web/third_party/bootstrap.bundle.min.js diff --git a/assets/assets_common/web/third_party/bootstrap.min.css b/src_assets/common/assets/web/third_party/bootstrap.min.css similarity index 100% rename from assets/assets_common/web/third_party/bootstrap.min.css rename to src_assets/common/assets/web/third_party/bootstrap.min.css diff --git a/assets/assets_common/web/third_party/vue.js b/src_assets/common/assets/web/third_party/vue.js similarity index 100% rename from assets/assets_common/web/third_party/vue.js rename to src_assets/common/assets/web/third_party/vue.js diff --git a/assets/assets_common/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html similarity index 100% rename from assets/assets_common/web/troubleshooting.html rename to src_assets/common/assets/web/troubleshooting.html diff --git a/assets/assets_common/web/welcome.html b/src_assets/common/assets/web/welcome.html similarity index 100% rename from assets/assets_common/web/welcome.html rename to src_assets/common/assets/web/welcome.html diff --git a/assets/assets_common/sunshine.conf b/src_assets/common/config/sunshine.conf similarity index 100% rename from assets/assets_common/sunshine.conf rename to src_assets/common/config/sunshine.conf diff --git a/assets/assets_linux/shaders/opengl/ConvertUV.frag b/src_assets/linux/assets/shaders/opengl/ConvertUV.frag similarity index 100% rename from assets/assets_linux/shaders/opengl/ConvertUV.frag rename to src_assets/linux/assets/shaders/opengl/ConvertUV.frag diff --git a/assets/assets_linux/shaders/opengl/ConvertUV.vert b/src_assets/linux/assets/shaders/opengl/ConvertUV.vert similarity index 100% rename from assets/assets_linux/shaders/opengl/ConvertUV.vert rename to src_assets/linux/assets/shaders/opengl/ConvertUV.vert diff --git a/assets/assets_linux/shaders/opengl/ConvertY.frag b/src_assets/linux/assets/shaders/opengl/ConvertY.frag similarity index 100% rename from assets/assets_linux/shaders/opengl/ConvertY.frag rename to src_assets/linux/assets/shaders/opengl/ConvertY.frag diff --git a/assets/assets_linux/shaders/opengl/Scene.frag b/src_assets/linux/assets/shaders/opengl/Scene.frag similarity index 100% rename from assets/assets_linux/shaders/opengl/Scene.frag rename to src_assets/linux/assets/shaders/opengl/Scene.frag diff --git a/assets/assets_linux/shaders/opengl/Scene.vert b/src_assets/linux/assets/shaders/opengl/Scene.vert similarity index 100% rename from assets/assets_linux/shaders/opengl/Scene.vert rename to src_assets/linux/assets/shaders/opengl/Scene.vert diff --git a/assets/assets_linux/apps.json b/src_assets/linux/config/apps.json similarity index 100% rename from assets/assets_linux/apps.json rename to src_assets/linux/config/apps.json diff --git a/src_assets/linux/deb/conffiles b/src_assets/linux/deb/conffiles new file mode 100644 index 00000000000..4a35822bf61 --- /dev/null +++ b/src_assets/linux/deb/conffiles @@ -0,0 +1,2 @@ +/usr/local/sunshine/config/sunshine.conf +/usr/local/sunshine/config/apps.json diff --git a/assets/linux-deb/postinst b/src_assets/linux/deb/postinst similarity index 59% rename from assets/linux-deb/postinst rename to src_assets/linux/deb/postinst index d3195c6a4df..a42d3ca50c0 100644 --- a/assets/linux-deb/postinst +++ b/src_assets/linux/deb/postinst @@ -12,25 +12,25 @@ else echo "Warning: /etc/group not found" fi -if [ -f /etc/sunshine/sunshine.conf.old ]; then +if [ -f /usr/local/sunshine/config/sunshine.conf.old ]; then echo "Restoring old sunshine.conf" - mv /etc/sunshine/sunshine.conf.old /etc/sunshine/sunshine.conf + mv /usr/local/sunshine/config/sunshine.conf.old /usr/local/sunshine/config/sunshine.conf fi -if [ -f /etc/sunshine/apps.json.old ]; then +if [ -f /usr/local/sunshine/config/apps.json.old ]; then echo "Restoring old apps.json" - mv /etc/sunshine/apps.json.old /etc/sunshine/apps.json + mv /usr/local/sunshine/config/apps.json.old /usr/local/sunshine/config/apps.json fi # Update permissions on config files for Web Manager -if [ -f /etc/sunshine/apps.json ]; then +if [ -f /usr/local/sunshine/config/apps.json ]; then echo "chmod 666 /etc/sunshine/apps.json" - chmod 666 /etc/sunshine/apps.json + chmod 666 /usr/local/sunshine/config/apps.json fi -if [ -f /etc/sunshine/sunshine.conf ]; then +if [ -f /usr/local/sunshine/config/sunshine.conf ]; then echo "chmod 666 /etc/sunshine/sunshine.conf" - chmod 666 /etc/sunshine/sunshine.conf + chmod 666 /usr/local/sunshine/config/sunshine.conf fi # Ensure Sunshine can grab images from KMS diff --git a/src_assets/linux/deb/preinst b/src_assets/linux/deb/preinst new file mode 100644 index 00000000000..0522b5d6f84 --- /dev/null +++ b/src_assets/linux/deb/preinst @@ -0,0 +1,9 @@ +#!/bin/sh +#Store backup for old config files to prevent it from being overwritten +if [ -f /usr/local/sunshine/config/sunshine.conf ]; then + cp /usr/local/sunshine/config/sunshine.conf /usr/local/sunshine/config/sunshine.conf.old +fi + +if [ -f /usr/local/sunshine/config/apps.json ]; then + cp /usr/local/sunshine/config/apps.json /usr/local/sunshine/config/apps.json.old +fi diff --git a/assets/linux-misc/85-sunshine-rules.rules b/src_assets/linux/misc/85-sunshine-rules.rules similarity index 100% rename from assets/linux-misc/85-sunshine-rules.rules rename to src_assets/linux/misc/85-sunshine-rules.rules diff --git a/assets/assets_mac/Info.plist b/src_assets/macos/assets/Info.plist similarity index 100% rename from assets/assets_mac/Info.plist rename to src_assets/macos/assets/Info.plist diff --git a/assets/assets_mac/apps.json b/src_assets/macos/config/apps.json similarity index 100% rename from assets/assets_mac/apps.json rename to src_assets/macos/config/apps.json diff --git a/assets/assets_windows/shaders/directx/ConvertUVPS.hlsl b/src_assets/windows/assets/shaders/directx/ConvertUVPS.hlsl similarity index 100% rename from assets/assets_windows/shaders/directx/ConvertUVPS.hlsl rename to src_assets/windows/assets/shaders/directx/ConvertUVPS.hlsl diff --git a/assets/assets_windows/shaders/directx/ConvertUVVS.hlsl b/src_assets/windows/assets/shaders/directx/ConvertUVVS.hlsl similarity index 100% rename from assets/assets_windows/shaders/directx/ConvertUVVS.hlsl rename to src_assets/windows/assets/shaders/directx/ConvertUVVS.hlsl diff --git a/assets/assets_windows/shaders/directx/ConvertYPS.hlsl b/src_assets/windows/assets/shaders/directx/ConvertYPS.hlsl similarity index 100% rename from assets/assets_windows/shaders/directx/ConvertYPS.hlsl rename to src_assets/windows/assets/shaders/directx/ConvertYPS.hlsl diff --git a/assets/assets_windows/shaders/directx/ScenePS.hlsl b/src_assets/windows/assets/shaders/directx/ScenePS.hlsl similarity index 100% rename from assets/assets_windows/shaders/directx/ScenePS.hlsl rename to src_assets/windows/assets/shaders/directx/ScenePS.hlsl diff --git a/assets/assets_windows/shaders/directx/SceneVS.hlsl b/src_assets/windows/assets/shaders/directx/SceneVS.hlsl similarity index 100% rename from assets/assets_windows/shaders/directx/SceneVS.hlsl rename to src_assets/windows/assets/shaders/directx/SceneVS.hlsl diff --git a/assets/assets_windows/apps.json b/src_assets/windows/config/apps.json similarity index 100% rename from assets/assets_windows/apps.json rename to src_assets/windows/config/apps.json diff --git a/sunshine/config.cpp b/sunshine/config.cpp index 6aaeb3058e2..6dd3c1b2b67 100644 --- a/sunshine/config.cpp +++ b/sunshine/config.cpp @@ -20,7 +20,7 @@ using namespace std::literals; #define PRIVATE_KEY_FILE CA_DIR "/cakey.pem" #define CERTIFICATE_FILE CA_DIR "/cacert.pem" -#define APPS_JSON_PATH SUNSHINE_CONFIG_DIR "/" APPS_JSON +#define APPS_JSON_PATH SUNSHINE_CONFIG_DIR "/apps.json" namespace config { namespace nv { @@ -695,7 +695,7 @@ int apply_flags(const char *line) { void apply_config(std::unordered_map &&vars) { if(!fs::exists(stream.file_apps.c_str())) { - fs::copy_file(SUNSHINE_DEFAULT_DIR "/" APPS_JSON, stream.file_apps); + fs::copy_file(SUNSHINE_CONFIG_DIR "/apps.json", stream.file_apps); } for(auto &[name, val] : vars) { @@ -906,7 +906,7 @@ int parse(int argc, char *argv[]) { } if(!fs::exists(sunshine.config_file)) { - fs::copy_file(SUNSHINE_DEFAULT_DIR "/sunshine.conf", sunshine.config_file); + fs::copy_file(SUNSHINE_CONFIG_DIR "/sunshine.conf", sunshine.config_file); } auto vars = parse_config(read_file(sunshine.config_file.c_str())); From c719ddfc31e418c58b4b3244661e33ffd78032fb Mon Sep 17 00:00:00 2001 From: Karl Vogel Date: Sat, 14 May 2022 12:16:14 +0200 Subject: [PATCH 096/120] fedora: add libcap/libdrm-devel to enable KMS code --- scripts/Dockerfile-fedora_33 | 2 ++ scripts/Dockerfile-fedora_35 | 2 ++ 2 files changed, 4 insertions(+) diff --git a/scripts/Dockerfile-fedora_33 b/scripts/Dockerfile-fedora_33 index 136058c3ec7..320c6a6748c 100644 --- a/scripts/Dockerfile-fedora_33 +++ b/scripts/Dockerfile-fedora_33 @@ -21,6 +21,8 @@ RUN dnf -y update && \ openssl-devel \ opus-devel \ pulseaudio-libs-devel \ + libcap-devel \ + libdrm-devel \ rpm-build \ && dnf clean all \ && rm -rf /var/cache/yum diff --git a/scripts/Dockerfile-fedora_35 b/scripts/Dockerfile-fedora_35 index 18b04377c14..18f5bf53a56 100644 --- a/scripts/Dockerfile-fedora_35 +++ b/scripts/Dockerfile-fedora_35 @@ -25,6 +25,8 @@ RUN dnf -y update && \ openssl-devel \ opus-devel \ pulseaudio-libs-devel \ + libcap-devel \ + libdrm-devel \ rpm-build \ && dnf clean all \ && rm -rf /var/cache/yum From 4f6b00148355ecac62ddfb1ea74e04d371524521 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 14 May 2022 08:43:58 -0400 Subject: [PATCH 097/120] Update paths and dependencies - Updates paths for Linux and MacOS builds - Strategy matrix build for Linux (CPACK/AppImage) - Fix dependencies for rpm package --- .github/workflows/CI.yml | 54 ++++++++++++++++++------ CMakeLists.txt | 20 +++++---- Portfile.in | 4 +- src_assets/linux/{deb => misc}/conffiles | 0 src_assets/linux/{deb => misc}/postinst | 0 src_assets/linux/{deb => misc}/preinst | 0 6 files changed, 53 insertions(+), 25 deletions(-) rename src_assets/linux/{deb => misc}/conffiles (100%) rename src_assets/linux/{deb => misc}/postinst (100%) rename src_assets/linux/{deb => misc}/preinst (100%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 285ef5725e4..71abe96eef8 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -56,6 +56,19 @@ jobs: name: Linux runs-on: ubuntu-20.04 needs: check_changelog + strategy: + fail-fast: false # false to test all, true to fail entire job if any fail + matrix: + include: # package these differently + - type: cpack + CMAKE_INSTALL_PREFIX: '/usr/local/sunshine' + SUNSHINE_ASSETS_DIR: 'assets' + SUNSHINE_CONFIG_DIR: 'config' + - type: appimage + CMAKE_INSTALL_PREFIX: '.' + SUNSHINE_ASSETS_DIR: 'usr/local/sunshine/assets' + SUNSHINE_CONFIG_DIR: 'usr/local/sunshine/config' + steps: - name: Checkout uses: actions/checkout@v3 @@ -128,21 +141,39 @@ jobs: - name: Build Linux run: | mkdir -p build + mkdir -p artifacts cd build - cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=/usr/local/sunshine/.assets -DSUNSHINE_CONFIG_DIR=/usr/local/sunshine/config -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine -DSUNSHINE_ENABLE_WAYLAND=ON -DSUNSHINE_ENABLE_X11=ON -DSUNSHINE_ENABLE_DRM=ON -DSUNSHINE_ENABLE_CUDA=ON .. + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${{ matrix.CMAKE_INSTALL_PREFIX }} -DSUNSHINE_ASSETS_DIR=${{ matrix.SUNSHINE_ASSETS_DIR }} -DSUNSHINE_CONFIG_DIR=${{ matrix.SUNSHINE_CONFIG_DIR }} -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine -DSUNSHINE_ENABLE_WAYLAND=ON -DSUNSHINE_ENABLE_X11=ON -DSUNSHINE_ENABLE_DRM=ON -DSUNSHINE_ENABLE_CUDA=ON .. make -j ${nproc} + - name: Package Linux - CPACK + if: ${{ matrix.type == 'cpack' }} + working-directory: build + run: | + # package + cpack -G DEB + cpack -G RPM + + # move + mv ./cpack_artifacts/Sunshine.deb ../artifacts/sunshine.deb + mv ./cpack_artifacts/Sunshine.rpm ../artifacts/sunshine.rpm + - name: Set AppImage Version - if: ${{ needs.check_changelog.outputs.next_version_bare != needs.check_changelog.outputs.latest_version }} + if: ${{ matrix.type == 'appimage' && ( needs.check_changelog.outputs.next_version_bare != needs.check_changelog.outputs.latest_version ) }} run: | version=${{ needs.check_changelog.outputs.next_version_bare }} echo "VERSION=${version}" >> $GITHUB_ENV - - name: Package Linux + - name: Package Linux - AppImage + if: ${{ matrix.type == 'appimage' }} + working-directory: build run: | - mkdir -p artifacts - cd build + # install sunshine to the DESTDIR + make install DESTDIR=AppDir + + # testing only + ls AppDir # variables DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" @@ -160,7 +191,7 @@ jobs: # export DEPLOY_GTK_VERSION=3 ./linuxdeploy-x86_64.AppImage \ - --appdir . \ + --appdir ./AppDir \ --executable ./sunshine \ --icon-file "../$ICON_FILE" \ --desktop-file "./$DESKTOP_FILE" \ @@ -171,16 +202,11 @@ jobs: # # add this argument back if using gtk plugin # --plugin gtk \ - # package - cpack -G DEB - cpack -G RPM - # move mv Sunshine*.AppImage ../artifacts/sunshine.AppImage - mv ./cpack_artifacts/Sunshine.deb ../artifacts/sunshine.deb - mv ./cpack_artifacts/Sunshine.rpm ../artifacts/sunshine.rpm - name: Verify AppImage + if: ${{ matrix.type == 'appimage' }} run: | wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage chmod +x appimagelint-x86_64.AppImage @@ -193,7 +219,7 @@ jobs: if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: - name: sunshine-linux + name: sunshine-linux-${{ matrix.type }} path: artifacts/ - name: Create Release @@ -229,7 +255,7 @@ jobs: run: | mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=/usr/local/sunshine/.assets -DSUNSHINE_CONFIG_DIR=/usr/local/sunshine/config .. + cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=/usr/local/sunshine/assets -DSUNSHINE_CONFIG_DIR=/usr/local/sunshine/config .. make -j ${nproc} - name: Package MacOS diff --git a/CMakeLists.txt b/CMakeLists.txt index 68035d547d7..53358f35309 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -393,7 +393,7 @@ else() endif() if(NOT SUNSHINE_ASSETS_DIR) - set(SUNSHINE_ASSETS_DIR "${CMAKE_CURRENT_BINARY_DIR}/.assets") + set(SUNSHINE_ASSETS_DIR "${CMAKE_CURRENT_BINARY_DIR}/assets") endif() if(NOT SUNSHINE_CONFIG_DIR) @@ -535,13 +535,15 @@ if(WIN32) # see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.h set(CPACK_COMPONENT_SUNSHINESVC_GROUP "Tools") endif() if(UNIX) + # Installation destination dir + set(CPACK_SET_DESTDIR true) + if(NOT CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local/sunshine") + endif() + install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/" DESTINATION "${SUNSHINE_ASSETS_DIR}") install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/common/config/" DESTINATION "${SUNSHINE_CONFIG_DIR}") - - # Installation destination dir - set(CPACK_SET_DESTDIR true) - set(CMAKE_INSTALL_PREFIX "/usr/local/sunshine/") endif() if(APPLE) # TODO: test @@ -576,14 +578,14 @@ if(UNIX AND NOT APPLE) # Pre and post install set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA - "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/deb/preinst;${SUNSHINE_SOURCE_ASSETS_DIR}/linux/deb/postinst;${SUNSHINE_SOURCE_ASSETS_DIR}/linux/deb/conffiles") - set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/deb/preinst") - set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/deb/postinst") + "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/preinst;${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/postinst;${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/conffiles") + set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/preinst") + set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/postinst") # Dependencies set(CPACK_DEB_COMPONENT_INSTALL ON) set(CPACK_DEBIAN_PACKAGE_DEPENDS "libssl1.1 | libssl3.0, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2") - set(CPACK_RPM_PACKAGE_REQUIRES "libssl==1.1, libavdevice>=58, libboost-thread>=1.67.0, libboost-filesystem>=1.67.0, libboost-log>=1.67.0, libpulse>=0, libopus>=0, libxcb-shm>=0, libxcb-xfixes>=0, libxtst>=0, libevdev>=2.0, libdrm>=2.0, libcap>=2.0") + set(CPACK_RPM_PACKAGE_REQUIRES "openssl >= 1.1, libavdevice >= 4.3, boost-thread >= 1.67.0, boost-filesystem >= 1.67.0, boost-log >= 1.67.0, pulseaudio-libs >= 10.0, libopusenc >= 0.2.1, libxcb >= 1.13, libXtst >= 1.2.3, libevdev >= 1.5.6, libdrm >= 2.4.97, libcap >= 2.22") set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF) # This should automatically figure out dependencies, doesn't work with the current config # AppImage desktop file diff --git a/Portfile.in b/Portfile.in index 2cb3546681e..3ab6b0ffcde 100644 --- a/Portfile.in +++ b/Portfile.in @@ -31,8 +31,8 @@ depends_lib port:avahi \ boost.version 1.76 configure.args -DBOOST_ROOT=[boost::install_area] \ - -DSUNSHINE_ASSETS_DIR=${prefix}/usr/local/sunshine/.assets - -DSUNSHINE_CONFIG_DIR=${prefix}/usr/local/sunshine/config + -DSUNSHINE_ASSETS_DIR=${prefix}/etc/sunshine/assets + -DSUNSHINE_CONFIG_DIR=${prefix}/etc/sunshine/config cmake.out_of_source yes diff --git a/src_assets/linux/deb/conffiles b/src_assets/linux/misc/conffiles similarity index 100% rename from src_assets/linux/deb/conffiles rename to src_assets/linux/misc/conffiles diff --git a/src_assets/linux/deb/postinst b/src_assets/linux/misc/postinst similarity index 100% rename from src_assets/linux/deb/postinst rename to src_assets/linux/misc/postinst diff --git a/src_assets/linux/deb/preinst b/src_assets/linux/misc/preinst similarity index 100% rename from src_assets/linux/deb/preinst rename to src_assets/linux/misc/preinst From f2934c620bef48ee1c3f15b28ac941ec11c207a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Jun 2022 12:35:18 +0000 Subject: [PATCH 098/120] Bump DoozyX/clang-format-lint-action from 0.13 to 0.14 Bumps [DoozyX/clang-format-lint-action](https://github.com/DoozyX/clang-format-lint-action) from 0.13 to 0.14. - [Release notes](https://github.com/DoozyX/clang-format-lint-action/releases) - [Commits](https://github.com/DoozyX/clang-format-lint-action/compare/v0.13...v0.14) --- updated-dependencies: - dependency-name: DoozyX/clang-format-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index fd62d2611c2..3c0a70e6d59 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -15,7 +15,7 @@ jobs: uses: actions/checkout@v3 - name: Clang format lint - uses: DoozyX/clang-format-lint-action@v0.13 + uses: DoozyX/clang-format-lint-action@v0.14 with: source: './sunshine' extensions: 'cpp,h,m,mm' From 0f3eaf0f8406632a678a579e417d72d43bd405dc Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 7 Jun 2022 18:32:09 -0400 Subject: [PATCH 099/120] Add pip for dependabot --- .github/dependabot.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 60b85432016..32fce3f3d8d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,3 +6,10 @@ updates: interval: "daily" target-branch: "nightly" open-pull-requests-limit: 20 + + - package-ecosystem: "pip" + directory: "/scripts" + schedule: + interval: "daily" + target-branch: "nightly" + open-pull-requests-limit: 10 From e7ec6050d9a820549d556bf80e6dcb17460ee996 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 7 Jun 2022 18:32:28 -0400 Subject: [PATCH 100/120] Use portable config directory for AppImage --- .github/workflows/CI.yml | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 71abe96eef8..49436c28dd3 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -65,9 +65,9 @@ jobs: SUNSHINE_ASSETS_DIR: 'assets' SUNSHINE_CONFIG_DIR: 'config' - type: appimage - CMAKE_INSTALL_PREFIX: '.' - SUNSHINE_ASSETS_DIR: 'usr/local/sunshine/assets' - SUNSHINE_CONFIG_DIR: 'usr/local/sunshine/config' + CMAKE_INSTALL_PREFIX: '/usr' + SUNSHINE_ASSETS_DIR: 'sunshine.AppImage.config' + SUNSHINE_CONFIG_DIR: 'sunshine.AppImage.home' steps: - name: Checkout @@ -172,8 +172,11 @@ jobs: # install sunshine to the DESTDIR make install DESTDIR=AppDir - # testing only - ls AppDir + # portable home and config + # todo - this is ugly... we should use a custom AppRun script to take care of this + mv ./AppDir${{ matrix.CMAKE_INSTALL_PREFIX }}/sunshine.AppImage.* ../artifacts/ + mkdir -p ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/.config/sunshine/${{ matrix.SUNSHINE_CONFIG_DIR }} + cp ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/apps.json ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/.config/sunshine/${{ matrix.SUNSHINE_CONFIG_DIR }}/ # variables DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" @@ -204,6 +207,9 @@ jobs: # move mv Sunshine*.AppImage ../artifacts/sunshine.AppImage + + # permissions + chmod +x ../artifacts/sunshine.AppImage - name: Verify AppImage if: ${{ matrix.type == 'appimage' }} @@ -215,6 +221,17 @@ jobs: ./appimagelint-x86_64.AppImage ./artifacts/sunshine.AppImage + - name: Archive AppImage + if: ${{ matrix.type == 'appimage' }} + working-directory: artifacts + run: | + chmod +x ./sunshine.AppImage + + zip --recurse-paths --move --test ./sunshine-appimage.zip ./* + + # testing + ls + - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 From 91cf3bcdcc30d2af4eee6f086d18b64bc34ac2b6 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 7 Jun 2022 18:32:28 -0400 Subject: [PATCH 101/120] Use portable config directory for AppImage --- .github/workflows/CI.yml | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 71abe96eef8..6fa2d0048b4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -65,9 +65,9 @@ jobs: SUNSHINE_ASSETS_DIR: 'assets' SUNSHINE_CONFIG_DIR: 'config' - type: appimage - CMAKE_INSTALL_PREFIX: '.' - SUNSHINE_ASSETS_DIR: 'usr/local/sunshine/assets' - SUNSHINE_CONFIG_DIR: 'usr/local/sunshine/config' + CMAKE_INSTALL_PREFIX: '/usr' + SUNSHINE_ASSETS_DIR: 'sunshine.AppImage.config' + SUNSHINE_CONFIG_DIR: 'sunshine.AppImage.home' steps: - name: Checkout @@ -172,8 +172,11 @@ jobs: # install sunshine to the DESTDIR make install DESTDIR=AppDir - # testing only - ls AppDir + # portable home and config + # todo - this is ugly... we should use a custom AppRun script to take care of this + mv ./AppDir${{ matrix.CMAKE_INSTALL_PREFIX }}/sunshine.AppImage.* ../artifacts/ + mkdir -p ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/.config/sunshine/${{ matrix.SUNSHINE_CONFIG_DIR }} + cp ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/apps.json ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/.config/sunshine/${{ matrix.SUNSHINE_CONFIG_DIR }}/ # variables DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" @@ -204,6 +207,9 @@ jobs: # move mv Sunshine*.AppImage ../artifacts/sunshine.AppImage + + # permissions + chmod +x ../artifacts/sunshine.AppImage - name: Verify AppImage if: ${{ matrix.type == 'appimage' }} @@ -215,6 +221,14 @@ jobs: ./appimagelint-x86_64.AppImage ./artifacts/sunshine.AppImage + - name: Archive AppImage + if: ${{ matrix.type == 'appimage' }} + working-directory: artifacts + run: | + chmod +x ./sunshine.AppImage + + zip --recurse-paths --move --test ./sunshine-appimage.zip ./* + - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 From 34f1e89366bf716aadc40c1e287b303627cc5c58 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 8 Jun 2022 21:01:34 -0400 Subject: [PATCH 102/120] Update linux installation instructions --- docs/source/about/installation.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index 40eecd209c0..4fab6e686ec 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -43,22 +43,24 @@ The current known compatibility of the AppImage is shown below. #. Download and extract `sunshine-appimage.zip` +#. Edit ``/etc/udev/rules.d/85-sunshine-rules.rules`` and add + ``KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput"`` Debian Packages ^^^^^^^^^^^^^^^ .. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:linux:debian?logo=github&style=for-the-badge :alt: GitHub issues by-label -#. Download the corresponding `.deb` file, e.g. ``sunshine-ubuntu_20_04.deb`` -#. ``sudo apt install -f ``, e.g. ``sudo apt install -f ./sunshine-ubuntu_20_04.deb`` +#. Download ``sunshine.deb`` +#. ``sudo apt install -f ./sunshine.deb`` Red Hat Packages ^^^^^^^^^^^^^^^^ .. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:linux:fedora?logo=github&style=for-the-badge :alt: GitHub issues by-label -#. Download the corresponding `.rpm` file, e.g. ``sunshine-fedora_35.rpm`` -#. ``sudo dnf install ``, e.g. ``sudo dnf install ./sunshine-fedora_35.rpm`` +#. Download ``sunshine.rpm`` +#. ``sudo dnf install ./sunshine.rpm`` .. Hint:: If this is the first time installing. From 4a65d2cafcbd9baf0867168bf47824190e98bce8 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 8 Jun 2022 21:02:28 -0400 Subject: [PATCH 103/120] Fix libssl3 dependency for Ubuntu 22.04 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 53358f35309..6081f8d2c7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -584,7 +584,7 @@ if(UNIX AND NOT APPLE) # Dependencies set(CPACK_DEB_COMPONENT_INSTALL ON) - set(CPACK_DEBIAN_PACKAGE_DEPENDS "libssl1.1 | libssl3.0, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2") + set(CPACK_DEBIAN_PACKAGE_DEPENDS "libssl1.1 | libssl3, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2") set(CPACK_RPM_PACKAGE_REQUIRES "openssl >= 1.1, libavdevice >= 4.3, boost-thread >= 1.67.0, boost-filesystem >= 1.67.0, boost-log >= 1.67.0, pulseaudio-libs >= 10.0, libopusenc >= 0.2.1, libxcb >= 1.13, libXtst >= 1.2.3, libevdev >= 1.5.6, libdrm >= 2.4.97, libcap >= 2.22") set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF) # This should automatically figure out dependencies, doesn't work with the current config From 7cb0286414d6f60dc3f9256588fab0c7f926cf61 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 8 Jun 2022 21:27:41 -0400 Subject: [PATCH 104/120] Fix paths for linux cpack build --- .github/workflows/CI.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6fa2d0048b4..beea51ec686 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -61,9 +61,9 @@ jobs: matrix: include: # package these differently - type: cpack - CMAKE_INSTALL_PREFIX: '/usr/local/sunshine' - SUNSHINE_ASSETS_DIR: 'assets' - SUNSHINE_CONFIG_DIR: 'config' + CMAKE_INSTALL_PREFIX: '' + SUNSHINE_ASSETS_DIR: '/usr/local/sunshine/assets' + SUNSHINE_CONFIG_DIR: '/usr/local/sunshine/config' - type: appimage CMAKE_INSTALL_PREFIX: '/usr' SUNSHINE_ASSETS_DIR: 'sunshine.AppImage.config' From 9b4fc8a2708bc2ed9aee6baa92bbff32cb813b6f Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 8 Jun 2022 23:00:18 -0400 Subject: [PATCH 105/120] Fix udev rules - Adds to permission to create "Sunshine Mouse" --- src_assets/linux/misc/85-sunshine-rules.rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/linux/misc/85-sunshine-rules.rules b/src_assets/linux/misc/85-sunshine-rules.rules index 46a78a4a6da..77c337c4d42 100644 --- a/src_assets/linux/misc/85-sunshine-rules.rules +++ b/src_assets/linux/misc/85-sunshine-rules.rules @@ -1 +1 @@ -KERNEL=="uinput", GROUP="input", MODE="0660" \ No newline at end of file +KERNEL=="uinput", GROUP="input", MODE="0660", OPTION+="static_node=uinput" \ No newline at end of file From e9b46201fd65e53305bc6d510e4ce4dc6e43548e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Jun 2022 12:42:27 +0000 Subject: [PATCH 106/120] Bump actions/setup-python from 3 to 4 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3 to 4. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/localize.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/localize.yml b/.github/workflows/localize.yml index 31f2299738b..f4828e99cc6 100644 --- a/.github/workflows/localize.yml +++ b/.github/workflows/localize.yml @@ -22,7 +22,7 @@ jobs: uses: actions/checkout@v3 - name: Install Python 3.9 - uses: actions/setup-python@v3 # https://github.com/actions/setup-python + uses: actions/setup-python@v4 # https://github.com/actions/setup-python with: python-version: '3.9' From 65c4f019989009389ca95d9598b943acf96647e2 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 8 Jun 2022 23:00:59 -0400 Subject: [PATCH 107/120] Update documentation - Add copy button to code blocks - Fix some badges - Improve Linux installation instructions --- docs/source/about/advanced_usage.rst | 2 +- docs/source/about/installation.rst | 59 ++++++++++++++------ docs/source/about/third_party_packages.rst | 26 +++------ docs/source/about/usage.rst | 63 +++++++++++++++++----- docs/source/conf.py | 3 +- scripts/requirements.txt | 1 + 6 files changed, 105 insertions(+), 49 deletions(-) diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index 7699232c8e1..61c9e60f9f6 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -1055,7 +1055,7 @@ Description by Moonlight. Default - OS dependent + OS and package dependent Example .. code-block:: text diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index 4fab6e686ec..deb6f60a6ed 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -21,6 +21,26 @@ Docker Linux ----- +Follow the instructions for your preferred package type below. + +.. Hint:: If this is the first time installing. + + .. code-block:: bash + + sudo usermod -a -G input $USER + sudo reboot now + +.. Tip:: Optionally, run Sunshine in the background. + + .. code-block:: bash + + systemctl --user start sunshine + +.. Note:: If screencasting fails with Wayland, you may need to run the following to force screencasting with X11. + + .. code-block:: bash + + sudo setcap -r $(readlink -f $(which sunshine)) AppImage ^^^^^^^^ @@ -41,39 +61,40 @@ The current known compatibility of the AppImage is shown below. - [✖] Ubuntu trusty - [✖] CentOS 7 - -#. Download and extract `sunshine-appimage.zip` -#. Edit ``/etc/udev/rules.d/85-sunshine-rules.rules`` and add - ``KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput"`` +#. Download and extract ``sunshine-appimage.zip`` to your home directory. Debian Packages ^^^^^^^^^^^^^^^ .. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:linux:debian?logo=github&style=for-the-badge :alt: GitHub issues by-label -#. Download ``sunshine.deb`` -#. ``sudo apt install -f ./sunshine.deb`` +#. Download ``sunshine.deb`` and run the following code. + + .. code-block:: bash + + sudo apt install -f ./sunshine.deb + +.. Tip:: You can double click the deb file to see details about the package and begin installation. Red Hat Packages ^^^^^^^^^^^^^^^^ .. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:linux:fedora?logo=github&style=for-the-badge :alt: GitHub issues by-label -#. Download ``sunshine.rpm`` -#. ``sudo dnf install ./sunshine.rpm`` +#. Add `rpmfusion` repositories by running the following code. -.. Hint:: If this is the first time installing. + .. code-block:: bash - .. code-block:: bash + sudo dnf install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm \ + https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm - sudo usermod -a -G input $USER - sudo reboot now +#. Download ``sunshine.rpm`` and run the following code. -.. Tip:: Optionally, run Sunshine in the background. + .. code-block:: bash - .. code-block:: bash + sudo dnf install ./sunshine.rpm - systemctl --user start sunshine +.. Tip:: You can double click the rpm file to see details about the package and begin installation. MacOS ----- @@ -87,8 +108,12 @@ Disk Image File option: Portfile option: #. Install `MacPorts `_ - #. Download the ``Portfile`` to ``/tmp`` - #. In a terminal run ``cd /tmp && sudo port install`` + #. Download the ``Portfile`` to ``/tmp`` and run the following code. + + .. code-block:: bash + + cd /tmp && sudo port install + #. The first time you start Sunshine, you will be asked to grant access to screen recording and your microphone. Standalone option: diff --git a/docs/source/about/third_party_packages.rst b/docs/source/about/third_party_packages.rst index 6069258a505..5b63a496bdc 100644 --- a/docs/source/about/third_party_packages.rst +++ b/docs/source/about/third_party_packages.rst @@ -10,6 +10,7 @@ AUR (Arch Linux User Repository) .. image:: https://img.shields.io/aur/version/sunshine?style=for-the-badge&logo=archlinux :alt: AUR version + :target: https://aur.archlinux.org/packages/sunshine .. image:: https://img.shields.io/aur/last-modified/sunshine?style=for-the-badge&logo=archlinux :alt: AUR last modified @@ -20,38 +21,31 @@ AUR (Arch Linux User Repository) .. image:: https://img.shields.io/aur/maintainer/sunshine?style=for-the-badge&logo=archlinux :alt: AUR maintainer -.. image:: https://img.shields.io/static/v1?label=maintainer&message=hadogenes&color=blue&style=for-the-badge&logo=github - :alt: GitHub Maintainer - :target: https://github.com/hadogenes - Chocolatey ---------- .. image:: https://img.shields.io/chocolatey/v/Sunshine?style=for-the-badge&logo=chocolatey :alt: Chocolatey Version + :target: https://community.chocolatey.org/packages/sunshine .. image:: https://img.shields.io/chocolatey/dt/sunshine?style=for-the-badge&logo=chocolatey :alt: Chocolatey -.. image:: https://img.shields.io/static/v1?label=maintainer&message=AeliusSaionji&color=blue&style=for-the-badge&logo=github - :alt: GitHub Maintainer - :target: https://github.com/AeliusSaionji - Scoop ----- .. image:: https://img.shields.io/scoop/v/sunshine?bucket=extras&style=for-the-badge :alt: Scoop Version (extras bucket) - -.. image:: https://img.shields.io/static/v1?label=maintainer&message=sitiom&color=blue&style=for-the-badge&logo=github - :alt: GitHub Maintainer - :target: https://github.com/sitiom - + :target: https://scoop.sh/#/apps?s=0&d=1&o=true&q=sunshine Legacy GitHub Repo ------------------ -.. Attention:: This repo is no longer maintained. Thank you to Loki for bringing this amazing project to life! +.. Attention:: This repo is not maintained. Thank you to Loki for bringing this amazing project to life! + +.. image:: https://img.shields.io/static/v1?label=repo&message=loki-47-6F-64/sunshine&color=blue&style=for-the-badge&logo=github + :alt: GitHub Maintainer + :target: https://github.com/loki-47-6F-64/sunshine/releases .. image:: https://img.shields.io/github/last-commit/loki-47-6F-64/sunshine?style=for-the-badge&logo=github :alt: GitHub last commit @@ -61,7 +55,3 @@ Legacy GitHub Repo .. image:: https://img.shields.io/github/downloads/loki-47-6F-64/sunshine/total?style=for-the-badge&logo=github :alt: GitHub Releases - -.. image:: https://img.shields.io/static/v1?label=maintainer&message=loki-47-6F-64&color=blue&style=for-the-badge&logo=github - :alt: GitHub Maintainer - :target: https://github.com/loki-47-6F-64 diff --git a/docs/source/about/usage.rst b/docs/source/about/usage.rst index 4bb81bc5969..8f73d204197 100644 --- a/docs/source/about/usage.rst +++ b/docs/source/about/usage.rst @@ -23,8 +23,9 @@ Usage Add games and applications. This can be configured in the web ui. - .. Note:: Additionally, apps can be configured manually. `assets/apps_.json` is an example of a list of - applications that are started just before running a stream. + .. Note:: Additionally, apps can be configured manually. `src_assets//config/apps.json` is an example of a + list of applications that are started just before running a stream. This is the directory within the GitHub + repo. .. Attention:: Application list is not fully supported on MacOS @@ -55,6 +56,9 @@ Setup Linux ^^^^^ +The deb and rpm packages handle these steps automatically. The AppImage does not, and third party packages may not as +well. + Sunshine needs access to `uinput` to create mouse and gamepad events. Add user to group `input`. @@ -62,13 +66,23 @@ Add user to group `input`. usermod -a -G input $USER + .. Warning:: If the above doesn't work you can try the following. This is not an advised method as it makes the + current user the owner of ``/dev/uinput``. Use at your own risk. + + .. code-block:: bash + + sudo chown $USER /dev/uinput + Create `udev` rules. .. code-block:: bash nano /etc/udev/rules.d/85-sunshine-input.rules - Input the following contents: - ``KERNEL=="uinput", GROUP="input", MODE="0660"`` + Input the following contents. + + .. code-block:: + + KERNEL=="uinput", GROUP="input", MODE="0660", OPTION+="static_node=uinput" Save the file and exit: @@ -76,18 +90,43 @@ Create `udev` rules. #. ``Y`` to save modifications. Configure autostart service - `path/to/build/dir/sunshine.service` is used to start sunshine in the background. To use it, do the following: + - filename: ``~/.config/systemd/user/sunshine.service`` + - contents: + + .. code-block:: + + [Unit] + Description=Sunshine Gamestream Server for Moonlight - #. Copy it to the users systemd: ``cp sunshine.service ~/.config/systemd/user/`` - #. Starting + [Service] + ExecStart=~/sunshine.AppImage - - One time: ``systemctl --user start sunshine`` - - Always on boot: ``systemctl --user enable sunshine`` + [Install] + WantedBy=graphical-session.target + + Start once + .. code-block:: bash + + systemctl --user start sunshine + + Start on boot + .. code-block:: bash + + systemctl --user enable sunshine Additional Setup for KMS - .. Note:: ``cap_sys_admin`` may as well be root, except you don't need to be root to run it. + .. Note:: ``cap_sys_admin`` may as well be root, except you don't need to be root to run it. It is necessary to + allow Sunshine to use KMS. + + Enable + .. code-block:: bash + + sudo setcap cap_sys_admin+p $(readlink -f $(which sunshine)) + + Disable + .. code-block:: bash - It is necessary to allow Sunshine to use KMS: ``sudo setcap cap_sys_admin+p sunshine`` + sudo setcap -r $(readlink -f $(which sunshine)) MacOS ^^^^^ @@ -114,7 +153,7 @@ All shortcuts start with CTRL + ALT + SHIFT, just like Moonlight Application List ---------------- - You can use Environment variables in place of values -- ``$(HOME)` will be replaced by the value of ``$HOME`` +- ``$(HOME)`` will be replaced by the value of ``$HOME`` - ``$$`` will be replaced by ``$``, e.g. ``$$(HOME)`` will be replaced by ``$(HOME)`` - ``env`` - Adds or overwrites Environment variables for the commands/applications run by Sunshine - ``"Variable name":"Variable value"`` diff --git a/docs/source/conf.py b/docs/source/conf.py index f609783ce9f..f4873f1531a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -46,7 +46,8 @@ 'm2r2', # enable markdown files 'sphinx.ext.autosectionlabel', 'sphinx.ext.todo', # enable to-do sections - 'sphinx.ext.viewcode' # add links to view source code + 'sphinx.ext.viewcode', # add links to view source code + 'sphinx_copybutton', # add a copy button to code blocks ] # Add any paths that contain templates here, relative to this directory. diff --git a/scripts/requirements.txt b/scripts/requirements.txt index c089efd943c..73eefbe1ff1 100644 --- a/scripts/requirements.txt +++ b/scripts/requirements.txt @@ -1,4 +1,5 @@ Babel==2.9.1 m2r2==0.3.2 Sphinx==4.5.0 +sphinx-copybutton==0.5.0 sphinx-rtd-theme==1.0.0 From 7a5890469ca60bbe926a4f852f723c741dcbcf91 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 10 Jun 2022 23:20:24 -0400 Subject: [PATCH 108/120] Update MacOS build --- .github/workflows/CI.yml | 95 ++++++++++++++++++++++++++++-- CMakeLists.txt | 3 +- Portfile.in | 86 +++++++++++++++++---------- docs/source/about/installation.rst | 26 +++++++- 4 files changed, 172 insertions(+), 38 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index beea51ec686..b5c0772b6e9 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -247,7 +247,7 @@ jobs: build_mac: name: MacOS - runs-on: macos-11 + runs-on: macos-12 needs: check_changelog steps: @@ -264,12 +264,33 @@ jobs: # fix openssl header not found cd /usr/local/include ln -s ../opt/openssl/include/openssl . + + # update paths for macports + echo "/opt/local/sbin" >> $GITHUB_PATH + echo "/opt/local/bin" >> $GITHUB_PATH - name: Build MacOS run: | + # variables for Portfile + owner=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]' ) + repo=$(echo ${GITHUB_REPOSITORY#*/} | tr '[:upper:]' '[:lower:]' ) + branch=${GITHUB_HEAD_REF} + + # check the branch variable + if [ -z "$branch" ] + then + echo "This is a PUSH event" + branch=${GITHUB_BASE_REF} + else + echo "This is a PR event" + fi + echo "Owner: ${owner}" + echo "Repo: ${repo}" + echo "Branch: ${branch}" + mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=/usr/local/sunshine/assets -DSUNSHINE_CONFIG_DIR=/usr/local/sunshine/config .. + cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=/usr/local/sunshine/assets -DSUNSHINE_CONFIG_DIR=/usr/local/sunshine/config -DGITHUB_OWNER=${owner} -DGITHUB_REPO=${repo} -DGITHUB_BRANCH=${branch} .. make -j ${nproc} - name: Package MacOS @@ -279,12 +300,69 @@ jobs: # package cpack -G DragNDrop + mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine-macos-experimental-dragndrop.dmg + + cpack -G Bundle + mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine-macos-experimental-bundle.dmg + cpack -G ZIP + mv ./cpack_artifacts/Sunshine.zip ../artifacts/sunshine-macos-experimental-archive.zip # move mv Portfile ../artifacts/Portfile - mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine-macos.dmg - mv ./cpack_artifacts/Sunshine.zip ../artifacts/sunshine-macos.zip + + - name: Setup Macports + run : | + curl -O https://distfiles.macports.org/MacPorts/MacPorts-2.7.2.tar.bz2 + tar xf MacPorts-2.7.2.tar.bz2 + + cd MacPorts-2.7.2 + ./configure + make + sudo make install + cd ../ + rm -rf MacPorts-2.7.2* + + # update sources + sudo port -v selfupdate + + # use custom sources + sudo chmod 777 /opt/local/etc/macports/sources.conf + echo file://$(echo ~)/ports > /opt/local/etc/macports/sources.conf + echo rsync://rsync.macports.org/macports/release/tarballs/ports.tar [default] >> /opt/local/etc/macports/sources.conf + sudo chmod 644 /opt/local/etc/macports/sources.conf + + - name: Package with MacPorts + run: | + # setup custom port + mkdir -p ~/ports/multimedia/sunshine + + # copy configured Portfile + cp ./artifacts/Portfile ~/ports/multimedia/sunshine/ + + # index the ports + cd ~/ports + portindex + + # build port + sudo port install sunshine + # || cat /opt/local/var/macports/logs/_Users_runner_ports_multimedia_sunshine/Sunshine/main.log \ + # && exit 1 + + # create packages + sudo port dmg sunshine + sudo port pkg sunshine + + # move + mv $(port work sunshine)/Sunshine*.dmg ./artifacts/sunshine.dmg + mv $(port work sunshine)/Sunshine*.ppkg ./artifacts/sunshine.pkg + + # testing only + ls ~/ports/multimedia/sunshine + cat ~/ports/multimedia/sunshine/Portfile + cat /opt/local/etc/macports/sources.conf + cat ~/ports/Portindex + port search sunshine - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} @@ -293,6 +371,15 @@ jobs: name: sunshine-macos path: artifacts/ + # this step can be removed after packages are fixed + - name: Delete experimental packages + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + working-directory: artifacts + run: | + rm -f ./sunshine-macos-experimental-dragndrop.dmg + rm -f ./sunshine-macos-experimental-bundle.dmg + rm -f ./sunshine-macos-experimental-archive.zip + - name: Create Release if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} uses: SunshineStream/actions/create_release@master diff --git a/CMakeLists.txt b/CMakeLists.txt index 6081f8d2c7a..2963417e902 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -443,9 +443,7 @@ endforeach() target_compile_options(sunshine PRIVATE $<$:${SUNSHINE_COMPILE_OPTIONS}>;$<$:${SUNSHINE_COMPILE_OPTIONS_CUDA};-std=c++17>) -############# # CPACK / Packaging -#### # Common options set(CPACK_PACKAGE_NAME "SunshineStream") @@ -562,6 +560,7 @@ if(APPLE) # TODO: test set(CPACK_BUNDLE_NAME "${CMAKE_PROJECT_NAME}") set(CPACK_BUNDLE_PLIST "${APPLE_PLIST_FILE}") set(CPACK_BUNDLE_ICON "${PROJECT_SOURCE_DIR}/sunshine.icns") + # set(CPACK_BUNDLE_STARTUP_COMMAND "${INSTALL_RUNTIME_DIR}/sunshine") # Portfile configure_file(Portfile.in Portfile @ONLY) diff --git a/Portfile.in b/Portfile.in index 3ab6b0ffcde..36a7d476a24 100644 --- a/Portfile.in +++ b/Portfile.in @@ -1,49 +1,75 @@ # -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 -PortSystem 1.0 -PortGroup cmake 1.1 -PortGroup github 1.0 -PortGroup boost 1.0 +PortSystem 1.0 +PortGroup cmake 1.1 +PortGroup github 1.0 +PortGroup boost 1.0 -github.setup sunshinestream sunshine master -version @PROJECT_VERSION@ -revision 1 +# bump revision when changes are made to this file +revision 1 -categories multimedia -license GPL-3 -maintainers {sunshinestream @SunshineStream} {outlook.com:anselm.busse} -platforms darwin +github.setup @GITHUB_OWNER@ @GITHUB_REPO@ @GITHUB_BRANCH@ +name @PROJECT_NAME@ +version @PROJECT_VERSION@ +categories multimedia emulators games +platforms darwin +license GPL-3 +maintainers {@SunshineStream sunshinestream} +description @PROJECT_DESCRIPTION@ +long_description {*}${description} +homepage @PROJECT_HOMEPAGE_URL@ +master_sites https://github.com/@GITHUB_OWNER@/@GITHUB_REPO@/releases -fetch.type git +fetch.type git post-fetch { system -W ${worksrcpath} "${git.cmd} submodule update --init --recursive" } -description @PROJECT_DESCRIPTION@ -long_description {*}${description} -homepage @PROJECT_HOMEPAGE_URL@ +depends_lib port:avahi \ + port:ffmpeg \ + port:libopus -depends_lib port:avahi \ - port:ffmpeg \ - port:libopus +boost.version 1.76 +configure.args -DBOOST_ROOT=[boost::install_area] \ + -DSUNSHINE_ASSETS_DIR=${prefix}/etc/sunshine/assets \ + -DSUNSHINE_CONFIG_DIR=${prefix}/etc/sunshine/config -boost.version 1.76 +cmake.out_of_source yes -configure.args -DBOOST_ROOT=[boost::install_area] \ - -DSUNSHINE_ASSETS_DIR=${prefix}/etc/sunshine/assets - -DSUNSHINE_CONFIG_DIR=${prefix}/etc/sunshine/config - -cmake.out_of_source yes +startupitem.create yes +startupitem.executable "${prefix}/bin/{$name}" +startupitem.location LaunchDaemons +startupitem.name ${name} +startupitem.netchange yes +# is this actually necessary? this should all be handled by CMakeLists destroot { - xinstall -d -m 755 ${destroot}${prefix}/usr/local/${name}/.assets - xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/*] ${destroot}${prefix}/usr/local/${name}/.assets - xinstall {*}[glob ${worksrcpath}/src_assets/macos/assets/*] ${destroot}${prefix}/usr/local/${name}/.assets + # install assets + xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/assets + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/*.*] ${destroot}${prefix}/etc/${name}/assets + xinstall {*}[glob ${worksrcpath}/src_assets/macos/assets/*.*] ${destroot}${prefix}/etc/${name}/assets + + # install web assets + xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/assets/web/fonts/fontawesome-free-web/css + xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/assets/web/fonts/fontawesome-free-web/webfonts + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/web/*.*] ${destroot}${prefix}/etc/${name}/assets/web + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/web/fonts/fontawesome-free-web/*.*] ${destroot}${prefix}/etc/${name}/assets/web/fonts/fontawesome-free-web + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/web/fonts/fontawesome-free-web/css/*.*] ${destroot}${prefix}/etc/${name}/assets/web/fonts/fontawesome-free-web/css + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/*.*] ${destroot}${prefix}/etc/${name}/assets/web/fonts/fontawesome-free-web/webfonts + xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/assets/web/images + xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/assets/web/third_party + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/web/images/*.*] ${destroot}${prefix}/etc/${name}/assets/web/images + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/web/third_party/*.*] ${destroot}${prefix}/etc/${name}/assets/web/third_party + + xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/config + + # install sunshine.conf + xinstall {*}[glob ${worksrcpath}/src_assets/common/config/*.*] ${destroot}${prefix}/etc/${name}/config - xinstall -d -m 755 ${destroot}${prefix}/usr/local/${name}/config - xinstall {*}[glob ${worksrcpath}/src_assets/common/config/*] ${destroot}${prefix}/usr/local/${name}/config - xinstall {*}[glob ${worksrcpath}/src_assets/macos/config/*] ${destroot}${prefix}/usr/local/${name}/config + # install apps.json + xinstall {*}[glob ${worksrcpath}/src_assets/macos/config/*.*] ${destroot}${prefix}/etc/${name}/config + # install the binary xinstall ${workpath}/build/${name} ${destroot}${prefix}/bin } diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index deb6f60a6ed..ab4b688858e 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -108,13 +108,35 @@ Disk Image File option: Portfile option: #. Install `MacPorts `_ - #. Download the ``Portfile`` to ``/tmp`` and run the following code. + #. Update the Macports sources. .. code-block:: bash - cd /tmp && sudo port install + sudo nano /opt/local/etc/macports/sources.conf + + Add this line, replacing your username, below the line that starts with ``rsync``. + + file://Users//ports + + ``Ctrl+x``, then ``Y`` to exit and save changes. + + #. Download the ``Portfile`` to ``~/Downloads`` and run the following code. + + .. code-block:: bash + + mkdir -p ~/ports/multimedia/sunshine + mv ~/Downlaods/Portfile ~/ports/multimedia/sunshine + cd ~/ports + portindex + sudo port install sunshine #. The first time you start Sunshine, you will be asked to grant access to screen recording and your microphone. + #. Try to run the following code if you get this error: `Dynamic session lookup supported but failed: launchd did + not provide a socket path, verify that org.freedesktop.dbus-session.plist is loaded!` + + .. code-block:: bash + + launchctl load -w /Library/LaunchAgents/org.freedesktop.dbus-session.plist Standalone option: #. Download and extract ``sunshine-macos.zip`` From 1a1cf20152ebf7f4134b0a93505fe4912d7149f5 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 10 Jun 2022 23:20:24 -0400 Subject: [PATCH 109/120] Update MacOS build --- .github/workflows/CI.yml | 99 +++++++++++++++++++++++++++++- CMakeLists.txt | 3 +- Portfile.in | 86 +++++++++++++++++--------- docs/source/about/installation.rst | 26 +++++++- 4 files changed, 177 insertions(+), 37 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index beea51ec686..b9447f12561 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -264,12 +264,35 @@ jobs: # fix openssl header not found cd /usr/local/include ln -s ../opt/openssl/include/openssl . + + # update paths for macports + # echo "/opt/local/sbin" >> $GITHUB_PATH + echo "/Users/runner/macports/sbin" >> $GITHUB_PATH + # echo "/opt/local/bin" >> $GITHUB_PATH + echo "/Users/runner/macports/bin" >> $GITHUB_PATH - name: Build MacOS run: | + # variables for Portfile + owner=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]' ) + repo=$(echo ${GITHUB_REPOSITORY#*/} | tr '[:upper:]' '[:lower:]' ) + branch=${GITHUB_HEAD_REF} + + # check the branch variable + if [ -z "$branch" ] + then + echo "This is a PUSH event" + branch=${GITHUB_BASE_REF} + else + echo "This is a PR event" + fi + echo "Owner: ${owner}" + echo "Repo: ${repo}" + echo "Branch: ${branch}" + mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=/usr/local/sunshine/assets -DSUNSHINE_CONFIG_DIR=/usr/local/sunshine/config .. + cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=/usr/local/sunshine/assets -DSUNSHINE_CONFIG_DIR=/usr/local/sunshine/config -DGITHUB_OWNER=${owner} -DGITHUB_REPO=${repo} -DGITHUB_BRANCH=${branch} .. make -j ${nproc} - name: Package MacOS @@ -279,12 +302,73 @@ jobs: # package cpack -G DragNDrop + mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine-macos-experimental-dragndrop.dmg + + cpack -G Bundle + mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine-macos-experimental-bundle.dmg + cpack -G ZIP + mv ./cpack_artifacts/Sunshine.zip ../artifacts/sunshine-macos-experimental-archive.zip # move mv Portfile ../artifacts/Portfile - mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine-macos.dmg - mv ./cpack_artifacts/Sunshine.zip ../artifacts/sunshine-macos.zip + + - name: Setup Macports + run : | + curl -O https://distfiles.macports.org/MacPorts/MacPorts-2.7.2.tar.bz2 + tar xf MacPorts-2.7.2.tar.bz2 + + cd MacPorts-2.7.2 + ./configure --prefix=/Users/runner/macports + make + sudo make install + cd ../ + rm -rf MacPorts-2.7.2* + + # update sources + sudo port -v selfupdate + + # use custom sources + # sudo chmod 777 /opt/local/etc/macports/sources.conf + sudo chmod 777 /Users/runner/macports/etc/macports/sources.conf + # echo file://$(echo ~)/ports > /opt/local/etc/macports/sources.conf + echo file://$(echo ~)/ports > /Users/runner/macports/etc/macports/sources.conf + # echo rsync://rsync.macports.org/macports/release/tarballs/ports.tar [default] >> /opt/local/etc/macports/sources.conf + echo rsync://rsync.macports.org/macports/release/tarballs/ports.tar [default] >> /Users/runner/macports/etc/macports/sources.conf + # sudo chmod 644 /opt/local/etc/macports/sources.conf + sudo chmod 644 /Users/runner/macports/etc/macports/sources.conf + + - name: Package with MacPorts + run: | + # setup custom port + mkdir -p ~/ports/multimedia/sunshine + + # copy configured Portfile + cp ./artifacts/Portfile ~/ports/multimedia/sunshine/ + + # index the ports + cd ~/ports + portindex + + # build port + sudo port install sunshine + # || cat /opt/local/var/macports/logs/_Users_runner_ports_multimedia_sunshine/Sunshine/main.log \ + # && exit 1 + + # create packages + sudo port dmg sunshine + sudo port pkg sunshine + + # move + mv $(port work sunshine)/Sunshine*.dmg ./artifacts/sunshine.dmg + mv $(port work sunshine)/Sunshine*.ppkg ./artifacts/sunshine.pkg + + # testing only + # ls ~/ports/multimedia/sunshine + # cat ~/ports/multimedia/sunshine/Portfile + # cat /opt/local/etc/macports/sources.conf + # cat ~/ports/Portindex + # port search sunshine - name: Upload Artifacts if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} @@ -293,6 +377,15 @@ jobs: name: sunshine-macos path: artifacts/ + # this step can be removed after packages are fixed + - name: Delete experimental packages + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + working-directory: artifacts + run: | + rm -f ./sunshine-macos-experimental-dragndrop.dmg + rm -f ./sunshine-macos-experimental-bundle.dmg + rm -f ./sunshine-macos-experimental-archive.zip + - name: Create Release if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} uses: SunshineStream/actions/create_release@master diff --git a/CMakeLists.txt b/CMakeLists.txt index 6081f8d2c7a..2963417e902 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -443,9 +443,7 @@ endforeach() target_compile_options(sunshine PRIVATE $<$:${SUNSHINE_COMPILE_OPTIONS}>;$<$:${SUNSHINE_COMPILE_OPTIONS_CUDA};-std=c++17>) -############# # CPACK / Packaging -#### # Common options set(CPACK_PACKAGE_NAME "SunshineStream") @@ -562,6 +560,7 @@ if(APPLE) # TODO: test set(CPACK_BUNDLE_NAME "${CMAKE_PROJECT_NAME}") set(CPACK_BUNDLE_PLIST "${APPLE_PLIST_FILE}") set(CPACK_BUNDLE_ICON "${PROJECT_SOURCE_DIR}/sunshine.icns") + # set(CPACK_BUNDLE_STARTUP_COMMAND "${INSTALL_RUNTIME_DIR}/sunshine") # Portfile configure_file(Portfile.in Portfile @ONLY) diff --git a/Portfile.in b/Portfile.in index 3ab6b0ffcde..36a7d476a24 100644 --- a/Portfile.in +++ b/Portfile.in @@ -1,49 +1,75 @@ # -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 -PortSystem 1.0 -PortGroup cmake 1.1 -PortGroup github 1.0 -PortGroup boost 1.0 +PortSystem 1.0 +PortGroup cmake 1.1 +PortGroup github 1.0 +PortGroup boost 1.0 -github.setup sunshinestream sunshine master -version @PROJECT_VERSION@ -revision 1 +# bump revision when changes are made to this file +revision 1 -categories multimedia -license GPL-3 -maintainers {sunshinestream @SunshineStream} {outlook.com:anselm.busse} -platforms darwin +github.setup @GITHUB_OWNER@ @GITHUB_REPO@ @GITHUB_BRANCH@ +name @PROJECT_NAME@ +version @PROJECT_VERSION@ +categories multimedia emulators games +platforms darwin +license GPL-3 +maintainers {@SunshineStream sunshinestream} +description @PROJECT_DESCRIPTION@ +long_description {*}${description} +homepage @PROJECT_HOMEPAGE_URL@ +master_sites https://github.com/@GITHUB_OWNER@/@GITHUB_REPO@/releases -fetch.type git +fetch.type git post-fetch { system -W ${worksrcpath} "${git.cmd} submodule update --init --recursive" } -description @PROJECT_DESCRIPTION@ -long_description {*}${description} -homepage @PROJECT_HOMEPAGE_URL@ +depends_lib port:avahi \ + port:ffmpeg \ + port:libopus -depends_lib port:avahi \ - port:ffmpeg \ - port:libopus +boost.version 1.76 +configure.args -DBOOST_ROOT=[boost::install_area] \ + -DSUNSHINE_ASSETS_DIR=${prefix}/etc/sunshine/assets \ + -DSUNSHINE_CONFIG_DIR=${prefix}/etc/sunshine/config -boost.version 1.76 +cmake.out_of_source yes -configure.args -DBOOST_ROOT=[boost::install_area] \ - -DSUNSHINE_ASSETS_DIR=${prefix}/etc/sunshine/assets - -DSUNSHINE_CONFIG_DIR=${prefix}/etc/sunshine/config - -cmake.out_of_source yes +startupitem.create yes +startupitem.executable "${prefix}/bin/{$name}" +startupitem.location LaunchDaemons +startupitem.name ${name} +startupitem.netchange yes +# is this actually necessary? this should all be handled by CMakeLists destroot { - xinstall -d -m 755 ${destroot}${prefix}/usr/local/${name}/.assets - xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/*] ${destroot}${prefix}/usr/local/${name}/.assets - xinstall {*}[glob ${worksrcpath}/src_assets/macos/assets/*] ${destroot}${prefix}/usr/local/${name}/.assets + # install assets + xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/assets + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/*.*] ${destroot}${prefix}/etc/${name}/assets + xinstall {*}[glob ${worksrcpath}/src_assets/macos/assets/*.*] ${destroot}${prefix}/etc/${name}/assets + + # install web assets + xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/assets/web/fonts/fontawesome-free-web/css + xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/assets/web/fonts/fontawesome-free-web/webfonts + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/web/*.*] ${destroot}${prefix}/etc/${name}/assets/web + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/web/fonts/fontawesome-free-web/*.*] ${destroot}${prefix}/etc/${name}/assets/web/fonts/fontawesome-free-web + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/web/fonts/fontawesome-free-web/css/*.*] ${destroot}${prefix}/etc/${name}/assets/web/fonts/fontawesome-free-web/css + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/web/fonts/fontawesome-free-web/webfonts/*.*] ${destroot}${prefix}/etc/${name}/assets/web/fonts/fontawesome-free-web/webfonts + xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/assets/web/images + xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/assets/web/third_party + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/web/images/*.*] ${destroot}${prefix}/etc/${name}/assets/web/images + xinstall {*}[glob ${worksrcpath}/src_assets/common/assets/web/third_party/*.*] ${destroot}${prefix}/etc/${name}/assets/web/third_party + + xinstall -d -m 755 ${destroot}${prefix}/etc/${name}/config + + # install sunshine.conf + xinstall {*}[glob ${worksrcpath}/src_assets/common/config/*.*] ${destroot}${prefix}/etc/${name}/config - xinstall -d -m 755 ${destroot}${prefix}/usr/local/${name}/config - xinstall {*}[glob ${worksrcpath}/src_assets/common/config/*] ${destroot}${prefix}/usr/local/${name}/config - xinstall {*}[glob ${worksrcpath}/src_assets/macos/config/*] ${destroot}${prefix}/usr/local/${name}/config + # install apps.json + xinstall {*}[glob ${worksrcpath}/src_assets/macos/config/*.*] ${destroot}${prefix}/etc/${name}/config + # install the binary xinstall ${workpath}/build/${name} ${destroot}${prefix}/bin } diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index deb6f60a6ed..ab4b688858e 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -108,13 +108,35 @@ Disk Image File option: Portfile option: #. Install `MacPorts `_ - #. Download the ``Portfile`` to ``/tmp`` and run the following code. + #. Update the Macports sources. .. code-block:: bash - cd /tmp && sudo port install + sudo nano /opt/local/etc/macports/sources.conf + + Add this line, replacing your username, below the line that starts with ``rsync``. + + file://Users//ports + + ``Ctrl+x``, then ``Y`` to exit and save changes. + + #. Download the ``Portfile`` to ``~/Downloads`` and run the following code. + + .. code-block:: bash + + mkdir -p ~/ports/multimedia/sunshine + mv ~/Downlaods/Portfile ~/ports/multimedia/sunshine + cd ~/ports + portindex + sudo port install sunshine #. The first time you start Sunshine, you will be asked to grant access to screen recording and your microphone. + #. Try to run the following code if you get this error: `Dynamic session lookup supported but failed: launchd did + not provide a socket path, verify that org.freedesktop.dbus-session.plist is loaded!` + + .. code-block:: bash + + launchctl load -w /Library/LaunchAgents/org.freedesktop.dbus-session.plist Standalone option: #. Download and extract ``sunshine-macos.zip`` From 9990b9b04b1146680efd6fe8e8871a98ba0248d1 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Mon, 13 Jun 2022 20:50:22 -0400 Subject: [PATCH 110/120] Separate job for Macports build --- .github/workflows/CI.yml | 123 ++++++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 40 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index acf8b12070c..d777444bed4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -230,7 +230,6 @@ jobs: zip --recurse-paths --move --test ./sunshine-appimage.zip ./* - name: Upload Artifacts - if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: name: sunshine-linux-${{ matrix.type }} @@ -247,7 +246,7 @@ jobs: build_mac: name: MacOS - runs-on: macos-12 + runs-on: macos-11 needs: check_changelog steps: @@ -256,20 +255,20 @@ jobs: with: submodules: recursive + # this is for the macports job + - name: Cache Artifacts + uses: actions/cache@v3 + with: + path: artifacts + key: ${{ runner.os }}-artifacts + - name: Setup Dependencies MacOS run: | # install dependencies using homebrew brew install boost cmake ffmpeg opus # fix openssl header not found - cd /usr/local/include - ln -s ../opt/openssl/include/openssl . - - # update paths for macports - # echo "/opt/local/sbin" >> $GITHUB_PATH - echo "/Users/runner/macports/sbin" >> $GITHUB_PATH - # echo "/opt/local/bin" >> $GITHUB_PATH - echo "/Users/runner/macports/bin" >> $GITHUB_PATH + ln -sf /usr/local/opt/openssl/include/openssl /usr/local/include/openssl - name: Build MacOS run: | @@ -297,6 +296,10 @@ jobs: - name: Package MacOS run: | + # remove cached artifacts + rm -r -f ./artifacts + mkdir artifacts + mkdir -p artifacts cd build @@ -313,47 +316,98 @@ jobs: # move mv Portfile ../artifacts/Portfile + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: sunshine-macos + path: artifacts/ + + # this step can be removed after packages are fixed + - name: Delete experimental packages + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + working-directory: artifacts + run: | + rm -f ./sunshine-macos-experimental-dragndrop.dmg + rm -f ./sunshine-macos-experimental-bundle.dmg + rm -f ./sunshine-macos-experimental-archive.zip + + - name: Create Release + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + uses: SunshineStream/actions/create_release@master + with: + token: ${{ secrets.GITHUB_TOKEN }} + next_version: ${{ needs.check_changelog.outputs.next_version }} + last_version: ${{ needs.check_changelog.outputs.last_version }} + release_body: ${{ needs.check_changelog.outputs.release_body }} + + build_mac_port: + name: Macports + runs-on: macos-11 + needs: [check_changelog, build_mac] + if: never() # disable this job + + steps: + - name: Cache Artifacts + uses: actions/cache@v3 + with: + path: artifacts + key: ${{ runner.os }}-artifacts + - name: Setup Macports run : | + # update paths for macports + echo "/opt/local/sbin" >> $GITHUB_PATH + echo "/opt/local/bin" >> $GITHUB_PATH + + # Set OpenSSL 1.1 as default + # rm -rf /usr/local/opt/openssl + # rm -rf /usr/local/bin/openssl + # ln -sf /usr/local/Cellar/openssl@1.1/1.1.1o/bin/openssl /usr/local/bin/openssl + # ln -sf /usr/local/Cellar/openssl@1.1/1.1.1o /usr/local/opt/openssl + + # download and extract macports curl -O https://distfiles.macports.org/MacPorts/MacPorts-2.7.2.tar.bz2 tar xf MacPorts-2.7.2.tar.bz2 + # build macports cd MacPorts-2.7.2 - ./configure --prefix=/Users/runner/macports + ./configure make sudo make install cd ../ rm -rf MacPorts-2.7.2* - + + - name: Configure Macports + run: | # update sources sudo port -v selfupdate # use custom sources - # sudo chmod 777 /opt/local/etc/macports/sources.conf - sudo chmod 777 /Users/runner/macports/etc/macports/sources.conf - # echo file://$(echo ~)/ports > /opt/local/etc/macports/sources.conf - echo file://$(echo ~)/ports > /Users/runner/macports/etc/macports/sources.conf - # echo rsync://rsync.macports.org/macports/release/tarballs/ports.tar [default] >> /opt/local/etc/macports/sources.conf - echo rsync://rsync.macports.org/macports/release/tarballs/ports.tar [default] >> /Users/runner/macports/etc/macports/sources.conf - # sudo chmod 644 /opt/local/etc/macports/sources.conf - sudo chmod 644 /Users/runner/macports/etc/macports/sources.conf - - - name: Package with MacPorts - run: | + sudo chmod 777 /opt/local/etc/macports/sources.conf + echo file://$(echo ~)/ports > /opt/local/etc/macports/sources.conf + echo rsync://rsync.macports.org/macports/release/tarballs/ports.tar [default] >> /opt/local/etc/macports/sources.conf + sudo chmod 644 /opt/local/etc/macports/sources.conf + # setup custom port mkdir -p ~/ports/multimedia/sunshine # copy configured Portfile - cp ./artifacts/Portfile ~/ports/multimedia/sunshine/ + mv ./artifacts/Portfile ~/ports/multimedia/sunshine/ + + # remove remaining cached artifacts + rm -r -f ./artifacts + mkdir artifacts # index the ports cd ~/ports portindex - + + - name: Build + run: | # build port - sudo port install sunshine - # || cat /opt/local/var/macports/logs/_Users_runner_ports_multimedia_sunshine/Sunshine/main.log \ - # && exit 1 + sudo port install sunshine \ + || cat /opt/local/var/macports/logs/_Users_runner_ports_multimedia_sunshine/Sunshine/main.log \ + && exit 1 # create packages sudo port dmg sunshine @@ -371,21 +425,11 @@ jobs: # port search sunshine - name: Upload Artifacts - if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: - name: sunshine-macos + name: sunshine-macports path: artifacts/ - # this step can be removed after packages are fixed - - name: Delete experimental packages - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} - working-directory: artifacts - run: | - rm -f ./sunshine-macos-experimental-dragndrop.dmg - rm -f ./sunshine-macos-experimental-bundle.dmg - rm -f ./sunshine-macos-experimental-archive.zip - - name: Create Release if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} uses: SunshineStream/actions/create_release@master @@ -449,7 +493,6 @@ jobs: mv ./cpack_artifacts/Sunshine.zip ../artifacts/sunshine-windows.zip - name: Upload Artifacts - if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} uses: actions/upload-artifact@v3 with: name: sunshine-windows From ca21e6a8ac80c91767da5d6e52d4318f0ec35624 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 15 Jun 2022 15:52:38 -0400 Subject: [PATCH 111/120] Update documentation --- docs/source/about/installation.rst | 37 +---------------- docs/source/about/usage.rst | 41 ++++++++++++------- docs/source/toc.rst | 9 ++++ docs/source/troubleshooting/general.rst | 13 ++++++ docs/source/troubleshooting/linux.rst | 9 ++++ docs/source/troubleshooting/macos.rst | 14 +++++++ docs/source/troubleshooting/windows.rst | 7 ++++ src_assets/linux/misc/85-sunshine-rules.rules | 2 +- 8 files changed, 80 insertions(+), 52 deletions(-) create mode 100644 docs/source/troubleshooting/general.rst create mode 100644 docs/source/troubleshooting/linux.rst create mode 100644 docs/source/troubleshooting/macos.rst create mode 100644 docs/source/troubleshooting/windows.rst diff --git a/docs/source/about/installation.rst b/docs/source/about/installation.rst index ab4b688858e..2176206a851 100644 --- a/docs/source/about/installation.rst +++ b/docs/source/about/installation.rst @@ -23,25 +23,6 @@ Linux ----- Follow the instructions for your preferred package type below. -.. Hint:: If this is the first time installing. - - .. code-block:: bash - - sudo usermod -a -G input $USER - sudo reboot now - -.. Tip:: Optionally, run Sunshine in the background. - - .. code-block:: bash - - systemctl --user start sunshine - -.. Note:: If screencasting fails with Wayland, you may need to run the following to force screencasting with X11. - - .. code-block:: bash - - sudo setcap -r $(readlink -f $(which sunshine)) - AppImage ^^^^^^^^ .. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/pkg:appimage?logo=github&style=for-the-badge @@ -101,12 +82,7 @@ MacOS .. image:: https://img.shields.io/github/issues/sunshinestream/sunshine/os:macos?logo=github&style=for-the-badge :alt: GitHub issues by-label -Disk Image File option: - #. Download and install ``sunshine.dmg`` - - .. Warning:: The Disk Image File is experimental. Limited support will be provided. - -Portfile option: +Portfile #. Install `MacPorts `_ #. Update the Macports sources. @@ -131,17 +107,6 @@ Portfile option: sudo port install sunshine #. The first time you start Sunshine, you will be asked to grant access to screen recording and your microphone. - #. Try to run the following code if you get this error: `Dynamic session lookup supported but failed: launchd did - not provide a socket path, verify that org.freedesktop.dbus-session.plist is loaded!` - - .. code-block:: bash - - launchctl load -w /Library/LaunchAgents/org.freedesktop.dbus-session.plist - -Standalone option: - #. Download and extract ``sunshine-macos.zip`` - - .. Warning:: The Standalone package is experimental. Limited support will be provided. Windows ------- diff --git a/docs/source/about/usage.rst b/docs/source/about/usage.rst index 8f73d204197..79d285f9cfe 100644 --- a/docs/source/about/usage.rst +++ b/docs/source/about/usage.rst @@ -56,33 +56,26 @@ Setup Linux ^^^^^ -The deb and rpm packages handle these steps automatically. The AppImage does not, and third party packages may not as -well. +The deb and rpm packages handle these steps automatically. The AppImage does not, third party packages may not as well. Sunshine needs access to `uinput` to create mouse and gamepad events. -Add user to group `input`. +Add user to group `input`, if this is the first time installing. .. code-block:: bash - usermod -a -G input $USER - - .. Warning:: If the above doesn't work you can try the following. This is not an advised method as it makes the - current user the owner of ``/dev/uinput``. Use at your own risk. - - .. code-block:: bash - - sudo chown $USER /dev/uinput + sudo usermod -a -G input $USER + sudo reboot now Create `udev` rules. .. code-block:: bash - nano /etc/udev/rules.d/85-sunshine-input.rules + sudo nano /etc/udev/rules.d/85-sunshine-input.rules Input the following contents. .. code-block:: - KERNEL=="uinput", GROUP="input", MODE="0660", OPTION+="static_node=uinput" + KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput" Save the file and exit: @@ -99,11 +92,22 @@ Configure autostart service Description=Sunshine Gamestream Server for Moonlight [Service] - ExecStart=~/sunshine.AppImage + ExecStart= [Install] WantedBy=graphical-session.target + .. table:: + :widths: auto + + ======== =================== =============== + package ExecStart Auto Configured + ======== =================== =============== + deb /usr/bin/sunshine ✔ + rpm /usr/bin/sunshine ✔ + AppImage ~/sunshine.AppImage ✖ + ======== =================== =============== + Start once .. code-block:: bash @@ -137,7 +141,14 @@ select their sink as audio device in `sunshine.conf`. .. Note:: Command Keys are not forwarded by Moonlight. Right Option-Key is mapped to CMD-Key. -.. Caution:: Gamepads are not supported. +.. Caution:: Gamepads are not currently supported. + +Configure autostart service + + MacPorts + .. code-block:: bash + + sudo port load Sunshine Windows ^^^^^^^ diff --git a/docs/source/toc.rst b/docs/source/toc.rst index 9c0989eedcf..efafa92bff1 100644 --- a/docs/source/toc.rst +++ b/docs/source/toc.rst @@ -9,6 +9,15 @@ about/usage about/advanced_usage +.. toctree:: + :maxdepth: 2 + :caption: Troubleshooting + + troubleshooting/general + troubleshooting/linux + troubleshooting/macos + troubleshooting/windows + .. toctree:: :maxdepth: 2 :caption: Build diff --git a/docs/source/troubleshooting/general.rst b/docs/source/troubleshooting/general.rst new file mode 100644 index 00000000000..322327ccbab --- /dev/null +++ b/docs/source/troubleshooting/general.rst @@ -0,0 +1,13 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/troubleshooting/general.rst + +General +======= +If you forgot your credentials to the web UI, try this. + + .. code-block:: bash + + sunshine -creds + +Can't access the web UI? + + #. Check firefall rules. diff --git a/docs/source/troubleshooting/linux.rst b/docs/source/troubleshooting/linux.rst new file mode 100644 index 00000000000..71e9eac0e6c --- /dev/null +++ b/docs/source/troubleshooting/linux.rst @@ -0,0 +1,9 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/troubleshooting/linux.rst + +Linux +===== +If screencasting fails with Wayland, you may need to run the following to force screencasting with X11. + + .. code-block:: bash + + sudo setcap -r $(readlink -f $(which sunshine)) diff --git a/docs/source/troubleshooting/macos.rst b/docs/source/troubleshooting/macos.rst new file mode 100644 index 00000000000..18ea93615bf --- /dev/null +++ b/docs/source/troubleshooting/macos.rst @@ -0,0 +1,14 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/troubleshooting/macos.rst + +MacOS +===== +If you get this error: + + ``Dynamic session lookup supported but failed: launchd did not provide a socket path, verify that + org.freedesktop.dbus-session.plist is loaded!`` + + Try this. + + .. code-block:: bash + + launchctl load -w /Library/LaunchAgents/org.freedesktop.dbus-session.plist diff --git a/docs/source/troubleshooting/windows.rst b/docs/source/troubleshooting/windows.rst new file mode 100644 index 00000000000..461bce0a9e3 --- /dev/null +++ b/docs/source/troubleshooting/windows.rst @@ -0,0 +1,7 @@ +:github_url: https://github.com/SunshineStream/Sunshine/tree/nightly/docs/source/troubleshooting/windows.rst + +Windows +======= +No gamepad is detected. + + #. Verify that you've installed `ViGEmBus `_. diff --git a/src_assets/linux/misc/85-sunshine-rules.rules b/src_assets/linux/misc/85-sunshine-rules.rules index 77c337c4d42..a1ee7cd0e42 100644 --- a/src_assets/linux/misc/85-sunshine-rules.rules +++ b/src_assets/linux/misc/85-sunshine-rules.rules @@ -1 +1 @@ -KERNEL=="uinput", GROUP="input", MODE="0660", OPTION+="static_node=uinput" \ No newline at end of file +KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput" \ No newline at end of file From e86207606af6eee2a02e95e017ee2cf864d65662 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 15 Jun 2022 15:53:04 -0400 Subject: [PATCH 112/120] Use openssl for deb package instead of libssl1.1/3 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2963417e902..5c9a135f89a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -583,7 +583,7 @@ if(UNIX AND NOT APPLE) # Dependencies set(CPACK_DEB_COMPONENT_INSTALL ON) - set(CPACK_DEBIAN_PACKAGE_DEPENDS "libssl1.1 | libssl3, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2") + set(CPACK_DEBIAN_PACKAGE_DEPENDS "openssl, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2") set(CPACK_RPM_PACKAGE_REQUIRES "openssl >= 1.1, libavdevice >= 4.3, boost-thread >= 1.67.0, boost-filesystem >= 1.67.0, boost-log >= 1.67.0, pulseaudio-libs >= 10.0, libopusenc >= 0.2.1, libxcb >= 1.13, libXtst >= 1.2.3, libevdev >= 1.5.6, libdrm >= 2.4.97, libcap >= 2.22") set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF) # This should automatically figure out dependencies, doesn't work with the current config From dd73f45175c4028c24ea91f251eba7afcb6194df Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 15 Jun 2022 16:05:23 -0400 Subject: [PATCH 113/120] Deactivate mac port job --- .github/workflows/CI.yml | 195 +++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 98 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d777444bed4..18d7e89cc13 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -340,104 +340,103 @@ jobs: last_version: ${{ needs.check_changelog.outputs.last_version }} release_body: ${{ needs.check_changelog.outputs.release_body }} - build_mac_port: - name: Macports - runs-on: macos-11 - needs: [check_changelog, build_mac] - if: never() # disable this job - - steps: - - name: Cache Artifacts - uses: actions/cache@v3 - with: - path: artifacts - key: ${{ runner.os }}-artifacts - - - name: Setup Macports - run : | - # update paths for macports - echo "/opt/local/sbin" >> $GITHUB_PATH - echo "/opt/local/bin" >> $GITHUB_PATH - - # Set OpenSSL 1.1 as default - # rm -rf /usr/local/opt/openssl - # rm -rf /usr/local/bin/openssl - # ln -sf /usr/local/Cellar/openssl@1.1/1.1.1o/bin/openssl /usr/local/bin/openssl - # ln -sf /usr/local/Cellar/openssl@1.1/1.1.1o /usr/local/opt/openssl - - # download and extract macports - curl -O https://distfiles.macports.org/MacPorts/MacPorts-2.7.2.tar.bz2 - tar xf MacPorts-2.7.2.tar.bz2 - - # build macports - cd MacPorts-2.7.2 - ./configure - make - sudo make install - cd ../ - rm -rf MacPorts-2.7.2* - - - name: Configure Macports - run: | - # update sources - sudo port -v selfupdate - - # use custom sources - sudo chmod 777 /opt/local/etc/macports/sources.conf - echo file://$(echo ~)/ports > /opt/local/etc/macports/sources.conf - echo rsync://rsync.macports.org/macports/release/tarballs/ports.tar [default] >> /opt/local/etc/macports/sources.conf - sudo chmod 644 /opt/local/etc/macports/sources.conf - - # setup custom port - mkdir -p ~/ports/multimedia/sunshine - - # copy configured Portfile - mv ./artifacts/Portfile ~/ports/multimedia/sunshine/ - - # remove remaining cached artifacts - rm -r -f ./artifacts - mkdir artifacts - - # index the ports - cd ~/ports - portindex - - - name: Build - run: | - # build port - sudo port install sunshine \ - || cat /opt/local/var/macports/logs/_Users_runner_ports_multimedia_sunshine/Sunshine/main.log \ - && exit 1 - - # create packages - sudo port dmg sunshine - sudo port pkg sunshine - - # move - mv $(port work sunshine)/Sunshine*.dmg ./artifacts/sunshine.dmg - mv $(port work sunshine)/Sunshine*.ppkg ./artifacts/sunshine.pkg - - # testing only - # ls ~/ports/multimedia/sunshine - # cat ~/ports/multimedia/sunshine/Portfile - # cat /opt/local/etc/macports/sources.conf - # cat ~/ports/Portindex - # port search sunshine - - - name: Upload Artifacts - uses: actions/upload-artifact@v3 - with: - name: sunshine-macports - path: artifacts/ - - - name: Create Release - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} - uses: SunshineStream/actions/create_release@master - with: - token: ${{ secrets.GITHUB_TOKEN }} - next_version: ${{ needs.check_changelog.outputs.next_version }} - last_version: ${{ needs.check_changelog.outputs.last_version }} - release_body: ${{ needs.check_changelog.outputs.release_body }} +# build_mac_port: +# name: Macports +# runs-on: macos-11 +# needs: [check_changelog, build_mac] +# +# steps: +# - name: Cache Artifacts +# uses: actions/cache@v3 +# with: +# path: artifacts +# key: ${{ runner.os }}-artifacts +# +# - name: Setup Macports +# run : | +# # update paths for macports +# echo "/opt/local/sbin" >> $GITHUB_PATH +# echo "/opt/local/bin" >> $GITHUB_PATH +# +# # Set OpenSSL 1.1 as default +# # rm -rf /usr/local/opt/openssl +# # rm -rf /usr/local/bin/openssl +# # ln -sf /usr/local/Cellar/openssl@1.1/1.1.1o/bin/openssl /usr/local/bin/openssl +# # ln -sf /usr/local/Cellar/openssl@1.1/1.1.1o /usr/local/opt/openssl +# +# # download and extract macports +# curl -O https://distfiles.macports.org/MacPorts/MacPorts-2.7.2.tar.bz2 +# tar xf MacPorts-2.7.2.tar.bz2 +# +# # build macports +# cd MacPorts-2.7.2 +# ./configure +# make +# sudo make install +# cd ../ +# rm -rf MacPorts-2.7.2* +# +# - name: Configure Macports +# run: | +# # update sources +# sudo port -v selfupdate +# +# # use custom sources +# sudo chmod 777 /opt/local/etc/macports/sources.conf +# echo file://$(echo ~)/ports > /opt/local/etc/macports/sources.conf +# echo rsync://rsync.macports.org/macports/release/tarballs/ports.tar [default] >> /opt/local/etc/macports/sources.conf +# sudo chmod 644 /opt/local/etc/macports/sources.conf +# +# # setup custom port +# mkdir -p ~/ports/multimedia/sunshine +# +# # copy configured Portfile +# mv ./artifacts/Portfile ~/ports/multimedia/sunshine/ +# +# # remove remaining cached artifacts +# rm -r -f ./artifacts +# mkdir artifacts +# +# # index the ports +# cd ~/ports +# portindex +# +# - name: Build +# run: | +# # build port +# sudo port install sunshine \ +# || cat /opt/local/var/macports/logs/_Users_runner_ports_multimedia_sunshine/Sunshine/main.log \ +# && exit 1 +# +# # create packages +# sudo port dmg sunshine +# sudo port pkg sunshine +# +# # move +# mv $(port work sunshine)/Sunshine*.dmg ./artifacts/sunshine.dmg +# mv $(port work sunshine)/Sunshine*.ppkg ./artifacts/sunshine.pkg +# +# # testing only +# # ls ~/ports/multimedia/sunshine +# # cat ~/ports/multimedia/sunshine/Portfile +# # cat /opt/local/etc/macports/sources.conf +# # cat ~/ports/Portindex +# # port search sunshine +# +# - name: Upload Artifacts +# uses: actions/upload-artifact@v3 +# with: +# name: sunshine-macports +# path: artifacts/ +# +# - name: Create Release +# if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} +# uses: SunshineStream/actions/create_release@master +# with: +# token: ${{ secrets.GITHUB_TOKEN }} +# next_version: ${{ needs.check_changelog.outputs.next_version }} +# last_version: ${{ needs.check_changelog.outputs.last_version }} +# release_body: ${{ needs.check_changelog.outputs.release_body }} build_win: name: Windows From 0c827690ec8c12abaf54b522e42401c1997b138c Mon Sep 17 00:00:00 2001 From: Conn O'Griofa Date: Wed, 18 May 2022 17:52:43 +0100 Subject: [PATCH 114/120] config: move VideoToolbox variables into correct video_t struct location --- sunshine/config.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sunshine/config.cpp b/sunshine/config.cpp index 6dd3c1b2b67..e06a2801373 100644 --- a/sunshine/config.cpp +++ b/sunshine/config.cpp @@ -220,6 +220,12 @@ video_t video { std::nullopt, -1 }, // amd + { + 0, + 0, + 1, + -1 }, // vt + {}, // encoder {}, // adapter_name {}, // output_name @@ -722,11 +728,8 @@ void apply_config(std::unordered_map &&vars) { } int_f(vars, "vt_coder", video.vt.coder, vt::coder_from_view); - video.vt.allow_sw = 0; int_f(vars, "vt_software", video.vt.allow_sw, vt::allow_software_from_view); - video.vt.require_sw = 0; int_f(vars, "vt_software", video.vt.require_sw, vt::force_software_from_view); - video.vt.realtime = 1; int_f(vars, "vt_realtime", video.vt.realtime, vt::rt_from_view); string_f(vars, "encoder", video.encoder); From ab0a6b5fa645c51df4822ce7e0b12b88258a8caa Mon Sep 17 00:00:00 2001 From: Conn O'Griofa Date: Thu, 19 May 2022 20:11:44 +0100 Subject: [PATCH 115/120] webui: remove erroneous v-bind properties These were causing unusual behaviour (select dialogs displaying a blank label when a value should be selected, and values randomly setting themselves to undefined when switching tabs). --- src_assets/common/assets/web/config.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src_assets/common/assets/web/config.html b/src_assets/common/assets/web/config.html index 203e807fea5..425b953ed77 100644 --- a/src_assets/common/assets/web/config.html +++ b/src_assets/common/assets/web/config.html @@ -37,13 +37,13 @@

Configuration

class="form-select" v-model="config.min_log_level" > - - - - - - - + + + + + + +
The minimum log level printed to standard out @@ -497,7 +497,7 @@

Configuration

- + + + + +
+ Improves capture latency during mouse movement.
+ Enabling this may prevent the client's FPS from exceeding the host monitor's active refresh rate.
@@ -832,6 +843,7 @@

Configuration

this.config.key_rightalt_to_key_win || "disabled"; this.config.gamepad = this.config.gamepad || "x360"; this.config.upnp = this.config.upnp || "disabled"; + this.config.dwmflush = this.config.dwmflush || "disabled"; this.config.min_log_level = this.config.min_log_level || 2; this.config.origin_pin_allowed = this.config.origin_pin_allowed || "pc"; diff --git a/sunshine/config.cpp b/sunshine/config.cpp index e06a2801373..ac1d9ccff1d 100644 --- a/sunshine/config.cpp +++ b/sunshine/config.cpp @@ -226,9 +226,10 @@ video_t video { 1, -1 }, // vt - {}, // encoder - {}, // adapter_name - {}, // output_name + {}, // encoder + {}, // adapter_name + {}, // output_name + false // dwmflush }; audio_t audio {}; @@ -735,6 +736,7 @@ void apply_config(std::unordered_map &&vars) { string_f(vars, "encoder", video.encoder); string_f(vars, "adapter_name", video.adapter_name); string_f(vars, "output_name", video.output_name); + bool_f(vars, "dwmflush", video.dwmflush); path_f(vars, "pkey", nvhttp.pkey); path_f(vars, "cert", nvhttp.cert); diff --git a/sunshine/config.h b/sunshine/config.h index 183139612dc..4ecb9f3261f 100644 --- a/sunshine/config.h +++ b/sunshine/config.h @@ -44,6 +44,7 @@ struct video_t { std::string encoder; std::string adapter_name; std::string output_name; + bool dwmflush; }; struct audio_t { diff --git a/sunshine/platform/windows/display.h b/sunshine/platform/windows/display.h index 37020fef4f1..60539efcea5 100644 --- a/sunshine/platform/windows/display.h +++ b/sunshine/platform/windows/display.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -172,4 +173,4 @@ class display_vram_t : public display_base_t, public std::enable_shared_from_thi }; } // namespace platf::dxgi -#endif \ No newline at end of file +#endif diff --git a/sunshine/platform/windows/display_base.cpp b/sunshine/platform/windows/display_base.cpp index 02b08c37f79..12f8cad0978 100644 --- a/sunshine/platform/windows/display_base.cpp +++ b/sunshine/platform/windows/display_base.cpp @@ -20,6 +20,10 @@ capture_e duplication_t::next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::ch return capture_status; } + if(config::video.dwmflush) { + DwmFlush(); + } + auto status = dup->AcquireNextFrame(timeout.count(), &frame_info, res_p); switch(status) { From 2d969c2cccc61a3fdc718b7aaa0b13410cd850f0 Mon Sep 17 00:00:00 2001 From: Conn O'Griofa Date: Fri, 20 May 2022 16:25:09 +0100 Subject: [PATCH 118/120] platform/windows: change dwmflush default, add autodetection On each re/init, query the active monitor refresh rate via DwmGetCompositionTimingInfo. If the client requested framerate exceeds the host monitor refresh, automatically disable DwmFlush. This avoids the problem by which DwmFlush would constrain the client FPS if the host monitor runs at a lower refresh rate, thus allowing the feature to be enabled by default. If there are other issues caused by DwmFlush for certain systems, it can still be disabled via configuration. --- docs/source/about/advanced_usage.rst | 7 ++++--- src_assets/common/assets/web/config.html | 6 +++--- sunshine/config.cpp | 8 ++++---- sunshine/platform/windows/display.h | 1 + sunshine/platform/windows/display_base.cpp | 18 +++++++++++++++++- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index e071ada5a8d..e0903223454 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -339,11 +339,12 @@ dwmflush Description Invoke DwmFlush() to sync screen capture to the Windows presentation interval. - .. Caution:: Applies to Windows only. Alleviates visual stuttering during mouse movement, but causes the capture - rate to be limited to the host monitor's currently active refresh rate. + .. Caution:: Applies to Windows only. Alleviates visual stuttering during mouse movement. + If enabled, this feature will automatically deactivate if the client framerate exceeds + the host monitor's current refresh rate. Default - ``disabled`` + ``enabled`` Examples diff --git a/src_assets/common/assets/web/config.html b/src_assets/common/assets/web/config.html index 1d34512c981..01954e76e7b 100644 --- a/src_assets/common/assets/web/config.html +++ b/src_assets/common/assets/web/config.html @@ -410,8 +410,8 @@

Configuration

- Improves capture latency during mouse movement.
- Enabling this may prevent the client's FPS from exceeding the host monitor's active refresh rate. + Improves capture latency/smoothness during mouse movement.
+ Disable if you encounter any VSync-related issues.
@@ -843,7 +843,7 @@

Configuration

this.config.key_rightalt_to_key_win || "disabled"; this.config.gamepad = this.config.gamepad || "x360"; this.config.upnp = this.config.upnp || "disabled"; - this.config.dwmflush = this.config.dwmflush || "disabled"; + this.config.dwmflush = this.config.dwmflush || "enabled"; this.config.min_log_level = this.config.min_log_level || 2; this.config.origin_pin_allowed = this.config.origin_pin_allowed || "pc"; diff --git a/sunshine/config.cpp b/sunshine/config.cpp index ac1d9ccff1d..21c27e2d94b 100644 --- a/sunshine/config.cpp +++ b/sunshine/config.cpp @@ -226,10 +226,10 @@ video_t video { 1, -1 }, // vt - {}, // encoder - {}, // adapter_name - {}, // output_name - false // dwmflush + {}, // encoder + {}, // adapter_name + {}, // output_name + true // dwmflush }; audio_t audio {}; diff --git a/sunshine/platform/windows/display.h b/sunshine/platform/windows/display.h index 60539efcea5..6a1501354e4 100644 --- a/sunshine/platform/windows/display.h +++ b/sunshine/platform/windows/display.h @@ -96,6 +96,7 @@ class duplication_t { public: dup_t dup; bool has_frame {}; + bool use_dwmflush {}; capture_e next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::chrono::milliseconds timeout, resource_t::pointer *res_p); capture_e reset(dup_t::pointer dup_p = dup_t::pointer()); diff --git a/sunshine/platform/windows/display_base.cpp b/sunshine/platform/windows/display_base.cpp index 12f8cad0978..9ee9ad974e9 100644 --- a/sunshine/platform/windows/display_base.cpp +++ b/sunshine/platform/windows/display_base.cpp @@ -2,6 +2,7 @@ // Created by loki on 1/12/20. // +#include #include #include "display.h" @@ -20,7 +21,7 @@ capture_e duplication_t::next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::ch return capture_status; } - if(config::video.dwmflush) { + if(use_dwmflush) { DwmFlush(); } @@ -217,6 +218,21 @@ int display_base_t::init(int framerate, const std::string &display_name) { << "Offset : "sv << offset_x << 'x' << offset_y << std::endl << "Virtual Desktop : "sv << env_width << 'x' << env_height; + // Enable DwmFlush() only if the current refresh rate can match the client framerate. + auto refresh_rate = framerate; + DWM_TIMING_INFO timing_info; + timing_info.cbSize = sizeof(timing_info); + + status = DwmGetCompositionTimingInfo(NULL, &timing_info); + if(FAILED(status)) { + BOOST_LOG(warning) << "Failed to detect active refresh rate."; + } + else { + refresh_rate = std::round((double)timing_info.rateRefresh.uiNumerator / (double)timing_info.rateRefresh.uiDenominator); + } + + dup.use_dwmflush = config::video.dwmflush && !(framerate > refresh_rate) ? true : false; + // Bump up thread priority { const DWORD flags = TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY; From a02d314dde90a6163d926f3fc11af73988f286a5 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 15 Jun 2022 17:50:11 -0400 Subject: [PATCH 119/120] Update CHANGELOG.md for v0.14.0 --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a18ecbd748..1844e3559cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [0.14.0] - 2022-06-15 +### Added +- (Documentation) Added Sphinx documentation available at https://sunshinestream.readthedocs.io/en/latest/ +- (Development) Initial support for Localization +- (Linux) Add rpm package as release asset +- (MacOS) Add Portfile as release asset +- (Windows) Add DwmFlush() call to improve capture +- (Windows) Add Windows installer +### Fixed +- (AMD) Fixed hwdevice being destroyed before context +- (Linux) Added missing dependencies to AppImage +- (Linux) Fixed rumble events causing game to freeze +- (Linux) Improved Pulse/Pipewire compatibility +- (Linux) Moved to single deb package +- (MacOS) Fixed missing TPCircularBuffer submodule +- (Stream) Properly catch exceptions in stream broadcast handlers +- (Stream/Video) AVPacket fix + ## [0.13.0] - 2022-02-27 ### Added - (MacOS) Initial support for MacOS (#40) From 651d75fce760b41481fdb3ae358aad063306e46b Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 15 Jun 2022 18:17:12 -0400 Subject: [PATCH 120/120] Update version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8827b4539b2..44f24e7d6b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.0) -project(Sunshine VERSION 0.13.0 +project(Sunshine VERSION 0.14.0 DESCRIPTION "Sunshine is a Gamestream host for Moonlight." HOMEPAGE_URL "https://sunshinestream.github.io" )