teamsiso/CHANGELOG.md

9.4 KiB
Raw Blame History

Changelog

All notable changes to TeamsISO are documented here. The format follows Keep a Changelog and this project adheres to Semantic Versioning.

Unreleased

Added — May 2026 feature batch

Engine

  • NDI Groups: discovery + sender support so Teams' raw broadcasts can be pinned to a private "teamsiso-input" group while TeamsISO's own normalized outputs broadcast on Public.
  • One-click "Apply transcoder topology" writes ndi-config.v1.json so all Teams broadcasts go to the private group and TeamsISO re-emits on Public.
  • RawBgraRecorderSink per-output recorder: IRecorderSink interface + raw BGRA stream + manifest.json + convert.cmd script for FFmpeg conversion to H.264 MKV.
  • Recording markers: IRecorderSink.AddMarker(label) fan-out via IIsoController.AddRecordingMarker. Markers land in manifest.json under markers[] for post-production chaptering.
  • Preview thumbnails: IsoPipeline.LatestProcessedFrame published via Volatile.Read so the UI can render 160×90 BGRA thumbnails in the participants DataGrid at 1Hz.
  • Idempotent ParticipantTracker.HandleAdded: re-emitting Added for an already-live source refreshes LastSeen instead of duplicating the row. Fixes the "click Refresh and rows ghost-duplicate" bug introduced by the Refresh-Discovery affordance.
  • IIsoController.RefreshDiscovery() rebuilds the NDI finder on the next poll tick — useful right after applying a new transcoder topology.
  • IIsoController.AddRecordingMarker(label) fan-out to every active recorder.
  • IIsoController.SetRecording(enabled, dir) global recording toggle; per-participant override via EnableIsoAsync(...recordOverride...).

Host (WPF)

  • Active Speaker as a synthetic routable participant with deterministic v5 GUID derived from auto-mix:<machine>.
  • Auto-disable on departure: when a participant's NDI source disappears, optionally tear down their pipeline.
  • Operator presets: chromeless Presets… dialog with Save / Apply / Delete / Duplicate / Export / Import. Persisted at %LOCALAPPDATA%\TeamsISO\presets.json. Bundle format teamsiso-presets-bundle/v1 for migration between machines.
  • Auto-apply last preset on launch (configurable, off by default).
  • --apply-preset NAME CLI flag for desktop-shortcut workflows.
  • PresetApplier — single source of truth for "apply preset to live participants" used by the dialog, REST surface, and auto-apply path.
  • Live preview thumbnails per participant (160×90 BGRA WriteableBitmap).
  • Right-click context menu on participant rows: Toggle ISO, Record-this- participant, Copy NDI source name.
  • Live filter input (substring match on display name).
  • "Enable all online" + "Stop all ISOs" + "Refresh" header actions.
  • Per-participant recording opt-out checkbox (Rec column).
  • Custom NDI output name template with {name}/{guid}/{machine}/ {timestamp} tokens.
  • Phase E.1 — Launcher: rail "Launch / Stop Teams" toggle.
  • Phase E.2 — Window orchestration: hide / show Teams windows from the rail.
  • Phase E.3 — In-call controls (UIA): Mute, Camera, Share, Leave, Raise hand, plus PostMessage shortcut forwarding fallback. Candidate names localized for English / German / Spanish / French / Portuguese / Japanese.
  • Crash diagnostics: AppDomain + Dispatcher + TaskScheduler unhandled exception handlers wired to Serilog.Critical + user-facing dialog.
  • First-launch onboarding dialog with 5-step setup checklist.
  • About dialog gained "Show welcome", "Check for updates", "Export diagnostics" buttons.
  • Diagnostic bundle export: zips logs + config + presets + version metadata into ~/Downloads/teamsiso-diagnostics-<ts>.zip for bug reports.
  • Update check: manual via About + auto-on-launch banner (throttled to 24h, opt-out via flag file at %LOCALAPPDATA%\TeamsISO\no-update-check.flag).
  • Disk space watcher auto-disables recording at <1GB free.
  • Settings panel refactored into OUTPUT / NETWORK / DISPLAY tabs.
  • Reset-to-defaults button in OUTPUT tab.
  • Enriched footer: REC badge, control-surface badge, session timer (HH:MM:SS since first ISO went live), dynamic status text ("3/5 ISOs live · 2 recording").
  • Window-scoped keyboard shortcuts: F1 (help), Ctrl+M (marker), Ctrl+Shift+S (stop all), Ctrl+R (refresh discovery).
  • F1 help / cheat-sheet dialog.
  • UIPreferences static persists HideLocalSelf, AutoDisableOnDeparture, ParticipantSort (JoinOrder / Alphabetical / OnlineFirst) across launches to %LOCALAPPDATA%\TeamsISO\ui-prefs.json.
  • Pop-out per-participant preview window (right-click → Open preview…) refreshes at ~20Hz and is multi-monitor friendly.
  • Configurable participant sort order via the DISPLAY tab dropdown.
  • Stop-All confirms before tearing down running pipelines (catches mid-show misclicks).
  • About dialog gained "Logs / Recordings / Notes" folder shortcut buttons.
  • NotesWindow inline viewer for today's show-notes file with 2s polling.
  • Duplicate-preset action in the Presets dialog with smart (copy N) name suggestions.
  • --apply-preset NAME command-line flag for desktop-shortcut workflows.
  • New TeamsISO.App.Tests net8.0-windows test project. Initial coverage: OperatorPresetStoreTests (round-trip, name collisions, schema, bundle import/export, garbage-file resilience), OutputNameTemplateTests (token expansion + sanitization), OscMessageTests (wire-format parsing of int/float/string/T/F type tags). Backed by an InternalsVisibleTo grant
    • a test-only OperatorPresetStore.PathOverride hook.
  • IsoHealthStats.PeakAudioLevel field + DataGrid VU-bar UI scaffolding. Engine still emits 0.0 (audio capture is a focused follow-up); the bar's decay logic is in place so it animates as soon as engine-side audio parsing lands.
  • MediaFoundationRecorderSink scaffold under #if MF_AVAILABLE for inline H.264 encoding via Vortice.MediaFoundation. ~10× smaller files than the raw BGRA recorder. Activation steps documented at docs/REAL-TIME-RECORDING.md.
  • System-tray icon + minimize-to-tray toggle. Adds <UseWindowsForms>true</UseWindowsForms> for NotifyIcon; the TrayIconHost lives on App (process lifetime, not main-window lifetime). Right-click menu has Show / Stop all ISOs / Exit.
  • Built-in NDI test pattern: TeamsISO.Console --test-pattern broadcasts a synthetic 1280×720 30fps source named TEAMSISO_TEST showing SMPTE color bars + a moving sweep band. Verifies NDI runtime, sender configuration, and downstream discovery without needing Teams running. Backed by TestPatternGenerator in the engine + 4 unit tests covering buffer size, alpha, color distinctness, and sweep animation.
  • Always-toast on participant disconnect, regardless of AutoDisableOnDeparture setting. Distinguishes "ISO torn down" (auto-disable on) from "ISO still running on slate" (auto-disable off) so operators don't miss a silent drop mid-show.
  • Restart this ISO right-click action — disable + brief delay + re-enable for one participant only. Useful when a single feed flakes without affecting other ISOs.
  • Roll recording action: rolls every active recording into a new chunk (disable + re-enable each pipeline; recorder finalizes its manifest.json and starts a fresh subdirectory). Surfaced via MainViewModel.RollRecordingCommand, REST POST /recording/roll, and OSC /teamsiso/recording/roll. Useful for chaptering between show segments.

