From c28b045a3b79db2c84627f650c5f676f4c50c310 Mon Sep 17 00:00:00 2001 From: Kenth Fagerlund Date: Wed, 9 Sep 2026 07:13:15 +0100 Subject: [PATCH] chore(release): bump version to v0.5.0 --- AGENTS.md | 1 + Formula/halpradio.rb | 10 +++++----- README.md | 41 ++++++++++++++++++++++++++++++++++++++++- SECURITY.md | 1 + docs/ARCHITECTURE.md | 6 ++++-- docs/PACKAGING.md | 10 +++++----- install.sh | 2 +- pkg/app/app.go | 2 +- 8 files changed, 58 insertions(+), 15 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 8447f42..261392d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -40,6 +40,7 @@ halpradio/ ├── pkg/ ├── app/app.go # CLI flags (-backend, -theme, -version), config loading, tea.Program setup ├── player/player.go # Player interface, Manager struct, multi-backend exec, native Oto audio, ICY stream listener + ├── party/ # P2P mesh synchronized radio rooms, Argon2id/AES-256-GCM E2EE & protocol engine ├── plugin/ # Wazero Wasm sandbox, capability permissions, host API, registry client ├── radio/ # Store (bundled/local/favorites), Station struct, RadioBrowser HTTP client ├── theme/theme.go # Theme struct & color palettes (tokyonight, catppuccin, synthwave, nord, gruvbox, dracula) diff --git a/Formula/halpradio.rb b/Formula/halpradio.rb index 0cb01ec..4a866ad 100644 --- a/Formula/halpradio.rb +++ b/Formula/halpradio.rb @@ -4,22 +4,22 @@ class Halpradio < Formula desc "LazyVim-inspired Terminal Internet Radio Streamer" homepage "https://github.com/halpworld/halpradio" - version "0.4.0" + version "0.5.0" license "GPL-3.0-or-later" on_macos do if Hardware::CPU.arm? - url "https://github.com/halpworld/halpradio/releases/download/v0.4.0/halpradio_0.4.0_darwin_arm64.tar.gz" + url "https://github.com/halpworld/halpradio/releases/download/v0.5.0/halpradio_0.5.0_darwin_arm64.tar.gz" else - url "https://github.com/halpworld/halpradio/releases/download/v0.4.0/halpradio_0.4.0_darwin_amd64.tar.gz" + url "https://github.com/halpworld/halpradio/releases/download/v0.5.0/halpradio_0.5.0_darwin_amd64.tar.gz" end end on_linux do if Hardware::CPU.arm? && Hardware::CPU.is_64_bit? - url "https://github.com/halpworld/halpradio/releases/download/v0.4.0/halpradio_0.4.0_linux_arm64.tar.gz" + url "https://github.com/halpworld/halpradio/releases/download/v0.5.0/halpradio_0.5.0_linux_arm64.tar.gz" else - url "https://github.com/halpworld/halpradio/releases/download/v0.4.0/halpradio_0.4.0_linux_amd64.tar.gz" + url "https://github.com/halpworld/halpradio/releases/download/v0.5.0/halpradio_0.5.0_linux_amd64.tar.gz" end end diff --git a/README.md b/README.md index 4ab8630..66a574a 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ docker run --rm -it --device /dev/snd halpworld/halpradio:latest | **Linux MPRIS v2 & Media Keys** | ✅ **Native D-Bus + `playerctl`** | ❌ None | ❌ None | ❌ None | ⚠️ Basic MPRIS | | **Song Change Desktop Notifications** | ✅ **Native macOS/Linux/Win + Dedupe** | ❌ None | ❌ None | ❌ None | ❌ None | | **CLI & Hotkey Remote (`halpradio remote`)** | ✅ **macOS Shortcuts, Raycast, tmux** | ❌ None | ❌ None | ❌ None | ⚠️ Socket | +| **Terminal Party Line (`Ctrl+p`)** | ✅ **P2P Mesh Sync, E2EE Rooms & Reactions** | ❌ None | ❌ None | ❌ None | ❌ None | | **Acoustic Fingerprinting (`I`)** | ✅ **Chromaprint / AcoustID + Ad Strip** | ❌ None | ❌ None | ❌ None | ❌ None | | **Pomodoro & Sleep Timers (`z`)** | ✅ **Intervals, Station Switch & OS Notify** | ❌ None | ❌ None | ❌ None | ⚠️ Basic sleep | | **Beat-Reactive Animated Visualizers** | ✅ **5 Animal DJs + EQ Spectrum** | ❌ None | ❌ None | ❌ None | ⚠️ Basic VU | @@ -321,6 +322,42 @@ Internet radio ICY streams often emit dirty titles like: --- +## 🎉 Terminal Party Line: P2P Mesh Synchronized Radio Rooms & Reactions + +Share the groove with teammates, study groups, or friends with zero central audio relaying! `halpradio` features an end-to-end encrypted (E2EE) P2P mesh party system powered by WebRTC data channels: + +### 👥 In-TUI Party Manager (`Ctrl+p`) +- **Quick Create & Join**: Press `Ctrl+p` anywhere in the app to host a new room with a memorable 6-character room code (e.g. `#8X2K9P`) or join an existing session. +- **Argon2id & AES-256-GCM Encryption**: Every party room derives high-entropy session keys with Argon2id and encrypts all peer-to-peer control traffic using AES-256-GCM with CSPRNG nonces. +- **Zero Central Audio Relaying**: Audio streams directly from the source radio broadcast on each client while synchronization commands and metadata travel peer-to-peer over WebRTC data channels. +- **DJ Pass Governance**: Host can choose **Host Only** (only the room creator can change stations) or **Open Democracy** (any participant can tune stations). +- **Sub-Second Playback Sync**: Late-joining listeners automatically tune to the room's current broadcast with sub-second clock sync. +- **Deterministic Host Election**: If the room host disconnects, peers deterministically elect a successor host without interrupting playback. + +### 🎈 Live ASCII Reactions & Mini-Chat +- While in an active party room, press `1` - `5` anytime to float live reactions across connected listeners' terminals: + - `1`: 🔥 Fire + - `2`: ❤️ Heart + - `3`: ☕ Coffee + - `4`: 🚀 Rocket + - `5`: 👀 Eyes +- Floating reactions rise and decay gracefully over 3.5 seconds in the party bar without disturbing your TUI view. + +### ⌨️ CLI Party Commands +Control and join party rooms directly from your shell or tmux sessions: +```bash +halpradio party create "team-focus" # Create room and launch TUI +halpradio party create --dj-pass=open # Create room with democratic DJ control +halpradio party create --headless # Host room headlessly in server / tmux +halpradio party join 8X2K9P # Join room #8X2K9P with interactive TUI +halpradio party status # Inspect current room, listener count, and host +halpradio party react 1 # Send 🔥 reaction to current room +halpradio party chat "Loving this track!" # Send mini-chat ping to room +halpradio party leave # Disconnect from current room +``` + +--- + ## ⌨️ Navigation & Keybindings (Vim & Media Style) Press `?` or `F1` anywhere in **halpradio** to open the floating **WhichKey Overlay**. @@ -338,7 +375,9 @@ Press `?` or `F1` anywhere in **halpradio** to open the floating **WhichKey Over | | `0` / `F` | Jump directly to Analog Frequency Tuner (experimental) | | | `g` / `G` | Jump to top / bottom of list | | | `Ctrl+u` / `Ctrl+d` | Half page up / down | -| **Discovery & Sharing** | `I` | **Identify playing track** via acoustic stream fingerprinting (Chromaprint / AcoustID) | +| **Discovery & Sharing** | `Ctrl+p` | Open **Party Room Manager** (P2P mesh synchronized listening & room setup) | +| | `1` - `5` | Send live floating ASCII reaction (🔥 ❤️ ☕ 🚀 👀) when in Party Room | +| | `I` | **Identify playing track** via acoustic stream fingerprinting (Chromaprint / AcoustID) | | | `y` | Yank / copy track metadata (`Artist - Title`) or identified song to system clipboard | | | `o` | Open streaming search in default web browser (Spotify, YT Music, Apple, DDG, Google) | | | `s` | Star / bookmark track to `~/.config/halpradio/saved_tracks.txt` (on History tab) | diff --git a/SECURITY.md b/SECURITY.md index 49b6b40..7349613 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,6 +6,7 @@ We actively provide security patches and updates for the following versions of * | Version | Supported | | ------- | ------------------ | +| 0.5.x | :white_check_mark: | | 0.4.x | :white_check_mark: | | 0.3.x | :white_check_mark: | | 0.2.x | :white_check_mark: | diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 9cb798e..7810658 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -55,12 +55,13 @@ halpradio/ ├── app/ # CLI flag parsing, configuration loading & app bootstrap ├── player/ # Multi-backend audio playback engine & ICY stream reader │ └── fingerprint/ # Acoustic stream recognition, Chromaprint / AcoustID client, LRU cache + ├── party/ # P2P mesh synchronized radio rooms, Argon2id/AES-256-GCM E2EE & protocol engine ├── plugin/ # Wazero Wasm sandboxing engine, capability permissions, host API, registry client ├── radio/ # Station catalog store, YAML parser, RadioBrowser client & metadata sanitizer ├── theme/ # Theme definitions & color palette registry ├── timer/ # Pomodoro focus engine, sleep timer with volume fade, and OS event dispatcher ├── ui/ # Main Bubble Tea Model, Update, View, and Keymap logic - │ └── components/ # Modular UI sub-views (Header, StationList, PlayerBar, Visualizer, Modals) + │ └── components/ # Modular UI sub-views (Header, StationList, PlayerBar, Visualizer, Modals, PartyBar) └── util/ # OS configuration directory resolution & clipboard utilities ``` @@ -68,7 +69,8 @@ halpradio/ | Package | Key Types / Files | Responsibilities | |---|---|---| -| [`pkg/app`](../pkg/app/app.go) | `Run()`, `RunPluginCLI()` | Parses CLI flags (`--backend`, `--theme`, `--version`, `--fingerprint`, `--auto-identify`), handles CLI subcommands (`remote`, `plugin`), sets up store, instantiates `player.Manager`, initializes `tea.Program`. | +| [`pkg/app`](../pkg/app/app.go) | `Run()`, `RunPluginCLI()` | Parses CLI flags (`--backend`, `--theme`, `--version`, `--fingerprint`, `--auto-identify`), handles CLI subcommands (`remote`, `plugin`, `party`), sets up store, instantiates `player.Manager`, initializes `tea.Program`. | +| [`pkg/party`](../pkg/party/sync.go) | `Session`, `MeshNode`, `Packet`, `Crypto` | P2P mesh synchronized radio rooms, WebRTC data channels, Argon2id key derivation & AES-256-GCM encryption, sub-second playback sync, host election, ASCII reaction bus. | | [`pkg/player`](../pkg/player/player.go) | `Player`, `Manager`, `TrackInfo` | Detects audio CLI backends (`mpv`, `vlc`, `ffplay`, etc.) or falls back to native Go audio. Runs ICY metadata streaming goroutine. | | [`pkg/player/fingerprint`](../pkg/player/fingerprint/client.go) | `Client`, `Result`, `LRUCache` | Captures 5s audio buffers, computes Chromaprint subfingerprints, queries AcoustID & MusicBrainz APIs with LRU caching. | | [`pkg/plugin`](../pkg/plugin/manager.go) | `Manager`, `Sandbox`, `Manifest`, `RegistryClient` | Executes sandboxed WebAssembly plugins via Wazero with capability checks (`network`, `storage`, `events`). Fetches and verifies official registry packages. | diff --git a/docs/PACKAGING.md b/docs/PACKAGING.md index bd05a0e..68a6da1 100644 --- a/docs/PACKAGING.md +++ b/docs/PACKAGING.md @@ -26,7 +26,7 @@ For Arch Linux users, the binary package can be built using the following `PKGBU ```bash # Maintainer: halpworld pkgname=halpradio-bin -pkgver=0.4.0 +pkgver=0.5.0 pkgrel=1 pkgdesc="LazyVim-inspired Terminal Internet Radio Streamer" arch=('x86_64' 'aarch64') @@ -88,17 +88,17 @@ For Windows users using [Scoop](https://scoop.sh): ```json { - "version": "0.4.0", + "version": "0.5.0", "description": "LazyVim-inspired Terminal Internet Radio Streamer", "homepage": "https://github.com/halpworld/halpradio", "license": "GPL-3.0-or-later", "architecture": { "64bit": { - "url": "https://github.com/halpworld/halpradio/releases/download/v0.4.0/halpradio_0.4.0_windows_amd64.zip", + "url": "https://github.com/halpworld/halpradio/releases/download/v0.5.0/halpradio_0.5.0_windows_amd64.zip", "bin": "halpradio.exe" }, "arm64": { - "url": "https://github.com/halpworld/halpradio/releases/download/v0.4.0/halpradio_0.4.0_windows_arm64.zip", + "url": "https://github.com/halpworld/halpradio/releases/download/v0.5.0/halpradio_0.5.0_windows_arm64.zip", "bin": "halpradio.exe" } } @@ -114,7 +114,7 @@ For Windows users using [Scoop](https://scoop.sh): buildGoModule rec { pname = "halpradio"; - version = "0.4.0"; + version = "0.5.0"; src = fetchFromGitHub { owner = "halpworld"; diff --git a/install.sh b/install.sh index 9b8d301..a1967b4 100755 --- a/install.sh +++ b/install.sh @@ -33,7 +33,7 @@ if [ -z "${VERSION}" ]; then echo "🔍 Fetching latest halpradio release..." VERSION=$(curl -s "https://api.github.com/repos/${REPO}/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') if [ -z "${VERSION}" ]; then - VERSION="v0.4.0" + VERSION="v0.5.0" fi fi diff --git a/pkg/app/app.go b/pkg/app/app.go index a7916b6..7c4cdab 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -22,7 +22,7 @@ import ( "github.com/halpworld/halpradio/pkg/util" ) -var Version = "0.4.0" +var Version = "0.5.0" type AppInstance struct { Program *tea.Program