Dotfiles/setup/modules/optional-Modules/apps/plymouth.sh

202 lines
8.4 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/bin/bash
# plymouth.sh — Plymouth boot splash installer
#
# Installs the M-Archy Plymouth theme: skull logo centred on a dark background
# with a magenta spinning-dot animation below it.
#
# SVG NOTE: Plymouth's image loader (ply-image) is PNG-only — it links against
# libpng and has no SVG or gdk-pixbuf dependency. The ply-image.h header is
# even commented "png file loader". bg-skull.svg must be converted to PNG with
# rsvg-convert (higher fidelity than ImageMagick for SVG) before deployment.
#
# Logo resolution order:
# 1. $PLYMOUTH_LOGO_SRC env var — caller-supplied custom image (PNG or SVG)
# 2. $DOTFILES_DIR/resources/bg-skull.svg — repo copy, always present
# 3. /root/installer/resources/bg-skull.svg — archiso embedded copy
#
# PNG inputs are used directly; SVG inputs are converted via rsvg-convert.
#
# Steps:
# 1. Install plymouth (extra repo)
# 2. Install librsvg (rsvg-convert) if logo is SVG; imagemagick for dot
# 3. Produce logo.png (300 px wide) from the resolved source
# 4. Generate a 10×10 magenta dot.png for the spinner
# 5. Write the m-archy theme (.plymouth descriptor + .script animation)
# 6. Register with plymouth-set-default-theme
# 7. Inject plymouth / sd-plymouth hook into /etc/mkinitcpio.conf
# 8. Add 'quiet splash' to GRUB_CMDLINE_LINUX_DEFAULT
# 9. Regenerate GRUB config and initramfs
set -euo pipefail
source "$(dirname "${BASH_SOURCE[0]}")/../../lib/logging.sh"
THEME_DIR="/usr/share/plymouth/themes/m-archy"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOTFILES_DIR="$(cd "$SCRIPT_DIR/../../.." && pwd)"
# Resolve logo source — env var takes priority, then bundled SVG
LOGO_SRC="${PLYMOUTH_LOGO_SRC:-}"
if [[ -z "$LOGO_SRC" ]]; then
for _candidate in \
"$DOTFILES_DIR/resources/bg-skull.svg" \
"/root/installer/resources/bg-skull.svg"
do
if [[ -f "$_candidate" ]]; then
LOGO_SRC="$_candidate"
break
fi
done
fi
# ── Install Plymouth ──────────────────────────────────────────────────────────
log "Installing Plymouth..."
sudo pacman -S --noconfirm --needed plymouth
# ── Ensure conversion tools ───────────────────────────────────────────────────
# imagemagick is always needed for the spinner dot.
# librsvg (rsvg-convert) is only needed when the logo source is an SVG.
if ! command -v convert &>/dev/null; then
log "Installing imagemagick (dot generation)..."
sudo pacman -S --noconfirm --needed imagemagick
fi
# ── Produce logo.png ──────────────────────────────────────────────────────────
TMP_LOGO="$(mktemp /tmp/plymouth-logo.XXXXXX.png)"
TMP_DOT="/tmp/plymouth-dot.png"
trap 'rm -f "$TMP_LOGO" "$TMP_DOT"' EXIT
if [[ -z "$LOGO_SRC" ]]; then
warn "No logo source found — using transparent placeholder."
convert -size 300x300 xc:transparent "$TMP_LOGO"
elif [[ "${LOGO_SRC,,}" == *.png ]]; then
log "Using PNG directly: $LOGO_SRC"
cp "$LOGO_SRC" "$TMP_LOGO"
else
# SVG (or unknown) — convert via rsvg-convert for best fidelity
if ! command -v rsvg-convert &>/dev/null; then
log "Installing librsvg (rsvg-convert) for SVG→PNG conversion..."
sudo pacman -S --noconfirm --needed librsvg
fi
log "Converting $LOGO_SRC → PNG (300 px wide)..."
rsvg-convert -w 300 "$LOGO_SRC" -o "$TMP_LOGO"
fi
# ── Generate spinner dot ──────────────────────────────────────────────────────
# 10×10 magenta circle — centred at (5,5), radius 4 px
convert -size 10x10 xc:transparent \
-fill '#E40046' \
-draw 'circle 5,5 5,1' \
"$TMP_DOT"
# ── Install theme files ───────────────────────────────────────────────────────
log "Installing M-Archy Plymouth theme..."
sudo mkdir -p "$THEME_DIR"
sudo cp "$TMP_LOGO" "$THEME_DIR/logo.png"
sudo cp "$TMP_DOT" "$THEME_DIR/dot.png"
sudo tee "$THEME_DIR/m-archy.plymouth" > /dev/null <<'EOF'
[Plymouth Theme]
Name=M-Archy
Description=M-Archy boot splash — skull logo with spinning dots
ModuleName=script
[script]
ImageDir=/usr/share/plymouth/themes/m-archy
ScriptFile=/usr/share/plymouth/themes/m-archy/m-archy.script
EOF
sudo tee "$THEME_DIR/m-archy.script" > /dev/null <<'EOF'
# M-Archy Plymouth splash — skull logo + magenta spinner
Window.SetBackgroundTopColor (0.10, 0.10, 0.10);
Window.SetBackgroundBottomColor (0.07, 0.07, 0.07);
screen_width = Window.GetWidth ();
screen_height = Window.GetHeight ();
# Centred skull logo
logo.image = Image ("logo.png");
logo.sprite = Sprite (logo.image);
logo.sprite.SetX (Math.Int (screen_width / 2 - logo.image.GetWidth () / 2));
logo.sprite.SetY (Math.Int (screen_height / 2 - logo.image.GetHeight () / 2));
logo.sprite.SetZ (10);
# 12-dot spinner below the logo
num_dots = 12;
dot_r = 5;
orbit = 35;
cx = screen_width / 2;
cy = screen_height / 2 + logo.image.GetHeight () / 2 + 55;
dot.image = Image ("dot.png");
for (i = 0; i < num_dots; i++) {
dot[i].sprite = Sprite (dot.image);
dot[i].sprite.SetZ (20);
}
frame = 0;
fun refresh_callback () {
frame++;
step = 2 * Math.Pi / num_dots;
for (i = 0; i < num_dots; i++) {
angle = step * i + frame * 0.15;
dot[i].sprite.SetX (Math.Int (cx + Math.Cos (angle) * orbit - dot_r));
dot[i].sprite.SetY (Math.Int (cy + Math.Sin (angle) * orbit - dot_r));
t = (i + Math.Int (frame / 4) % num_dots) % num_dots;
f = t / num_dots;
dot[i].sprite.SetOpacity (0.15 + 0.85 * f * f);
}
}
Plymouth.SetRefreshFunction (refresh_callback);
EOF
# ── Register theme ────────────────────────────────────────────────────────────
log "Registering m-archy as default Plymouth theme..."
sudo plymouth-set-default-theme m-archy
# ── mkinitcpio: inject Plymouth hook ─────────────────────────────────────────
log "Adding Plymouth hook to /etc/mkinitcpio.conf..."
if grep -q '\bplymouth\b\|sd-plymouth' /etc/mkinitcpio.conf; then
skip "Plymouth hook already present in mkinitcpio.conf"
else
# systemd hook → sd-plymouth goes after systemd
# traditional udev hook → plymouth goes after udev
if grep -qE 'HOOKS=\([^)]*\bsystemd\b' /etc/mkinitcpio.conf; then
sudo sed -Ei 's/(\bsystemd\b)( |\))/\1 sd-plymouth\2/' /etc/mkinitcpio.conf
log "Injected sd-plymouth hook after systemd"
else
sudo sed -Ei 's/(\budev\b)( |\))/\1 plymouth\2/' /etc/mkinitcpio.conf
log "Injected plymouth hook after udev"
fi
if ! grep -q '\bplymouth\b\|sd-plymouth' /etc/mkinitcpio.conf; then
warn "Could not auto-inject Plymouth hook."
warn "Manually add 'plymouth' after 'udev' in /etc/mkinitcpio.conf."
fi
fi
# ── GRUB: add quiet splash ────────────────────────────────────────────────────
GRUB_CONF="/etc/default/grub"
if [[ -f "$GRUB_CONF" ]]; then
if grep -q '\bsplash\b' "$GRUB_CONF"; then
skip "'splash' already present in $GRUB_CONF"
else
log "Adding 'quiet splash' to GRUB_CMDLINE_LINUX_DEFAULT..."
sudo sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 quiet splash"/' "$GRUB_CONF"
sudo sed -i 's/quiet quiet/quiet/g' "$GRUB_CONF"
fi
log "Regenerating GRUB config..."
sudo grub-mkconfig -o /boot/grub/grub.cfg
else
warn "/etc/default/grub not found."
warn "If using systemd-boot, add 'quiet splash' to your loader entry manually."
fi
# ── Rebuild initramfs ─────────────────────────────────────────────────────────
log "Rebuilding initramfs (this bakes the theme into the initrd)..."
sudo mkinitcpio -P
log "Plymouth m-archy theme installed. Reboot to see the splash screen."