diff --git a/.github/workflows/runner.yml b/.github/workflows/runner.yml index 0e2b2d01..dd79f7b1 100644 --- a/.github/workflows/runner.yml +++ b/.github/workflows/runner.yml @@ -46,6 +46,11 @@ jobs: - name: Setup Docker Buildx uses: docker/setup-buildx-action@v3 + - + name: Set Swap Space + uses: pierotofy/set-swap-space@master + with: + swap-size-gb: 10 - name: Cache Docker layers uses: actions/cache@v4 @@ -63,13 +68,13 @@ jobs: push: false load: true cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + cache-to: type=local,dest=/tmp/.buildx-cache,mode=max tags: nestri:runner - - - name: Move cache - run: | - rm -rf /tmp/.buildx-cache - mv /tmp/.buildx-cache-new /tmp/.buildx-cache + # - + # name: Move cache + # run: | + # rm -rf /tmp/.buildx-cache + # mv /tmp/.buildx-cache-new /tmp/.buildx-cache build-docker-main: name: Build image on main diff --git a/apps/www/src/routes/(play)/play/[id]/index.tsx b/apps/www/src/routes/(play)/play/[id]/index.tsx index 7720c94f..868361f8 100644 --- a/apps/www/src/routes/(play)/play/[id]/index.tsx +++ b/apps/www/src/routes/(play)/play/[id]/index.tsx @@ -80,6 +80,8 @@ export default component$(() => { window.nestrikeyboard.dispose(); // @ts-ignore window.nestrikeyboard = undefined; + // @ts-ignore + window.nestriLock = undefined; } }); }; @@ -147,7 +149,7 @@ export default component$(() => { ref={canvas} onClick$={async () => { // @ts-ignore - if (canvas.value && window.hasstream) { + if (canvas.value && window.hasstream && !window.nestriLock) { // Do not use - unadjustedMovement: true - breaks input on linux await canvas.value.requestPointerLock(); await canvas.value.requestFullscreen() @@ -168,14 +170,20 @@ export default component$(() => { window.navigator.keyboard.lock(keys).then( () => { console.log("keyboard lock success"); + // @ts-ignore + window.nestriLock = true; } ).catch( (e: any) => { console.log("keyboard lock failed: ", e); + // @ts-ignore + window.nestriLock = false; } ) } else { console.log("keyboard lock not supported, navigator is: ", window.navigator, navigator); + // @ts-ignore + window.nestriLock = undefined; } } } diff --git a/containers/runner.Containerfile b/containers/runner.Containerfile index de8a267f..ccb9d0c2 100644 --- a/containers/runner.Containerfile +++ b/containers/runner.Containerfile @@ -8,7 +8,7 @@ FROM ${BASE_IMAGE} AS gst-builder WORKDIR /builder/ # Grab build and rust packages # -RUN pacman -Syu --noconfirm meson pkgconf cmake git gcc make rustup \ +RUN pacman -Sy --noconfirm meson pkgconf cmake git gcc make rustup \ gstreamer gst-plugins-base gst-plugins-good gst-plugin-rswebrtc # Setup stable rust toolchain # @@ -34,7 +34,7 @@ FROM ${BASE_IMAGE} AS gstwayland-builder WORKDIR /builder/ # Grab build and rust packages # -RUN pacman -Syu --noconfirm meson pkgconf cmake git gcc make rustup \ +RUN pacman -Sy --noconfirm meson pkgconf cmake git gcc make rustup \ libxkbcommon wayland gstreamer gst-plugins-base gst-plugins-good libinput # Setup stable rust toolchain # @@ -71,11 +71,19 @@ FROM ${BASE_IMAGE} AS runtime ## Install Graphics, Media, and Audio packages ## RUN sed -i '/#\[multilib\]/,/#Include = \/etc\/pacman.d\/mirrorlist/ s/#//' /etc/pacman.conf && \ sed -i "s/#Color/Color/" /etc/pacman.conf && \ - pacman --noconfirm -Syu archlinux-keyring && \ + pacman --noconfirm -Sy archlinux-keyring && \ dirmngr /dev/null 2>&1 && \ + # Install mesa-git before Steam for simplicity + pacman --noconfirm -Sy mesa-git && \ # Install Steam - pacman --noconfirm -S steam && \ - pacman -Syu --noconfirm --needed \ + pacman --noconfirm -Sy steam steam-native-runtime && \ + # Clean up pacman cache + paccache -rk1 && \ + rm -rf /usr/share/info/* && \ + rm -rf /usr/share/man/* && \ + rm -rf /usr/share/doc/ + +RUN pacman -Sy --noconfirm --needed \ # Graphics packages sudo xorg-xwayland labwc wlr-randr mangohud \ # GStreamer and plugins @@ -84,6 +92,8 @@ RUN sed -i '/#\[multilib\]/,/#Include = \/etc\/pacman.d\/mirrorlist/ s/#//' /et gst-plugin-rswebrtc gst-plugin-rsrtp \ # Audio packages pipewire pipewire-pulse pipewire-alsa wireplumber \ + # Non-latin fonts + noto-fonts-cjk \ # Other requirements supervisor jq chwd lshw pacman-contrib && \ # Clean up pacman cache @@ -91,13 +101,16 @@ RUN sed -i '/#\[multilib\]/,/#Include = \/etc\/pacman.d\/mirrorlist/ s/#//' /et rm -rf /usr/share/info/* && \ rm -rf /usr/share/man/* && \ rm -rf /usr/share/doc/* - + + +# Regenerate locale +RUN locale-gen ## User ## # Create and setup user # ENV USER="nestri" \ - UID=99 \ - GID=100 \ + UID=1000 \ + GID=1000 \ USER_PWD="nestri1234" RUN mkdir -p /home/${USER} && \ @@ -114,7 +127,8 @@ RUN mkdir -p /run/user/${UID} && \ # Groups # RUN usermod -aG input root && usermod -aG input ${USER} && \ usermod -aG video root && usermod -aG video ${USER} && \ - usermod -aG render root && usermod -aG render ${USER} + usermod -aG render root && usermod -aG render ${USER} && \ + usermod -aG seat root && usermod -aG seat ${USER} ## Copy files from builders ## # this is done here at end to not trigger full rebuild on changes to builder @@ -139,10 +153,13 @@ ENV XDG_RUNTIME_DIR=/run/user/${UID} \ # Required for NVIDIA.. they want to be special like that # ENV NVIDIA_DRIVER_CAPABILITIES=all +# DBus run directory creation # +RUN mkdir -p /run/dbus + # Wireplumber disable suspend # # Remove suspend node RUN sed -z -i 's/{[[:space:]]*name = node\/suspend-node\.lua,[[:space:]]*type = script\/lua[[:space:]]*provides = hooks\.node\.suspend[[:space:]]*}[[:space:]]*//g' /usr/share/wireplumber/wireplumber.conf # Remove "hooks.node.suspend" want RUN sed -i '/wants = \[/{s/hooks\.node\.suspend\s*//; s/,\s*\]/]/}' /usr/share/wireplumber/wireplumber.conf -ENTRYPOINT ["supervisord", "-c", "/etc/nestri/supervisord.conf"] \ No newline at end of file +ENTRYPOINT ["supervisord", "-c", "/etc/nestri/supervisord.conf"] diff --git a/packages/scripts/entrypoint.sh b/packages/scripts/entrypoint.sh index acf7a8b3..9d46ca8a 100644 --- a/packages/scripts/entrypoint.sh +++ b/packages/scripts/entrypoint.sh @@ -31,10 +31,6 @@ if [ ! -e "$PIPEWIRE_SOCKET" ]; then exit 1 fi -# Update system packages before proceeding -echo "Upgrading system packages..." -pacman -Syu --noconfirm - echo "Detecting GPU vendor and installing necessary GStreamer plugins..." source /etc/nestri/gpu_helpers.sh @@ -43,14 +39,14 @@ get_gpu_info # Identify vendor if [[ "${vendor_full_map[0],,}" =~ "intel" ]]; then echo "Intel GPU detected, installing required packages..." - chwd -a - pacman -Syu --noconfirm gstreamer-vaapi gst-plugin-va gst-plugin-qsv + #chwd -a + pacman -Sy --noconfirm gstreamer-vaapi gst-plugin-va gst-plugin-qsv # chwd missed a thing - pacman -Syu --noconfirm vpl-gpu-rt + pacman -Sy --noconfirm vpl-gpu-rt elif [[ "${vendor_full_map[0],,}" =~ "amd" ]]; then echo "AMD GPU detected, installing required packages..." - chwd -a - pacman -Syu --noconfirm gstreamer-vaapi gst-plugin-va + #chwd -a + pacman -Sy --noconfirm gstreamer-vaapi gst-plugin-va elif [[ "${vendor_full_map[0],,}" =~ "nvidia" ]]; then echo "NVIDIA GPU detected. Assuming drivers are linked" else @@ -62,4 +58,6 @@ echo "Cleaning up old package cache..." paccache -rk1 echo "Switching to nestri user for application startup..." +# Make sure user home dir is owned properly +chown ${USER}:${USER} /home/${USER} exec sudo -E -u nestri /etc/nestri/entrypoint_nestri.sh diff --git a/packages/scripts/entrypoint_nestri.sh b/packages/scripts/entrypoint_nestri.sh index 749b73bb..2d895e0b 100644 --- a/packages/scripts/entrypoint_nestri.sh +++ b/packages/scripts/entrypoint_nestri.sh @@ -15,26 +15,20 @@ MAX_RETRIES=3 # Helper function to restart the chain restart_chain() { - echo "Restarting nestri-server, labwc, and wlr-randr..." - - # Kill all child processes safely (if running) - if [[ -n "${NESTRI_PID:-}" ]] && kill -0 "${NESTRI_PID}" 2 >/dev/null; then - kill "${NESTRI_PID}" - fi - if [[ -n "${LABWC_PID:-}" ]] && kill -0 "${LABWC_PID}" 2 >/dev/null; then - kill "${LABWC_PID}" - fi - - wait || true + echo "Restarting nestri-server, compositor..." # Start nestri-server start_nestri_server RETRY_COUNT=0 } - # Function to start nestri-server start_nestri_server() { + if [[ -n "${NESTRI_PID:-}" ]] && kill -0 "${NESTRI_PID}" 2 >/dev/null; then + echo "Killing existing nestri-server process..." + kill "${NESTRI_PID}" + fi + echo "Starting nestri-server..." nestri-server $(echo $NESTRI_PARAMS) & NESTRI_PID=$! @@ -45,7 +39,8 @@ start_nestri_server() { for _ in {1..15}; do # Wait up to 15 seconds if [ -e "$WAYLAND_SOCKET" ]; then echo "Wayland display 'wayland-1' is ready." - start_labwc + sleep 1 # necessary sleep - reduces chance that non-ready socket is used + start_compositor return fi sleep 1 @@ -60,37 +55,44 @@ start_nestri_server() { restart_chain } -# Function to start labwc -start_labwc() { - echo "Starting labwc..." +# Function to start compositor (labwc) +start_compositor() { + if [[ -n "${COMPOSITOR_PID:-}" ]] && kill -0 "${COMPOSITOR_PID}" 2 >/dev/null; then + echo "Killing existing compositor process..." + kill "${COMPOSITOR_PID}" + fi + + echo "Starting compositor..." rm -rf /tmp/.X11-unix && mkdir -p /tmp/.X11-unix && chown nestri:nestri /tmp/.X11-unix WAYLAND_DISPLAY=wayland-1 WLR_BACKENDS=wayland labwc & - LABWC_PID=$! + COMPOSITOR_PID=$! - # Wait for labwc to initialize (using `wlr-randr` as an indicator) - echo "Waiting for labwc to initialize..." + # Wait for compositor to initialize + echo "Waiting for compositor to initialize..." + COMPOSITOR_SOCKET="/run/user/${UID}/wayland-0" for _ in {1..15}; do - if wlr-randr --json | jq -e '.[] | select(.enabled == true)' >/dev/null; then - echo "labwc is initialized and Wayland outputs are ready." + if [ -e "$COMPOSITOR_SOCKET" ]; then + echo "compositor is initialized, wayland-0 output ready." + sleep 1 # necessary sleep - reduces chance that non-ready socket is used start_wlr_randr return fi sleep 1 done - echo "Error: labwc did not initialize correctly. Incrementing retry count..." + echo "Error: compositor did not initialize correctly. Incrementing retry count..." ((RETRY_COUNT++)) if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then - echo "Max retries reached for labwc. Exiting." + echo "Max retries reached for compositor. Exiting." exit 1 fi - restart_chain + start_compositor } # Function to run wlr-randr start_wlr_randr() { echo "Configuring resolution with wlr-randr..." - OUTPUT_NAME=$(wlr-randr --json | jq -r '.[] | select(.enabled == true) | .name' | head -n 1) + OUTPUT_NAME=$(WAYLAND_DISPLAY=wayland-0 wlr-randr --json | jq -r '.[] | select(.enabled == true) | .name' | head -n 1) if [ -z "$OUTPUT_NAME" ]; then echo "Error: No enabled outputs detected. Skipping wlr-randr." return @@ -116,8 +118,8 @@ main_loop() { if [[ -n "${NESTRI_PID:-}" ]] && kill -0 "${NESTRI_PID}" 2>/dev/null; then kill "${NESTRI_PID}" fi -if [[ -n "${LABWC_PID:-}" ]] && kill -0 "${LABWC_PID}" 2>/dev/null; then -kill "${LABWC_PID}" +if [[ -n "${COMPOSITOR_PID:-}" ]] && kill -0 "${COMPOSITOR_PID}" 2>/dev/null; then +kill "${COMPOSITOR_PID}" fi exit 0' SIGINT SIGTERM @@ -134,14 +136,14 @@ fi exit 1 fi restart_chain - elif ! kill -0 ${LABWC_PID:-} 2 >/dev/null; then - echo "labwc crashed. Restarting labwc and wlr-randr..." + elif ! kill -0 ${COMPOSITOR_PID:-} 2 >/dev/null; then + echo "compositor crashed. Restarting compositor..." ((RETRY_COUNT++)) if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then - echo "Max retries reached for labwc. Exiting." + echo "Max retries reached for compositor. Exiting." exit 1 fi - start_labwc + start_compositor fi done } diff --git a/packages/server/src/main.rs b/packages/server/src/main.rs index 9052e09a..99c32860 100644 --- a/packages/server/src/main.rs +++ b/packages/server/src/main.rs @@ -331,6 +331,7 @@ async fn main() -> Result<(), Box> { } // Optimize latency of pipeline + video_source.sync_state_with_parent().expect("failed to sync with parent"); video_source.set_property("do-timestamp", &true); audio_source.set_property("do-timestamp", &true); pipeline.set_property("latency", &0u64);