diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f379431..752d824 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,10 +1,42 @@ -## v0.3.1 (2026-05-25) +## v0.4.0 (2026-05-28) -Hotfix for the v0.3.0 production-readiness release: the new WebSocket Origin allow-list rejected same-origin connections from any LAN IP, breaking the Web UI on `host: 0.0.0.0` deployments unless `cors_origins` was explicitly configured. +Two headline changes since v0.3.1: **Media Server now ships first-class Linux and macOS builds** (no more Windows-only), and the **Windows app icon was redesigned** with a proper multi-resolution ICO so the installer, Start Menu, desktop shortcut, Alt+Tab, and system tray all render sharp. + +### Features + +- **Linux support, production-ready.** New `linux` extra (`dbus-python`, `PyGObject`, `python-xlib`) plus a `build-dist-linux.sh` that emits a portable tarball and a systemd user unit. The unit sets `DBUS_SESSION_BUS_ADDRESS`, `XDG_RUNTIME_DIR`, and `ReadWritePaths` for `~/.config` / `~/.cache` so MPRIS works and audit-log / thumbnail writes aren't blocked by `ProtectHome`. The Linux MPRIS controller now connects to the session bus lazily — a missing or late bus no longer crashes lifespan startup, and the user is logged a one-line hint about `loginctl enable-linger`. ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c)) +- **macOS support.** New `macos` extra (`pyobjc-framework-Cocoa`, `pyobjc-framework-Quartz`), a `build-dist-macos.sh` script, and a per-user LaunchAgent installer producing `MediaServer-vX.Y-macos-{arm64,x86_64}.tar.gz` artifacts. Spotify URL artwork is wired through `MediaController.get_album_art()`. ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c)) +- **Cross-platform album artwork.** `MediaController.get_album_art()` is now abstract with Linux (`mpris:artUrl`, `file://` + `http(s)://`) and macOS (Spotify URL) implementations; the `/api/media/artwork` endpoint awaits the controller. ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c)) +- **Per-OS unavailable reasons on `/api/media/visualizer/status`** so the Web UI can explain *why* the visualizer is off on Linux / macOS instead of just hiding it. ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c)) +- **Startup preflight on Linux** warns when `DBUS_SESSION_BUS_ADDRESS` or `XDG_RUNTIME_DIR` is unset and informs the user when running under Wayland disables the foreground-window probe — so silent loss of features is now diagnosable from the log. ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c)) +- **Redesigned app icon ("Beacon").** Replaces the generic Spotify-green circle with a refined squircle + deep-teal diagonal gradient (`#0B3D3B → #1A6B5E`) + warm parchment play triangle (`#F5F1E8`) with a drop shadow, top sheen, and ghosted echo-chevrons that hint at broadcast/stream. ([d798fed](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/d798fed)) +- **Multi-resolution Windows ICO.** `icon.ico` grew from a single 16×16 frame (208 B) to a 10-frame ICO (16/20/24/32/40/48/64/96/128/256 — ~37 KB) so Windows no longer upscales 16×16 into mush for the installer chrome, Start Menu, desktop shortcuts, Alt+Tab, and File Explorer tiles. ([d798fed](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/d798fed)) +- **System tray uses the new icon.** `tray.py` now picks a 64×64 frame from the multi-res ICO; the procedural fallback was reskinned to the same Beacon palette so a missing ICO no longer regresses the tray back to the old Spotify-green circle. ([d798fed](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/d798fed)) ### Bug Fixes -- **WebSocket Origin check now accepts same-origin connections.** When `cors_origins` is unset, the default allow-list was hard-coded to `http://localhost:` + `http://127.0.0.1:`, so a browser opening the UI via the LAN IP (e.g. `http://192.168.2.100:8765`) had its WebSocket closed with code 4003 ("Origin not allowed") and never recovered. The endpoint now also accepts any `Origin` whose authority matches the request's `Host` header (with either `http://` or `https://` scheme) — same-origin connections are by definition not CSWSH, so the cross-origin defence introduced in v0.3.0 is preserved. ([9b9a2b5](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/9b9a2b5)) +- **`tray._confirm` guarded against `ctypes.windll` on non-Windows** so the new Linux / macOS builds don't crash when the tray prompts for confirmation. ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c)) +- **`config.example.yaml` defaults are now cross-platform.** Per-OS commented examples for the on/off scripts, and `on_turn_off` defaults to a harmless `echo` (the previous default silently failed everywhere but Windows). ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c)) + +--- + +### Development / Internal + +#### Build & Packaging + +- **`scripts/generate-icon.py`** — SVG is the canonical source; `resvg-py` rasterizes every ICO size; Pillow packs the multi-resolution `icon.ico`. Re-run any time the SVG changes. ([d798fed](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/d798fed)) +- **Dependency reorganization in `pyproject.toml`** — `screen-brightness-control` and `monitorcontrol` are cross-platform and moved to base deps; new `linux` and `macos` optional-deps groups with `sys_platform` markers. `resvg-py` added to `[dev]` for the icon-generation script. ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c), [d798fed](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/d798fed)) +- **`install_linux.sh`** — dropped the dead `requirements.txt` path; now installs via `pip install ".[linux]"` and pre-creates the writable state dirs. ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c)) +- **Templated `media-server.service`** updated to match the new dist layout, with proper session-bus env vars and a writable state-dir grant. ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c)) + +#### CI + +- **New `linux-smoke` job** in `.gitea/workflows/test.yml` — installs `.[linux]`, boots the server under `dbus-run-session`, and asserts `/api/health`. Catches dependency-resolution and import-time regressions for the Linux dist path. ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c)) +- **Release workflow gains apt-deps step** for the Linux build and a best-effort macOS build job that produces the per-arch macOS tarballs. ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c)) + +#### Documentation + +- **README rewritten for the new extras** — replaces the stale `pip install -r requirements.txt` instructions, adds a systemd-lingering note + troubleshooting section, and a macOS LaunchAgent section. ([ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c)) --- @@ -13,6 +45,7 @@ Hotfix for the v0.3.0 production-readiness release: the new WebSocket Origin all | Hash | Message | Author | |------|---------|--------| -| [9b9a2b5](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/9b9a2b5) | fix(ws): accept same-origin WebSocket connections in default Origin allow-list | alexei.dolgolyov | +| [d798fed](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/d798fed) | feat(icon): redesign app icon as "Beacon" and ship multi-resolution ICO | alexei.dolgolyov | +| [ddf4a6c](https://git.dolgolyov-family.by/alexei.dolgolyov/media-player-server/commit/ddf4a6c) | feat: production-ready Linux & macOS support | alexei.dolgolyov | diff --git a/package-lock.json b/package-lock.json index 3b2b820..fd1809d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "media-server-frontend", - "version": "0.2.7", + "version": "0.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "media-server-frontend", - "version": "0.2.7", + "version": "0.4.0", "devDependencies": { "esbuild": "^0.27.4" } diff --git a/package.json b/package.json index 59a277a..c70cf8d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "media-server-frontend", - "version": "0.3.0", + "version": "0.4.0", "private": true, "description": "Frontend build tooling for media server WebUI", "scripts": { diff --git a/pyproject.toml b/pyproject.toml index c75e70d..001085d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "media-server" -version = "0.3.1" +version = "0.4.0" description = "REST API server for controlling system-wide media playback" readme = "README.md" license = { text = "MIT" }