From de57f8add18b2c4f49d35198ff2f91256a27b169 Mon Sep 17 00:00:00 2001 From: Jonas Snellinckx Date: Thu, 20 Feb 2020 22:43:19 +0100 Subject: [PATCH] build: try and build snap in main repo --- .electron-react/webpack.renderer.config.js | 3 +- build/icons/128x128.png | Bin build/icons/16x16.png | Bin build/icons/24x24.png | Bin build/icons/256x256.png | Bin build/icons/32x32.png | Bin build/icons/48x48.png | Bin build/icons/512x512.png | Bin build/icons/64x64.png | Bin build/icons/96x96.png | Bin package.json | 4 +- scripts/command.sh | 2 + scripts/desktop-common.sh | 439 +++++++++++++++++++++ scripts/desktop-gnome-specific.sh | 31 ++ scripts/desktop-init.sh | 50 +++ snap/gui/auryo.desktop | 10 + snap/gui/icon.png | Bin 0 -> 26408 bytes snap/snapcraft.yaml | 179 +++++++++ snap/snapcraft.yaml-e | 55 +++ src/main/app.ts | 77 ++-- src/main/utils/logger.ts | 2 +- 21 files changed, 802 insertions(+), 50 deletions(-) mode change 100755 => 100644 build/icons/128x128.png mode change 100755 => 100644 build/icons/16x16.png mode change 100755 => 100644 build/icons/24x24.png mode change 100755 => 100644 build/icons/256x256.png mode change 100755 => 100644 build/icons/32x32.png mode change 100755 => 100644 build/icons/48x48.png mode change 100755 => 100644 build/icons/512x512.png mode change 100755 => 100644 build/icons/64x64.png mode change 100755 => 100644 build/icons/96x96.png create mode 100755 scripts/command.sh create mode 100755 scripts/desktop-common.sh create mode 100755 scripts/desktop-gnome-specific.sh create mode 100755 scripts/desktop-init.sh create mode 100644 snap/gui/auryo.desktop create mode 100644 snap/gui/icon.png create mode 100644 snap/snapcraft.yaml create mode 100644 snap/snapcraft.yaml-e diff --git a/.electron-react/webpack.renderer.config.js b/.electron-react/webpack.renderer.config.js index b036f02b..79409164 100644 --- a/.electron-react/webpack.renderer.config.js +++ b/.electron-react/webpack.renderer.config.js @@ -244,7 +244,8 @@ if (isProd) { rendererConfig.plugins.push( new SentryCliPlugin({ release: appVersion, - include: [path.join(__dirname, '../dist/electron')] + include: [path.join(__dirname, '../dist/electron')], + urlPrefix: 'app:///dist/electron/' }) ); } diff --git a/build/icons/128x128.png b/build/icons/128x128.png old mode 100755 new mode 100644 diff --git a/build/icons/16x16.png b/build/icons/16x16.png old mode 100755 new mode 100644 diff --git a/build/icons/24x24.png b/build/icons/24x24.png old mode 100755 new mode 100644 diff --git a/build/icons/256x256.png b/build/icons/256x256.png old mode 100755 new mode 100644 diff --git a/build/icons/32x32.png b/build/icons/32x32.png old mode 100755 new mode 100644 diff --git a/build/icons/48x48.png b/build/icons/48x48.png old mode 100755 new mode 100644 diff --git a/build/icons/512x512.png b/build/icons/512x512.png old mode 100755 new mode 100644 diff --git a/build/icons/64x64.png b/build/icons/64x64.png old mode 100755 new mode 100644 diff --git a/build/icons/96x96.png b/build/icons/96x96.png old mode 100755 new mode 100644 diff --git a/package.json b/package.json index ad627f0f..5cd58485 100755 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "repository": "Superjo149/auryo", "homepage": "http://auryo.com", "productName": "Auryo", - "version": "2.5.1", + "version": "2.5.2", "author": { "name": "Jonas Snellinckx", "email": "jonas.snellinckx@gmail.com" @@ -28,7 +28,7 @@ "package:dir": "npm run build && electron-builder --dir", "package:win": "electron-builder --win --x64", "package:mac": "electron-builder --mac", - "package:linux": "electron-builder --linux", + "package:linux": "electron-builder --linux deb", "package:all": "electron-builder -mwl", "release": "electron-builder -wl --ia32 --x64 --publish onTagOrDraft", "release:win": "electron-builder -w --ia32 --x64 --publish onTagOrDraft", diff --git a/scripts/command.sh b/scripts/command.sh new file mode 100755 index 00000000..148015e9 --- /dev/null +++ b/scripts/command.sh @@ -0,0 +1,2 @@ +#!/bin/bash -e +exec "$SNAP/desktop-init.sh" "$SNAP/desktop-common.sh" "$SNAP/desktop-gnome-specific.sh" "$SNAP/opt/Auryo/auryo" "$@" --no-sandbox \ No newline at end of file diff --git a/scripts/desktop-common.sh b/scripts/desktop-common.sh new file mode 100755 index 00000000..22c4db19 --- /dev/null +++ b/scripts/desktop-common.sh @@ -0,0 +1,439 @@ +#!/bin/bash -e + +############################################### +# Launcher common exports for any desktop app # +############################################### + +function prepend_dir() { + local var="$1" + local dir="$2" + if [ -d "$dir" ]; then + eval "export $var=\"\$dir\${$var:+:\$$var}\"" + fi +} + +function append_dir() { + local var="$1" + local dir="$2" + if [ -d "$dir" ]; then + eval "export $var=\"\${$var:+\$$var:}\$dir\"" + fi +} + +function can_open_file() { + head -c0 "$1" &> /dev/null +} + +function update_xdg_dirs_values() { + local save_initial_values=false + local XDG_DIRS="DOCUMENTS DESKTOP DOWNLOAD MUSIC PICTURES VIDEOS PUBLICSHARE TEMPLATES" + unset XDG_SPECIAL_DIRS_PATHS + + if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs" ]; then + # shellcheck source=/dev/null + source "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs" + fi + + if [ -z ${XDG_SPECIAL_DIRS+x} ]; then + save_initial_values=true + fi + + for d in $XDG_DIRS; do + var="XDG_${d}_DIR" + value="${!var}" + + if [ "$save_initial_values" = true ]; then + XDG_SPECIAL_DIRS+=("$var") + if [ -n "$value" ]; then + XDG_SPECIAL_DIRS_INITIAL_PATHS+=("$value") + fi + fi + + if [ -n "$value" ]; then + XDG_SPECIAL_DIRS_PATHS+=("$value") + fi + done +} + +function is_subpath() { + dir="$(realpath "$1")" + parent="$(realpath "$2")" + [ "${dir##$parent/}" != "$dir" ] && return 0 || return 1 +} + +if [ -n "$SNAP_DESKTOP_RUNTIME" ]; then + # add general paths not added by snapcraft due to runtime snap + append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/lib/$SNAP_DESKTOP_ARCH_TRIPLET" + append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET" + append_dir PATH "$SNAP_DESKTOP_RUNTIME/usr/bin" +fi + +# 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/data-dir/icons" + +# Mesa Libs for OpenGL support +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/mesa" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/mesa-egl" + +# Tell libGL where to find the drivers +export LIBGL_DRIVERS_PATH="$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/dri" +append_dir LD_LIBRARY_PATH "$LIBGL_DRIVERS_PATH" +export LIBVA_DRIVERS_PATH=$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/dri + +# 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 + +# Unity7 export (workaround for https://launchpad.net/bugs/1638405) +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/libunity" + +# Pulseaudio export +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/pulseaudio" + +# EGL vendor files on glvnd enabled systems +[ -d /var/lib/snapd/lib/glvnd/egl_vendor.d ] && \ + append_dir __EGL_VENDOR_LIBRARY_DIRS /var/lib/snapd/lib/glvnd/egl_vendor.d + +# Tell GStreamer where to find its plugins +export GST_PLUGIN_PATH="$SNAP/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gstreamer-1.0" +export GST_PLUGIN_SYSTEM_PATH="$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/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/$SNAP_DESKTOP_ARCH_TRIPLET/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner" + +# XDG Config +[ -n "$SNAP_DESKTOP_RUNTIME" ] && prepend_dir XDG_CONFIG_DIRS "$SNAP_DESKTOP_RUNTIME/etc/xdg" +prepend_dir XDG_CONFIG_DIRS "$SNAP/etc/xdg" + +# Define snaps' own data dir +[ -n "$SNAP_DESKTOP_RUNTIME" ] && 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" + +# Set XDG_DATA_HOME to local path +export XDG_DATA_HOME="$SNAP_USER_DATA/.local/share" +mkdir -p "$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 +mkdir -p "$XDG_CACHE_HOME" + +# Set config folder to local path +export XDG_CONFIG_HOME="$SNAP_USER_DATA/.config" +mkdir -p "$XDG_CONFIG_HOME" + +# Create $XDG_RUNTIME_DIR if not exists (to be removed when LP: #1656340 is fixed) +if [ -n "$XDG_RUNTIME_DIR" ]; then + mkdir -p "$XDG_RUNTIME_DIR" + chmod 700 "$XDG_RUNTIME_DIR" +fi + +# Ensure the app finds locale definitions (requires locales-all to be installed) +append_dir LOCPATH "$SNAP_DESKTOP_RUNTIME/usr/lib/locale" + +# If any, keep track of where XDG dirs were so we can potentially migrate the content later +update_xdg_dirs_values + +# Setup user-dirs.* or run xdg-user-dirs-update if needed +needs_xdg_update=false +needs_xdg_reload=false +needs_xdg_links=false + +if [ "$HOME" != "$SNAP_USER_DATA" ] && ! is_subpath "$XDG_CONFIG_HOME" "$HOME"; then + for f in user-dirs.dirs user-dirs.locale; do + if [ -f "$HOME/.config/$f" ]; then + mv "$HOME/.config/$f" "$XDG_CONFIG_HOME" + needs_xdg_reload=true + fi + done +fi + +if can_open_file "$REALHOME/.config/user-dirs.dirs" && can_open_file "$REALHOME/.config/user-dirs.locale"; then + if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ] || [ $needs_xdg_reload = true ]; then + sed "/^#/!s#\$HOME#${REALHOME}#g" "$REALHOME/.config/user-dirs.dirs" > "$XDG_CONFIG_HOME/user-dirs.dirs" + cp -a "$REALHOME/.config/user-dirs.locale" "$XDG_CONFIG_HOME" + for f in user-dirs.dirs user-dirs.locale; do + md5sum < "$REALHOME/.config/$f" > "$XDG_CONFIG_HOME/$f.md5sum" + done + needs_xdg_reload=true + fi +else + needs_xdg_update=true + needs_xdg_links=true +fi + +if [ $needs_xdg_reload = true ]; then + update_xdg_dirs_values + needs_xdg_reload=false +fi + +# Check if we can actually read the contents of each xdg dir +for ((i = 0; i < ${#XDG_SPECIAL_DIRS_PATHS[@]}; i++)); do + if ! can_open_file "${XDG_SPECIAL_DIRS_PATHS[$i]}"; then + needs_xdg_update=true + needs_xdg_links=true + break + fi +done + +# If needs XDG update and xdg-user-dirs-update exists in $PATH, run it +if [ $needs_xdg_update = true ] && command -v xdg-user-dirs-update >/dev/null; then + xdg-user-dirs-update + update_xdg_dirs_values +fi + +# Create links for user-dirs.dirs +if [ $needs_xdg_links = true ]; then + for ((i = 0; i < ${#XDG_SPECIAL_DIRS_PATHS[@]}; i++)); do + b="$(realpath "${XDG_SPECIAL_DIRS_PATHS[$i]}" --relative-to="$HOME")" + if [ -e "$REALHOME/$b" ]; then + if [ -d "$HOME/$b" ]; then + rmdir "$HOME/$b" 2> /dev/null + fi + if [ ! -e "$HOME/$b" ]; then + ln -s "$REALHOME/$b" "$HOME/$b" + fi + fi + done +else + # If we aren't creating new links, check if we have content saved in old locations and move it + for ((i = 0; i < ${#XDG_SPECIAL_DIRS[@]}; i++)); do + old="${XDG_SPECIAL_DIRS_INITIAL_PATHS[$i]}" + new="${XDG_SPECIAL_DIRS_PATHS[$i]}" + if [ -L "$old" ] && [ -d "$new" ] && [ "$(readlink "$old")" != "$new" ]; then + mv -vn "$old"/* "$new"/ 2>/dev/null + elif [ -d "$old" ] && [ -d "$new" ] && [ "$old" != "$new" ] && + (is_subpath "$old" "$SNAP_USER_DATA" || is_subpath "$old" "$SNAP_USER_COMMON"); then + mv -vn "$old"/* "$new"/ 2>/dev/null + fi + done +fi + +# 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. +SNAP_DESKTOP_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 + SNAP_DESKTOP_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 + +# GI repository +[ -n "$SNAP_DESKTOP_RUNTIME" ] && prepend_dir GI_TYPELIB_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/girepository-1.0" +[ -n "$SNAP_DESKTOP_RUNTIME" ] && prepend_dir GI_TYPELIB_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/girepository-1.0" +prepend_dir GI_TYPELIB_PATH "$SNAP/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/girepository-1.0" +prepend_dir GI_TYPELIB_PATH "$SNAP/usr/lib/girepository-1.0" +prepend_dir GI_TYPELIB_PATH "$SNAP/usr/lib/gjs/girepository-1.0" + +# Keep an array of data dirs, for looping through them +IFS=':' read -r -a data_dirs_array <<< "$XDG_DATA_DIRS" + +# Font Config and themes +export FONTCONFIG_PATH="$SNAP_DESKTOP_RUNTIME/etc/fonts" +export FONTCONFIG_FILE="$SNAP_DESKTOP_RUNTIME/etc/fonts/fonts.conf" + +function make_user_fontconfig { + echo "" + if [ -d "$REALHOME/.local/share/fonts" ]; then + echo " $REALHOME/.local/share/fonts" + fi + if [ -d "$REALHOME/.fonts" ]; then + echo " $REALHOME/.fonts" + fi + for ((i = 0; i < ${#data_dirs_array[@]}; i++)); do + if [ -d "${data_dirs_array[$i]}/fonts" ]; then + echo " ${data_dirs_array[$i]}/fonts" + fi + done + echo ' conf.d' + # We need to include this default cachedir first so that caching + # works: without it, fontconfig will try to write to the real user home + # cachedir and be blocked by AppArmor. + echo ' fontconfig' + if [ -d "$REALHOME/.cache/fontconfig" ]; then + echo " $REALHOME/.cache/fontconfig" + fi + echo "" +} + +if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then + rm -rf "$XDG_DATA_HOME"/{fontconfig,fonts,fonts-*,themes,.themes} + + # This fontconfig fragment is installed in a location that is + # included by the system fontconfig configuration: namely the + # etc/fonts/conf.d/50-user.conf file. + mkdir -p "$XDG_CONFIG_HOME/fontconfig" + make_user_fontconfig > "$XDG_CONFIG_HOME/fontconfig/fonts.conf" + + # the themes symlink are needed for GTK 3.18 when the prefix isn't changed + # GTK 3.20 looks into XDG_DATA_DIR which has connected themes. + ln -sf "$SNAP/data-dir/themes" "$XDG_DATA_HOME" + ln -sfn "$SNAP/data-dir/themes" "$SNAP_USER_DATA/.themes" +fi + +# Build mime.cache +# needed for gtk and qt icon +if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then + rm -rf "$XDG_DATA_HOME/mime" + if [ ! -f "$SNAP_DESKTOP_RUNTIME/usr/share/mime/mime.cache" ]; then + if command -v update-mime-database >/dev/null; then + cp --preserve=timestamps -dR "$SNAP_DESKTOP_RUNTIME/usr/share/mime" "$XDG_DATA_HOME" + update-mime-database "$XDG_DATA_HOME/mime" + fi + fi +fi + +# Gio modules and cache (including gsettings module) +export GIO_MODULE_DIR="$XDG_CACHE_HOME/gio-modules" +if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then + if [ -f "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/glib-2.0/gio-querymodules" ]; then + rm -rf "$GIO_MODULE_DIR" + mkdir -p "$GIO_MODULE_DIR" + ln -sf "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gio/modules/"*.so "$GIO_MODULE_DIR" + ln -sf "$SNAP/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gio/modules/"*.so "$GIO_MODULE_DIR" + "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/glib-2.0/gio-querymodules" "$GIO_MODULE_DIR" + fi +fi + +# Setup compiled gsettings schema +GS_SCHEMA_DIR="$XDG_DATA_HOME/glib-2.0/schemas" +function compile_schemas { + if [ -f "$1" ]; then + rm -rf "$GS_SCHEMA_DIR" + mkdir -p "$GS_SCHEMA_DIR" + for ((i = 0; i < ${#data_dirs_array[@]}; i++)); do + schema_dir="${data_dirs_array[$i]}/glib-2.0/schemas" + if [ -f "$schema_dir/gschemas.compiled" ]; then + # This directory already has compiled schemas + continue + fi + if [ -n "$(ls -A "$schema_dir"/*.xml 2>/dev/null)" ]; then + ln -s "$schema_dir"/*.xml "$GS_SCHEMA_DIR" + fi + if [ -n "$(ls -A "$schema_dir"/*.override 2>/dev/null)" ]; then + ln -s "$schema_dir"/*.override "$GS_SCHEMA_DIR" + fi + done + # Only compile schemas if we copied anything + if [ -n "$(ls -A "$GS_SCHEMA_DIR"/*.xml "$GS_SCHEMA_DIR"/*.override 2>/dev/null)" ]; then + "$1" "$GS_SCHEMA_DIR" + fi + fi +} +if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then + compile_schemas "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/glib-2.0/glib-compile-schemas" +fi + +# Enable gsettings user changes +# symlink the dconf file if home plug is connected for read +DCONF_DEST_USER_DIR="$SNAP_USER_DATA/.config/dconf" +if [ ! -f "$DCONF_DEST_USER_DIR/user" ]; then + if [ -f "$REALHOME/.config/dconf/user" ]; then + mkdir -p "$DCONF_DEST_USER_DIR" + ln -s "$REALHOME/.config/dconf/user" "$DCONF_DEST_USER_DIR" + fi +fi + +# Testability support +append_dir LD_LIBRARY_PATH "$SNAP/testability" +append_dir LD_LIBRARY_PATH "$SNAP/testability/$SNAP_DESKTOP_ARCH_TRIPLET" +append_dir LD_LIBRARY_PATH "$SNAP/testability/$SNAP_DESKTOP_ARCH_TRIPLET/mesa" + +# Gdk-pixbuf loaders +export GDK_PIXBUF_MODULE_FILE=$XDG_CACHE_HOME/gdk-pixbuf-loaders.cache +export GDK_PIXBUF_MODULEDIR=$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gdk-pixbuf-2.0/2.10.0/loaders +if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then + rm -f "$GDK_PIXBUF_MODULE_FILE" + if [ -f "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders" ]; then + "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders" > "$GDK_PIXBUF_MODULE_FILE" + fi +fi + +# Icon themes cache +if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then + rm -rf "$XDG_DATA_HOME/icons" + mkdir -p "$XDG_DATA_HOME/icons" + for ((i = 0; i < ${#data_dirs_array[@]}; i++)); do + for theme in "${data_dirs_array[$i]}/icons/"*; do + if [ -f "$theme/index.theme" ] && [ ! -f "$theme/icon-theme.cache" ]; then + theme_dir="$XDG_DATA_HOME/icons/$(basename "$theme")" + if [ ! -d "$theme_dir" ]; then + mkdir -p "$theme_dir" + ln -s "$theme"/* "$theme_dir" + if [ -f "$SNAP_DESKTOP_RUNTIME/usr/sbin/update-icon-caches" ]; then + "$SNAP_DESKTOP_RUNTIME/usr/sbin/update-icon-caches" "$theme_dir" + elif [ -f "$SNAP_DESKTOP_RUNTIME/usr/sbin/update-icon-cache.gtk2" ]; then + "$SNAP_DESKTOP_RUNTIME/usr/sbin/update-icon-cache.gtk2" "$theme_dir" + fi + fi + fi + done + done +fi + +# GTK theme and behavior modifier +# Those can impact the theme engine used by Qt as well +gtk_configs=(gtk-3.0/settings.ini gtk-3.0/bookmarks gtk-2.0/gtkfilechooser.ini) +for f in "${gtk_configs[@]}"; do + dest="$XDG_CONFIG_HOME/$f" + if [ ! -L "$dest" ]; then + mkdir -p "$(dirname "$dest")" + ln -s "$REALHOME/.config/$f" "$dest" + fi +done + +# create symbolic link to ibus socket path for ibus to look up its socket files +# (see comments #3 and #6 on https://launchpad.net/bugs/1580463) +IBUS_CONFIG_PATH="$XDG_CONFIG_HOME/ibus" +mkdir -p "$IBUS_CONFIG_PATH" +[ -d "$IBUS_CONFIG_PATH/bus" ] && rm -rf "$IBUS_CONFIG_PATH/bus" +ln -sfn "$REALHOME/.config/ibus/bus" "$IBUS_CONFIG_PATH" + +export SNAP_DESKTOP_WAYLAND_AVAILABLE + +exec "$@" \ No newline at end of file diff --git a/scripts/desktop-gnome-specific.sh b/scripts/desktop-gnome-specific.sh new file mode 100755 index 00000000..523778f4 --- /dev/null +++ b/scripts/desktop-gnome-specific.sh @@ -0,0 +1,31 @@ +#!/bin/bash -e + +############################## +# GTK launcher specific part # +############################## + +if [ "$SNAP_DESKTOP_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 + +export GTK_PATH="$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gtk-3.0" + +# ibus and fcitx integration +GTK_IM_MODULE_DIR=$XDG_CACHE_HOME/immodules +export GTK_IM_MODULE_FILE=$GTK_IM_MODULE_DIR/immodules.cache +if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then + rm -rf "$GTK_IM_MODULE_DIR" + mkdir -p "$GTK_IM_MODULE_DIR" + if [ -x "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/libgtk-3-0/gtk-query-immodules-3.0" ]; then + ln -sf "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gtk-3.0/3.0.0/immodules"/*.so "$GTK_IM_MODULE_DIR" + "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/libgtk-3-0/gtk-query-immodules-3.0" > "$GTK_IM_MODULE_FILE" + elif [ -x "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/libgtk2.0-0/gtk-query-immodules-2.0" ]; then + ln -sf "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gtk-2.0/2.10.0/immodules"/*.so "$GTK_IM_MODULE_DIR" + "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/libgtk2.0-0/gtk-query-immodules-2.0" > "$GTK_IM_MODULE_FILE" + fi +fi + +exec "$@" \ No newline at end of file diff --git a/scripts/desktop-init.sh b/scripts/desktop-init.sh new file mode 100755 index 00000000..cccb22d2 --- /dev/null +++ b/scripts/desktop-init.sh @@ -0,0 +1,50 @@ +#!/bin/bash -e + +################# +# Launcher init # +################# + +SNAP_DESKTOP_COMPONENTS_NEED_UPDATE="true" + +# shellcheck source=/dev/null +. "$SNAP_USER_DATA/.last_revision" 2>/dev/null || true +if [ "$SNAP_DESKTOP_LAST_REVISION" = "$SNAP_REVISION" ]; then + SNAP_DESKTOP_COMPONENTS_NEED_UPDATE="false" +else + echo "SNAP_DESKTOP_LAST_REVISION=$SNAP_REVISION" > "$SNAP_USER_DATA/.last_revision" +fi + +# Set $REALHOME to the users real home directory +REALHOME="$(getent passwd $UID | cut -d ':' -f 6)" + +# If the user has modified their user-dirs settings, force an update +if [[ -f "$XDG_CONFIG_HOME/user-dirs.dirs.md5sum" && -f "$XDG_CONFIG_HOME/user-dirs.locale.md5sum" ]]; then + if [[ "$(md5sum < "$REALHOME/.config/user-dirs.dirs")" != "$(cat "$XDG_CONFIG_HOME/user-dirs.dirs.md5sum")" || + "$(md5sum < "$REALHOME/.config/user-dirs.locale")" != "$(cat "$XDG_CONFIG_HOME/user-dirs.locale.md5sum")" ]]; then + SNAP_DESKTOP_COMPONENTS_NEED_UPDATE="true" + fi +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 + +SNAP_DESKTOP_ARCH_TRIPLET="$ARCH" + +if [ -f "$SNAP/lib/bindtextdomain.so" ]; then + export LD_PRELOAD="$LD_PRELOAD:$SNAP/lib/bindtextdomain.so" +fi + +export REALHOME +export SNAP_DESKTOP_COMPONENTS_NEED_UPDATE +export SNAP_DESKTOP_ARCH_TRIPLET + +exec "$@" \ No newline at end of file diff --git a/snap/gui/auryo.desktop b/snap/gui/auryo.desktop new file mode 100644 index 00000000..98f6b42c --- /dev/null +++ b/snap/gui/auryo.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Name=Auryo +Exec=auryo +Terminal=false +Type=Application +Icon=${SNAP}/meta/gui/icon.png +StartupWMClass=Auryo +Comment=Listen to SoundCloud® from the comfort of your desktop. Use keyboard shortcuts to navigate through your music. Be more productive. +MimeType=x-scheme-handler/auryo; +Categories=Audio; diff --git a/snap/gui/icon.png b/snap/gui/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0286ebff37ee3d15b7dbffac9e43e748bca240cb GIT binary patch literal 26408 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 NQd81WEPaR!`X9jtH|YQX literal 0 HcmV?d00001 diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml new file mode 100644 index 00000000..57e8769d --- /dev/null +++ b/snap/snapcraft.yaml @@ -0,0 +1,179 @@ +base: core18 +grade: stable +confinement: strict +parts: + launch-scripts: + plugin: dump + source: scripts + gnome-platform-empty-dirs: + plugin: nil + override-build: | + mkdir -p "$SNAPCRAFT_PART_INSTALL/data-dir/themes" mkdir -p "$SNAPCRAFT_PART_INSTALL/data-dir/icons" mkdir -p "$SNAPCRAFT_PART_INSTALL/data-dir/sounds" mkdir $SNAPCRAFT_PART_INSTALL/gnome-platform + app-files: + plugin: dump + source: https://github.com/Superjo149/auryo/releases/download/v2.5.1/Auryo_2.5.1_amd64.deb + source-type: deb + app: + plugin: nil + stage: + - '-usr/lib/python*' + - '-usr/bin/python*' + - '-var/lib/ucf' + - '-usr/include' + - '-usr/lib/X11' + - '-usr/share' + - '-usr/sbin' + - '-usr/bin' + - '-usr/lib/*/libicudata.*' + - '-usr/lib/*/libicui18n.*' + - '-usr/lib/*/libgtk-*' + - '-usr/lib/*/libgdk-*' + - '-usr/lib/*/glib-*' + - '-usr/lib/*/gtk-*' + - '-usr/lib/*/gdk-*' + - '-usr/lib/*/krb5' + - '-usr/lib/systemd' + - '-usr/lib/glib-networking' + - '-usr/lib/dconf' + - '-usr/lib/*/avahi' + - '-usr/lib/*/gio' + - '-usr/lib/*/libatk*' + - '-usr/lib/*/libatspi*' + - '-usr/lib/*/libavahi*' + - '-usr/lib/*/libcairo*' + - '-usr/lib/*/libcolordprivate*' + - '-usr/lib/*/libcolord*' + - '-usr/lib/*/libcroco*' + - '-usr/lib/*/libcups*' + - '-usr/lib/*/libdatrie*' + - '-usr/lib/*/libdconf*' + - '-usr/lib/*/libepoxy*' + - '-usr/lib/*/libexpatw*' + - '-usr/lib/*/libffi*' + - '-usr/lib/*/libfontconfig*' + - '-usr/lib/*/libfreetype*' + - '-usr/lib/*/libgdk_pixbuf*' + - '-usr/lib/*/libgdk_pixbuf_xlib*' + - '-usr/lib/*/libgio*' + - '-usr/lib/*/libglib*' + - '-usr/lib/*/libgmodule*' + - '-usr/lib/*/libgmp*' + - '-usr/lib/*/libgnutls*' + - '-usr/lib/*/libgobject*' + - '-usr/lib/*/libgraphite2*' + - '-usr/lib/*/libgssapi_krb5*' + - '-usr/lib/*/libgthread*' + - '-usr/lib/*/libharfbuzz*' + - '-usr/lib/*/libhogweed*' + - '-usr/lib/*/libicuio*' + - '-usr/lib/*/libicutest*' + - '-usr/lib/*/libicutu*' + - '-usr/lib/*/libicuuc*' + - '-usr/lib/*/libidn2*' + - '-usr/lib/*/libjbig*' + - '-usr/lib/*/libjpeg*' + - '-usr/lib/*/libjson*' + - '-usr/lib/*/libk5crypto*' + - '-usr/lib/*/libkrb5*' + - '-usr/lib/*/libkrb5support*' + - '-usr/lib/*/liblcms2*' + - '-usr/lib/*/libnettle*' + - '-usr/lib/*/libp11*' + - '-usr/lib/*/libpango*' + - '-usr/lib/*/libpangocairo*' + - '-usr/lib/*/libpangoft2*' + - '-usr/lib/*/libpixman*' + - '-usr/lib/*/libpng16*' + - '-usr/lib/*/libproxy*' + - '-usr/lib/*/librest*' + - '-usr/lib/*/librsvg*' + - '-usr/lib/*/libsecret*' + - '-usr/lib/*/libsoup*' + - '-usr/lib/*/libsqlite3*' + - '-usr/lib/*/libtasn1*' + - '-usr/lib/*/libthai*' + - '-usr/lib/*/libtiff*' + - '-usr/lib/*/libunistring*' + - '-usr/lib/*/libwayland*' + - '-usr/lib/*/libX11*' + - '-usr/lib/*/libXau*' + - '-usr/lib/*/libxcb*' + - '-usr/lib/*/libXcomposite*' + - '-usr/lib/*/libXcursor*' + - '-usr/lib/*/libXdamage*' + - '-usr/lib/*/libXdmcp*' + - '-usr/lib/*/libXext*' + - '-usr/lib/*/libXfixes*' + - '-usr/lib/*/libXinerama*' + - '-usr/lib/*/libXi*' + - '-usr/lib/*/libxkbcommon*' + - '-usr/lib/*/libxml2*' + - '-usr/lib/*/libXrandr*' + - '-usr/lib/*/libXrender*' + stage-packages: + - libasound2 + - libgconf2-4 + - libnotify4 + - libnspr4 + - libnss3 + - libpcre3 + - libpulse0 + - libxss1 + - libxtst6 + build-packages: + - execstack +plugs: + gnome-3-28-1804: + interface: content + target: $SNAP/gnome-platform + default-provider: gnome-3-28-1804 + gtk-3-themes: + interface: content + target: $SNAP/data-dir/themes + default-provider: gtk-common-themes + icon-themes: + interface: content + target: $SNAP/data-dir/icons + default-provider: gtk-common-themes + sound-themes: + interface: content + target: $SNAP/data-dir/sounds + default-provider: gtk-common-themes +name: auryo +version: 2.5.1 +summary: A SoundCloud client for your desktop +description: Listen to SoundCloud® from the comfort of your desktop. Use keyboard shortcuts to navigate through your music. Be more productive. +architectures: + - amd64 +apps: + auryo: + command: command.sh + plugs: + - bluez + - browser-support + - gsettings + - home + - mount-observe + - network + - opengl + - pulseaudio + - unity7 + - x11 + - mpris + slots: + - auryo-player-mpris + + adapter: none + environment: + DISABLE_WAYLAND: '1' + TMPDIR: $XDG_RUNTIME_DIR + PATH: '$SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$PATH' + SNAP_DESKTOP_RUNTIME: $SNAP/gnome-platform + LD_LIBRARY_PATH: '$SNAP_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/x86_64-linux-gnu:$SNAP/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/x86_64-linux-gnu:$SNAP/usr/lib/x86_64-linux-gnu' +icon: snap/gui/icon.png + +slots: + auryo-player-mpris: + interface: mpris + name: auryo_player + diff --git a/snap/snapcraft.yaml-e b/snap/snapcraft.yaml-e new file mode 100644 index 00000000..dc38f286 --- /dev/null +++ b/snap/snapcraft.yaml-e @@ -0,0 +1,55 @@ +name: auryo +version: {VERSION} +summary: A SoundCloud client for your desktop +description: | + Listen to SoundCloud® from the comfort of your desktop. Use keyboard + shortcuts to navigate through your music. Be more productive. +grade: stable +confinement: strict + +parts: + auryo: + plugin: dump + source: https://github.com/Superjo149/auryo/releases/download/v{VERSION}/Auryo_{VERSION}_amd64.deb + source-type: deb + after: + - desktop-gtk3 + # Correct path to icon. + # Clear the execstack - https://forum.snapcraft.io/t/snap-and-executable-stacks/1812 + prepare: | + sed -i 's|Icon=auryo|Icon=/usr/share/icons/hicolor/256x256/apps/auryo\.png|' usr/share/applications/auryo.desktop + execstack --clear-execstack opt/Auryo/auryo + build-packages: + - execstack + stage-packages: + - libasound2 + - libgconf2-4 + - libnotify4 + - libnspr4 + - libnss3 + - libpcre3 + - libpulse0 + - libxss1 + - libxtst6 + +apps: + auryo: + command: bin/desktop-launch $SNAP/opt/Auryo/auryo --no-sandbox + environment: + TMPDIR: $XDG_RUNTIME_DIR + plugs: + - bluez + - browser-support + - gsettings + - home + - mount-observe + - network + - opengl + - pulseaudio + - unity7 + - x11 + +slots: + auryo-player-mpris: + interface: mpris + name: auryo_player \ No newline at end of file diff --git a/src/main/app.ts b/src/main/app.ts index 43f95022..b7173d61 100755 --- a/src/main/app.ts +++ b/src/main/app.ts @@ -5,7 +5,16 @@ import { EVENTS } from '@common/constants/events'; import { StoreState } from '@common/store'; import { addToast, setConfigKey } from '@common/store/actions'; // eslint-disable-next-line import/no-extraneous-dependencies -import { app, BrowserWindow, BrowserWindowConstructorOptions, Menu, nativeImage, protocol, shell } from 'electron'; +import { + app, + BrowserWindow, + BrowserWindowConstructorOptions, + Menu, + nativeImage, + protocol, + shell, + Event +} from 'electron'; import is from 'electron-is'; import windowStateKeeper from 'electron-window-state'; import _ from 'lodash'; @@ -44,7 +53,18 @@ export class Auryo { app.setAppUserModelId('com.auryo.core'); - app.requestSingleInstanceLock(); + app.on('before-quit', () => { + this.logger.info('Application exiting...'); + this.quitting = true; + }); + + const isPrimaryInstance = app.requestSingleInstanceLock(); + + if (!isPrimaryInstance) { + this.logger.debug(`Not the first instance - quit`); + app.quit(); + return; + } app.on('second-instance', () => { // handle protocol for windows @@ -53,33 +73,15 @@ export class Auryo { this.handleProtocolUrl(arg); }); } - - app.exit(); - }); - - app.on('before-quit', () => { - this.logger.info('Application exiting...'); - this.quitting = true; }); } public async start() { - app.setAsDefaultProtocolClient('auryo'); - - protocol.registerHttpProtocol('stream', async (request, callback) => { - const { - config: { - app: { overrideClientId } - } - } = this.store.getState(); - const trackId = request.url.substr(9); - const mp3Url = await this.getPlayingTrackStreamUrl(trackId, overrideClientId || CONFIG.CLIENT_ID || ''); + if (this.quitting) { + return; + } - callback({ - url: mp3Url, - method: 'GET' - }); - }); + app.setAsDefaultProtocolClient('auryo'); app.on('open-url', (event, data) => { event.preventDefault(); @@ -245,25 +247,8 @@ export class Auryo { } }); - this.mainWindow.webContents.session.webRequest.onBeforeRequest( - { - urls: ['https://local.stream/*'] - }, - async (details, callback) => { - const { - config: { - app: { overrideClientId } - } - } = this.store.getState(); - const { 1: trackId } = details.url.split('https://local.stream/'); - const mp3Url = await this.getPlayingTrackStreamUrl(trackId, overrideClientId || CONFIG.CLIENT_ID || ''); - - callback({ - redirectURL: mp3Url - }); - } - ); - + // SoundCloud's API gave a lot of 401s using the /stream to get the audio file + // This is a hacky way to circumvent this :) this.mainWindow.webContents.session.webRequest.onBeforeRequest( { urls: ['http://localhost:8888/stream/*'] @@ -338,11 +323,11 @@ export class Auryo { private readonly registerListeners = () => { if (this.mainWindow) { - this.mainWindow.webContents.on('crashed', (event: any) => { - this.logger.fatal(JSON.stringify(event), 'App Crashed'); + this.mainWindow.webContents.on('crashed', (event: Event) => { + this.logger.fatal(event, 'App Crashed'); }); - this.mainWindow.on('unresponsive', (event: any) => { + this.mainWindow.on('unresponsive', (event: Event) => { this.logger.fatal(event, 'App unresponsive'); }); diff --git a/src/main/utils/logger.ts b/src/main/utils/logger.ts index ec2535bf..c1dcef79 100644 --- a/src/main/utils/logger.ts +++ b/src/main/utils/logger.ts @@ -3,7 +3,7 @@ import rfs from 'rotating-file-stream'; // eslint-disable-next-line import/no-cycle import { Utils } from './utils'; -const isProd = false; // process.env.NODE_ENV === "production" && process.env.ENV !== "development"; +const isProd = process.env.NODE_ENV === 'production' && process.env.ENV !== 'development'; let stream: pino.DestinationStream;