Merge remote-tracking branch 'sunshine/master'
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
# install dependencies for C++ analysis
|
# install dependencies for C++ analysis
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
# setup homebrew for x86_64
|
||||||
|
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||||
|
eval "$(/usr/local/bin/brew shellenv)"
|
||||||
|
|
||||||
# install dependencies
|
# install dependencies
|
||||||
dependencies=(
|
dependencies=(
|
||||||
"boost"
|
"boost"
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/misc/service/"
|
|||||||
install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/misc/migration/"
|
install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/misc/migration/"
|
||||||
DESTINATION "scripts"
|
DESTINATION "scripts"
|
||||||
COMPONENT assets)
|
COMPONENT assets)
|
||||||
|
install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/misc/path/"
|
||||||
|
DESTINATION "scripts"
|
||||||
|
COMPONENT assets)
|
||||||
|
|
||||||
# Configurable options for the service
|
# Configurable options for the service
|
||||||
install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/misc/autostart/"
|
install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/misc/autostart/"
|
||||||
@@ -69,6 +72,7 @@ SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS
|
|||||||
IfSilent +2 0
|
IfSilent +2 0
|
||||||
# ExecShell 'open' 'https://docs.lizardbyte.dev/projects/sunshine'
|
# ExecShell 'open' 'https://docs.lizardbyte.dev/projects/sunshine'
|
||||||
nsExec::ExecToLog 'icacls \\\"$INSTDIR\\\" /reset'
|
nsExec::ExecToLog 'icacls \\\"$INSTDIR\\\" /reset'
|
||||||
|
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\update-path.bat\\\" add'
|
||||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\drivers\\\\sudovda\\\\install.bat\\\"'
|
nsExec::ExecToLog '\\\"$INSTDIR\\\\drivers\\\\sudovda\\\\install.bat\\\"'
|
||||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\migrate-config.bat\\\"'
|
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\migrate-config.bat\\\"'
|
||||||
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\add-firewall-rule.bat\\\"'
|
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\add-firewall-rule.bat\\\"'
|
||||||
@@ -99,16 +103,18 @@ set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS
|
|||||||
'Do you want to remove $INSTDIR (this includes the configuration, cover images, and settings)?' \
|
'Do you want to remove $INSTDIR (this includes the configuration, cover images, and settings)?' \
|
||||||
/SD IDNO IDNO NoDelete
|
/SD IDNO IDNO NoDelete
|
||||||
RMDir /r \\\"$INSTDIR\\\"; skipped if no
|
RMDir /r \\\"$INSTDIR\\\"; skipped if no
|
||||||
|
nsExec::ExecToLog '\\\"$INSTDIR\\\\scripts\\\\update-path.bat\\\" remove'
|
||||||
NoDelete:
|
NoDelete:
|
||||||
")
|
")
|
||||||
|
|
||||||
# Adding an option for the start menu
|
# Adding an option for the start menu
|
||||||
set(CPACK_NSIS_MODIFY_PATH "OFF")
|
set(CPACK_NSIS_MODIFY_PATH OFF)
|
||||||
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
||||||
# This will be shown on the installed apps Windows settings
|
# This will be shown on the installed apps Windows settings
|
||||||
set(CPACK_NSIS_INSTALLED_ICON_NAME "sunshine.exe")
|
set(CPACK_NSIS_INSTALLED_ICON_NAME "sunshine.exe")
|
||||||
set(CPACK_NSIS_CREATE_ICONS_EXTRA
|
set(CPACK_NSIS_CREATE_ICONS_EXTRA
|
||||||
"${CPACK_NSIS_CREATE_ICONS_EXTRA}
|
"${CPACK_NSIS_CREATE_ICONS_EXTRA}
|
||||||
|
SetOutPath '\$INSTDIR'
|
||||||
CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${CMAKE_PROJECT_NAME}.lnk' \
|
CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${CMAKE_PROJECT_NAME}.lnk' \
|
||||||
'\$INSTDIR\\\\sunshine.exe' '--shortcut'
|
'\$INSTDIR\\\\sunshine.exe' '--shortcut'
|
||||||
")
|
")
|
||||||
|
|||||||
@@ -335,8 +335,6 @@ recommended for most users. No support will be provided!}
|
|||||||
scripts/uninstall-service.bat
|
scripts/uninstall-service.bat
|
||||||
```
|
```
|
||||||
|
|
||||||
To uninstall, delete the extracted directory which contains the `sunshine.exe` file.
|
|
||||||
|
|
||||||
## Initial Setup
|
## Initial Setup
|
||||||
After installation, some initial setup is required.
|
After installation, some initial setup is required.
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,16 @@ system. You may also want to enable decoders, however that is not required for S
|
|||||||
```
|
```
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### Input not working
|
||||||
|
After installation, the `udev` rules need to be reloaded. Our post-install script tries to do this for you
|
||||||
|
automatically, but if it fails you may need to restart your system.
|
||||||
|
|
||||||
|
If the input is still not working, you may need to add your user to the `input` group.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo usermod -aG input $USER
|
||||||
|
```
|
||||||
|
|
||||||
@note{Other build options are listed in the
|
@note{Other build options are listed in the
|
||||||
[meson options](https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/meson_options.txt) file.}
|
[meson options](https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/meson_options.txt) file.}
|
||||||
|
|
||||||
|
|||||||
@@ -538,11 +538,11 @@ ext-js:
|
|||||||
<div class="card-footer p-3 px-4">
|
<div class="card-footer p-3 px-4">
|
||||||
<a class="latest-button btn btn-outline-light me-3 mb-3 d-none" href="https://github.com/LizardByte/Sunshine/releases/latest" target="_blank">
|
<a class="latest-button btn btn-outline-light me-3 mb-3 d-none" href="https://github.com/LizardByte/Sunshine/releases/latest" target="_blank">
|
||||||
<i class="fa-fw fab fa-github"></i>
|
<i class="fa-fw fab fa-github"></i>
|
||||||
Latest: <span id="latest-version"></span>
|
Latest: <span id="latest-version" class="crowdin-ignore"></span>
|
||||||
</a>
|
</a>
|
||||||
<a class="beta-button btn btn-outline-light me-3 mb-3 d-none" href="#" target="_blank">
|
<a class="beta-button btn btn-outline-light me-3 mb-3 d-none" href="#" target="_blank">
|
||||||
<i class="fa-fw fas fa-flask"></i>
|
<i class="fa-fw fas fa-flask"></i>
|
||||||
Beta: <span id="beta-version"></span>
|
Beta: <span id="beta-version" class="crowdin-ignore"></span>
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-outline-light me-3 mb-3" href="https://github.com/LizardByte/pacman-repo" target="_blank">
|
<a class="btn btn-outline-light me-3 mb-3" href="https://github.com/LizardByte/pacman-repo" target="_blank">
|
||||||
<i class="fa-fw fab fa-linux"></i>
|
<i class="fa-fw fab fa-linux"></i>
|
||||||
@@ -577,16 +577,21 @@ ext-js:
|
|||||||
// Filter the releases to get only the stable releases
|
// Filter the releases to get only the stable releases
|
||||||
const stableReleases = data.filter(release => !release.prerelease);
|
const stableReleases = data.filter(release => !release.prerelease);
|
||||||
|
|
||||||
|
const latestButton = document.querySelector('.latest-button');
|
||||||
|
const latestVersion = document.querySelector('#latest-version');
|
||||||
|
const betaButton = document.querySelector('.beta-button');
|
||||||
|
const betaVersion = document.querySelector('#beta-version');
|
||||||
|
|
||||||
// If there are no stable releases, hide the latest download button
|
// If there are no stable releases, hide the latest download button
|
||||||
if (stableReleases.length === 0) {
|
if (stableReleases.length === 0) {
|
||||||
document.querySelector('.latest-button').classList.add('d-none');
|
latestButton.classList.add('d-none');
|
||||||
} else {
|
} else {
|
||||||
// Show the latest download button
|
// Show the latest download button
|
||||||
document.querySelector('.latest-button').classList.remove('d-none');
|
latestButton.classList.remove('d-none');
|
||||||
|
|
||||||
// Get the latest stable release
|
// Get the latest stable release
|
||||||
const latestStableRelease = stableReleases[0];
|
const latestStableRelease = stableReleases[0];
|
||||||
document.querySelector('#latest-version').textContent = latestStableRelease.tag_name;
|
latestVersion.textContent = latestStableRelease.tag_name;
|
||||||
|
|
||||||
// If there is a pre-release, update the href attribute of the anchor tag
|
// If there is a pre-release, update the href attribute of the anchor tag
|
||||||
if (preReleases.length > 0) {
|
if (preReleases.length > 0) {
|
||||||
@@ -598,16 +603,16 @@ ext-js:
|
|||||||
|
|
||||||
// If the pre-release is newer, update the href attribute of the anchor tag
|
// If the pre-release is newer, update the href attribute of the anchor tag
|
||||||
if (preReleaseDate > stableReleaseDate) {
|
if (preReleaseDate > stableReleaseDate) {
|
||||||
document.querySelector('.beta-button').href = latestPreRelease.html_url;
|
betaButton.href = latestPreRelease.html_url;
|
||||||
document.querySelector('#beta-version').textContent = latestPreRelease.tag_name;
|
betaVersion.textContent = latestPreRelease.tag_name;
|
||||||
document.querySelector('.beta-button').classList.remove('d-none');
|
betaButton.classList.remove('d-none');
|
||||||
} else {
|
} else {
|
||||||
// If the pre-release is older, hide the button
|
// If the pre-release is older, hide the button
|
||||||
document.querySelector('.beta-button').classList.add('d-none');
|
betaButton.classList.add('d-none');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If there is no pre-release, hide the button
|
// If there is no pre-release, hide the button
|
||||||
document.querySelector('.beta-button').classList.add('d-none');
|
betaButton.classList.add('d-none');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"serve": "serve ./tests/fixtures/http --no-port-switching"
|
"serve": "serve ./tests/fixtures/http --no-port-switching"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lizardbyte/shared-web": "2025.221.2011",
|
"@lizardbyte/shared-web": "2025.326.11214",
|
||||||
"vue": "3.5.13",
|
"vue": "3.5.13",
|
||||||
"vue-i18n": "11.1.2"
|
"vue-i18n": "11.1.2"
|
||||||
},
|
},
|
||||||
|
|||||||
Submodule packaging/linux/flatpak/deps/shared-modules updated: a6c788b38f...1f8e591b26
@@ -50,14 +50,32 @@
|
|||||||
"name": "libXmu",
|
"name": "libXmu",
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "git",
|
||||||
"url": "https://xorg.freedesktop.org/archive/individual/lib/libXmu-1.2.1.tar.gz",
|
"url": "https://github.com/LizardByte-infrastructure/libxmu.git",
|
||||||
"sha256": "bf0902583dd1123856c11e0a5085bd3c6e9886fbbd44954464975fd7d52eb599",
|
"tag": "libXmu-1.2.1",
|
||||||
|
"commit": "792f80402ee06ce69bca3a8f2a84295999c3a170",
|
||||||
"x-checker-data": {
|
"x-checker-data": {
|
||||||
"type": "anitya",
|
"type": "anitya",
|
||||||
"project-id": 1785,
|
"project-id": 1785,
|
||||||
"stable-only": true,
|
"stable-only": true,
|
||||||
"url-template": "https://xorg.freedesktop.org/archive/individual/lib/libXmu-$version.tar.gz"
|
"tag-template": "libXmu-$version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "font-util",
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/LizardByte-infrastructure/font-util.git",
|
||||||
|
"tag": "font-util-1.4.1",
|
||||||
|
"commit": "b5ca142f81a6f14eddb23be050291d1c25514777",
|
||||||
|
"x-checker-data": {
|
||||||
|
"type": "anitya",
|
||||||
|
"project-id": 15055,
|
||||||
|
"stable-only": true,
|
||||||
|
"tag-template": "font-util-$version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -66,14 +84,15 @@
|
|||||||
"name": "libfontenc",
|
"name": "libfontenc",
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "git",
|
||||||
"url": "https://xorg.freedesktop.org/archive/individual/lib/libfontenc-1.1.8.tar.xz",
|
"url": "https://github.com/LizardByte-infrastructure/libfontenc.git",
|
||||||
"sha256": "7b02c3d405236e0d86806b1de9d6868fe60c313628b38350b032914aa4fd14c6",
|
"tag": "libfontenc-1.1.8",
|
||||||
|
"commit": "92a85fda2acb4e14ec0b2f6d8fe3eaf2b687218c",
|
||||||
"x-checker-data": {
|
"x-checker-data": {
|
||||||
"type": "anitya",
|
"type": "anitya",
|
||||||
"project-id": 1613,
|
"project-id": 1613,
|
||||||
"stable-only": true,
|
"stable-only": true,
|
||||||
"url-template": "https://xorg.freedesktop.org/archive/individual/lib/libfontenc-$version.tar.xz"
|
"tag-template": "libfontenc-$version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -97,34 +116,19 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "font-util",
|
|
||||||
"sources": [
|
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"url": "https://xorg.freedesktop.org/archive/individual/font/font-util-1.4.1.tar.gz",
|
|
||||||
"sha256": "f029ae80cdd75d89bee7f7af61c21e07982adfb9f72344a158b99f91f77ef5ed",
|
|
||||||
"x-checker-data": {
|
|
||||||
"type": "anitya",
|
|
||||||
"project-id": 15055,
|
|
||||||
"stable-only": true,
|
|
||||||
"url-template": "https://xorg.freedesktop.org/archive/individual/font/font-util-$version.tar.gz"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "xvfb-libXfont2",
|
"name": "xvfb-libXfont2",
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "git",
|
||||||
"url": "https://xorg.freedesktop.org/archive/individual/lib/libXfont2-2.0.6.tar.gz",
|
"url": "https://github.com/LizardByte-infrastructure/libxfont.git",
|
||||||
"sha256": "a944df7b6837c8fa2067f6a5fc25d89b0acc4011cd0bc085106a03557fb502fc",
|
"tag": "libXfont2-2.0.6",
|
||||||
|
"commit": "d54aaf2483df6a1f98fadc09004157e657b7f73e",
|
||||||
"x-checker-data": {
|
"x-checker-data": {
|
||||||
"type": "anitya",
|
"type": "anitya",
|
||||||
"project-id": 17165,
|
"project-id": 17165,
|
||||||
"stable-only": true,
|
"stable-only": true,
|
||||||
"url-template": "https://xorg.freedesktop.org/archive/individual/lib/libXfont2-$version.tar.gz"
|
"tag-template": "libXfont2-$version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -8,4 +8,4 @@ echo Sunshine User Service has been removed.
|
|||||||
|
|
||||||
# Udev rule
|
# Udev rule
|
||||||
flatpak-spawn --host pkexec sh -c "rm /etc/udev/rules.d/60-sunshine.rules"
|
flatpak-spawn --host pkexec sh -c "rm /etc/udev/rules.d/60-sunshine.rules"
|
||||||
echo Mouse permission removed. Restart computer to take effect.
|
echo Input rules removed. Restart computer to take effect.
|
||||||
|
|||||||
@@ -665,9 +665,13 @@ namespace config {
|
|||||||
// Lists might contain newlines
|
// Lists might contain newlines
|
||||||
if (*begin_val == '[') {
|
if (*begin_val == '[') {
|
||||||
endl = skip_list(begin_val + 1, end);
|
endl = skip_list(begin_val + 1, end);
|
||||||
if (endl == end) {
|
|
||||||
std::cout << "Warning: Config option ["sv << to_string(begin, end_name) << "] Missing ']'"sv;
|
|
||||||
|
|
||||||
|
// Check if we reached the end of the file without finding a closing bracket
|
||||||
|
// We know we have a valid closing bracket if:
|
||||||
|
// 1. We didn't reach the end, or
|
||||||
|
// 2. We reached the end but the last character was the matching closing bracket
|
||||||
|
if (endl == end && end == begin_val + 1) {
|
||||||
|
BOOST_LOG(warning) << "config: Missing ']' in config option: " << to_string(begin, end_name);
|
||||||
return std::make_pair(endl, std::nullopt);
|
return std::make_pair(endl, std::nullopt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1027,7 +1031,7 @@ namespace config {
|
|||||||
|
|
||||||
// The list needs to be a multiple of 2
|
// The list needs to be a multiple of 2
|
||||||
if (list.size() % 2) {
|
if (list.size() % 2) {
|
||||||
std::cout << "Warning: expected "sv << name << " to have a multiple of two elements --> not "sv << list.size() << std::endl;
|
BOOST_LOG(warning) << "config: expected "sv << name << " to have a multiple of two elements --> not "sv << list.size();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1057,7 +1061,7 @@ namespace config {
|
|||||||
config::sunshine.flags[config::flag::UPNP].flip();
|
config::sunshine.flags[config::flag::UPNP].flip();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::cout << "Warning: Unrecognized flag: ["sv << *line << ']' << std::endl;
|
BOOST_LOG(warning) << "config: Unrecognized flag: ["sv << *line << ']' << std::endl;
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1083,11 +1087,7 @@ namespace config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto &[name, val] : vars) {
|
for (auto &[name, val] : vars) {
|
||||||
#ifdef _WIN32
|
BOOST_LOG(info) << "config: '"sv << name << "' = "sv << val;
|
||||||
std::cout << "["sv << name << "] -- ["sv << utf8ToAcp(val) << ']' << std::endl;
|
|
||||||
#else
|
|
||||||
std::cout << "["sv << name << "] -- ["sv << val << ']' << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_f(vars, "headless_mode", video.headless_mode);
|
bool_f(vars, "headless_mode", video.headless_mode);
|
||||||
@@ -1485,7 +1485,7 @@ namespace config {
|
|||||||
shell_exec_info.nShow = SW_NORMAL;
|
shell_exec_info.nShow = SW_NORMAL;
|
||||||
if (!ShellExecuteExW(&shell_exec_info)) {
|
if (!ShellExecuteExW(&shell_exec_info)) {
|
||||||
auto winerr = GetLastError();
|
auto winerr = GetLastError();
|
||||||
std::cout << "Error: ShellExecuteEx() failed:"sv << winerr << std::endl;
|
BOOST_LOG(error) << "Failed executing shell command: " << winerr << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,10 +108,6 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
mail::man = std::make_shared<safe::mail_raw_t>();
|
mail::man = std::make_shared<safe::mail_raw_t>();
|
||||||
|
|
||||||
if (config::parse(argc, argv)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto log_deinit_guard = logging::init(config::sunshine.min_log_level, config::sunshine.log_file);
|
auto log_deinit_guard = logging::init(config::sunshine.min_log_level, config::sunshine.log_file);
|
||||||
if (!log_deinit_guard) {
|
if (!log_deinit_guard) {
|
||||||
BOOST_LOG(error) << "Logging failed to initialize"sv;
|
BOOST_LOG(error) << "Logging failed to initialize"sv;
|
||||||
@@ -125,6 +121,11 @@ int main(int argc, char *argv[]) {
|
|||||||
// Log publisher metadata
|
// Log publisher metadata
|
||||||
log_publisher_data();
|
log_publisher_data();
|
||||||
|
|
||||||
|
// parse config file
|
||||||
|
if (config::parse(argc, argv)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!config::sunshine.cmd.name.empty()) {
|
if (!config::sunshine.cmd.name.empty()) {
|
||||||
auto fn = cmd_to_func.find(config::sunshine.cmd.name);
|
auto fn = cmd_to_func.find(config::sunshine.cmd.name);
|
||||||
if (fn == std::end(cmd_to_func)) {
|
if (fn == std::end(cmd_to_func)) {
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ namespace platf {
|
|||||||
rumble_triggers, ///< Rumble triggers
|
rumble_triggers, ///< Rumble triggers
|
||||||
set_motion_event_state, ///< Set motion event state
|
set_motion_event_state, ///< Set motion event state
|
||||||
set_rgb_led, ///< Set RGB LED
|
set_rgb_led, ///< Set RGB LED
|
||||||
|
set_adaptive_triggers, ///< Set adaptive triggers
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gamepad_feedback_msg_t {
|
struct gamepad_feedback_msg_t {
|
||||||
@@ -142,6 +143,14 @@ namespace platf {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gamepad_feedback_msg_t make_adaptive_triggers(std::uint16_t id, uint8_t event_flags, uint8_t type_left, uint8_t type_right, const std::array<uint8_t, 10> &left, const std::array<uint8_t, 10> &right) {
|
||||||
|
gamepad_feedback_msg_t msg;
|
||||||
|
msg.type = gamepad_feedback_e::set_adaptive_triggers;
|
||||||
|
msg.id = id;
|
||||||
|
msg.data.adaptive_triggers = {.event_flags = event_flags, .type_left = type_left, .type_right = type_right, .left = left, .right = right};
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
gamepad_feedback_e type;
|
gamepad_feedback_e type;
|
||||||
std::uint16_t id;
|
std::uint16_t id;
|
||||||
|
|
||||||
@@ -166,6 +175,15 @@ namespace platf {
|
|||||||
std::uint8_t g;
|
std::uint8_t g;
|
||||||
std::uint8_t b;
|
std::uint8_t b;
|
||||||
} rgb_led;
|
} rgb_led;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint16_t controllerNumber;
|
||||||
|
uint8_t event_flags;
|
||||||
|
uint8_t type_left;
|
||||||
|
uint8_t type_right;
|
||||||
|
std::array<uint8_t, 10> left;
|
||||||
|
std::array<uint8_t, 10> right;
|
||||||
|
} adaptive_triggers;
|
||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace platf::gamepad {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto create_ds5() {
|
auto create_ds5() {
|
||||||
return inputtino::PS5Joypad::create({.name = "Sunshine DualSense (virtual) pad", .vendor_id = 0x054C, .product_id = 0x0CE6, .version = 0x8111});
|
return inputtino::PS5Joypad::create({.name = "Sunshine PS5 (virtual) pad", .vendor_id = 0x054C, .product_id = 0x0CE6, .version = 0x8111});
|
||||||
}
|
}
|
||||||
|
|
||||||
int alloc(input_raw_t *raw, const gamepad_id_t &id, const gamepad_arrival_t &metadata, feedback_queue_t feedback_queue) {
|
int alloc(input_raw_t *raw, const gamepad_id_t &id, const gamepad_arrival_t &metadata, feedback_queue_t feedback_queue) {
|
||||||
@@ -152,6 +152,10 @@ namespace platf::gamepad {
|
|||||||
gamepad->last_rgb_led = msg;
|
gamepad->last_rgb_led = msg;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
(*ds5).set_on_trigger_effect([feedback_queue, idx = id.clientRelativeIndex](const inputtino::PS5Joypad::TriggerEffect &trigger_effect) {
|
||||||
|
feedback_queue->raise(gamepad_feedback_msg_t::make_adaptive_triggers(idx, trigger_effect.event_flags, trigger_effect.type_left, trigger_effect.type_right, trigger_effect.left, trigger_effect.right));
|
||||||
|
});
|
||||||
|
|
||||||
// Activate the motion sensors
|
// Activate the motion sensors
|
||||||
feedback_queue->raise(gamepad_feedback_msg_t::make_motion_event_state(id.clientRelativeIndex, LI_MOTION_TYPE_ACCEL, 100));
|
feedback_queue->raise(gamepad_feedback_msg_t::make_motion_event_state(id.clientRelativeIndex, LI_MOTION_TYPE_ACCEL, 100));
|
||||||
feedback_queue->raise(gamepad_feedback_msg_t::make_motion_event_state(id.clientRelativeIndex, LI_MOTION_TYPE_GYRO, 100));
|
feedback_queue->raise(gamepad_feedback_msg_t::make_motion_event_state(id.clientRelativeIndex, LI_MOTION_TYPE_GYRO, 100));
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ extern "C" {
|
|||||||
#define IDX_EXEC_SERVER_CMD 15
|
#define IDX_EXEC_SERVER_CMD 15
|
||||||
#define IDX_SET_CLIPBOARD 16
|
#define IDX_SET_CLIPBOARD 16
|
||||||
#define IDX_FILE_TRANSFER_NONCE_REQUEST 17
|
#define IDX_FILE_TRANSFER_NONCE_REQUEST 17
|
||||||
|
#define IDX_SET_ADAPTIVE_TRIGGERS 18
|
||||||
|
|
||||||
static const short packetTypes[] = {
|
static const short packetTypes[] = {
|
||||||
0x0305, // Start A
|
0x0305, // Start A
|
||||||
@@ -72,6 +73,7 @@ static const short packetTypes[] = {
|
|||||||
0x3000, // Execute Server Command (Apollo protocol extension)
|
0x3000, // Execute Server Command (Apollo protocol extension)
|
||||||
0x3001, // Set Clipboard (Apollo protocol extension)
|
0x3001, // Set Clipboard (Apollo protocol extension)
|
||||||
0x3002, // File transfer nonce request (Apollo protocol extension)
|
0x3002, // File transfer nonce request (Apollo protocol extension)
|
||||||
|
0x5503, // Set Adaptive triggers (Sunshine protocol extension)
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
@@ -193,6 +195,21 @@ namespace stream {
|
|||||||
std::uint8_t b;
|
std::uint8_t b;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct control_adaptive_triggers_t {
|
||||||
|
control_header_v2 header;
|
||||||
|
|
||||||
|
std::uint16_t id;
|
||||||
|
/**
|
||||||
|
* 0x04 - Right trigger
|
||||||
|
* 0x08 - Left trigger
|
||||||
|
*/
|
||||||
|
std::uint8_t event_flags;
|
||||||
|
std::uint8_t type_left;
|
||||||
|
std::uint8_t type_right;
|
||||||
|
std::uint8_t left[DS_EFFECT_PAYLOAD_SIZE];
|
||||||
|
std::uint8_t right[DS_EFFECT_PAYLOAD_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
struct control_hdr_mode_t {
|
struct control_hdr_mode_t {
|
||||||
control_header_v2 header;
|
control_header_v2 header;
|
||||||
|
|
||||||
@@ -846,6 +863,22 @@ namespace stream {
|
|||||||
plaintext.b = data.b;
|
plaintext.b = data.b;
|
||||||
|
|
||||||
BOOST_LOG(verbose) << "RGB: "sv << msg.id << " :: "sv << util::hex(data.r).to_string_view() << util::hex(data.g).to_string_view() << util::hex(data.b).to_string_view();
|
BOOST_LOG(verbose) << "RGB: "sv << msg.id << " :: "sv << util::hex(data.r).to_string_view() << util::hex(data.g).to_string_view() << util::hex(data.b).to_string_view();
|
||||||
|
std::array<std::uint8_t, sizeof(control_encrypted_t) + crypto::cipher::round_to_pkcs7_padded(sizeof(plaintext)) + crypto::cipher::tag_size>
|
||||||
|
encrypted_payload;
|
||||||
|
|
||||||
|
payload = encode_control(session, util::view(plaintext), encrypted_payload);
|
||||||
|
} else if (msg.type == platf::gamepad_feedback_e::set_adaptive_triggers) {
|
||||||
|
control_adaptive_triggers_t plaintext;
|
||||||
|
plaintext.header.type = packetTypes[IDX_SET_ADAPTIVE_TRIGGERS];
|
||||||
|
plaintext.header.payloadLength = sizeof(plaintext) - sizeof(control_header_v2);
|
||||||
|
|
||||||
|
plaintext.id = util::endian::little(msg.id);
|
||||||
|
plaintext.event_flags = msg.data.adaptive_triggers.event_flags;
|
||||||
|
plaintext.type_left = msg.data.adaptive_triggers.type_left;
|
||||||
|
std::ranges::copy(msg.data.adaptive_triggers.left, plaintext.left);
|
||||||
|
plaintext.type_right = msg.data.adaptive_triggers.type_right;
|
||||||
|
std::ranges::copy(msg.data.adaptive_triggers.right, plaintext.right);
|
||||||
|
|
||||||
std::array<std::uint8_t, sizeof(control_encrypted_t) + crypto::cipher::round_to_pkcs7_padded(sizeof(plaintext)) + crypto::cipher::tag_size>
|
std::array<std::uint8_t, sizeof(control_encrypted_t) + crypto::cipher::round_to_pkcs7_padded(sizeof(plaintext)) + crypto::cipher::tag_size>
|
||||||
encrypted_payload;
|
encrypted_payload;
|
||||||
|
|
||||||
|
|||||||
@@ -94,8 +94,8 @@
|
|||||||
<b>{{ $t('_common.success') }}</b> {{ $t('config.restart_note') }}
|
<b>{{ $t('_common.success') }}</b> {{ $t('config.restart_note') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3 buttons">
|
<div class="mb-3 buttons">
|
||||||
<button class="btn btn-primary" @click="save">{{ $t('_common.save') }}</button>
|
<button class="btn btn-primary mr-3" @click="save">{{ $t('_common.save') }}</button>
|
||||||
<button class="btn btn-success mx-2" @click="apply" v-if="saved && !restarted">{{ $t('_common.apply') }}</button>
|
<button class="btn btn-success" @click="apply" v-if="saved && !restarted">{{ $t('_common.apply') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,2 +1,11 @@
|
|||||||
|
# Allows Sunshine to acces /dev/uinput
|
||||||
KERNEL=="uinput", SUBSYSTEM=="misc", OPTIONS+="static_node=uinput", TAG+="uaccess"
|
KERNEL=="uinput", SUBSYSTEM=="misc", OPTIONS+="static_node=uinput", TAG+="uaccess"
|
||||||
|
|
||||||
|
# Allows Sunshine to access /dev/uhid
|
||||||
KERNEL=="uhid", TAG+="uaccess"
|
KERNEL=="uhid", TAG+="uaccess"
|
||||||
|
|
||||||
|
# Joypads
|
||||||
|
KERNEL=="hidraw*" ATTRS{name}=="Sunshine PS5 (virtual) pad" MODE="0660", TAG+="uaccess"
|
||||||
|
SUBSYSTEMS=="input", ATTRS{name}=="Sunshine X-Box One (virtual) pad", MODE="0660", TAG+="uaccess"
|
||||||
|
SUBSYSTEMS=="input", ATTRS{name}=="Sunshine gamepad (virtual) motion sensors", MODE="0660", TAG+="uaccess"
|
||||||
|
SUBSYSTEMS=="input", ATTRS{name}=="Sunshine Nintendo (virtual) pad", MODE="0660", TAG+="uaccess"
|
||||||
|
|||||||
@@ -7,17 +7,12 @@ rem Note: We use exit code 2 to indicate success because either 0 or 1 may be re
|
|||||||
rem based on the PowerShell version if an exception occurs.
|
rem based on the PowerShell version if an exception occurs.
|
||||||
powershell -c Exit $(if ((Get-Item "$env:SystemRoot\System32\drivers\ViGEmBus.sys").VersionInfo.FileVersion -ge [System.Version]"1.17") { 2 } Else { 1 })
|
powershell -c Exit $(if ((Get-Item "$env:SystemRoot\System32\drivers\ViGEmBus.sys").VersionInfo.FileVersion -ge [System.Version]"1.17") { 2 } Else { 1 })
|
||||||
if %ERRORLEVEL% EQU 2 (
|
if %ERRORLEVEL% EQU 2 (
|
||||||
goto skip
|
echo "The installed version is 1.17 or later, no update needed. Exiting."
|
||||||
|
exit /b 0
|
||||||
)
|
)
|
||||||
goto continue
|
|
||||||
|
|
||||||
:skip
|
|
||||||
echo "The installed version is 1.17 or later, no update needed. Exiting."
|
|
||||||
exit /b 0
|
|
||||||
|
|
||||||
:continue
|
|
||||||
rem Get temp directory
|
rem Get temp directory
|
||||||
set temp_dir=%temp%/Sunshine
|
set temp_dir=%temp%/Apollo
|
||||||
|
|
||||||
rem Create temp directory if it doesn't exist
|
rem Create temp directory if it doesn't exist
|
||||||
if not exist "%temp_dir%" mkdir "%temp_dir%"
|
if not exist "%temp_dir%" mkdir "%temp_dir%"
|
||||||
|
|||||||
111
src_assets/windows/misc/path/update-path.bat
Normal file
111
src_assets/windows/misc/path/update-path.bat
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
|
rem Check if parameter is provided
|
||||||
|
if "%~1"=="" (
|
||||||
|
echo Usage: %0 [add^|remove]
|
||||||
|
echo add - Adds Apollo directories to system PATH
|
||||||
|
echo remove - Removes Apollo directories from system PATH
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
rem Get Apollo root directory
|
||||||
|
for %%I in ("%~dp0\..") do set "ROOT_DIR=%%~fI"
|
||||||
|
echo Apollo root directory: !ROOT_DIR!
|
||||||
|
|
||||||
|
rem Define directories to add to path
|
||||||
|
set "PATHS_TO_MANAGE[0]=!ROOT_DIR!"
|
||||||
|
set "PATHS_TO_MANAGE[1]=!ROOT_DIR!\tools"
|
||||||
|
|
||||||
|
rem System path registry location
|
||||||
|
set "KEY_NAME=HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
|
||||||
|
set "VALUE_NAME=Path"
|
||||||
|
|
||||||
|
rem Get the current path
|
||||||
|
for /f "tokens=2*" %%A in ('reg query "%KEY_NAME%" /v "%VALUE_NAME%"') do set "CURRENT_PATH=%%B"
|
||||||
|
echo Current path: !CURRENT_PATH!
|
||||||
|
|
||||||
|
rem Check if adding to path
|
||||||
|
if /i "%~1"=="add" (
|
||||||
|
set "NEW_PATH=!CURRENT_PATH!"
|
||||||
|
|
||||||
|
rem Process each directory to add
|
||||||
|
for /L %%i in (0,1,1) do (
|
||||||
|
set "DIR_TO_ADD=!PATHS_TO_MANAGE[%%i]!"
|
||||||
|
|
||||||
|
rem Check if path already contains this directory
|
||||||
|
echo "!CURRENT_PATH!" | findstr /i /c:"!DIR_TO_ADD!" > nul
|
||||||
|
if !ERRORLEVEL!==0 (
|
||||||
|
echo !DIR_TO_ADD! already in path
|
||||||
|
) else (
|
||||||
|
echo Adding to path: !DIR_TO_ADD!
|
||||||
|
set "NEW_PATH=!NEW_PATH!;!DIR_TO_ADD!"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
rem Only update if path was changed
|
||||||
|
if "!NEW_PATH!" neq "!CURRENT_PATH!" (
|
||||||
|
rem Set the new path in the registry
|
||||||
|
reg add "%KEY_NAME%" /v "%VALUE_NAME%" /t REG_EXPAND_SZ /d "!NEW_PATH!" /f
|
||||||
|
if !ERRORLEVEL!==0 (
|
||||||
|
echo Successfully added Apollo directories to PATH
|
||||||
|
) else (
|
||||||
|
echo Failed to add Apollo directories to PATH
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
echo No changes needed to PATH
|
||||||
|
)
|
||||||
|
exit /b !ERRORLEVEL!
|
||||||
|
)
|
||||||
|
|
||||||
|
rem Check if removing from path
|
||||||
|
if /i "%~1"=="remove" (
|
||||||
|
set "CHANGES_MADE=0"
|
||||||
|
|
||||||
|
rem Process each directory to remove
|
||||||
|
for /L %%i in (0,1,1) do (
|
||||||
|
set "DIR_TO_REMOVE=!PATHS_TO_MANAGE[%%i]!"
|
||||||
|
|
||||||
|
rem Check if path contains this directory
|
||||||
|
echo "!CURRENT_PATH!" | findstr /i /c:"!DIR_TO_REMOVE!" > nul
|
||||||
|
if !ERRORLEVEL!==0 (
|
||||||
|
echo Removing from path: !DIR_TO_REMOVE!
|
||||||
|
|
||||||
|
rem Build a new path by parsing and filtering the current path
|
||||||
|
set "NEW_PATH="
|
||||||
|
for %%p in ("!CURRENT_PATH:;=" "!") do (
|
||||||
|
set "PART=%%~p"
|
||||||
|
if /i "!PART!" NEQ "!DIR_TO_REMOVE!" (
|
||||||
|
if defined NEW_PATH (
|
||||||
|
set "NEW_PATH=!NEW_PATH!;!PART!"
|
||||||
|
) else (
|
||||||
|
set "NEW_PATH=!PART!"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
set "CURRENT_PATH=!NEW_PATH!"
|
||||||
|
set "CHANGES_MADE=1"
|
||||||
|
) else (
|
||||||
|
echo !DIR_TO_REMOVE! not found in path
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
rem Only update if path was changed
|
||||||
|
if "!CHANGES_MADE!"=="1" (
|
||||||
|
rem Set the new path in the registry
|
||||||
|
reg add "%KEY_NAME%" /v "%VALUE_NAME%" /t REG_EXPAND_SZ /d "!CURRENT_PATH!" /f
|
||||||
|
if !ERRORLEVEL!==0 (
|
||||||
|
echo Successfully removed Apollo directories from PATH
|
||||||
|
) else (
|
||||||
|
echo Failed to remove Apollo directories from PATH
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
echo No changes needed to PATH
|
||||||
|
)
|
||||||
|
exit /b !ERRORLEVEL!
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Unknown parameter: %~1
|
||||||
|
echo Usage: %0 [add^|remove]
|
||||||
|
exit /b 1
|
||||||
2
third-party/build-deps
vendored
2
third-party/build-deps
vendored
Submodule third-party/build-deps updated: 0f8f2af955...b567d3c479
2
third-party/inputtino
vendored
2
third-party/inputtino
vendored
Submodule third-party/inputtino updated: 1170b1e4ad...fd136cfe49
2
third-party/moonlight-common-c
vendored
2
third-party/moonlight-common-c
vendored
Submodule third-party/moonlight-common-c updated: 40bec19cc1...40a4e68787
Reference in New Issue
Block a user