Add headless streaming mode + Mac client + full docs
Headless mode (new) — for KVM-attached hosts streaming to disconnected clients - --headless / --mirror flags; default headless on hostname JARVIS, mirror elsewhere - New lib/headless.sh installs prep-cmd hooks to ~/.local/share/omarchy-moonlight/bin - bin/sunshine-stream-do.sh creates/resizes a Hyprland HEADLESS-1 output to the connecting client's resolution and migrates the active workspace onto it - bin/sunshine-stream-undo.sh tears down the headless output on disconnect and returns the workspace to a non-headless monitor when one is available - lib/config.sh writes capture=wlr, output_name=HEADLESS-1, and the JSON global_prep_cmd entry referencing the installed hook paths - lib/preflight.sh adds a preflight_headless step that checks hyprctl, jq, and a running Hyprland session (warn-only, install can proceed) - lib/verify.sh adds checks for the hook scripts and the wlr/global_prep_cmd config lines Mac client - client/install-macos.sh: Darwin guard, Homebrew presence check, brew cask install of Moonlight, idempotent - client/README.md: per-platform install (macOS / Android / iOS / Apple TV / Linux + Steam Deck) and the five-step first-pair walkthrough Other - jq added to the helper install set in lib/packages.sh (hooks parse Hyprland JSON output) - README.md rewritten to cover both modes, the new flags, the tuned defaults per mode + per vendor, the headless internals, and the client pointer
This commit is contained in:
125
client/README.md
Normal file
125
client/README.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Moonlight clients
|
||||
|
||||
This directory covers installing Moonlight on the devices that connect to your
|
||||
Sunshine host. The host side (Sunshine on Linux) is documented in the
|
||||
[top-level README](../README.md).
|
||||
|
||||
## Install
|
||||
|
||||
### macOS
|
||||
|
||||
From a Mac that has this repo checked out:
|
||||
|
||||
```sh
|
||||
./client/install-macos.sh
|
||||
```
|
||||
|
||||
The script verifies Homebrew is present and runs `brew install --cask moonlight`.
|
||||
It will not install Homebrew for you.
|
||||
|
||||
Manual equivalent:
|
||||
|
||||
```sh
|
||||
brew install --cask moonlight
|
||||
```
|
||||
|
||||
Fallback (no Homebrew): download a signed DMG from the official releases page
|
||||
and drag `Moonlight.app` into `/Applications`:
|
||||
|
||||
- https://github.com/moonlight-stream/moonlight-qt/releases
|
||||
|
||||
### Android
|
||||
|
||||
Install "Moonlight Game Streaming" from the Play Store:
|
||||
|
||||
- https://play.google.com/store/apps/details?id=com.limelight
|
||||
|
||||
### iOS / iPadOS
|
||||
|
||||
Install "Moonlight Game Streaming" from the App Store:
|
||||
|
||||
- https://apps.apple.com/us/app/moonlight-game-streaming/id1000551566
|
||||
|
||||
### Apple TV
|
||||
|
||||
Same listing on the tvOS App Store. Search "Moonlight Game Streaming" on the
|
||||
Apple TV itself, or use the App Store link above from an iOS device signed in
|
||||
to the same Apple ID.
|
||||
|
||||
### Steam Deck / Linux
|
||||
|
||||
Use `moonlight-qt` from your distro's package manager (Flatpak on Steam Deck,
|
||||
`pacman`/`apt` elsewhere). It is the same Qt-based client as macOS and Windows.
|
||||
|
||||
## First pair
|
||||
|
||||
The pairing flow is the same on every client.
|
||||
|
||||
1. Confirm the host is healthy. On the host machine:
|
||||
|
||||
```sh
|
||||
./install.sh --doctor
|
||||
```
|
||||
|
||||
Sunshine must be running and reachable on the LAN.
|
||||
|
||||
2. On the client, open Moonlight. The host should appear automatically via
|
||||
mDNS as long as the client is on the same LAN. If it does not appear, use
|
||||
"Add Host Manually" and enter the host's LAN IP address.
|
||||
|
||||
3. Click or tap the host. Moonlight displays a 4-digit PIN.
|
||||
|
||||
4. On the host machine, open the Sunshine web UI:
|
||||
|
||||
```
|
||||
https://localhost:47990
|
||||
```
|
||||
|
||||
Accept the self-signed certificate. Log in (credentials are set the first
|
||||
time you visit). Go to the PIN tab, enter the 4-digit PIN from the client,
|
||||
and submit. Pairing typically completes within about 5 seconds.
|
||||
|
||||
5. Back in Moonlight, the host now shows as "Paired". Click it to see the
|
||||
available apps. The default app is "Desktop", which is either a full-screen
|
||||
mirror of the host's display or a headless virtual display, depending on
|
||||
how the host is configured.
|
||||
|
||||
## Streaming notes
|
||||
|
||||
- **Resolution.** Moonlight lets you pick a target stream resolution per host.
|
||||
On a headless-configured host, that resolution is what the host actually
|
||||
renders at. On a mirror-configured host, the host renders at its native
|
||||
resolution and Moonlight downscales on the client.
|
||||
|
||||
- **Bitrate.** Moonlight's defaults are conservative for general internet use.
|
||||
For LAN streaming, bump it to 50-100 Mbps.
|
||||
|
||||
- **Audio.** By default, Moonlight captures audio from the host and plays it
|
||||
on the client. If you want the host's speakers/monitor to keep playing
|
||||
audio while you stream, enable "Play audio on host" in Moonlight's stream
|
||||
settings.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **"Host not found" / host does not appear automatically.** Confirm both
|
||||
machines are on the same LAN/VLAN. mDNS does not traverse VLANs without an
|
||||
mDNS reflector. Fall back to "Add Host Manually" with the host's IP.
|
||||
|
||||
- **Pairing PIN does not work.** Two common causes: the Sunshine web UI
|
||||
session has timed out (log in again and re-enter the PIN), or the PIN is
|
||||
being entered into the wrong host (multiple Sunshine instances on the LAN).
|
||||
Cancel and re-trigger pair from the client to get a fresh PIN.
|
||||
|
||||
- **Black screen after pairing.** This is a host-side problem. On the host:
|
||||
|
||||
```sh
|
||||
./install.sh --doctor
|
||||
```
|
||||
|
||||
- **Mac cannot reach `brew`.** Homebrew is not installed (or not on `PATH`).
|
||||
Install it per https://brew.sh, open a fresh shell, then re-run
|
||||
`./client/install-macos.sh`.
|
||||
|
||||
- **Android sees the host but cannot connect.** The Android device is
|
||||
probably on a guest WiFi SSID that is isolated from the main LAN. Move it
|
||||
to the main LAN, or use "Add Host Manually" with the host IP.
|
||||
61
client/install-macos.sh
Executable file
61
client/install-macos.sh
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
# Install Moonlight on macOS via Homebrew cask.
|
||||
# Standalone: does not source lib/common.sh (intended to run on a Mac that
|
||||
# may not have the full repo checked out yet).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -t 1 ]]; then
|
||||
BOLD=$'\033[1m'
|
||||
RED=$'\033[31m'
|
||||
GREEN=$'\033[32m'
|
||||
YELLOW=$'\033[33m'
|
||||
BLUE=$'\033[34m'
|
||||
RESET=$'\033[0m'
|
||||
else
|
||||
BOLD="" RED="" GREEN="" YELLOW="" BLUE="" RESET=""
|
||||
fi
|
||||
|
||||
step() { printf '\n%s==>%s %s%s%s\n' "$BLUE" "$RESET" "$BOLD" "$*" "$RESET"; }
|
||||
info() { printf ' %s\n' "$*"; }
|
||||
ok() { printf ' %s✓%s %s\n' "$GREEN" "$RESET" "$*"; }
|
||||
warn() { printf ' %s!%s %s\n' "$YELLOW" "$RESET" "$*" >&2; }
|
||||
err() { printf ' %s✗%s %s\n' "$RED" "$RESET" "$*" >&2; }
|
||||
|
||||
# Refuse to run anywhere but macOS.
|
||||
if [[ "$(uname -s)" != "Darwin" ]]; then
|
||||
err "This script only runs on macOS (Darwin). Detected: $(uname -s)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
step "Checking for Homebrew"
|
||||
if ! command -v brew >/dev/null 2>&1; then
|
||||
err "Homebrew is not installed."
|
||||
info "Install it with the official one-liner, then re-run this script:"
|
||||
info ""
|
||||
info ' /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'
|
||||
info ""
|
||||
info "See https://brew.sh for details."
|
||||
exit 1
|
||||
fi
|
||||
ok "Homebrew found: $(command -v brew)"
|
||||
|
||||
step "Installing Moonlight (brew cask)"
|
||||
# brew install --cask is idempotent: re-running on an already-installed cask
|
||||
# is a no-op and exits 0.
|
||||
if brew install --cask moonlight; then
|
||||
ok "Moonlight installed (or already present)."
|
||||
else
|
||||
err "brew install --cask moonlight failed."
|
||||
warn "Try: brew update && brew install --cask moonlight"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
step "Next steps"
|
||||
info "App location: /Applications/Moonlight.app"
|
||||
info "Launch: open -a Moonlight"
|
||||
info ""
|
||||
info "Pair this Mac with your Sunshine host by following the walkthrough in:"
|
||||
info " client/README.md"
|
||||
info ""
|
||||
ok "Done."
|
||||
Reference in New Issue
Block a user