Files
peerspeak/docs/FEATURES.md
T
molluskandClaude Fable 5 76c62e5ac3
CI / check (push) Failing after 5s
cargo-deny / cargo-deny (push) Has been cancelled
windows-build / windows-build (push) Has been cancelled
docs: mark connection badge field-verified (2-machine call 2026-07-08)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 17:07:54 -04:00

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_statscore::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:

  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.
  7. 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 + mpv on 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.