Add a Scale option (1.0 native, 0.5 half, etc.) that downsamples the
captured BGRA frame with bilinear interpolation before JPEG encoding.
Config carries the scale factor; the GUI exposes a Scale dropdown
(100%/75%/50%/25%) that applies live via SetConfig.
Verified: OBS displays the image at the reduced resolution matching the
selected scale, without restarting the stream.
- sender tracks payload bytes; engine measures stream bitrate over a
sliding window and exposes it in Status
- GUI status label and tray tooltip show the live bitrate (e.g. 36 Mbps)
- add a Preset dropdown (Low/Medium/High/Ultra) that sets quality+fps
together and applies live via SetConfig
Verified: 36 Mbps shown for Medium (quality 70 @ 30fps) matches the
wire measurement.
Add flinger.SetConfig to update FPS/quality/name/audio/announce without
restarting the stream. Fields that require a restart (source, port,
stream-index) are preserved. The video loop reads the live config each
frame so changes apply immediately, and the GUI Quality/Frame-rate
dropdowns push changes to a running engine.
Verified live: fps 12->33 and JPEG size 210KB->1.3MB on quality change.
- Remove the project-local gitea MCP (opencode.json) and gitea-mcp-server
from the dev shell — the gitea MCP is now installed globally and points
at https://gitea.edley.me
- Update README/project.md links and the flake package homepage to the
new public instance
- The GITEA_ACCESS_TOKEN for the old homeserver is removed from
.secrets.env (gitignored); the global token from /run/secrets is used
Commit the prebuilt AppImage and Debian .deb under dist/ so they are
downloadable from the remote. appimagetool and intermediate build output
remain gitignored. README links to both artifacts.
- flake: build teleportfling and teleportfling-gui as nixpkgs packages
(buildGoModule) with a .desktop entry and icon for the GUI
- packaging/appimage.sh: bundle the GUI + runtime libs (recursive ldd)
into a self-contained AppImage via appimagetool
- packaging/deb.sh: build a .deb for Debian/Ubuntu with both binaries,
desktop entry, icon and declared runtime dependencies
- README: document all three packaging methods
- .gitignore: ignore dist/
Enumerate monitors via hyprctl (Hyprland) and present them as a
dropdown in the settings window instead of a raw index. The picker is
enabled only for the screen source and persists the selected monitor as
stream_index. Falls back to a single indexed option when enumeration is
unavailable (non-Hyprland).
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.