-
+
@@ -514,7 +519,7 @@ ext-js:
@@ -537,27 +542,37 @@ ext-js:
diff --git a/package.json b/package.json
index 96fc8fc8..f504e49c 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"vue-i18n": "11.1.3"
},
"devDependencies": {
+ "@codecov/vite-plugin": "1.9.0",
"@vitejs/plugin-vue": "4.6.2",
"serve": "14.2.3",
"vite": "4.5.9",
diff --git a/packaging/linux/flatpak/deps/flatpak-builder-tools b/packaging/linux/flatpak/deps/flatpak-builder-tools
index aac65cf4..bf91cb0b 160000
--- a/packaging/linux/flatpak/deps/flatpak-builder-tools
+++ b/packaging/linux/flatpak/deps/flatpak-builder-tools
@@ -1 +1 @@
-Subproject commit aac65cf44cd4e008594a9d9ac1db08e2025067a6
+Subproject commit bf91cb0bee7ce0c8021e223e3ea9c5110ebb82de
diff --git a/packaging/sunshine.rb b/packaging/sunshine.rb
index 81e42b09..f13a5a38 100644
--- a/packaging/sunshine.rb
+++ b/packaging/sunshine.rb
@@ -29,6 +29,7 @@ class @PROJECT_NAME@ < Formula
depends_on "cmake" => :build
depends_on "doxygen" => :build
depends_on "graphviz" => :build
+ depends_on "ninja" => :build
depends_on "node" => :build
depends_on "pkg-config" => :build
depends_on "curl"
@@ -38,6 +39,24 @@ class @PROJECT_NAME@ < Formula
depends_on "icu4c" => :recommended
on_linux do
+ # the "build" dependencies are for libayatana-appindicator
+ depends_on "at-spi2-core" => :build
+ depends_on "cairo" => :build
+ depends_on "fontconfig" => :build
+ depends_on "freetype" => :build
+ depends_on "fribidi" => :build
+ depends_on "gettext" => :build
+ depends_on "gobject-introspection" => :build
+ depends_on "graphite2" => :build
+ depends_on "gtk+3" => :build
+ depends_on "harfbuzz" => :build
+ depends_on "intltool" => :build
+ depends_on "libepoxy" => :build
+ depends_on "libxdamage" => :build
+ depends_on "libxkbcommon" => :build
+ depends_on "pango" => :build
+ depends_on "perl" => :build
+ depends_on "pixman" => :build
depends_on "avahi"
depends_on "libcap"
depends_on "libdrm"
@@ -56,6 +75,128 @@ class @PROJECT_NAME@ < Formula
depends_on "pulseaudio"
depends_on "systemd"
depends_on "wayland"
+
+ # resources that do not have brew packages
+ resource "libayatana-appindicator" do
+ url "https://github.com/AyatanaIndicators/libayatana-appindicator/archive/refs/tags/0.5.94.tar.gz"
+ sha256 "884a6bc77994c0b58c961613ca4c4b974dc91aa0f804e70e92f38a542d0d0f90"
+ end
+
+ resource "libdbusmenu" do
+ url "https://launchpad.net/libdbusmenu/16.04/16.04.0/+download/libdbusmenu-16.04.0.tar.gz"
+ sha256 "b9cc4a2acd74509435892823607d966d424bd9ad5d0b00938f27240a1bfa878a"
+
+ patch 'From 729546c51806a1b3ea6cb6efb7a115b1baa811f1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stefan=20Br=C3=BCns?=
+Date: Mon, 18 Nov 2019 19:58:53 +0100
+Subject: [PATCH 1/1] Fix HAVE_VALGRIND AM_CONDITIONAL
+
+The AM_CONDITIONAL should also be run with --disable-tests, otherwise
+HAVE_VALGRIND is undefined.
+---
+ configure | 4 ++--
+ configure.ac | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/configure b/configure
+index 831a3bb..8913b9b 100644
+--- a/configure
++++ b/configure
+@@ -14801,6 +14801,8 @@ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+ $as_echo "yes" >&6; }
+ have_valgrind=yes
++fi
++
+ fi
+ if test "x$have_valgrind" = "xyes"; then
+ HAVE_VALGRIND_TRUE=
+@@ -14811,8 +14813,6 @@ else
+ fi
+
+
+-fi
+-
+
+
+
+diff --git a/configure.ac b/configure.ac
+index ace54d1..cbd38a6 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -120,8 +120,8 @@ PKG_CHECK_MODULES(DBUSMENUTESTS, json-glib-1.0 >= $JSON_GLIB_REQUIRED_VERSION
+ [have_tests=yes]
+ )
+ PKG_CHECK_MODULES(DBUSMENUTESTSVALGRIND, valgrind, have_valgrind=yes, have_valgrind=no)
+-AM_CONDITIONAL([HAVE_VALGRIND], [test "x$have_valgrind" = "xyes"])
+ ])
++AM_CONDITIONAL([HAVE_VALGRIND], [test "x$have_valgrind" = "xyes"])
+
+ AC_SUBST(DBUSMENUTESTS_CFLAGS)
+ AC_SUBST(DBUSMENUTESTS_LIBS)
+--
+2.46.2
+
+
+'
+ end
+
+ resource "ayatana-ido" do
+ url "https://github.com/AyatanaIndicators/ayatana-ido/archive/refs/tags/0.10.4.tar.gz"
+ sha256 "bd59abd5f1314e411d0d55ce3643e91cef633271f58126be529de5fb71c5ab38"
+
+ patch 'From 8a09e6ad33c58c017c0c8fd756da036fc39428ea Mon Sep 17 00:00:00 2001
+From: Alexander Koskovich
+Date: Sun, 29 Sep 2024 13:47:54 -0400
+Subject: [PATCH 1/1] Make introspection configurable
+
+---
+ CMakeLists.txt | 1 +
+ src/CMakeLists.txt | 4 ++++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 0e13fcd..f3e9ec0 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -12,6 +12,7 @@ endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ option(ENABLE_TESTS "Enable all tests and checks" OFF)
+ option(ENABLE_COVERAGE "Enable coverage reports (includes enabling all tests and checks)" OFF)
+ option(ENABLE_WERROR "Treat all build warnings as errors" OFF)
++option(ENABLE_INTROSPECTION "Enable introspection" ON)
+
+ if(ENABLE_COVERAGE)
+ set(ENABLE_TESTS ON)
+diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
+index 5b3638d..aca9481 100644
+--- a/src/CMakeLists.txt
++++ b/src/CMakeLists.txt
+@@ -108,6 +108,8 @@ install(TARGETS "ayatana-ido3-0.4" LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIB
+
+ # AyatanaIdo3-0.4.gir
+
++if (ENABLE_INTROSPECTION)
++
+ find_package(GObjectIntrospection REQUIRED QUIET)
+
+ if (INTROSPECTION_FOUND)
+@@ -183,3 +185,5 @@ if (INTROSPECTION_FOUND)
+ endif ()
+
+ endif ()
++
++endif ()
+--
+2.46.2
+
+
+'
+ end
+
+ resource "libayatana-indicator" do
+ url "https://github.com/AyatanaIndicators/libayatana-indicator/archive/refs/tags/0.9.4.tar.gz"
+ sha256 "a18d3c682e29afd77db24366f8475b26bda22b0e16ff569a2ec71cd6eb4eac95"
+ end
end
def install
@@ -65,12 +206,12 @@ class @PROJECT_NAME@ < Formula
args = %W[
-DBUILD_WERROR=ON
+ -DCMAKE_CXX_STANDARD=20
-DCMAKE_INSTALL_PREFIX=#{prefix}
-DHOMEBREW_ALLOW_FETCHCONTENT=ON
-DOPENSSL_ROOT_DIR=#{Formula["openssl"].opt_prefix}
-DSUNSHINE_ASSETS_DIR=sunshine/assets
-DSUNSHINE_BUILD_HOMEBREW=ON
- -DSUNSHINE_ENABLE_TRAY=OFF
-DSUNSHINE_PUBLISHER_NAME='LizardByte'
-DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev'
-DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'
@@ -105,16 +246,69 @@ class @PROJECT_NAME@ < Formula
end
args << "-DCUDA_FAIL_ON_MISSING=OFF" if OS.linux?
+ args << "-DSUNSHINE_ENABLE_TRAY=OFF" if OS.mac?
- system "cmake", "-S", ".", "-B", "build", *std_cmake_args, *args
+ # Handle system tray on Linux
+ if OS.linux?
+ # Build and install libayatana components
- cd "build" do
- system "make"
- system "make", "install"
+ # Build libdbusmenu
+ resource("libdbusmenu").stage do
+ system "./configure",
+ "--prefix=#{prefix}",
+ "--with-gtk=3",
+ "--disable-dumper",
+ "--disable-static",
+ "--disable-tests",
+ "--disable-gtk-doc",
+ "--enable-introspection=no",
+ "--disable-vala"
+ system "make", "install"
+ end
- bin.install "tests/test_sunshine"
+ # Build ayatana-ido
+ resource("ayatana-ido").stage do
+ system "cmake", "-S", ".", "-B", "build", "-G", "Ninja",
+ "-DCMAKE_INSTALL_PREFIX=#{prefix}",
+ "-DENABLE_INTROSPECTION=OFF",
+ *std_cmake_args
+ system "ninja", "-C", "build"
+ system "ninja", "-C", "build", "install"
+ end
+
+ # Build libayatana-indicator
+ resource("libayatana-indicator").stage do
+ ENV.append_path "PKG_CONFIG_PATH", "#{lib}/pkgconfig"
+ ENV.append "LDFLAGS", "-L#{lib}"
+
+ system "cmake", "-S", ".", "-B", "build", "-G", "Ninja",
+ "-DCMAKE_INSTALL_PREFIX=#{prefix}",
+ *std_cmake_args
+ system "ninja", "-C", "build"
+ system "ninja", "-C", "build", "install"
+ end
+
+ # Build libayatana-appindicator
+ resource("libayatana-appindicator").stage do
+ system "cmake", "-S", ".", "-B", "build", "-G", "Ninja",
+ "-DCMAKE_INSTALL_PREFIX=#{prefix}",
+ "-DENABLE_BINDINGS_MONO=OFF",
+ "-DENABLE_BINDINGS_VALA=OFF",
+ "-DENABLE_GTKDOC=OFF",
+ *std_cmake_args
+ system "ninja", "-C", "build"
+ system "ninja", "-C", "build", "install"
+ end
end
+ system "cmake", "-S", ".", "-B", "build", "-G", "Unix Makefiles",
+ *std_cmake_args,
+ *args
+
+ system "make", "-C", "build"
+ system "make", "-C", "build", "install"
+ bin.install "build/tests/test_sunshine"
+
# codesign the binary on intel macs
system "codesign", "-s", "-", "--force", "--deep", bin/"sunshine" if OS.mac? && Hardware::CPU.intel?
@@ -157,6 +351,7 @@ class @PROJECT_NAME@ < Formula
system bin/"sunshine", "--version"
# run the test suite
- system bin/"test_sunshine", "--gtest_color=yes"
+ system bin/"test_sunshine", "--gtest_color=yes", "--gtest_output=xml:test_results.xml"
+ assert_path_exists testpath/"test_results.xml"
end
end
diff --git a/scripts/linux_build.sh b/scripts/linux_build.sh
index f80ed7bf..eb901b8b 100644
--- a/scripts/linux_build.sh
+++ b/scripts/linux_build.sh
@@ -90,6 +90,52 @@ shift $((OPTIND -1))
# dependencies array to build out
dependencies=()
+function add_arch_deps() {
+ dependencies+=(
+ 'avahi'
+ 'base-devel'
+ 'cmake'
+ 'curl'
+ "gcc${gcc_version}"
+ "gcc${gcc_version}-libs"
+ 'git'
+ 'libayatana-appindicator'
+ 'libcap'
+ 'libdrm'
+ 'libevdev'
+ 'libmfx'
+ 'libnotify'
+ 'libpulse'
+ 'libva'
+ 'libx11'
+ 'libxcb'
+ 'libxfixes'
+ 'libxrandr'
+ 'libxtst'
+ 'miniupnpc'
+ 'ninja'
+ 'nodejs'
+ 'npm'
+ 'numactl'
+ 'openssl'
+ 'opus'
+ 'udev'
+ 'wayland'
+ )
+
+ if [ "$skip_libva" == 0 ]; then
+ dependencies+=(
+ "libva" # VA-API
+ )
+ fi
+
+ if [ "$skip_cuda" == 0 ]; then
+ dependencies+=(
+ "cuda" # VA-API
+ )
+ fi
+}
+
function add_debian_based_deps() {
dependencies+=(
"bison" # required if we need to compile doxygen
@@ -157,8 +203,8 @@ function add_fedora_deps() {
dependencies+=(
"cmake"
"doxygen"
- "gcc"
- "g++"
+ "gcc${gcc_version}"
+ "gcc${gcc_version}-c++"
"git"
"graphviz"
"libappindicator-gtk3-devel"
@@ -198,9 +244,15 @@ function add_fedora_deps() {
}
function install_cuda() {
+ nvcc_path=$(command -v nvcc 2>/dev/null) || true
+ if [ -n "$nvcc_path" ]; then
+ echo "found system cuda"
+ return
+ fi
# check if we need to install cuda
if [ -f "${build_dir}/cuda/bin/nvcc" ]; then
- echo "cuda already installed"
+ nvcc_path="${build_dir}/cuda/bin/nvcc"
+ echo "found local cuda"
return
fi
@@ -237,11 +289,13 @@ function install_cuda() {
chmod a+x "${build_dir}/cuda.run"
"${build_dir}/cuda.run" --silent --toolkit --toolkitpath="${build_dir}/cuda" --no-opengl-libs --no-man-page --no-drm
rm "${build_dir}/cuda.run"
+ nvcc_path="${build_dir}/cuda/bin/nvcc"
}
function check_version() {
local package_name=$1
local min_version=$2
+ local max_version=$3
local installed_version
echo "Checking if $package_name is installed and at least version $min_version"
@@ -250,6 +304,8 @@ function check_version() {
installed_version=$(dpkg -s "$package_name" 2>/dev/null | grep '^Version:' | awk '{print $2}')
elif [ "$distro" == "fedora" ]; then
installed_version=$(rpm -q --queryformat '%{VERSION}' "$package_name" 2>/dev/null)
+ elif [ "$distro" == "arch" ]; then
+ installed_version=$(pacman -Q "$package_name" | awk '{print $2}' )
else
echo "Unsupported Distro"
return 1
@@ -260,11 +316,12 @@ function check_version() {
return 1
fi
- if [ "$(printf '%s\n' "$installed_version" "$min_version" | sort -V | head -n1)" = "$min_version" ]; then
- echo "$package_name version $installed_version is at least $min_version"
+if [[ "$(printf '%s\n' "$installed_version" "$min_version" | sort -V | head -n1)" = "$min_version" ]] && \
+ [[ "$(printf '%s\n' "$installed_version" "$max_version" | sort -V | head -n1)" = "$installed_version" ]]; then
+ echo "Installed version is within range"
return 0
else
- echo "$package_name version $installed_version is less than $min_version"
+ echo "$package_name version $installed_version is out of range"
return 1
fi
}
@@ -305,7 +362,9 @@ function run_install() {
# Update the package list
$package_update_command
- if [ "$distro" == "debian" ]; then
+ if [ "$distro" == "arch" ]; then
+ add_arch_deps
+ elif [ "$distro" == "debian" ]; then
add_debian_deps
elif [ "$distro" == "ubuntu" ]; then
add_ubuntu_deps
@@ -314,7 +373,7 @@ function run_install() {
${sudo_cmd} dnf group install "development-tools" -y
elif [ "$distro" == "fedora" ] && [ "$version" <= "40" ]; then
add_fedora_deps
- ${sudo_cmd} dnf group install "Development Tools" -y
+ ${sudo_cmd} dnf group install "$dev_tools_group" -y
fi
@@ -333,8 +392,11 @@ function run_install() {
"gcc-ranlib"
)
- # update alternatives for gcc and g++ if a debian based distro
- if [ "$distro" == "debian" ] || [ "$distro" == "ubuntu" ]; then
+ #set gcc version based on distros
+ if [ "$distro" == "arch" ]; then
+ export CC=gcc-14
+ export CXX=g++-14
+ elif [ "$distro" == "debian" ] || [ "$distro" == "ubuntu" ]; then
for file in "${gcc_alternative_files[@]}"; do
file_path="/etc/alternatives/$file"
if [ -e "$file_path" ]; then
@@ -353,7 +415,7 @@ function run_install() {
# compile cmake if the version is too low
cmake_min="3.25.0"
target_cmake_version="3.30.1"
- if ! check_version "cmake" "$cmake_min"; then
+ if ! check_version "cmake" "$cmake_min" "inf"; then
cmake_prefix="https://github.com/Kitware/CMake/releases/download/v"
if [ "$architecture" == "x86_64" ]; then
cmake_arch="x86_64"
@@ -371,7 +433,8 @@ function run_install() {
# compile doxygen if version is too low
doxygen_min="1.10.0"
_doxygen_min="1_10_0"
- if ! check_version "doxygen" "$doxygen_min"; then
+ doxygen_max="1.12.0"
+ if ! check_version "doxygen" "$doxygen_min" "$doxygen_max"; then
if [ "${SUNSHINE_COMPILE_DOXYGEN}" == "true" ]; then
echo "Compiling doxygen"
doxygen_url="https://github.com/doxygen/doxygen/releases/download/Release_${_doxygen_min}/doxygen-${doxygen_min}.src.tar.gz"
@@ -383,7 +446,7 @@ function run_install() {
ninja -C "build" -j"${num_processors}"
ninja -C "build" install
else
- echo "Doxygen version too low, skipping docs"
+ echo "Doxygen version not in range, skipping docs"
cmake_args+=("-DBUILD_DOCS=OFF")
fi
fi
@@ -399,12 +462,10 @@ function run_install() {
fi
# run the cuda install
- if [ -n "$cuda_version" ] && [ "$skip_cuda" == 0 ]; then
+ if [ "$skip_cuda" == 0 ]; then
install_cuda
cmake_args+=("-DSUNSHINE_ENABLE_CUDA=ON")
- cmake_args+=("-DCMAKE_CUDA_COMPILER:PATH=${build_dir}/cuda/bin/nvcc")
- else
- cmake_args+=("-DSUNSHINE_ENABLE_CUDA=OFF")
+ cmake_args+=("-DCMAKE_CUDA_COMPILER:PATH=$nvcc_path")
fi
# Cmake stuff here
@@ -444,7 +505,15 @@ function run_install() {
# Determine the OS and call the appropriate function
cat /etc/os-release
-if grep -q "Debian GNU/Linux 12 (bookworm)" /etc/os-release; then
+
+if grep -q "Arch Linux" /etc/os-release; then
+ distro="arch"
+ version=""
+ package_update_command="${sudo_cmd} pacman -Syu --noconfirm"
+ package_install_command="${sudo_cmd} pacman -Sy --needed"
+ nvm_node=0
+ gcc_version="14"
+elif grep -q "Debian GNU/Linux 12 (bookworm)" /etc/os-release; then
distro="debian"
version="12"
package_update_command="${sudo_cmd} apt-get update"
@@ -453,33 +522,36 @@ if grep -q "Debian GNU/Linux 12 (bookworm)" /etc/os-release; then
cuda_build="525.60.13"
gcc_version="12"
nvm_node=0
-elif grep -q "PLATFORM_ID=\"platform:f39\"" /etc/os-release; then
- distro="fedora"
- version="39"
- package_update_command="${sudo_cmd} dnf update -y"
- package_install_command="${sudo_cmd} dnf install -y"
- cuda_version="12.4.0"
- cuda_build="550.54.14"
- gcc_version="13"
- nvm_node=0
elif grep -q "PLATFORM_ID=\"platform:f40\"" /etc/os-release; then
distro="fedora"
version="40"
package_update_command="${sudo_cmd} dnf update -y"
package_install_command="${sudo_cmd} dnf install -y"
- cuda_version=
- cuda_build=
+ cuda_version=12.6.3
+ cuda_build=560.35.05
gcc_version="13"
nvm_node=0
+ dev_tools_group="Development Tools"
elif grep -q "PLATFORM_ID=\"platform:f41\"" /etc/os-release; then
distro="fedora"
version="41"
package_update_command="${sudo_cmd} dnf update -y"
package_install_command="${sudo_cmd} dnf install -y"
- cuda_version=
- cuda_build=
+ cuda_version=12.6.3
+ cuda_build=560.35.05
gcc_version="13"
nvm_node=0
+ dev_tools_group="development-tools"
+elif grep -q "PLATFORM_ID=\"platform:f42\"" /etc/os-release; then
+ distro="fedora"
+ version="42"
+ package_update_command="${sudo_cmd} dnf update -y"
+ package_install_command="${sudo_cmd} dnf install -y"
+ cuda_version=12.8.1
+ cuda_build=570.124.06
+ gcc_version="14"
+ nvm_node=0
+ dev_tools_group="development-tools"
elif grep -q "Ubuntu 22.04" /etc/os-release; then
distro="ubuntu"
version="22.04"
diff --git a/scripts/requirements.txt b/scripts/requirements.txt
index 7cfbae48..b2c50014 100644
--- a/scripts/requirements.txt
+++ b/scripts/requirements.txt
@@ -1,2 +1,2 @@
Babel==2.17.0
-clang-format
+clang-format==20.*
diff --git a/src/audio.cpp b/src/audio.cpp
index 8eaa7f76..18cf7f05 100644
--- a/src/audio.cpp
+++ b/src/audio.cpp
@@ -129,13 +129,10 @@ namespace audio {
void capture(safe::mail_t mail, config_t config, void *channel_data) {
auto shutdown_event = mail->event(mail::shutdown);
-
- if (config.input_only) {
- BOOST_LOG(info) << "Input only session, audio will not be captured."sv;
+ if (!config::audio.stream || config.input_only) {
shutdown_event->view();
return;
}
-
auto stream = stream_configs[map_stream(config.channels, config.flags[config_t::HIGH_QUALITY])];
if (config.flags[config_t::CUSTOM_SURROUND_PARAMS]) {
apply_surround_params(stream, config.customStreamParams);
diff --git a/src/config.cpp b/src/config.cpp
index 8eca6ee1..31e5c452 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -416,12 +416,7 @@ namespace config {
auto final_resolution = entry.template get_optional("final_resolution"s);
auto final_refresh_rate = entry.template get_optional("final_refresh_rate"s);
- output_field.push_back(video_t::dd_t::mode_remapping_entry_t {
- requested_resolution.value_or(""),
- requested_fps.value_or(""),
- final_resolution.value_or(""),
- final_refresh_rate.value_or("")
- });
+ output_field.push_back(video_t::dd_t::mode_remapping_entry_t {requested_resolution.value_or(""), requested_fps.value_or(""), final_resolution.value_or(""), final_refresh_rate.value_or("")});
}
}};
@@ -523,6 +518,7 @@ namespace config {
audio_t audio {
{}, // audio_sink
{}, // virtual_sink
+ true, // stream audio
true, // install_steam_drivers
true, // keep_sink_default
true, // auto_capture
@@ -1215,6 +1211,7 @@ namespace config {
string_f(vars, "audio_sink", audio.sink);
string_f(vars, "virtual_sink", audio.virtual_sink);
+ bool_f(vars, "stream_audio", audio.stream);
bool_f(vars, "install_steam_audio_drivers", audio.install_steam_drivers);
bool_f(vars, "keep_sink_default", audio.keep_default);
bool_f(vars, "auto_capture_sink", audio.auto_capture);
diff --git a/src/config.h b/src/config.h
index 0e5a2a76..e77acfb6 100644
--- a/src/config.h
+++ b/src/config.h
@@ -152,6 +152,7 @@ namespace config {
struct audio_t {
std::string sink;
std::string virtual_sink;
+ bool stream;
bool install_steam_drivers;
bool keep_default;
bool auto_capture;
diff --git a/src/network.cpp b/src/network.cpp
index 070a4c44..d388afd6 100644
--- a/src/network.cpp
+++ b/src/network.cpp
@@ -186,7 +186,7 @@ namespace net {
std::uint16_t map_port(int port) {
// calculate the port from the config port
- auto mapped_port = (std::uint16_t)((int) config::sunshine.port + port);
+ auto mapped_port = (std::uint16_t) ((int) config::sunshine.port + port);
// Ensure port is in the range of 1024-65535
if (mapped_port < 1024 || mapped_port > 65535) {
diff --git a/src/platform/linux/graphics.cpp b/src/platform/linux/graphics.cpp
index 568067f3..245addb6 100644
--- a/src/platform/linux/graphics.cpp
+++ b/src/platform/linux/graphics.cpp
@@ -19,7 +19,7 @@ extern "C" {
// There aren't that many DRM_FORMAT I need to use, so define them here
//
// They aren't likely to change any time soon.
-#define fourcc_code(a, b, c, d) ((std::uint32_t)(a) | ((std::uint32_t)(b) << 8) | ((std::uint32_t)(c) << 16) | ((std::uint32_t)(d) << 24))
+#define fourcc_code(a, b, c, d) ((std::uint32_t) (a) | ((std::uint32_t) (b) << 8) | ((std::uint32_t) (c) << 16) | ((std::uint32_t) (d) << 24))
#define fourcc_mod_code(vendor, val) ((((uint64_t) vendor) << 56) | ((val) & 0x00ffffffffffffffULL))
#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(0, ((1ULL << 56) - 1))
diff --git a/src/platform/windows/audio.cpp b/src/platform/windows/audio.cpp
index a166d3b0..04bfe198 100644
--- a/src/platform/windows/audio.cpp
+++ b/src/platform/windows/audio.cpp
@@ -117,15 +117,26 @@ namespace {
using virtual_sink_waveformats_t = std::vector;
+ /**
+ * @brief List of supported waveformats for an N-channel virtual audio device
+ * @tparam channel_count Number of virtual audio channels
+ * @returns std::vector
+ * @note The list of virtual formats returned are sorted in preference order and the first valid
+ * format will be used. All bits-per-sample options are listed because we try to match
+ * this to the default audio device. See also: set_format() below.
+ */
template
virtual_sink_waveformats_t create_virtual_sink_waveformats() {
if constexpr (channel_count == 2) {
auto channel_mask = waveformat_mask_stereo;
- // only choose 24 or 16-bit formats to avoid clobbering existing Dolby/DTS spatial audio settings
+ // The 32-bit formats are a lower priority for stereo because using one will disable Dolby/DTS
+ // spatial audio mode if the user enabled it on the Steam speaker.
return {
create_waveformat(sample_format_e::s24in32, channel_count, channel_mask),
create_waveformat(sample_format_e::s24, channel_count, channel_mask),
create_waveformat(sample_format_e::s16, channel_count, channel_mask),
+ create_waveformat(sample_format_e::f32, channel_count, channel_mask),
+ create_waveformat(sample_format_e::s32, channel_count, channel_mask),
};
} else if (channel_count == 6) {
auto channel_mask1 = waveformat_mask_surround51_with_backspeakers;
@@ -298,6 +309,10 @@ namespace platf::audio {
auto waveformatext_pointer = reinterpret_cast(mixer_waveformat.get());
capture_waveformat.dwChannelMask = waveformatext_pointer->dwChannelMask;
}
+
+ BOOST_LOG(info) << "Audio mixer format is "sv << mixer_waveformat->wBitsPerSample << "-bit, "sv
+ << mixer_waveformat->nSamplesPerSec << " Hz, "sv
+ << ((mixer_waveformat->nSamplesPerSec != 48000) ? "will be resampled to 48000 by Windows"sv : "no resampling needed"sv);
}
status = audio_client->Initialize(
@@ -315,7 +330,7 @@ namespace platf::audio {
return nullptr;
}
- BOOST_LOG(info) << "Audio capture format is " << logging::bracket(waveformat_to_pretty_string(capture_waveformat));
+ BOOST_LOG(info) << "Audio capture format is "sv << logging::bracket(waveformat_to_pretty_string(capture_waveformat));
return audio_client;
}
@@ -795,6 +810,22 @@ namespace platf::audio {
}
}
+ // When switching to a Steam virtual speaker device, try to retain the bit depth of the
+ // default audio device. Switching from a 16-bit device to a 24-bit one has been known to
+ // cause glitches for some users.
+ int wanted_bits_per_sample = 32;
+ auto current_default_dev = default_device(device_enum);
+ if (current_default_dev) {
+ audio::prop_t prop;
+ prop_var_t current_device_format;
+
+ if (SUCCEEDED(current_default_dev->OpenPropertyStore(STGM_READ, &prop)) && SUCCEEDED(prop->GetValue(PKEY_AudioEngine_DeviceFormat, ¤t_device_format.prop))) {
+ auto *format = (WAVEFORMATEXTENSIBLE *) current_device_format.prop.blob.pBlobData;
+ wanted_bits_per_sample = format->Samples.wValidBitsPerSample;
+ BOOST_LOG(info) << "Virtual audio device will use "sv << wanted_bits_per_sample << "-bit to match default device"sv;
+ }
+ }
+
auto &device_id = virtual_sink_info->first;
auto &waveformats = virtual_sink_info->second.get().virtual_sink_waveformats;
for (const auto &waveformat : waveformats) {
@@ -804,6 +835,10 @@ namespace platf::audio {
auto waveformat_copy = waveformat;
auto waveformat_copy_pointer = reinterpret_cast(&waveformat_copy);
+ if (wanted_bits_per_sample != waveformat.Samples.wValidBitsPerSample) {
+ continue;
+ }
+
WAVEFORMATEXTENSIBLE p {};
if (SUCCEEDED(policy->SetDeviceFormat(device_id_copy.c_str(), waveformat_copy_pointer, (WAVEFORMATEX *) &p))) {
BOOST_LOG(info) << "Changed virtual audio sink format to " << logging::bracket(waveformat_to_pretty_string(waveformat));
diff --git a/src/platform/windows/display_vram.cpp b/src/platform/windows/display_vram.cpp
index bf85af4f..7a8b0705 100644
--- a/src/platform/windows/display_vram.cpp
+++ b/src/platform/windows/display_vram.cpp
@@ -219,7 +219,7 @@ namespace platf::dxgi {
{
util::buffer_t cursor_img = img_data;
std::for_each((std::uint32_t *) std::begin(cursor_img), (std::uint32_t *) std::end(cursor_img), [](auto &pixel) {
- auto alpha = (std::uint8_t)((pixel >> 24) & 0xFF);
+ auto alpha = (std::uint8_t) ((pixel >> 24) & 0xFF);
if (alpha == 0xFF) {
// Pixels with 0xFF alpha will be XOR-blended as is.
} else if (alpha == 0x00) {
@@ -286,7 +286,7 @@ namespace platf::dxgi {
{
util::buffer_t cursor_img = img_data;
std::for_each((std::uint32_t *) std::begin(cursor_img), (std::uint32_t *) std::end(cursor_img), [](auto &pixel) {
- auto alpha = (std::uint8_t)((pixel >> 24) & 0xFF);
+ auto alpha = (std::uint8_t) ((pixel >> 24) & 0xFF);
if (alpha == 0xFF) {
// Pixels with 0xFF alpha will be XOR-blended by make_cursor_xor_image().
// We make them transparent for the alpha-blended cursor image.
diff --git a/src/platform/windows/input.cpp b/src/platform/windows/input.cpp
index 53591bd7..50f8aab8 100644
--- a/src/platform/windows/input.cpp
+++ b/src/platform/windows/input.cpp
@@ -92,10 +92,10 @@ namespace platf {
constexpr float EARTH_G = 9.80665f;
-#define MPS2_TO_DS4_ACCEL(x) (int32_t)(((x) / EARTH_G) * 8192)
-#define DPS_TO_DS4_GYRO(x) (int32_t)((x) * (1024 / 64))
+#define MPS2_TO_DS4_ACCEL(x) (int32_t) (((x) / EARTH_G) * 8192)
+#define DPS_TO_DS4_GYRO(x) (int32_t) ((x) * (1024 / 64))
-#define APPLY_CALIBRATION(val, bias, scale) (int32_t)(((float) (val) + (bias)) / (scale))
+#define APPLY_CALIBRATION(val, bias, scale) (int32_t) (((float) (val) + (bias)) / (scale))
constexpr DS4_TOUCH ds4_touch_unused = {
.bPacketCounter = 0,
diff --git a/src/rtsp.cpp b/src/rtsp.cpp
index 9a1529ab..b6998ebf 100644
--- a/src/rtsp.cpp
+++ b/src/rtsp.cpp
@@ -112,7 +112,7 @@ namespace rtsp_stream {
boost::asio::async_read(sock, boost::asio::buffer(begin, sizeof(encrypted_rtsp_header_t)), boost::bind(&socket_t::handle_read_encrypted_header, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
} else {
sock.async_read_some(
- boost::asio::buffer(begin, (std::size_t)(std::end(msg_buf) - begin)),
+ boost::asio::buffer(begin, (std::size_t) (std::end(msg_buf) - begin)),
boost::bind(
&socket_t::handle_read_plaintext,
shared_from_this(),
@@ -253,7 +253,7 @@ namespace rtsp_stream {
}
sock.async_read_some(
- boost::asio::buffer(begin, (std::size_t)(std::end(msg_buf) - begin)),
+ boost::asio::buffer(begin, (std::size_t) (std::end(msg_buf) - begin)),
boost::bind(
&socket_t::handle_plaintext_payload,
shared_from_this(),
@@ -289,7 +289,7 @@ namespace rtsp_stream {
auto end = socket->begin + bytes;
msg_t req {new msg_t::element_type {}};
- if (auto status = parseRtspMessage(req.get(), socket->msg_buf.data(), (std::size_t)(end - socket->msg_buf.data()))) {
+ if (auto status = parseRtspMessage(req.get(), socket->msg_buf.data(), (std::size_t) (end - socket->msg_buf.data()))) {
BOOST_LOG(error) << "Malformed RTSP message: ["sv << status << ']';
respond(socket->sock, *socket->session, nullptr, 400, "BAD REQUEST", 0, {});
@@ -321,7 +321,7 @@ namespace rtsp_stream {
if (end - socket->crlf >= content_length) {
if (end - socket->crlf > content_length) {
- BOOST_LOG(warning) << "(end - socket->crlf) > content_length -- "sv << (std::size_t)(end - socket->crlf) << " > "sv << content_length;
+ BOOST_LOG(warning) << "(end - socket->crlf) > content_length -- "sv << (std::size_t) (end - socket->crlf) << " > "sv << content_length;
}
fg.disable();
diff --git a/src/utility.h b/src/utility.h
index 8e4ab136..63b16433 100644
--- a/src/utility.h
+++ b/src/utility.h
@@ -377,7 +377,7 @@ namespace util {
return (std::uint8_t) ch - '0';
}
- return (std::uint8_t)(ch | (char) 32) - 'a' + (char) 10;
+ return (std::uint8_t) (ch | (char) 32) - 'a' + (char) 10;
};
std::fill_n(buf + buf_size, padding, 0);
@@ -431,7 +431,7 @@ namespace util {
return (std::uint8_t) ch - '0';
}
- return (std::uint8_t)(ch | (char) 32) - 'a' + (char) 10;
+ return (std::uint8_t) (ch | (char) 32) - 'a' + (char) 10;
};
for (auto &el : buf) {
@@ -509,12 +509,12 @@ namespace util {
std::int64_t res {};
std::int64_t mul = 1;
while (begin != --end) {
- res += (std::int64_t)(*end - '0') * mul;
+ res += (std::int64_t) (*end - '0') * mul;
mul *= 10;
}
- return *begin != '-' ? res + (std::int64_t)(*begin - '0') * mul : -res;
+ return *begin != '-' ? res + (std::int64_t) (*begin - '0') * mul : -res;
}
inline std::int64_t from_view(const std::string_view &number) {
@@ -981,7 +981,7 @@ namespace util {
template
std::string_view view(It begin, It end) {
- return std::string_view {(const char *) begin, (std::size_t)(end - begin)};
+ return std::string_view {(const char *) begin, (std::size_t) (end - begin)};
}
template
diff --git a/src_assets/common/assets/web/configs/tabs/AudioVideo.vue b/src_assets/common/assets/web/configs/tabs/AudioVideo.vue
index f6a303b8..f8d9576a 100644
--- a/src_assets/common/assets/web/configs/tabs/AudioVideo.vue
+++ b/src_assets/common/assets/web/configs/tabs/AudioVideo.vue
@@ -100,6 +100,13 @@ const validateFallbackMode = (event) => {
+
+