Record the most recent runtime error (capture, encode, packet, audio)
in the engine and expose it via Status.Err. The GUI shows it in the
status label (highlighted as a danger) and in the tray tooltip, so a
denied screen-share or encoder failure is visible without reading logs.
Document the two ports TeleportFling needs (TCP 9756 stream, UDP 9999
multicast discovery) and how to open them on NixOS and other firewalls,
based on the two-machine test.
- contrib/teleportfling.service: per-user unit running the headless CLI
with its own config (~/.config/teleportfling/daemon.json)
- contrib/install-daemon.sh: builds the binary, installs the unit and a
starter daemon config
- contrib/README.md: install and management instructions
- todo.md: mark --config and daemon items complete
Add config.LoadFrom/SaveTo for arbitrary paths and thread a --config
flag through both entry points:
- CLI: --config loads a file first; explicit flags override file values
- GUI: --config selects the settings file used for load and save
- tests for LoadFrom/SaveTo and default fallback
- tray icon and tooltip now reflect engine state: grey when stopped,
green + live frame/drop counters in the tooltip while streaming
- generate a proper app icon (assets/, via cmd/teleportfling-icon) and
embed it so the window and tray carry the icon without runtime files
- add a .desktop entry template for launching from an app menu
- run Fyne UI updates (status label, tray icon/tooltip) on the main
thread via fyne.Do to satisfy the threading model
- config: validate port/quality/fps/source/stream-index ranges on load
and before engine start (flinger.Config.Validate)
- discovery: add Announce option to disable multicast (GUI checkbox,
CLI --no-announce); absent JSON key keeps the default true
- backpressure: count dropped frames in the TCP sender, expose via
engine Status and a live counter in the GUI status label
- docs: record M3/M4 decisions and X11 coverage via the portal backend
- internal/gui: settings form (name, port, source, quality, fps, audio)
wired to the flinger engine, config save/load, start/stop toggle
- system tray via Fyne's StatusNotifierItem: Show (raises window),
Start/Stop, Quit; left-click shows the settings window
- cmd/teleportfling-gui entry point
Verified on Hyprland: tray icon registers, start/stop streaming works,
window shows and focuses from the tray.
Move the capture/encode/send pipeline out of cmd/teleportfling into a
GUI-free Engine so the CLI and the desktop app share one implementation:
- flinger: Config/Engine/Status, audio+video+stats loops, pattern source
- config: JSON persistence at ~/.config/teleportfling/config.json
- cmd/teleportfling: thin CLI wrapper around the engine (same flags)
- golangci: extend exclusions to flinger/config
Add libGL, mesa, wayland, libxkbcommon and the X client libraries the
Fyne cgo toolchain links against, plus LIBRARY_PATH so Go's linker finds
them (it does not read NIX_LDFLAGS).
Capture the Wayland desktop via xdg-desktop-portal + PipeWire using
go2tv.app/screencast (MIT), and stream it to OBS:
- internal/capture: Capture/FrameSource/AudioSource interfaces and the
PipeWire backend (BGRA frames at monitor resolution, S16 48 kHz stereo
system audio)
- protocol: EncodeBGRA fast path producing 4:2:0 YCbCr JPEGs
- cmd: --source screen|pattern, --audio, --stream-index flags; real
capture feeds the existing sender
- share one wall-clock reference between the audio and video loops so
OBS receives aligned A/V timestamps (avoids multi-second latency)
Verified end-to-end: real desktop at 30 fps renders in OBS with
sub-second latency.
Stream a synthetic test pattern and silent PCM audio over the OBS
Teleport protocol:
- protocol: wire format (Header/ImageHeader/WaveHeader), BT.709 full
range colour matrix, JPEG encode via turbojpeg cgo, WAVE packet builder
- output: TCP sender with per-connection buffered channels and drop-on-overflow
- discovery: multicast announce via peerdiscovery
- cmd: teleportfling CLI with flags, test-pattern frame generator
Verified end-to-end: OBS discovers and renders the stream with correct
colours and motion.