# PeerSpeak AppImage

A "thin" AppImage: the `peerspeak` binary, the bundled `pixelpass` screen-share
helper, a launcher (`AppRun`), and the desktop entry + icon. Run
`./build-appimage.sh` to produce `peerspeak-<version>-x86_64.AppImage`.

## Why thin, and why pixelpass is bundled

PeerSpeak owns voice; **pixelpass** owns pixels. They are never Cargo
dependencies of each other — peerspeak shells out to the `pixelpass` binary over
its CLI. The AppImage co-locates `pixelpass` in `usr/bin`, and `AppRun` prepends
`usr/bin` to `PATH`, so peerspeak's normal `$PATH` lookup finds it with no code
change. Joe gets one file, and screen-share works out of the box.

Almost nothing is bundled: peerspeak's own assets (notification WAVs, avatar
presets, window icon, fonts) are `include_bytes!`-embedded, and the graphics
stack (`libGL`, `libvulkan`, `libwayland-*`, `libxkbcommon`, X11) is dlopen'd at
runtime and on the AppImage excludelist because it must match the host driver.
So the image carries just the two binaries plus a handful of small libs.

## Host requirements

The AppImage runs on any reasonably current glibc-based distro that has:

- **A Vulkan-capable GPU + driver** (peerspeak's iced/wgpu renderer). Mesa/RADV
  on AMD/Intel or the NVIDIA driver all work.
- **PipeWire** with the PulseAudio shim, `pactl`, and the host `libpulse.so.0`
  client library. The Pulse client stack is deliberately not bundled because
  PixelPass launches host GStreamer tools that must keep using the host's
  matching multimedia libraries.
- For **screen-share only** — pixelpass shells out to these on the host `PATH`;
  it prints the exact package names for your distro if any are missing:
  - **GStreamer + plugins** (`gst-launch-1.0`/`gst-inspect-1.0`, base,
    good/bad/ugly, libav, and the PipeWire plugin),
  - **mpv** (or vlc) for the viewer side,
  - on X11, `xwininfo` for single-window capture.

On Arch/Artix that is one pacman line, e.g.:

```sh
sudo pacman -S gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad \
  gst-plugins-ugly gst-libav gst-plugin-pipewire mpv xorg-xwininfo libpulse
```

(Add `gstreamer-vaapi` for hardware H.264 encode on AMD/Intel; the software
x264 path always works. On XLibre / X11 the capture path uses `ximagesrc` and
needs no XDG portal — no systemd required.)

## Building for broad compatibility (glibc baseline)

An AppImage requires a host glibc **at least as new** as the build host's. Built
on a rolling distro (glibc 2.43) it only runs on equally-new systems. Build
inside **Ubuntu 24.04** (glibc 2.39, PipeWire 1.0.5) for wide reach — pixelpass's
`pipewire` crate binds the system PipeWire headers and needs PipeWire >= 1.0, so
the older Debian 12 `peerspeak-bookworm` box (PW 0.3.65) cannot build it. 2.39
covers Debian 13+, Fedora 40+, and current rolling distros.

```sh
# One-time: an Ubuntu 24.04 distrobox that reuses the host rustup toolchain.
distrobox create --yes --image ubuntu:24.04 --name peerspeak-appimage
distrobox enter peerspeak-appimage -- sudo apt-get update
distrobox enter peerspeak-appimage -- sudo apt-get install -y \
  build-essential cmake clang libclang-dev pkg-config \
  libpipewire-0.3-dev libspa-0.2-dev libpulse-dev libasound2-dev libxcb1-dev \
  curl ca-certificates file patchelf git
rustup toolchain install 1.97.1 --profile default

# PeerSpeak's ownership validator needs the modern SPA-JSON parser headers it
# is tested against. Distrobox exposes the host's headers under /run/host;
# pkg-config still links Ubuntu's older ABI-compatible libraries, preserving
# the glibc baseline. This checkout's verified host-header version is 1.6.8:
test -f /run/host/usr/include/spa-0.2/spa/utils/json-core.h

# Build with the repository's pinned Rust version (the host's ~/.rustup
# toolchain is glibc-2.17-baseline, so it runs in the box; isolated
# CARGO_TARGET_DIRs keep it off the host target/):
distrobox enter peerspeak-appimage -- env \
  PATH="$HOME/.rustup/toolchains/1.97.1-x86_64-unknown-linux-gnu/bin:$PATH" \
  SYSTEM_DEPS_LIBSPA_INCLUDE="/run/host/usr/include/spa-0.2" \
  SYSTEM_DEPS_LIBPIPEWIRE_INCLUDE="/run/host/usr/include/pipewire-0.3:/run/host/usr/include/spa-0.2" \
  ./packaging/appimage/build-appimage.sh
```

## Caveats

- **Hardware encode (VAAPI)** uses the host GPU driver and can't be bundled; the
  software x264 path always works.
- The bundled `pixelpass` is built headless (no `gui` feature) — it is only ever
  driven by peerspeak, never launched standalone from this image.
