teamsiso/CHANGELOG.md

168 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Changelog
All notable changes to TeamsISO are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [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.
[Unreleased]: https://forge.wilddragon.net/zgaetano/teamsiso/compare/v0.1.0...HEAD