Control surface

  • REST API on 127.0.0.1:9755 with endpoints for participant ISO toggle (by Id or display name), preset apply, refresh discovery, stop-all, recording on/off, marker drop, notes, and Teams in-call commands. Documented at docs/CONTROL-SURFACE.md.
  • WebSocket /ws pushes live participant state at 4Hz with snapshot diffing.
  • OSC bridge on UDP 127.0.0.1:9000 mirrors the REST vocabulary (/teamsiso/iso "Jane" 1, /teamsiso/preset "...", etc.).
  • Embedded HTML control panel at GET /ui — phone-friendly remote with live state and one-click action buttons.
  • Show notes service: POST /notes and /teamsiso/notes "..." append timestamped lines to %LOCALAPPDATA%\TeamsISO\Notes\<YYYY-MM-DD>.md.

CI / Release

  • Forgejo CI is green; tag-push release workflow builds + tests + publishes
    • builds MSI on a Windows runner and attaches it to the auto-created release via the REST API.
  • Optional MSI + exe code-signing wired into release.yml — gated on SIGN_CERT_PFX_BASE64 + SIGN_CERT_PASSWORD Forgejo Secrets.

Fixed

  • .slnf path-separator mismatch (forward slashes for cross-platform).
  • NDI native DLL resolution via NativeLibrary resolver.
  • ExpectedRuntimeVersionPrefix updated to NDI 6 banner format.
  • NdiSourceParser accepts current Teams desktop's MS Teams - <name> brand format.
  • ActiveSpeaker source removal no longer poisons the rename-window heuristic for a Participant joining the same machine within the window.
  • IsoPipeline.State access synchronized via Volatile.Read/Write.
  • REST handlers now correctly marshal ObservableCollection reads + writes through the UI dispatcher.
  • WebSocket upgrade no longer falls into res.Close() finally block (was killing freshly-upgraded connections).
  • ParticipantViewModel.UpdateThumbnail defends against malformed frames (width*height*4 > Pixels.Length).
  • HasThumbnail correctly fires PropertyChanged when Thumbnail transitions from null.