docs: add user-facing feature inventory with field-test status
Capability list of what PeerSpeak already does, companion to ARCHITECTURE.md, so the feature surface doesn't have to be re-derived from the code each session. Marks each row verified / tests-green / plumbing, and collects the outstanding 2-machine field-test debt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,132 @@
|
|||||||
|
# PeerSpeak Feature Inventory
|
||||||
|
|
||||||
|
A capability list of what PeerSpeak **already does**, so we don't keep
|
||||||
|
re-deriving it. This is the user-facing companion to `ARCHITECTURE.md` (which
|
||||||
|
covers internals). When you ship a feature, add it here.
|
||||||
|
|
||||||
|
**Field-test status legend:**
|
||||||
|
|
||||||
|
- ✅ **Verified** — confirmed working on a real call (usually desktop ↔ dopedart).
|
||||||
|
- 🧪 **Tests-green** — unit-tested and/or smoke-tested locally, but **not** yet
|
||||||
|
exercised on a real 2-machine call. Treat as unproven.
|
||||||
|
- ⚙️ **Plumbing** — wiring/persistence that has no separate field test of its own.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rooms & sessions
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Create a room → shareable join ticket | ✅ | Ticket carries host addr + topic id. |
|
||||||
|
| Join a room via ticket | ✅ | Paste ticket on the launch screen. |
|
||||||
|
| Leave a room | ✅ | |
|
||||||
|
| Multi-peer rooms (mesh) | ✅ | Presence over the iroh gossip plane. |
|
||||||
|
| Copy ticket to clipboard | ✅ | Button on the room screen. |
|
||||||
|
| Remembered nickname | ✅ | `config.username` pre-fills the launch field, saved on join/create. |
|
||||||
|
| In-call duration timer | ✅ | `call_started` drives the header clock. |
|
||||||
|
|
||||||
|
## Audio I/O & codec
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| PipeWire capture + playback | ✅ | `src/audio/pipewire_impl.rs`. |
|
||||||
|
| Input device selection | ✅ | |
|
||||||
|
| Output device selection | ✅ | |
|
||||||
|
| App-internal input (mic) gain slider | ✅ | Unity default; applied pre-gate/encode. |
|
||||||
|
| App-internal output gain slider | ✅ | Unity default; applied on the mixed output. |
|
||||||
|
| Opus codec | ✅ | 48 kHz mono, `Application::Voip`, 20 ms / 960-sample frames. |
|
||||||
|
| Adaptive jitter buffer + Opus PLC | 🧪 | `src/core/jitter.rs`; reorders by seq, adaptive playout delay, conceals drops. Not field-tested. |
|
||||||
|
|
||||||
|
## Voice controls
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Self mute | ✅ | |
|
||||||
|
| Deafen | ✅ | |
|
||||||
|
| Push-to-talk + rebindable hotkey | ✅ | `TogglePtt` / `StartSettingHotkey`; gate ahead of the encoder. |
|
||||||
|
| Noise gate (hysteresis + attack/release/hangover) | ✅ | `src/audio/gate.rs`. |
|
||||||
|
| Draggable gate threshold on the mic meter | ✅ | Discord/OBS-style `GateMeter` canvas widget. |
|
||||||
|
| Mic level meter — in-call | ✅ | |
|
||||||
|
| Mic level meter — off-call "Test mic" | ✅ | `SetMicMonitor` / standalone capture stream. |
|
||||||
|
| Mix-bus soft limiter | 🧪 | `src/audio/limiter.rs`; A/B never confirmed on a real call. |
|
||||||
|
| Echo cancellation (opt-in) | 🧪 | `src/audio/echo_cancel.rs`; PipeWire `module-echo-cancel` (WebRTC AEC+NS+AGC) via RAII pactl guard. **Needs a 2-machine call through speakers, not headphones.** |
|
||||||
|
|
||||||
|
## Per-peer controls
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Per-peer volume | ✅ | `SetPeerVolume`. |
|
||||||
|
| Per-peer local mute | ✅ | Still decoded (levels show) but not mixed. |
|
||||||
|
| Per-peer speaking indicator | ✅ | `audio_levels` per `EndpointId`. |
|
||||||
|
|
||||||
|
## Text chat
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| In-room text chat | 🧪 | Over the gossip plane; full-width bottom-dock UI. 2-machine delivery not confirmed. |
|
||||||
|
| Outgoing + incoming sanitization | ✅ | `sanitize_chat`: strips control chars, collapses whitespace, caps 2000. |
|
||||||
|
| History cap | ⚙️ | `CHAT_HISTORY_MAX = 300`. |
|
||||||
|
| Local echo of own messages | ✅ | |
|
||||||
|
|
||||||
|
## Recording
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Local call recording (mic + incoming mix → WAV) | 🧪 | `src/audio/recorder.rs`; writes to `~/peerspeak-recordings/`. Solo + 2-machine recording not confirmed. Header REC timer present. |
|
||||||
|
|
||||||
|
## Notifications & sounds
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Desktop notifications toggle | ✅ | `notifications_enabled`. |
|
||||||
|
| Event chimes | ✅ | 8 events: self-join, peer-join, peer-leave, reconnect-attempt, reconnected, self-leave, mic-toggle, reconnect-failed. |
|
||||||
|
| Per-event custom sound override | ✅ | `custom_sound_*` paths in config. |
|
||||||
|
|
||||||
|
## Networking & privacy
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| iroh QUIC transport | ✅ | |
|
||||||
|
| Network mode picker | ✅ | `RelayNoDiscovery` (default), `N0Full`, `DirectOnly`. Takes effect next join. |
|
||||||
|
| Retained-address reconnect | ✅ | Dials last-known full addr before falling back to bare id. |
|
||||||
|
| Reconnect + eviction model | ✅ | Incl. two-outage reconnect-eviction fix + regression test. |
|
||||||
|
| Self-hosted relay | ❌ | Decided against — rely on n0 relays, `RelayNoDiscovery` default. |
|
||||||
|
|
||||||
|
## UI & layout
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Selectable room layouts | ✅ | 3-Column, Bottom Dock (default), Drawer. |
|
||||||
|
| Layout picker popup w/ canvas thumbnails | ✅ | `LayoutThumb`, no image dependency. |
|
||||||
|
| Draggable + persisted panel dividers | ✅ | Per-layout, clamped to window; saved on drag-release. |
|
||||||
|
| Chat drawer toggle (drawer layout) | 🧪 | Toggle + restart-persistence not explicitly confirmed. |
|
||||||
|
| Responsive full-window Settings screen | ✅ | |
|
||||||
|
|
||||||
|
## Persistence
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Config file | ✅ | `~/.config/peerspeak/config.json`. |
|
||||||
|
| Backward-compatible loading | ✅ | serde `default`s fill missing fields; unknown fields tolerated. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Known field-test debt (the 🧪 rows above, collected)
|
||||||
|
|
||||||
|
Re-run on a real desktop ↔ dopedart call before calling these done:
|
||||||
|
|
||||||
|
1. **Echo cancellation** — 2-machine call *through speakers* (the only path that
|
||||||
|
actually exercises AEC).
|
||||||
|
2. **Mix-bus soft limiter** — A/B a hot signal.
|
||||||
|
3. **Local call recording** — solo + 2-machine, verify the WAV.
|
||||||
|
4. **In-room text chat** — 2-machine delivery.
|
||||||
|
5. **Adaptive jitter buffer** — behaviour under real packet loss/jitter.
|
||||||
|
6. **Chat drawer** — toggle + persistence across restart.
|
||||||
|
|
||||||
|
## Not built (candidate features)
|
||||||
|
|
||||||
|
Things that came up but **do not** exist yet:
|
||||||
|
|
||||||
|
- Soundboard (play short clips into the call mix).
|
||||||
|
- Video / screen share.
|
||||||
|
- Invite links beyond the raw ticket / room persistence.
|
||||||
Reference in New Issue
Block a user