From fefe280ccdca10e80bace7c56e5806beec1d459e Mon Sep 17 00:00:00 2001 From: Soumyadeep Ghosh Date: Sun, 3 Nov 2024 17:46:59 +0530 Subject: [PATCH 1/5] backend: add path to get real release for snaps --- src/backend/utils/systeminfo/osInfo/linux.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/utils/systeminfo/osInfo/linux.ts b/src/backend/utils/systeminfo/osInfo/linux.ts index fbc2ffaec3..deb8e07c15 100644 --- a/src/backend/utils/systeminfo/osInfo/linux.ts +++ b/src/backend/utils/systeminfo/osInfo/linux.ts @@ -14,7 +14,7 @@ function stripQuotes(stringMaybeWithQuotes: string): string { async function osInfo_linux(): Promise<{ name: string; version?: string }> { let os_release_path: string | null = null - for (const potPath of ['/run/host/os-release', '/etc/os-release']) { + for (const potPath of ['/run/host/os-release', '/var/lib/snapd/hostfs/etc/os-release', '/etc/os-release']) { try { await stat(potPath) os_release_path = potPath From 1d97c120a81a4d2a45534ff9dfb70b61904c55fa Mon Sep 17 00:00:00 2001 From: Soumyadeep Ghosh Date: Sun, 3 Nov 2024 18:29:53 +0530 Subject: [PATCH 2/5] snap: added snap manifest --- snap/gui/heroic.desktop | 12 + snap/hooks/configure | 45 ++++ snap/local/src/desktop-launch | 356 ++++++++++++++++++++++++ snap/local/src/heroicreport | 472 ++++++++++++++++++++++++++++++++ snap/local/src/nvidia32 | 171 ++++++++++++ snap/snapcraft.yaml | 490 ++++++++++++++++++++++++++++++++++ 6 files changed, 1546 insertions(+) create mode 100644 snap/gui/heroic.desktop create mode 100644 snap/hooks/configure create mode 100755 snap/local/src/desktop-launch create mode 100755 snap/local/src/heroicreport create mode 100755 snap/local/src/nvidia32 create mode 100644 snap/snapcraft.yaml diff --git a/snap/gui/heroic.desktop b/snap/gui/heroic.desktop new file mode 100644 index 0000000000..342dbe94ee --- /dev/null +++ b/snap/gui/heroic.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +#Name=Heroic Games Launcher +Name=Heroic Snap +Exec=heroic %u +Terminal=false +Type=Application +Icon=${SNAP}/meta/gui/heroic.png +StartupWMClass=Heroic +Comment=An Open Source GOG and Epic Games launcher +Comment[de]=Ein Open Source Spielelauncher for GOG und Epic Games +MimeType=x-scheme-handler/heroic; +Categories=Game; diff --git a/snap/hooks/configure b/snap/hooks/configure new file mode 100644 index 0000000000..5fbd8681ec --- /dev/null +++ b/snap/hooks/configure @@ -0,0 +1,45 @@ +#!/bin/sh + +# https://github.com/canonical/steam-snap/issues/19#issuecomment-1171984524 +# https://gist.github.com/jhenstridge/425c769949d034033f3d5d90acc2f181 + +set -e + +mkdir -p $SNAP_DATA/etc + +snap_ld_so_conf=$SNAP_DATA/etc/snap-ld.so.conf +snap_ld_so_cache=$SNAP_DATA/etc/snap-ld.so.cache +real_ld_so_cache=$SNAP_DATA/etc/ld.so.cache + +RUNTIME=$SNAP/gnome-platform + +cat > "$snap_ld_so_conf" < $real_ld_so_cache diff --git a/snap/local/src/desktop-launch b/snap/local/src/desktop-launch new file mode 100755 index 0000000000..204d239e45 --- /dev/null +++ b/snap/local/src/desktop-launch @@ -0,0 +1,356 @@ +#!/bin/bash +################# +# Launcher init # +################# + +# shellcheck disable=SC2034 +START=$(date +%s.%N) + +if ! snapctl is-connected "gaming-mesa"; then + echo "ERROR: not connected to the gaming-mesa content interface." + echo "To connect:" + echo "sudo snap connect heroic:gaming-mesa gaming-graphics-core22" + exit 1 +fi + +# ensure_dir_exists calls `mkdir -p` if the given path is not a directory. +# This speeds up execution time by avoiding unnecessary calls to mkdir. +# +# Usage: ensure_dir_exists []... +# +function ensure_dir_exists() { + [ -d "$1" ] || mkdir -p "$@" +} + +declare -A PIDS +function async_exec() { + "$@" & + PIDS[$!]=$* +} +function wait_for_async_execs() { + for pid in "${!PIDS[@]}" + do + wait "$pid" && continue || echo "ERROR: ${PIDS[$pid]} exited abnormally with status $?" + done +} + +# shellcheck source=/dev/null +source "$SNAP_USER_DATA/.last_revision" 2>/dev/null || true +if [ "$SNAP_DESKTOP_LAST_REVISION" = "$SNAP_REVISION" ]; then + needs_update=false +else + needs_update=true +fi + +# Set $REALHOME to the users real home directory +REALHOME=$(getent passwd $UID | cut -d ':' -f 6) + +export SNAP_DESKTOP_RUNTIME=$SNAP + +# Set config folder to local path +export XDG_CONFIG_HOME="$SNAP_USER_COMMON/.config" +ensure_dir_exists "$XDG_CONFIG_HOME" +chmod 700 "$XDG_CONFIG_HOME" + +# If the user has modified their user-dirs settings, force an update +if [[ -f "$XDG_CONFIG_HOME/user-dirs.dirs.md5sum" ]]; then + if [[ "$(md5sum < "$REALHOME/.config/user-dirs.dirs")" != "$(cat "$XDG_CONFIG_HOME/user-dirs.dirs.md5sum")" || + ( -f "$XDG_CONFIG_HOME/user-dirs.locale.md5sum" && + "$(md5sum < "$REALHOME/.config/user-dirs.locale")" != "$(cat "$XDG_CONFIG_HOME/user-dirs.locale.md5sum")" ) ]]; then + needs_update=true + fi +else + # shellcheck disable=SC2034 + needs_update=true +fi + +# If the user has saves in the old $SNAP_USER_DATA/.config, move them +# to $SNAP_USER_COMMON/.config +if [[ -d $SNAP_USER_DATA/.config ]]; then + mv -n $SNAP_USER_DATA/.config/* $XDG_CONFIG_HOME + rm -r $SNAP_USER_DATA/.config +fi + +if [ "$SNAP_ARCH" = "amd64" ]; then + ARCH="x86_64-linux-gnu" +elif [ "$SNAP_ARCH" = "armhf" ]; then + ARCH="arm-linux-gnueabihf" +elif [ "$SNAP_ARCH" = "arm64" ]; then + ARCH="aarch64-linux-gnu" +elif [ "$SNAP_ARCH" = "ppc64el" ]; then + ARCH="powerpc64le-linux-gnu" +else + ARCH="$SNAP_ARCH-linux-gnu" +fi + +# Force i386 +export ARCH="i386-linux-gnu" +export SNAP_LAUNCHER_ARCH_TRIPLET="$ARCH" + +############################################### +# Launcher common exports for any desktop app # +############################################### + +# Note: We avoid using `eval` because we don't want to expand variable names +# in paths. For example: LD_LIBRARY_PATH paths might contain `$LIB`. +function prepend_dir() { + local -n var="$1" + local dir="$2" + # We can't check if the dir exists when the dir contains variables + if [[ "$dir" == *"\$"* || -d "$dir" ]]; then + export "${!var}=${dir}${var:+:$var}" + fi +} + +function append_dir() { + local -n var="$1" + local dir="$2" + # We can't check if the dir exists when the dir contains variables + if [[ "$dir" == *"\$"* || -d "$dir" ]]; then + export "${!var}=${var:+$var:}${dir}" + fi +} + + +function strip_unreachable_dirs() { + local -n var=$1 + local dirs="${var}" + + tmp="" + local IFS=: + for d in $dirs; do + # Just checking existence and the `x` bit isn't enough + # we need to see if we can actually `ls` it because of apparmor + # quirks + ls $d > /dev/null 2>&1 + if [[ $? -eq 0 ]]; then + append_dir tmp "$d" + else + echo "INFO: filtering $d out of ${!var} because it is unreachable" + fi + + done + + export "${!var}=${tmp}" + unset tmp +} + +function is_subpath() { + dir="$(realpath "$1")" + parent="$(realpath "$2")" + [ "${dir##$parent/}" != "$dir" ] && return 0 || return 1 +} + +append_dir PATH "$SNAP_DESKTOP_RUNTIME/usr/bin" + +# XKB config +export XKB_CONFIG_ROOT="$SNAP_DESKTOP_RUNTIME/usr/share/X11/xkb" + +# Give XOpenIM a chance to locate locale data. +# This is required for text input to work in SDL2 games. +export XLOCALEDIR="$SNAP_DESKTOP_RUNTIME/usr/share/X11/locale" + +# Set XCursors path +export XCURSOR_PATH="$SNAP_DESKTOP_RUNTIME/usr/share/icons" +prepend_dir XCURSOR_PATH "$SNAP/share/icons" + +# Mesa Libs for OpenGL support +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/mesa" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/mesa-egl" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/x86_64-linux-gnu/mesa" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/x86_64-linux-gnu/mesa-egl" +# append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/$ARCH/mesa" +# append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/$ARCH/mesa-egl" +# append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/x86_64-linux-gnu/mesa" +# append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/x86_64-linux-gnu/mesa-egl" + +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/$ARCH" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/x86_64-linux-gnu" + +# Tell libGL and libva where to find the drivers +export LIBGL_DRIVERS_PATH="$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/dri" +append_dir LIBGL_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/x86_64-linux-gnu/dri" +append_dir LIBGL_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/$ARCH/dri" +append_dir LIBGL_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/x86_64-linux-gnu/dri" +append_dir LIBGL_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/i386-linux-gnu/dri" +append_dir LD_LIBRARY_PATH "$LIBGL_DRIVERS_PATH" + +append_dir LIBVA_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/dri" +append_dir LIBVA_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/x86_64-linux-gnu/dri" +append_dir LIBVA_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/$ARCH/dri" +append_dir LIBVA_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/x86_64-linux-gnu/dri" + +# Set where the VDPAU drivers are located +export VDPAU_DRIVER_PATH="/usr/lib/$ARCH/vdpau/" +if [ -e "/var/lib/snapd/lib/gl/vdpau/libvdpau_nvidia.so" ]; then + export VDPAU_DRIVER_PATH="/var/lib/snapd/lib/gl/vdpau" + # Prevent picking VA-API (Intel/AMD) over NVIDIA VDPAU; on PRIME systems for example + unset LIBVA_DRIVERS_PATH +fi + +# Export Vulkan ICD filename paths +export VK_ICD_FILENAMES="/var/lib/snapd/lib/vulkan/icd.d/nvidia_icd.json:$SNAP/graphics/usr/share/vulkan/icd.d/radeon_icd.x86_64.json:$SNAP/graphics/usr/share/vulkan/icd.d/radeon_icd.i686.json:$SNAP/graphics/usr/share/vulkan/icd.d/intel_icd.x86_64.json:$SNAP/graphics/usr/share/vulkan/icd.d/intel_icd.i686.json" + +# Workaround in snapd for proprietary nVidia drivers mounts the drivers in +# /var/lib/snapd/lib/gl that needs to be in LD_LIBRARY_PATH +# Without that OpenGL using apps do not work with the nVidia drivers. +# Ref.: https://bugs.launchpad.net/snappy/+bug/1588192 +append_dir LD_LIBRARY_PATH "/var/lib/snapd/lib/gl" +append_dir LD_LIBRARY_PATH "/var/lib/snapd/lib/gl/vdpau" + +# By sheer luck, this was working in the past, but we need this explicitly +append_dir LD_LIBRARY_PATH "/var/lib/snapd/lib/gl32" +append_dir LD_LIBRARY_PATH "/var/lib/snapd/lib/gl32/vdpau" + +# Unity7 export (workaround for https://launchpad.net/bugs/1638405) +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/libunity" + +# Pulseaudio export +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/pulseaudio" + +# EGL vendor files on glvnd enabled systems +prepend_dir __EGL_VENDOR_LIBRARY_DIRS "/var/lib/snapd/lib/glvnd/egl_vendor.d" +append_dir __EGL_VENDOR_LIBRARY_DIRS "$SNAP_DESKTOP_RUNTIME/usr/share/glvnd/egl_vendor.d" + +# Tell GStreamer where to find its plugins +export GST_PLUGIN_PATH="$SNAP/usr/lib/$ARCH/gstreamer-1.0" +export GST_PLUGIN_SYSTEM_PATH="$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/gstreamer-1.0" +# gst plugin scanner doesn't install in the correct path: https://github.com/ubuntu/snapcraft-desktop-helpers/issues/43 +export GST_PLUGIN_SCANNER="$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner" + +# XDG Config +prepend_dir XDG_CONFIG_DIRS "$SNAP_DESKTOP_RUNTIME/etc/xdg" +prepend_dir XDG_CONFIG_DIRS "$SNAP/etc/xdg" + +# Define snaps' own data dir +prepend_dir XDG_DATA_DIRS "$SNAP_DESKTOP_RUNTIME/usr/share" +prepend_dir XDG_DATA_DIRS "$SNAP/usr/share" +prepend_dir XDG_DATA_DIRS "$SNAP/share" +prepend_dir XDG_DATA_DIRS "$SNAP/data-dir" +prepend_dir XDG_DATA_DIRS "$SNAP_USER_DATA" +append_dir XDG_DATA_DIRS "$SNAP/graphics/usr/share" + +# Set XDG_DATA_HOME to local path +# heroic snap +export XDG_DATA_HOME="$SNAP_USER_COMMON/.local/share" +ensure_dir_exists "$XDG_DATA_HOME" + +# Workaround for GLib < 2.53.2 not searching for schemas in $XDG_DATA_HOME: +# https://bugzilla.gnome.org/show_bug.cgi?id=741335 +prepend_dir XDG_DATA_DIRS "$XDG_DATA_HOME" + +# Set cache folder to local path +export XDG_CACHE_HOME="$SNAP_USER_COMMON/.cache" +if [[ -d "$SNAP_USER_DATA/.cache" && ! -e "$XDG_CACHE_HOME" ]]; then + # the .cache directory used to be stored under $SNAP_USER_DATA, migrate it + mv "$SNAP_USER_DATA/.cache" "$SNAP_USER_COMMON/" +fi +ensure_dir_exists "$XDG_CACHE_HOME" + +# Create $XDG_RUNTIME_DIR if not exists (to be removed when LP: #1656340 is fixed) +# shellcheck disable=SC2174 +ensure_dir_exists "$XDG_RUNTIME_DIR" -m 700 + +# Ensure the app finds locale definitions (requires locales-all to be installed) +append_dir LOCPATH "$SNAP_DESKTOP_RUNTIME/usr/lib/locale" + +# If detect wayland server socket, then set environment so applications prefer +# wayland, and setup compat symlink (until we use user mounts. Remember, +# XDG_RUNTIME_DIR is /run/user//snap.$SNAP so look in the parent directory +# for the socket. For details: +# https://forum.snapcraft.io/t/wayland-dconf-and-xdg-runtime-dir/186/10 +# Applications that don't support wayland natively may define DISABLE_WAYLAND +# (to any non-empty value) to skip that logic entirely. +wayland_available=false +if [[ -n "$XDG_RUNTIME_DIR" && -z "$DISABLE_WAYLAND" ]]; then + wdisplay="wayland-0" + if [ -n "$WAYLAND_DISPLAY" ]; then + wdisplay="$WAYLAND_DISPLAY" + fi + wayland_sockpath="$XDG_RUNTIME_DIR/../$wdisplay" + wayland_snappath="$XDG_RUNTIME_DIR/$wdisplay" + if [ -S "$wayland_sockpath" ]; then + # if running under wayland, use it + #export WAYLAND_DEBUG=1 + # shellcheck disable=SC2034 + wayland_available=true + # create the compat symlink for now + if [ ! -e "$wayland_snappath" ]; then + ln -s "$wayland_sockpath" "$wayland_snappath" + fi + fi +fi + +# Make PulseAudio socket available inside the snap-specific $XDG_RUNTIME_DIR +if [ -n "$XDG_RUNTIME_DIR" ]; then + pulsenative="pulse/native" + pulseaudio_sockpath="$XDG_RUNTIME_DIR/../$pulsenative" + if [ -S "$pulseaudio_sockpath" ]; then + export PULSE_SERVER="unix:${pulseaudio_sockpath}" + fi +fi + +# Keep an array of data dirs, for looping through them +IFS=':' read -r -a data_dirs_array <<< "$XDG_DATA_DIRS" + +if [ "$needs_update" = true ]; then + rm -rf "$XDG_DATA_HOME"/{themes,.themes} +fi + +############################## +# GTK launcher specific part # +############################## + +# shellcheck disable=SC2154 +if [ "$wayland_available" = true ]; then + export GDK_BACKEND="wayland" + export CLUTTER_BACKEND="wayland" + # Does not hurt to specify this as well, just in case + export QT_QPA_PLATFORM=wayland-egl +fi +append_dir GTK_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/gtk-3.0" + +############################### +# Mark update and exec binary # +############################### + +# shellcheck disable=SC2154 +[ "$needs_update" = true ] && echo "SNAP_DESKTOP_LAST_REVISION=$SNAP_REVISION" > "$SNAP_USER_DATA/.last_revision" + +wait_for_async_execs + +if [ -n "$SNAP_DESKTOP_DEBUG" ]; then + echo "desktop-launch elapsed time: $(date +%s.%N --date="$START seconds ago")" + echo "Now running: exec $*" +fi + +# Fix default run command +# The default works on a system with only the Snap installed, but if they also +# have the deb then the default command will run the deb instead of the Snap. +find "$SNAP_USER_COMMON/.local/share/applications" -type f | while read -r file; do + sed -i "s/Exec=heroic/Exec=snap run heroic/" "$file" +done + +# Links game icons to host +find "$SNAP_USER_COMMON/.local/share/icons/hicolor" -type f -name "heroic_icon_*.png" | while read -r file; do + dest="${file/$SNAP_USER_COMMON/$REALHOME}" + ensure_dir_exists "$(dirname $dest)" + ln -sf "$file" "$dest" +done + +# Link .desktop files to host +ln -sf $SNAP_USER_COMMON/.local/share/applications/* $REALHOME/.local/share/applications/ + +strip_unreachable_dirs XDG_DATA_DIRS +strip_unreachable_dirs XDG_CONFIG_DIRS +strip_unreachable_dirs XDG_SPECIAL_DIRS + +# Even with libfuse, appimages need to be extracted to run. +# This is a workaround until we figure out something better, because it makes +# launching AppImage games way slower +# +# That said, they're really rare so it's not a big deal +export APPIMAGE_EXTRACT_AND_RUN=1 + +$SNAP/bin/nvidia32 & +"$@" diff --git a/snap/local/src/heroicreport b/snap/local/src/heroicreport new file mode 100755 index 0000000000..ae865920b4 --- /dev/null +++ b/snap/local/src/heroicreport @@ -0,0 +1,472 @@ +#!/usr/bin/python3 + +import os +import sys +import webbrowser +import argparse +from collections import defaultdict +import requests +import gi +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk, Gdk + +ISSUE_URL = "https://github.com/canonical/steam-snap/issues/new?assignees=&labels=bug&projects=&template=bug_report.yml" +DISCUSSION_URL = "https://github.com/canonical/steam-snap/discussions/new?category=game-reports" +WIKI_URL = "https://github.com/canonical/steam-snap/wiki/Troubleshooting#submitting-a-steam-report" +GRAPHQL_URL = "https://api.github.com/graphql" +TOKEN_URL = "https://github.com/settings/tokens/new" + +DISCUSSION_CATEGORY_ID = "DIC_kwDOC5Gtms4CR-_9" + +BODY_SUFFIX = "" +SNAP_COMMAND = """snap connect steam:hardware-observe +snap connect steam:system-observe""" + +data = {} + +class SteamReportWindow(Gtk.Window): + def __init__(self, args): + super().__init__() + self.set_resizable(True) + self.set_border_width(10) + self.set_position(Gtk.WindowPosition.CENTER) + self.set_default_size(-1, 450) + + grid = Gtk.Grid( + row_spacing=10, + column_spacing=10, + column_homogeneous=True, + ) + self.add(grid) + + label = Gtk.Label(halign=Gtk.Align.START) + label.set_markup( + "Below is the hardware information collected from your system." + f"\nSee {WIKI_URL} for more information." + ) + grid.attach(label, 0, 0, 5, 1) + + copy_button = Gtk.Button.new_from_icon_name("edit-copy-symbolic", Gtk.IconSize.MENU) + copy_button.set_tooltip_text("Copy") + copy_button.connect("clicked", lambda x: self.button_copy()) + copy_button.set_halign(Gtk.Align.END) + grid.attach_next_to(copy_button, label, Gtk.PositionType.RIGHT, 1, 1) + + scrolled_window = Gtk.ScrolledWindow() + scrolled_window.set_vexpand(True) + textview = Gtk.TextView( + editable=False, + monospace=True, + top_margin=5, + bottom_margin=5, + right_margin=10, + left_margin=10 + ) + textview.get_buffer().set_text(dict_to_string(gather_data(args)).strip()) + scrolled_window.add(textview) + grid.attach(scrolled_window, 0, 2, 6, 1) + + issue_button = Gtk.Button( + label="Open New Issue", + tooltip_text="Opens a new Steam Snap issue to report a bug or problem" + ) + issue_button.connect("clicked", lambda x: self.button_issue()) + grid.attach_next_to(issue_button, scrolled_window, Gtk.PositionType.BOTTOM, 2, 1) + + report_button = Gtk.Button( + label="Open New Game Report", + tooltip_text="Opens a new Steam Snap discussion to report the functionality of a specific game" + ) + report_button.connect("clicked", lambda x: self.button_report()) + grid.attach_next_to(report_button, issue_button, Gtk.PositionType.RIGHT, 2, 1) + + ok_button = Gtk.Button(label="Ok") + ok_button.connect("clicked", lambda x: self.close()) + grid.attach_next_to(ok_button, report_button, Gtk.PositionType.RIGHT, 2, 1) + + + def button_copy(self): + clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) + clipboard.set_text(dict_to_string(data), -1) + + + def button_issue(self): + open_issue(data) + + + def button_report(self): + open_discussion(data) + + +class NeedPlugsWindow(Gtk.Window): + def __init__(self, args): + super().__init__() + self.set_resizable(False) + self.set_border_width(10) + self.set_position(Gtk.WindowPosition.CENTER) + + grid = Gtk.Grid( + row_spacing=10, + column_spacing=10, + column_homogeneous=True + ) + self.add(grid) + + title_label = Gtk.Label() + title_label.set_markup( + "Unable to collect hardware information due to missing plugs." + ) + grid.attach(title_label, 0, 0, 4, 1) + + prompt_label = Gtk.Label(margin_top=20) + prompt_label.set_markup( + "Run the following commands in a terminal to connect the missing plugs:" + ) + grid.attach_next_to(prompt_label, title_label, Gtk.PositionType.BOTTOM, 3, 1) + + copy_button = Gtk.Button.new_from_icon_name("edit-copy-symbolic", Gtk.IconSize.MENU) + copy_button.set_margin_top(20) + copy_button.set_tooltip_text("Copy") + copy_button.connect("clicked", lambda x: self.button_copy()) + copy_button.set_halign(Gtk.Align.END) + grid.attach_next_to(copy_button, prompt_label, Gtk.PositionType.RIGHT, 1, 1) + + textview = Gtk.TextView( + editable=False, + monospace=True, + top_margin=5, + bottom_margin=5, + right_margin=10, + left_margin=10 + ) + textview.get_buffer().set_text(SNAP_COMMAND) + grid.attach_next_to(textview, prompt_label, Gtk.PositionType.BOTTOM, 4, 1) + + retry_button = Gtk.Button(label="Retry") + retry_button.connect("clicked", lambda x: self.button_retry(args)) + grid.attach(retry_button, 2, 3, 1, 1) + + ok_button = Gtk.Button(label="Ok") + ok_button.connect("clicked", lambda x: self.close()) + grid.attach_next_to(ok_button, retry_button, Gtk.PositionType.RIGHT, 1, 1) + + + def button_copy(self): + clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) + clipboard.set_text(SNAP_COMMAND, - 1) + + + def button_retry(self, args): + self.close() + create_window(args) + + +def summary(): + """Summarize discussion data based on labels""" + + if "GITHUB_ACCESS_TOKEN" not in os.environ: + print("Please set the environment variable GITHUB_ACCESS_TOKEN to a valid token") + print(f"Generate a token here: {TOKEN_URL}") + return + + print("Gathering most recent 100 reports...") + + PDB_RATINGS = [ + "pdb-borked", + "pdb-bronze", + "pdb-silver", + "pdb-gold", + "pdb-platinum", + "pdb-native", + ] + RATINGS = [ + "borked", + "bronze", + "silver", + "gold", + "platinum", + "", + ] + + access_token = os.environ["GITHUB_ACCESS_TOKEN"] + headers = { + "Authorization": f"token {access_token}", + "Content-Type": "application/json" + } + response = requests.post(GRAPHQL_URL, headers=headers, json={"query":""" + query { + repository(owner: "canonical", name: "steam-snap") { + discussions(first: 100, categoryId: "%s") { + nodes { + title + labels(first: 10) { + nodes { + name + } + } + } + } + } + } + """ % (DISCUSSION_CATEGORY_ID)}) + discussions = response.json()["data"]["repository"]["discussions"] + + total_count = 0 + counts = {rating: 0 for rating in RATINGS if rating} + comparisons = { + "worse": 0, + "expected": 0, + "better": 0 + } + + for discussion in discussions["nodes"]: + labels = discussion["labels"]["nodes"] + rating = len(RATINGS) - 1 + pdb_rating = len(PDB_RATINGS) - 1 + valid = False + + for label in labels: + if label["name"] in counts: + counts[label["name"]] += 1 + valid = True + total_count += 1 + if label["name"] in RATINGS: + rating = min(rating, RATINGS.index(label["name"])) + if label["name"] in PDB_RATINGS: + pdb_rating = min(pdb_rating, PDB_RATINGS.index(label["name"])) + + if valid: + if rating > pdb_rating: + comparisons["better"] += 1 + elif rating < pdb_rating: + comparisons["worse"] += 1 + else: + comparisons["expected"] += 1 + + print(f"Valid reports: {total_count}\n") + + print("Grade Counts") + print("------------") + print(f"{'Grade':<12} {'Count':<6} {'Percent'}") + for count in counts.items(): + perc = round(count[1] * 100 / total_count, 2) + print(f"{count[0].title():<12} {count[1]:<6} {perc:>5} %") + print() + + print("Comparisons to ProtonDB") + print("-----------------------") + print(f"{'Performance':<12} {'Count':<6} {'Percent':<8}") + for comparison in comparisons.items(): + perc = round(comparison[1] * 100 / total_count, 2) + print(f"{comparison[0].title():<12} {comparison[1]:<6} {perc:>5} %") + + +def default(): + return "ERROR" + + +def dict_to_string(d, n = 0): + """Convert a dict to yaml-like string.""" + + s = "" + for key in d: + line = f"{' ' * n}{key}:" + if type(d[key]) is dict: + line += f"\n{dict_to_string(d[key], n + 1)}" + else: + line += f"{' ' * (24 - len(line))}{d[key]}\n" + s += line + return s + + +def plugs_connected(): + + return os.environ.get("SNAP") != None\ + and not bool(os.system("snapctl is-connected system-observe"))\ + and not bool(os.system("snapctl is-connected hardware-observe")) + + +def gather_data(args): + """Gathers system information, returning a data object.""" + + global data + data = {} + # /etc/os-release + os_release = defaultdict(default) + os_release_lookup = [ + "/var/lib/snapd/hostfs/etc/os-release", # system-observe host os-release + "/etc/os-release", # usual system os-release + ] + + for path in os_release_lookup: + try: + with open(path, "r") as reader: + for line in reader: + line = line.strip() + if (not line): continue + + key, val = line.split("=", 1) + os_release[key] = val + break + except FileNotFoundError: + continue + + if args.verbose: + data["os_release"] = dict(os_release) + else: + data["os_release"] = { + "name": os_release["NAME"], + "version": os_release["VERSION"] + } + + # snap info + data["snap_info"] = { + "steam_revision": os.environ.get("SNAP_REVISION"), + "snapd_revision": os.popen("readlink /snap/snapd/current").read().strip() + } + + # lspci + lspci = defaultdict(default) + for line in os.popen("lspci | grep -E 'VGA|3D controller'").read().split("\n"): + line = line.strip() + if not line: continue + key, val = line.split(" ", 1) + val = val.strip()\ + .removeprefix("VGA compatible controller: ")\ + .removeprefix("3D controller: ") + lspci[key.strip()] = val + + data["lspci"] = dict(lspci) + + # glxinfo -B + glxinfo = defaultdict(default) + for line in os.popen("glxinfo -B").read().split("\n"): + line = line.strip() + if not line: continue + key, val = line.split(":", 1) + glxinfo[key.strip()] = val.strip() + + if args.verbose: + data["glxinfo"] = dict(glxinfo) + else: + data["glxinfo"] = { + "gpu": glxinfo["OpenGL renderer string"], + "gpu_version": glxinfo["OpenGL core profile version string"] + } + + # lscpu + lscpu = defaultdict(default) + for line in os.popen("lscpu").read().split("\n"): + line = line.strip() + if (not line): continue + key, val = line.split(":", 1) + lscpu[key.strip()] = val.strip() + + if args.verbose: + data["lscpu"] = dict(lscpu) + else: + data["lscpu"] = { + "model_name": lscpu["Model name"] + } + + # XDG_DESKTOP_SESSION & DESKTOP_SESSION + data["xdg_current_desktop"] = os.environ.get("XDG_CURRENT_DESKTOP") + data["desktop_session"] = os.environ.get("DESKTOP_SESSION") + + return data + + +def open_discussion(data): + """Open web-browser and fill in system information.""" + + url = DISCUSSION_URL + url += f"&title=Report: GAME_TITLE" + url += f"&body=```\n{dict_to_string(data)}```\n".replace("\n", "%0A") + url += BODY_SUFFIX + print("Opening new discussion in web-browser...") + webbrowser.open_new_tab(url) + + +def open_issue(data): + """Open web-browser and fill in system information.""" + + url = ISSUE_URL + url += f"&environment={dict_to_string(data)}".replace("\n", "%0A") + print("Opening new issue in web-browser...") + webbrowser.open_new_tab(url) + + +def create_window(args): + window: Gtk.Window = None + if plugs_connected() or args.force: + window = SteamReportWindow(args) + else: + window = NeedPlugsWindow(args) + window.connect("destroy", Gtk.main_quit) + window.show_all() + Gtk.main() + + +def main(): + # Parse commandline arguments + parser = argparse.ArgumentParser( + description=f"Visit {WIKI_URL} for more information." + ) + parser.add_argument( + "--no-submit", "-n", + help="Do not open web browser to a new discussion post.", + const=True, + action="store_const" + ) + parser.add_argument( + "--verbose", "-v", + help="Include entire output from data collection.", + const=True, + action="store_const" + ) + parser.add_argument( + "--force", "-f", + help="Skip environment checks and run anyway.", + const=True, + action="store_const" + ) + parser.add_argument( + "--summary", "-s", + help="Display summary of discussion posts. Requires a GitHub key defined in GITHUB_ACCESS_TOKEN.", + const=True, + action="store_const" + ) + parser.add_argument( + "--cli", "-c", + help="Use the classic CLI-based tool instead of the new GTK-based one.", + const=True, + action="store_const" + ) + args = parser.parse_args() + + if args.summary: + summary() + sys.exit() + + # Test environment + if not args.force and args.cli: + if not plugs_connected(): + sys.exit( + "This program relies on the system-observe and hardware-observe Snap plugs." + "\nOutside of the Snap, run the following commands to connect them:" + "\nsnap connect steam:system-observe" + "\nsnap connect steam:hardware-observe" + ) + + # Gather and submit data + if args.cli: + data = gather_data(args) + print(dict_to_string(data)) + if not args.no_submit: + open_discussion(data) + else: + create_window(args) + + +if __name__ == "__main__": + main() diff --git a/snap/local/src/nvidia32 b/snap/local/src/nvidia32 new file mode 100755 index 0000000000..6f8b55145a --- /dev/null +++ b/snap/local/src/nvidia32 @@ -0,0 +1,171 @@ +#!/usr/bin/python3 + +import gi +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk, Gdk +import os +import argparse + +TITLE = "NVIDIA 32-bit Not Found" +TEXT = """32-bit NVIDIA driver files were not found on your host system. +It is recommended that you install them for the best experience. + +See https://github.com/canonical/steam-snap/wiki/FAQ#32-bit-driver for more information.""" +COMMAND = """sudo dpkg --add-architecture i386 +sudo apt update +sudo apt install libnvidia-gl-{}:i386""" + +DO_NOT_SHOW_PATH = os.path.expandvars("$SNAP_USER_COMMON/.nvidia32") + +def do_not_show_file(do_not_show: bool): + """Ok button press. + + `do_not_show`: whether the Do not show again checkbox is checked or not + """ + if do_not_show: + open(DO_NOT_SHOW_PATH, "a").close() + elif os.path.exists(DO_NOT_SHOW_PATH): + os.remove(DO_NOT_SHOW_PATH) + + +def nvidia_version(): + """Try to find NVIDIA driver version from modinfo. + + Returns a tuple of the full NVIDIA version triplet and NVIDIA major version. + """ + modinfo = os.popen( + "modinfo /usr/lib/modules/$(uname -r)/updates/dkms/nvidia.ko* 2> /dev/null" + " | grep -m 1 '^version:'" + " | sed 's/version:\s*//'" + ).read().splitlines() + modinfo = modinfo or os.popen( + "modinfo /usr/lib/modules/$(uname -r)/kernel/nvidia*/nvidia.ko* 2> /dev/null" + " | grep -m 1 '^version:'" + " | sed 's/version:\s*//'" + ).read().splitlines() + + if not modinfo: + return () + nvidia_version = modinfo[0].strip() + nvidia_version_major = nvidia_version.split(".")[0] + return (nvidia_version, nvidia_version_major) + + +def nvidia_missing(): + """Returns whether NVIDIA 32 is missing or not. + """ + version = nvidia_version() + if not version: + return False + + print(f"Found NVIDIA version: {version[0]}") + needs_32 = os.path.exists(f"/var/lib/snapd/hostfs/usr/lib/x86_64-linux-gnu/libnvidia-glcore.so.{version[0]}")\ + and not os.path.exists(f"/var/lib/snapd/hostfs/usr/lib/i386-linux-gnu/libnvidia-glcore.so.{version[0]}") + print(f"Need NVIDIA 32-bit: {needs_32}") + return needs_32 + + +class NvidiaWindow(Gtk.Window): + def __init__(self): + super().__init__() + self.set_resizable(False) + self.set_border_width(10) + self.set_position(Gtk.WindowPosition.CENTER) + self.set_keep_above(True) + + header = Gtk.HeaderBar(title=TITLE) + self.set_titlebar(header) + + self.grid = Gtk.Grid( + row_spacing=10, + column_spacing=10 + ) + self.add(self.grid) + + # main text + self.label = Gtk.Label() + self.label.set_markup(TEXT) + self.grid.attach(self.label, 0, 0, 2, 1) + + # run prompt + self.run_label = Gtk.Label( + margin_top=20, + halign=Gtk.Align.START + ) + self.run_label.set_markup("To install, run:") + self.grid.attach_next_to(self.run_label, self.label, Gtk.PositionType.BOTTOM, 1, 1) + + # copy button + self.copy_btn = Gtk.Button.new_from_icon_name("edit-copy-symbolic", Gtk.IconSize.MENU) + self.copy_btn.set_margin_top(20) + self.copy_btn.set_tooltip_text("Copy") + self.copy_btn.connect("clicked", lambda x: self.button_copy()) + self.copy_btn.set_halign(Gtk.Align.END) + self.grid.attach_next_to(self.copy_btn, self.run_label, Gtk.PositionType.RIGHT, 1, 1) + + # command text + self.nvidia_version = nvidia_version() + self.textview = Gtk.TextView( + editable=False, + monospace=True, + top_margin=5, + bottom_margin=5, + right_margin=10, + left_margin=10 + ) + command_text = COMMAND.format("") + if self.nvidia_version: command_text = COMMAND.format(self.nvidia_version[1]) + self.textview.get_buffer().set_text(command_text) + self.grid.attach_next_to(self.textview, self.run_label, Gtk.PositionType.BOTTOM, 2, 1) + + # Do not show again button + self.checkbox = Gtk.CheckButton( + label="Do not show again", + halign=Gtk.Align.END, + tooltip_markup="This window can always be shown again by running " + "$SNAP/bin/nvidia32 --reset in the Steam Snap shell." + ) + self.grid.attach_next_to(self.checkbox, self.textview, Gtk.PositionType.BOTTOM, 1, 1) + + # Ok button + self.btn = Gtk.Button(label="Ok") + self.btn.connect("clicked", lambda x: self.button_ok(self.checkbox.get_active())) + self.grid.attach_next_to(self.btn, self.checkbox, Gtk.PositionType.RIGHT, 1, 1) + + + def button_ok(self, toggled: bool): + do_not_show_file(toggled) + self.close() + + + def button_copy(self): + clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) + clipboard.set_text(COMMAND.format(self.nvidia_version[1]), -1) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--reset", + help="Show the dialog again if you selected 'Do not show again'", + action="store_true" + ) + parser.add_argument( + "--show", + help="Show the dialog regardless of conditions met", + action="store_true" + ) + args = parser.parse_args() + + if args.reset: + do_not_show_file(False) + + if args.show or (nvidia_missing() and not os.path.exists(DO_NOT_SHOW_PATH)): + win = NvidiaWindow() + win.connect("destroy", Gtk.main_quit) + win.show_all() + Gtk.main() + + +if __name__ == "__main__": + main() diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml new file mode 100644 index 0000000000..48bf94d7ff --- /dev/null +++ b/snap/snapcraft.yaml @@ -0,0 +1,490 @@ +name: heroic +summary: An Open Source Launcher for GOG Amazon and Epic Games +description: | + Heroic is an Open Source Games Launcher. Right now it supports launching games from the Epic Games + Store using Legendary Amazon Games using Nile and GOG Games using our custom implementations Nile and gogdl. +adopt-info: heroic +icon: src/frontend/assets/heroic-icon.svg +grade: stable +confinement: strict +architectures: + - build-on: amd64 +base: core22 +compression: lzo +assumes: + - snapd2.62 + +lint: + # Snapcraft's `ldd` lint can't handle 32-bit things, + # So just make it quiet and also make builds a surprising amount faster + ignore: + - library: + - lib/i386-linux-gnu/** + - usr/lib/i386-linux-gnu/** + - lib32/** + - usr/lib32/** + +package-repositories: + - type: apt + components: [main] + suites: [jammy] + architectures: [amd64, i386] + key-id: 9FD3B784BC1C6FC31A8A0A1C1655A0AB68576280 + url: https://deb.nodesource.com/node_20.x + +layout: + /usr/share/zenity: + bind: $SNAP/usr/share/zenity + # https://discourse.ubuntu.com/t/the-graphics-core20-snap-interface/23000 + /usr/share/drirc.d: + bind: $SNAP/graphics/usr/share/drirc.d + /usr/share/glvnd/egl_vendor.d: + bind: $SNAP/graphics/usr/share/glvnd/egl_vendor.d + /usr/lib/x86_64-linux-gnu/alsa-lib: + bind: $SNAP/usr/lib/x86_64-linux-gnu/alsa-lib + /usr/share/alsa: + bind: $SNAP/usr/share/alsa + /usr/share/X11/xkb: + bind: $SNAP/usr/share/X11/xkb + /etc/ld.so.cache: + bind-file: $SNAP_DATA/etc/ld.so.cache + /etc/fonts: + bind: $SNAP/etc/fonts + +plugs: + gaming-mesa: + interface: content + target: $SNAP/graphics + default-provider: gaming-graphics-core22 + gtk-3-themes: + interface: content + target: $SNAP/share/themes + default-provider: gtk-common-themes + icon-themes: + interface: content + target: $SNAP/share/icons + default-provider: gtk-common-themes + sound-themes: + interface: content + target: $SNAP/share/sounds + default-provider: gtk-common-themes + dot-local-share-steam: + interface: personal-files + write: + - $HOME/.local/share/Steam + - $HOME/Steam + - $HOME/snap/steam/common/.steam + dot-local-share-applications: + interface: personal-files + write: + - $HOME/.local/share/applications + dot-local-share-icons: + interface: personal-files + write: + - $HOME/.local/share/icons + desktop: + mount-host-font-cache: false + shmem: + interface: shared-memory + private: true + +hooks: + configure: + plugs: + - opengl + +parts: + launcher: + after: [heroic] + plugin: nil + source: $CRAFT_PROJECT_DIR/snap/local/src + override-build: | + mkdir -p $CRAFT_PART_INSTALL/usr/bin + cp * $CRAFT_PART_INSTALL/usr/bin/ + stage-packages: + - python3-gi + - gir1.2-gtk-3.0 + stage: + - bin/* + - usr/lib/python3/dist-packages/* + - usr/share/mime/* + - usr/share/icons/* + - usr/lib/**/gtk-3.0* + - etc/gtk-3.0* + - usr/share/*/gir1.2-gtk-3.0* + - usr/**/libfontconfig* + - usr/**/cairo-1* + - usr/**/libatspi* + - usr/**/libavahi-client* + - usr/**/libavahi-common* + - usr/**/libcairo-gobject* + - usr/**/libcairo* + - usr/**/libcolord* + - usr/**/libcups* + - usr/**/libdatrie* + - usr/**/libdconf* + - usr/**/libdeflate* + - usr/**/libepoxy* + - usr/**/libfribidi* + - usr/**/*girepository* + - usr/**/libgraphite2* + - usr/**/libgtk-3* + - usr/**/libharfbuzz* + - usr/**/libjbig* + - usr/**/libjpeg* + - usr/**/liblcms2* + - usr/**/libpango-1* + - usr/**/libpangocairo-1* + - usr/**/libpangoft2-1* + - usr/**/libpangoxft-1* + - usr/**/libpixman-1* + - usr/**/libthai* + - usr/**/libtiff* + - usr/**/libwayland-cursor* + - usr/**/libwebp* + - usr/**/libxcb-render* + - usr/**/libxkbcommon* + prime: + - -etc/dconf + - -etc/gtk* + - -etc/init* + - -etc/ld* + - -etc/vulkan + - -etc/X11 + - -etc/xdg + + # alsa-mixin: + # plugin: dump + # source: https://github.com/diddlesnaps/snapcraft-alsa.git + # source-subdir: snapcraft-assets + # source-depth: 1 + # build-packages: + # - libasound2-dev + # stage-packages: + # - libasound2 + # - libasound2-plugins + # - yad + # stage: + # # restrict to only audio-related files - you need to ensure + # # that gtk3 is staged for yad to work correctly, to prompt + # # users to connect the alsa plug or proceed with pulseaudio. + # # + # # This helps prevent symbol conflicts in situations where + # # you're using a non-default library, such as those that the + # # gnome-3-34 extension for core18 provides. + # - etc/asound.conf + # - snap/command-chain/alsa-launch + # - usr/bin/yad* + # - usr/lib/*/alsa-lib + # - usr/lib/*/libasound* + # - usr/lib/*/libasyncns* + # - usr/lib/*/libdnsfile* + # - usr/lib/*/libFLAC* + # - usr/lib/*/libjack* + # - usr/lib/*/libpulse* + # - usr/lib/*/libsamplerate* + # - usr/lib/*/libsndfile* + # - usr/lib/*/libspeex* + # - usr/lib/*/libvorbis* + # - usr/lib/*/pulseaudio + # - usr/share/alsa + + ninja: + after: [heroic] + plugin: nil + source: https://github.com/ninja-build/ninja.git + source-tag: "v1.12.1" + override-build: | + rm -rf build + rm -f ninja + rm -f ninja_bootstrap + sed -i 's_^#!/usr/bin/env python$_#!/usr/bin/env python3_g' configure.py + ./configure.py --bootstrap + mv ninja ninja_bootstrap + rm -rf build + ./ninja_bootstrap + rm -f ninja_bootstrap + mkdir -p $CRAFT_PART_INSTALL/usr/bin + mv ninja $CRAFT_PART_INSTALL/usr/bin/ + build-packages: + - python3 + prime: + - -* + + meson-deps: + after: [ninja] + plugin: nil + source: https://github.com/mesonbuild/meson.git + source-tag: "1.4.1" + source-depth: 1 + override-build: | + python3 -m pip install . + mkdir -p $CRAFT_PART_INSTALL/usr/lib/python3/dist-packages + rm -rf $CRAFT_PART_INSTALL/usr/lib/python3/dist-packages/meson* + python3 -m pip install --target=$CRAFT_PART_INSTALL/usr . + mv $CRAFT_PART_INSTALL/usr/meson* $CRAFT_PART_INSTALL/usr/lib/python3/dist-packages/ + sed -i "s%^#!/usr/bin/python3$%#!/usr/bin/env python3%g" /usr/local/bin/meson + sed -i "s%^#!/usr/bin/python3$%#!/usr/bin/env python3%g" $CRAFT_PART_INSTALL/usr/bin/meson + build-packages: + - python3-pip + prime: + - -* + + mangohud: + after: [meson-deps] + source: https://github.com/flightlessmango/MangoHud.git + source-tag: "v0.7.2" + source-depth: 1 + plugin: meson + organize: + snap/heroic/current/usr: usr + build-environment: + - PKG_CONFIG_PATH: /usr/lib/i386-linux-gnu/pkgconfig:/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig + meson-parameters: + - --prefix=/usr + - --libdir=lib/i386-linux-gnu + - -Dappend_libdir_mangohud=false + build-packages: + - gcc + - gcc-multilib + - g++ + - g++-multilib + - glslang-dev + - glslang-tools + - libdbus-1-dev + - libgl-dev + - libglvnd-dev + - libx11-dev + - libxnvctrl-dev + - mesa-common-dev + - python3-mako + - libwayland-dev + - libxkbcommon-dev + # Fixes the $LIB being escaped for some reason + override-build: | + craftctl default + sed -i 's/\/usr\/\\\$LIB/\$SNAP\/usr\/lib\/x86_64-linux-gnu/' $CRAFT_PART_INSTALL/usr/bin/mangohud + + mangohud64: + after: [meson-deps, mangohud] + source: https://github.com/flightlessmango/MangoHud.git + source-tag: "v0.7.2" + source-depth: 1 + plugin: meson + organize: + snap/heroic/current/usr: usr + meson-parameters: + - --prefix=/usr + - --libdir=lib/x86_64-linux-gnu + - -Dappend_libdir_mangohud=false + stage: + - -usr/bin/mangohud + - -usr/share/vulkan/implicit_layer.d/MangoHud.json + - -usr/share/vulkan/implicit_layer.d/MangoHud.x86_64.json + - -usr/share/vulkan/implicit_layer.d/libMangoApp.json + - -usr/share/doc/mangohud/MangoHud.conf.example + - -usr/share/man/man1/mangohud.1 + + gamemode: + after: [meson-deps] + source: https://github.com/FeralInteractive/gamemode.git + source-tag: "1.8.2" + source-depth: 1 + plugin: meson + organize: + snap/heroic/current/usr: usr + meson-parameters: + - --prefix=/usr + build-packages: + - libsystemd-dev + - pkg-config + - libdbus-1-dev + prime: + - usr/bin/gamemoderun + - usr/lib/*/libgamemode*.so.* + + heroic: + source: https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher.git + source-tag: 'v2.15.2' + source-depth: 1 + plugin: dump + build-packages: + - dpkg-dev + - nodejs + prime: + - -chrome-* + - -chrome_crashpad_handler + - -usr/share/doc + - -usr/share/man + - -usr/share/bug + - -usr/share/gdb + - -usr/share/emacs* + - -usr/share/lintian + - -usr/share/drirc.d + - -usr/share/vulkan + - -usr/share/Xsession.d + - -usr/lib/*/dri + - -usr/lib/*/vdpau + - -usr/lib/*/libvkd3d* + - -usr/lib/*/libvulkan* + - -usr/lib/*/libVk* + - -usr/lib/*/libLLVM* + override-build: | + set -eux + patch -p1 < $CRAFT_PROJECT_DIR/dist.patch + if [[ -n "${http_proxy:-}" ]]; then + export HTTP_PROXY="${http_proxy:-}" + export HTTPS_PROXY="${http_proxy:-}" + export ELECTRON_GET_USE_PROXY=1 + export GLOBAL_AGENT_HTTP_PROXY="${http_proxy:-}" + export GLOBAL_AGENT_HTTPS_PROXY="${http_proxy:-}" + fi + npm config set -g registry https://registry.npmjs.org/ + npm config set -g proxy "${http_proxy:-}" + npm config set -g https-proxy "${http_proxy:-}" + npm install -g pnpm + pnpm config set -g registry https://github.com/ + pnpm config set -g proxy "${http_proxy:-}" + pnpm config set -g https-proxy "${http_proxy:-}" + pnpm config set -g registry https://registry.npmjs.org/ + pnpm config set -g proxy "${http_proxy:-}" + pnpm config set -g https-proxy "${http_proxy:-}" + pnpm install + pnpm run download-helper-binaries + pnpm dist:linux --dir + cp -a dist/linux-unpacked/* $CRAFT_PART_INSTALL/ + + debs: + plugin: nil + stage-packages: + - libappindicator3-1 + - libgtk-3-0 + - libpangoxft-1.0-0 + - libsasl2-2 + - libasound2 + - libnspr4 + - libnss3 + - libcurl4 + - libxcb-dri3-0:amd64 + - libxcb-dri3-0:i386 + - libpci3 + - libvulkan1:i386 + - libvulkan1:amd64 + - libxml2:i386 + - libxml2:amd64 + - libicu70:i386 + - libicu70:amd64 + - zlib1g:i386 + - zlib1g:amd64 + - xdg-utils + - xdg-user-dirs + - xz-utils + - fontconfig-config + - fontconfig:i386 + - fontconfig:amd64 + - pciutils + - lsof + - usbutils # Allows finding controllers etc + - psmisc + - libfuse2:amd64 + - libfuse2:i386 + - libxss1:amd64 + - libxss1:i386 + - x11-xserver-utils + prime: + - -etc/dconf + - -etc/gtk* + - -etc/init* + - -etc/ld* + - -etc/vulkan + - -etc/X11 + - -etc/xdg + - -usr/bin/cpp* + - -usr/bin/X11 + - -usr/bin/browse + - -usr/bin/x86* + - -usr/bin/iceauth + - -usr/include + - -usr/lib/gcc + - -usr/lib/systemd + - -usr/lib/X11 + - -usr/sbin + - -usr/share/doc* + - -usr/share/man + - -usr/share/bug + - -usr/share/apport + - -usr/share/gcc + - -usr/share/lintian + - -usr/share/libthai + - -usr/share/pkgconfig + - -usr/share/themes + - -usr/libexec + + + conditioning: + after: [heroic, debs] + plugin: nil + build-packages: + - shared-mime-info + - gtk-update-icon-cache + override-prime: | + set -eux + craftctl default + for dir in usr/share/icons/*; do + if [ -f "$dir/index.theme" ]; then + gtk-update-icon-cache --force "$dir" + fi + done + + cleanup: + after: [heroic, conditioning] + plugin: nil + build-snaps: + - gaming-graphics-core22/kisak-fresh/candidate + override-prime: | + set -eux + cd /snap/gaming-graphics-core22/current/usr/lib + find . -type f,l -exec rm -rf $CRAFT_PRIME/usr/lib/{} \; + cd /snap/gaming-graphics-core22/current/usr/share + find . -type f,l -exec rm -rf $CRAFT_PRIME/usr/share/{} \; + for snap in "core22"; do + cd "/snap/$snap/current" && find . -type f,l -exec rm -rf "$CRAFT_PRIME/{}" \; + done + +apps: + heroic: + command-chain: [bin/desktop-launch] + command: heroic --no-sandbox + environment: + HOME: $SNAP_USER_COMMON + #LIBGL_DEBUG: verbose + TMPDIR: $XDG_RUNTIME_DIR + ALWAYS_USE_PULSEAUDIO: 1 + PYTHONPATH: $SNAP/usr/lib/python3/dist-packages + GI_TYPELIB_PATH: $SNAP/usr/lib/x86_64-linux-gnu/girepository-1.0 + plugs: + - shmem + - desktop + - desktop-legacy + - wayland + - home + - x11 + - gsettings + - hardware-observe + - mount-observe + - system-observe + - joystick + - network + - network-bind + - opengl + - audio-playback + - audio-record + - screen-inhibit-control + - process-control + - bluez + - network-control + - fuse-support + - steam-support + - removable-media + - upower-observe + - uinput From d88524516e66eed1bd834eb081adf703b95cae71 Mon Sep 17 00:00:00 2001 From: Soumyadeep Ghosh Date: Sun, 3 Nov 2024 20:01:39 +0530 Subject: [PATCH 3/5] backend: fix lint --- snap/gui/heroic.desktop | 3 +-- snap/snapcraft.yaml | 21 ++++++++++---------- src/backend/utils/systeminfo/osInfo/linux.ts | 14 ++++++++----- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/snap/gui/heroic.desktop b/snap/gui/heroic.desktop index 342dbe94ee..c874ce97f1 100644 --- a/snap/gui/heroic.desktop +++ b/snap/gui/heroic.desktop @@ -1,6 +1,5 @@ [Desktop Entry] -#Name=Heroic Games Launcher -Name=Heroic Snap +Name=Heroic Games Launcher Exec=heroic %u Terminal=false Type=Application diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 48bf94d7ff..60a697acbf 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -30,7 +30,7 @@ package-repositories: suites: [jammy] architectures: [amd64, i386] key-id: 9FD3B784BC1C6FC31A8A0A1C1655A0AB68576280 - url: https://deb.nodesource.com/node_20.x + url: https://deb.nodesource.com/node_20.x layout: /usr/share/zenity: @@ -97,7 +97,7 @@ parts: launcher: after: [heroic] plugin: nil - source: $CRAFT_PROJECT_DIR/snap/local/src + source: $CRAFT_PROJECT_DIR/snap/local/src override-build: | mkdir -p $CRAFT_PART_INSTALL/usr/bin cp * $CRAFT_PART_INSTALL/usr/bin/ @@ -193,7 +193,7 @@ parts: after: [heroic] plugin: nil source: https://github.com/ninja-build/ninja.git - source-tag: "v1.12.1" + source-tag: 'v1.12.1' override-build: | rm -rf build rm -f ninja @@ -215,7 +215,7 @@ parts: after: [ninja] plugin: nil source: https://github.com/mesonbuild/meson.git - source-tag: "1.4.1" + source-tag: '1.4.1' source-depth: 1 override-build: | python3 -m pip install . @@ -233,7 +233,7 @@ parts: mangohud: after: [meson-deps] source: https://github.com/flightlessmango/MangoHud.git - source-tag: "v0.7.2" + source-tag: 'v0.7.2' source-depth: 1 plugin: meson organize: @@ -262,13 +262,13 @@ parts: - libxkbcommon-dev # Fixes the $LIB being escaped for some reason override-build: | - craftctl default - sed -i 's/\/usr\/\\\$LIB/\$SNAP\/usr\/lib\/x86_64-linux-gnu/' $CRAFT_PART_INSTALL/usr/bin/mangohud + craftctl default + sed -i 's/\/usr\/\\\$LIB/\$SNAP\/usr\/lib\/x86_64-linux-gnu/' $CRAFT_PART_INSTALL/usr/bin/mangohud mangohud64: after: [meson-deps, mangohud] source: https://github.com/flightlessmango/MangoHud.git - source-tag: "v0.7.2" + source-tag: 'v0.7.2' source-depth: 1 plugin: meson organize: @@ -283,12 +283,12 @@ parts: - -usr/share/vulkan/implicit_layer.d/MangoHud.x86_64.json - -usr/share/vulkan/implicit_layer.d/libMangoApp.json - -usr/share/doc/mangohud/MangoHud.conf.example - - -usr/share/man/man1/mangohud.1 + - -usr/share/man/man1/mangohud.1 gamemode: after: [meson-deps] source: https://github.com/FeralInteractive/gamemode.git - source-tag: "1.8.2" + source-tag: '1.8.2' source-depth: 1 plugin: meson organize: @@ -420,7 +420,6 @@ parts: - -usr/share/themes - -usr/libexec - conditioning: after: [heroic, debs] plugin: nil diff --git a/src/backend/utils/systeminfo/osInfo/linux.ts b/src/backend/utils/systeminfo/osInfo/linux.ts index deb8e07c15..5bbb884ffc 100644 --- a/src/backend/utils/systeminfo/osInfo/linux.ts +++ b/src/backend/utils/systeminfo/osInfo/linux.ts @@ -14,7 +14,11 @@ function stripQuotes(stringMaybeWithQuotes: string): string { async function osInfo_linux(): Promise<{ name: string; version?: string }> { let os_release_path: string | null = null - for (const potPath of ['/run/host/os-release', '/var/lib/snapd/hostfs/etc/os-release', '/etc/os-release']) { + for (const potPath of [ + '/run/host/os-release', + '/var/lib/snapd/hostfs/etc/os-release', + '/etc/os-release' + ]) { try { await stat(potPath) os_release_path = potPath @@ -41,13 +45,13 @@ async function osInfo_linux(): Promise<{ name: string; version?: string }> { const osName = nameMatch ? stripQuotes(nameMatch) : prettyNameMatch - ? stripQuotes(prettyNameMatch) - : 'Linux' + ? stripQuotes(prettyNameMatch) + : 'Linux' const osVersion = versionMatch ? stripQuotes(versionMatch) : versionId && versionCodename - ? `${versionId} ${versionCodename}` - : undefined + ? `${versionId} ${versionCodename}` + : undefined if (osVersion) return { name: osName, version: osVersion } return { name: osName } } From ea272ff3f46398577cc6cc720501ab89f2060f2d Mon Sep 17 00:00:00 2001 From: Soumyadeep Ghosh Date: Mon, 16 Dec 2024 19:23:55 +0530 Subject: [PATCH 4/5] misc: fix lint --- src/backend/utils/systeminfo/osInfo/linux.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backend/utils/systeminfo/osInfo/linux.ts b/src/backend/utils/systeminfo/osInfo/linux.ts index 5bbb884ffc..231e4f3556 100644 --- a/src/backend/utils/systeminfo/osInfo/linux.ts +++ b/src/backend/utils/systeminfo/osInfo/linux.ts @@ -45,13 +45,13 @@ async function osInfo_linux(): Promise<{ name: string; version?: string }> { const osName = nameMatch ? stripQuotes(nameMatch) : prettyNameMatch - ? stripQuotes(prettyNameMatch) - : 'Linux' + ? stripQuotes(prettyNameMatch) + : 'Linux' const osVersion = versionMatch ? stripQuotes(versionMatch) : versionId && versionCodename - ? `${versionId} ${versionCodename}` - : undefined + ? `${versionId} ${versionCodename}` + : undefined if (osVersion) return { name: osName, version: osVersion } return { name: osName } } From ea9837f8d4cdc4c8cf2d2e814cdafe3c4d55a6cb Mon Sep 17 00:00:00 2001 From: Soumyadeep Ghosh Date: Sat, 25 Jan 2025 20:08:38 +0530 Subject: [PATCH 5/5] snap: remove unneeded files and codes --- snap/local/src/heroicreport | 472 ------------------------------------ snap/snapcraft.yaml | 37 --- 2 files changed, 509 deletions(-) delete mode 100755 snap/local/src/heroicreport diff --git a/snap/local/src/heroicreport b/snap/local/src/heroicreport deleted file mode 100755 index ae865920b4..0000000000 --- a/snap/local/src/heroicreport +++ /dev/null @@ -1,472 +0,0 @@ -#!/usr/bin/python3 - -import os -import sys -import webbrowser -import argparse -from collections import defaultdict -import requests -import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk - -ISSUE_URL = "https://github.com/canonical/steam-snap/issues/new?assignees=&labels=bug&projects=&template=bug_report.yml" -DISCUSSION_URL = "https://github.com/canonical/steam-snap/discussions/new?category=game-reports" -WIKI_URL = "https://github.com/canonical/steam-snap/wiki/Troubleshooting#submitting-a-steam-report" -GRAPHQL_URL = "https://api.github.com/graphql" -TOKEN_URL = "https://github.com/settings/tokens/new" - -DISCUSSION_CATEGORY_ID = "DIC_kwDOC5Gtms4CR-_9" - -BODY_SUFFIX = "" -SNAP_COMMAND = """snap connect steam:hardware-observe -snap connect steam:system-observe""" - -data = {} - -class SteamReportWindow(Gtk.Window): - def __init__(self, args): - super().__init__() - self.set_resizable(True) - self.set_border_width(10) - self.set_position(Gtk.WindowPosition.CENTER) - self.set_default_size(-1, 450) - - grid = Gtk.Grid( - row_spacing=10, - column_spacing=10, - column_homogeneous=True, - ) - self.add(grid) - - label = Gtk.Label(halign=Gtk.Align.START) - label.set_markup( - "Below is the hardware information collected from your system." - f"\nSee {WIKI_URL} for more information." - ) - grid.attach(label, 0, 0, 5, 1) - - copy_button = Gtk.Button.new_from_icon_name("edit-copy-symbolic", Gtk.IconSize.MENU) - copy_button.set_tooltip_text("Copy") - copy_button.connect("clicked", lambda x: self.button_copy()) - copy_button.set_halign(Gtk.Align.END) - grid.attach_next_to(copy_button, label, Gtk.PositionType.RIGHT, 1, 1) - - scrolled_window = Gtk.ScrolledWindow() - scrolled_window.set_vexpand(True) - textview = Gtk.TextView( - editable=False, - monospace=True, - top_margin=5, - bottom_margin=5, - right_margin=10, - left_margin=10 - ) - textview.get_buffer().set_text(dict_to_string(gather_data(args)).strip()) - scrolled_window.add(textview) - grid.attach(scrolled_window, 0, 2, 6, 1) - - issue_button = Gtk.Button( - label="Open New Issue", - tooltip_text="Opens a new Steam Snap issue to report a bug or problem" - ) - issue_button.connect("clicked", lambda x: self.button_issue()) - grid.attach_next_to(issue_button, scrolled_window, Gtk.PositionType.BOTTOM, 2, 1) - - report_button = Gtk.Button( - label="Open New Game Report", - tooltip_text="Opens a new Steam Snap discussion to report the functionality of a specific game" - ) - report_button.connect("clicked", lambda x: self.button_report()) - grid.attach_next_to(report_button, issue_button, Gtk.PositionType.RIGHT, 2, 1) - - ok_button = Gtk.Button(label="Ok") - ok_button.connect("clicked", lambda x: self.close()) - grid.attach_next_to(ok_button, report_button, Gtk.PositionType.RIGHT, 2, 1) - - - def button_copy(self): - clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) - clipboard.set_text(dict_to_string(data), -1) - - - def button_issue(self): - open_issue(data) - - - def button_report(self): - open_discussion(data) - - -class NeedPlugsWindow(Gtk.Window): - def __init__(self, args): - super().__init__() - self.set_resizable(False) - self.set_border_width(10) - self.set_position(Gtk.WindowPosition.CENTER) - - grid = Gtk.Grid( - row_spacing=10, - column_spacing=10, - column_homogeneous=True - ) - self.add(grid) - - title_label = Gtk.Label() - title_label.set_markup( - "Unable to collect hardware information due to missing plugs." - ) - grid.attach(title_label, 0, 0, 4, 1) - - prompt_label = Gtk.Label(margin_top=20) - prompt_label.set_markup( - "Run the following commands in a terminal to connect the missing plugs:" - ) - grid.attach_next_to(prompt_label, title_label, Gtk.PositionType.BOTTOM, 3, 1) - - copy_button = Gtk.Button.new_from_icon_name("edit-copy-symbolic", Gtk.IconSize.MENU) - copy_button.set_margin_top(20) - copy_button.set_tooltip_text("Copy") - copy_button.connect("clicked", lambda x: self.button_copy()) - copy_button.set_halign(Gtk.Align.END) - grid.attach_next_to(copy_button, prompt_label, Gtk.PositionType.RIGHT, 1, 1) - - textview = Gtk.TextView( - editable=False, - monospace=True, - top_margin=5, - bottom_margin=5, - right_margin=10, - left_margin=10 - ) - textview.get_buffer().set_text(SNAP_COMMAND) - grid.attach_next_to(textview, prompt_label, Gtk.PositionType.BOTTOM, 4, 1) - - retry_button = Gtk.Button(label="Retry") - retry_button.connect("clicked", lambda x: self.button_retry(args)) - grid.attach(retry_button, 2, 3, 1, 1) - - ok_button = Gtk.Button(label="Ok") - ok_button.connect("clicked", lambda x: self.close()) - grid.attach_next_to(ok_button, retry_button, Gtk.PositionType.RIGHT, 1, 1) - - - def button_copy(self): - clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) - clipboard.set_text(SNAP_COMMAND, - 1) - - - def button_retry(self, args): - self.close() - create_window(args) - - -def summary(): - """Summarize discussion data based on labels""" - - if "GITHUB_ACCESS_TOKEN" not in os.environ: - print("Please set the environment variable GITHUB_ACCESS_TOKEN to a valid token") - print(f"Generate a token here: {TOKEN_URL}") - return - - print("Gathering most recent 100 reports...") - - PDB_RATINGS = [ - "pdb-borked", - "pdb-bronze", - "pdb-silver", - "pdb-gold", - "pdb-platinum", - "pdb-native", - ] - RATINGS = [ - "borked", - "bronze", - "silver", - "gold", - "platinum", - "", - ] - - access_token = os.environ["GITHUB_ACCESS_TOKEN"] - headers = { - "Authorization": f"token {access_token}", - "Content-Type": "application/json" - } - response = requests.post(GRAPHQL_URL, headers=headers, json={"query":""" - query { - repository(owner: "canonical", name: "steam-snap") { - discussions(first: 100, categoryId: "%s") { - nodes { - title - labels(first: 10) { - nodes { - name - } - } - } - } - } - } - """ % (DISCUSSION_CATEGORY_ID)}) - discussions = response.json()["data"]["repository"]["discussions"] - - total_count = 0 - counts = {rating: 0 for rating in RATINGS if rating} - comparisons = { - "worse": 0, - "expected": 0, - "better": 0 - } - - for discussion in discussions["nodes"]: - labels = discussion["labels"]["nodes"] - rating = len(RATINGS) - 1 - pdb_rating = len(PDB_RATINGS) - 1 - valid = False - - for label in labels: - if label["name"] in counts: - counts[label["name"]] += 1 - valid = True - total_count += 1 - if label["name"] in RATINGS: - rating = min(rating, RATINGS.index(label["name"])) - if label["name"] in PDB_RATINGS: - pdb_rating = min(pdb_rating, PDB_RATINGS.index(label["name"])) - - if valid: - if rating > pdb_rating: - comparisons["better"] += 1 - elif rating < pdb_rating: - comparisons["worse"] += 1 - else: - comparisons["expected"] += 1 - - print(f"Valid reports: {total_count}\n") - - print("Grade Counts") - print("------------") - print(f"{'Grade':<12} {'Count':<6} {'Percent'}") - for count in counts.items(): - perc = round(count[1] * 100 / total_count, 2) - print(f"{count[0].title():<12} {count[1]:<6} {perc:>5} %") - print() - - print("Comparisons to ProtonDB") - print("-----------------------") - print(f"{'Performance':<12} {'Count':<6} {'Percent':<8}") - for comparison in comparisons.items(): - perc = round(comparison[1] * 100 / total_count, 2) - print(f"{comparison[0].title():<12} {comparison[1]:<6} {perc:>5} %") - - -def default(): - return "ERROR" - - -def dict_to_string(d, n = 0): - """Convert a dict to yaml-like string.""" - - s = "" - for key in d: - line = f"{' ' * n}{key}:" - if type(d[key]) is dict: - line += f"\n{dict_to_string(d[key], n + 1)}" - else: - line += f"{' ' * (24 - len(line))}{d[key]}\n" - s += line - return s - - -def plugs_connected(): - - return os.environ.get("SNAP") != None\ - and not bool(os.system("snapctl is-connected system-observe"))\ - and not bool(os.system("snapctl is-connected hardware-observe")) - - -def gather_data(args): - """Gathers system information, returning a data object.""" - - global data - data = {} - # /etc/os-release - os_release = defaultdict(default) - os_release_lookup = [ - "/var/lib/snapd/hostfs/etc/os-release", # system-observe host os-release - "/etc/os-release", # usual system os-release - ] - - for path in os_release_lookup: - try: - with open(path, "r") as reader: - for line in reader: - line = line.strip() - if (not line): continue - - key, val = line.split("=", 1) - os_release[key] = val - break - except FileNotFoundError: - continue - - if args.verbose: - data["os_release"] = dict(os_release) - else: - data["os_release"] = { - "name": os_release["NAME"], - "version": os_release["VERSION"] - } - - # snap info - data["snap_info"] = { - "steam_revision": os.environ.get("SNAP_REVISION"), - "snapd_revision": os.popen("readlink /snap/snapd/current").read().strip() - } - - # lspci - lspci = defaultdict(default) - for line in os.popen("lspci | grep -E 'VGA|3D controller'").read().split("\n"): - line = line.strip() - if not line: continue - key, val = line.split(" ", 1) - val = val.strip()\ - .removeprefix("VGA compatible controller: ")\ - .removeprefix("3D controller: ") - lspci[key.strip()] = val - - data["lspci"] = dict(lspci) - - # glxinfo -B - glxinfo = defaultdict(default) - for line in os.popen("glxinfo -B").read().split("\n"): - line = line.strip() - if not line: continue - key, val = line.split(":", 1) - glxinfo[key.strip()] = val.strip() - - if args.verbose: - data["glxinfo"] = dict(glxinfo) - else: - data["glxinfo"] = { - "gpu": glxinfo["OpenGL renderer string"], - "gpu_version": glxinfo["OpenGL core profile version string"] - } - - # lscpu - lscpu = defaultdict(default) - for line in os.popen("lscpu").read().split("\n"): - line = line.strip() - if (not line): continue - key, val = line.split(":", 1) - lscpu[key.strip()] = val.strip() - - if args.verbose: - data["lscpu"] = dict(lscpu) - else: - data["lscpu"] = { - "model_name": lscpu["Model name"] - } - - # XDG_DESKTOP_SESSION & DESKTOP_SESSION - data["xdg_current_desktop"] = os.environ.get("XDG_CURRENT_DESKTOP") - data["desktop_session"] = os.environ.get("DESKTOP_SESSION") - - return data - - -def open_discussion(data): - """Open web-browser and fill in system information.""" - - url = DISCUSSION_URL - url += f"&title=Report: GAME_TITLE" - url += f"&body=```\n{dict_to_string(data)}```\n".replace("\n", "%0A") - url += BODY_SUFFIX - print("Opening new discussion in web-browser...") - webbrowser.open_new_tab(url) - - -def open_issue(data): - """Open web-browser and fill in system information.""" - - url = ISSUE_URL - url += f"&environment={dict_to_string(data)}".replace("\n", "%0A") - print("Opening new issue in web-browser...") - webbrowser.open_new_tab(url) - - -def create_window(args): - window: Gtk.Window = None - if plugs_connected() or args.force: - window = SteamReportWindow(args) - else: - window = NeedPlugsWindow(args) - window.connect("destroy", Gtk.main_quit) - window.show_all() - Gtk.main() - - -def main(): - # Parse commandline arguments - parser = argparse.ArgumentParser( - description=f"Visit {WIKI_URL} for more information." - ) - parser.add_argument( - "--no-submit", "-n", - help="Do not open web browser to a new discussion post.", - const=True, - action="store_const" - ) - parser.add_argument( - "--verbose", "-v", - help="Include entire output from data collection.", - const=True, - action="store_const" - ) - parser.add_argument( - "--force", "-f", - help="Skip environment checks and run anyway.", - const=True, - action="store_const" - ) - parser.add_argument( - "--summary", "-s", - help="Display summary of discussion posts. Requires a GitHub key defined in GITHUB_ACCESS_TOKEN.", - const=True, - action="store_const" - ) - parser.add_argument( - "--cli", "-c", - help="Use the classic CLI-based tool instead of the new GTK-based one.", - const=True, - action="store_const" - ) - args = parser.parse_args() - - if args.summary: - summary() - sys.exit() - - # Test environment - if not args.force and args.cli: - if not plugs_connected(): - sys.exit( - "This program relies on the system-observe and hardware-observe Snap plugs." - "\nOutside of the Snap, run the following commands to connect them:" - "\nsnap connect steam:system-observe" - "\nsnap connect steam:hardware-observe" - ) - - # Gather and submit data - if args.cli: - data = gather_data(args) - print(dict_to_string(data)) - if not args.no_submit: - open_discussion(data) - else: - create_window(args) - - -if __name__ == "__main__": - main() diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 60a697acbf..b4625e2bc4 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -153,42 +153,6 @@ parts: - -etc/X11 - -etc/xdg - # alsa-mixin: - # plugin: dump - # source: https://github.com/diddlesnaps/snapcraft-alsa.git - # source-subdir: snapcraft-assets - # source-depth: 1 - # build-packages: - # - libasound2-dev - # stage-packages: - # - libasound2 - # - libasound2-plugins - # - yad - # stage: - # # restrict to only audio-related files - you need to ensure - # # that gtk3 is staged for yad to work correctly, to prompt - # # users to connect the alsa plug or proceed with pulseaudio. - # # - # # This helps prevent symbol conflicts in situations where - # # you're using a non-default library, such as those that the - # # gnome-3-34 extension for core18 provides. - # - etc/asound.conf - # - snap/command-chain/alsa-launch - # - usr/bin/yad* - # - usr/lib/*/alsa-lib - # - usr/lib/*/libasound* - # - usr/lib/*/libasyncns* - # - usr/lib/*/libdnsfile* - # - usr/lib/*/libFLAC* - # - usr/lib/*/libjack* - # - usr/lib/*/libpulse* - # - usr/lib/*/libsamplerate* - # - usr/lib/*/libsndfile* - # - usr/lib/*/libspeex* - # - usr/lib/*/libvorbis* - # - usr/lib/*/pulseaudio - # - usr/share/alsa - ninja: after: [heroic] plugin: nil @@ -331,7 +295,6 @@ parts: - -usr/lib/*/libLLVM* override-build: | set -eux - patch -p1 < $CRAFT_PROJECT_DIR/dist.patch if [[ -n "${http_proxy:-}" ]]; then export HTTP_PROXY="${http_proxy:-}" export HTTPS_PROXY="${http_proxy:-}"