9.3 KiB
9.3 KiB
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 | ✅ |
Screen share (via pixelpass)
| Feature | Status | Notes |
|---|---|---|
| Share your screen | ✅ | Spawns pixelpass --host --output json, announces the ticket on presence. src/screenshare/mod.rs. Field-verified desktop↔dopedart 2026-06-06. Capture portal appears on the host when the first viewer connects. |
| Watch a peer's share | ✅ | 👁 Watch spawns a pixelpass viewer → opens the stream in mpv (vlc fallback). Field-verified: laptop watched the desktop's screen. |
| Live badge on sharing peers | ✅ | 🔴 Live on the peer card; 🔴 Sharing badge on the self card. |
| Multiple simultaneous sharers | 🧪 | Discord-style: each sharer is an independent pixelpass host; the room shows one offer per sharer. Single-sharer path verified; concurrent not yet. |
| Late-joiner sees in-progress share | 🧪 | Sharing rides presence, so the existing gossip re-announce delivers the offer to late joiners. Not yet explicitly tested. |
| Graceful "needs pixelpass" state | ✅ | Share button disabled + labelled when the binary isn't on $PATH. Config override: pixelpass_path. |
| Viewer limit | ⚙️ | Not overridden — pixelpass bandwidth-measures its own safe cap (protects the sharer's uplink); refusals surface as an error. |
| Audio of the share | ⚙️ | Video only on the room path (so it can't echo/double with the voice mix). |
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. |
| Per-peer connection badge (direct/relay + RTT, hover for addr/loss/bitrate) | ✅ | Peer-card badge fed by a 1 Hz poll of the live audio link's selected QUIC path (connection_stats → core::connstats::derive). Field-verified on a real 2-machine call 2026-07-08. |
| 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 | ✅ | |
| Canvas-drawn icon set | ✅ | 18 icons (Icon/IconKind in src/app/mod.rs), no image/font dep, theme-recolored. Replaces all emoji; SVG design source in ~/Documents/peerspeak-mockups/icons/. |
| Selectable UI themes | ✅ | 10 palettes (src/theme.rs): Catppuccin Mocha (default)/Macchiato/Frappé/Latte, Dracula, Nord, Tokyo Night, Gruvbox Dark, Solarized Light, Gruvbox Light. Picked via canvas palette swatches in Settings (ThemeSwatch), applied live + persisted (config.theme). All palettes unit-tested for WCAG-AA text legibility. |
Persistence
| Feature | Status | Notes |
|---|---|---|
| Config file | ✅ | ~/.config/peerspeak/config.json. |
| Backward-compatible loading | ✅ | serde defaults fill missing fields; unknown fields tolerated. |
| Window size restored | ✅ | window_width/window_height, saved on close. |
| Window position restored | ✅ | window_x/window_y, saved on close. X11 only — see Platform support. |
Platform support (Linux desktop)
| Concern | Status | Notes |
|---|---|---|
| Wayland | ✅ | Default on this dev box; winit's Wayland backend. App/taskbar icon comes from the .desktop file matched by application_id = "peerspeak". |
| X11 (incl. XWayland) | ✅ | winit's X11 backend (both backends compile in by default; winit auto-selects — Wayland if WAYLAND_DISPLAY is set, else X11 via DISPLAY). Launch verified rendering on X11. The embedded RGBA window icon (from_rgba) is honored on X11 even without the .desktop installed. |
| Window position restore | X11 only | Wayland's xdg-shell gives clients no way to place their own window, so we center there. On X11 the saved window_x/window_y is restored via Position::Specific (outer position; no drift across save/restore — iced's Moved and Position::Specific both use the outer position). Verified live on X11 (saved an off-center position; the window reopened there, not centered). Gated by is_wayland() (src/app/mod.rs); decision logic unit-tested (initial_window_position). |
Known field-test debt (the 🧪 rows above, collected)
Re-run on a real desktop ↔ dopedart call before calling these done:
- Echo cancellation — 2-machine call through speakers (the only path that actually exercises AEC).
- Mix-bus soft limiter — A/B a hot signal.
- Local call recording — solo + 2-machine, verify the WAV.
- In-room text chat — 2-machine delivery.
- Adaptive jitter buffer — behaviour under real packet loss/jitter.
- Chat drawer — toggle + persistence across restart.
- Screen share — single-sharer 2-machine path VERIFIED 2026-06-06
(desktop hosted, laptop watched via mpv). Remaining: multiple concurrent
sharers, late-joiner sees an in-progress share, and Stop clears the peer's
badge. Requires
pixelpass+mpvon both ends.
Not built (candidate features)
Things that came up but do not exist yet:
- Soundboard (play short clips into the call mix).
- Invite links beyond the raw ticket / room persistence.