From 608f772ccc1457f245907f6ac30c26f6ffdac610 Mon Sep 17 00:00:00 2001 From: "Josh.5" Date: Sun, 10 Sep 2023 19:40:00 +1200 Subject: [PATCH] Add support for automatic refresh rate switching in Sunshine/Moonlight --- Dockerfile.debian | 25 ++++++++++++++++------ overlay/usr/bin/sunshine-run | 40 +++++++++++++++++++++++++++++++++++ overlay/usr/bin/sunshine-stop | 17 +++++++++++++++ 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/Dockerfile.debian b/Dockerfile.debian index 170a6b8..a4eb54c 100644 --- a/Dockerfile.debian +++ b/Dockerfile.debian @@ -493,13 +493,26 @@ RUN \ echo # Install Sunshine -ARG SUNSHINE_VERSION=0.20.0 +COPY --from=lizardbyte/sunshine:b00d7af-debian-bookworm /sunshine.deb /usr/src/sunshine.deb RUN \ + echo "**** Update apt database ****" \ + && apt-get update \ + && \ + echo "**** Install Sunshine requirements ****" \ + && apt-get install -y \ + va-driver-all \ + && \ echo "**** Install Sunshine ****" \ - && wget -O /usr/bin/sunshine \ - https://github.com/LizardByte/Sunshine/releases/download/v${SUNSHINE_VERSION}/sunshine.AppImage \ - && chmod +x /usr/bin/sunshine \ - && setcap cap_sys_admin+p /usr/bin/sunshine \ + && apt-get install -y \ + /usr/src/sunshine.deb \ + && \ + echo "**** Section cleanup ****" \ + && apt-get clean autoclean -y \ + && apt-get autoremove -y \ + && rm -rf \ + /var/lib/apt/lists/* \ + /var/tmp/* \ + /tmp/* \ && \ echo @@ -508,7 +521,7 @@ RUN \ echo "**** Update apt database ****" \ && apt-get update \ && \ - echo "**** Install Intel media drivers and VAAPI ****" \ + echo "**** Install Steam ****" \ && apt-get install -y --no-install-recommends \ steam \ && \ diff --git a/overlay/usr/bin/sunshine-run b/overlay/usr/bin/sunshine-run index df782ab..657d705 100755 --- a/overlay/usr/bin/sunshine-run +++ b/overlay/usr/bin/sunshine-run @@ -33,6 +33,46 @@ trap '_term QUIT' SIGQUIT trap '_term HUP' SIGHUP trap '_term TERM' SIGTERM +# Wipe session config +echo "" > /tmp/sunshine-exec-run.conf + +# Update display resolution and refresh reate if client provided the required details +if ([ "X${SUNSHINE_CLIENT_WIDTH:-}" != "X" ] && [ "X${SUNSHINE_CLIENT_HEIGHT:-}" != "X" ] && [ "X${SUNSHINE_CLIENT_FPS:-}" != "X" ]); then + echo " - Setting display resolution to ${SUNSHINE_CLIENT_WIDTH:?}x${SUNSHINE_CLIENT_HEIGHT:?} ${SUNSHINE_CLIENT_FPS:?}Hz" + + # Read current display mode and extract resolution and refresh rate from the mode string + __xrandr_out="$(xrandr)" + __current_current_mode=$(echo "${__xrandr_out:?}" | awk '/\*/ {print $0}') + __current_resolution=$(echo ${__current_current_mode:?} | awk '{print $1}') + __current_refresh_rate=$(echo ${__current_current_mode:?} | awk '{sub(/\*/, "", $2); print $2}') + + # Get the primary output device + __primary_output="$(echo "${__xrandr_out:?}" | grep primary | awk '{print $1}')" + + # Get the modeline from cvt and extract the second line (which contains the modeline) + __client_modeline=$(cvt "${SUNSHINE_CLIENT_WIDTH:?}" "${SUNSHINE_CLIENT_HEIGHT:?}" "${SUNSHINE_CLIENT_FPS:?}" | grep Modeline | sed -e 's/Modeline //') + + # Create a new mode for this. This allows us to force a set refresh rate that may not be supported by the display + __client_mode=$(echo "${__client_modeline:?}" | awk -F '"' '{print $2}') + + # Check if tthis mode is alread added to the primary display + if ! echo "${__xrandr_out:?}" | grep -q "${__client_mode:?}"; then + echo " - Adding new mode '${__client_mode:?}' with new modeline '${__client_modeline:?}'" + xrandr --newmode "${__client_mode:?}" ${__client_modeline##*\"} + echo " - Adding new mode '${__client_mode:?}' to device '${__primary_output:?}'" + xrandr --addmode "${__primary_output:?}" "${__client_mode:?}" + fi + + # Set the current resoultion to the new mode + echo " - Setting the display mode to '${__client_mode:?}'" + xrandr --output "${__primary_output:?}" --mode "${__client_mode:?}" --rate "${SUNSHINE_CLIENT_FPS:?}" + + # Save original display settings to config file. This will be read and used to restore the original display settings when the client disconnects. + echo "primary_output='${__primary_output:?}'" >> /tmp/sunshine-exec-run.conf + echo "display_mode='${__current_resolution:?}'" >> /tmp/sunshine-exec-run.conf + echo "display_rate='${__current_refresh_rate:?}'" >> /tmp/sunshine-exec-run.conf +fi + # Run child process /usr/bin/dumb-init "${@}" & proc_pid=$! diff --git a/overlay/usr/bin/sunshine-stop b/overlay/usr/bin/sunshine-stop index 6db2e2f..ed0562e 100755 --- a/overlay/usr/bin/sunshine-stop +++ b/overlay/usr/bin/sunshine-stop @@ -21,13 +21,20 @@ echo echo "**** Execute sunshine-stop ****" echo +# Read the run config +if [ -f /tmp/sunshine-exec-run.conf ]; then + . /tmp/sunshine-exec-run.conf +fi +# Read the process PID process_pid="$(cat /tmp/sunshine-exec-run.pid)" echo " - Found initial sunshine-run PID '${process_pid}'" +# Send a INT signal to the PID echo " - Sending SIGINT to PID '${process_pid}'" kill -INT "${process_pid}" +# Run a loop to check for any other "sunshine-run" processes and send them also a INT signal echo " - Checking for other sunshine-run processes '${process_pid}'" for process_pid in $(ps aux | grep -v grep | grep sunshine-run | awk '{print $2}'); do echo " - Sending SIGINT to PID '${process_pid}'" @@ -51,6 +58,16 @@ for process_pid in $(ps aux | grep -v grep | grep sunshine-run | awk '{print $2} done done +# Check if the required information was stored for resetting the display resolution and refresh rate +if ([ "X${primary_output:-}" != "X" ] && [ "X${display_mode:-}" != "X" ] && [ "X${display_rate:-}" != "X" ]); then + # Reset display resolution and refresh rate + echo " - Resetting display resolution to ${display_mode:?} ${display_rate:?}Hz" + xrandr --output "${primary_output:?}" --mode "${display_mode:?}" --rate "${display_rate:?}" +fi + +# Clean up config file +rm -f /tmp/sunshine-exec-run.conf + # Clean up PID file rm -f /tmp/sunshine-exec-run.pid