diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml
index f60d9ef..9a16e0c 100644
--- a/.forgejo/workflows/ci.yml
+++ b/.forgejo/workflows/ci.yml
@@ -1,4 +1,4 @@
-name: CI
+name: CI
on:
push:
@@ -21,15 +21,15 @@ jobs:
echo "$HOME/.dotnet" >> $GITHUB_PATH
echo "DOTNET_ROOT=$HOME/.dotnet" >> $GITHUB_ENV
- - name: Restore (Linux solution filter — excludes Windows-only WPF app)
- run: dotnet restore TeamsISO.Linux.slnf
+ - name: Restore (Linux solution filter — excludes Windows-only WPF app)
+ run: dotnet restore Dragon-ISO.Linux.slnf
- name: Build (Release, treat warnings as errors)
- run: dotnet build TeamsISO.Linux.slnf --configuration Release --no-restore
+ run: dotnet build Dragon-ISO.Linux.slnf --configuration Release --no-restore
- name: Test (excluding requires=ndi)
run: >
- dotnet test TeamsISO.Linux.slnf
+ dotnet test Dragon-ISO.Linux.slnf
--configuration Release
--no-build
--logger "trx;LogFileName=test-results.trx"
@@ -47,7 +47,7 @@ jobs:
-reports:"**/coverage.cobertura.xml" \
-targetdir:coverage-report \
-reporttypes:"Cobertura;TextSummary" \
- -assemblyfilters:"+TeamsISO.Engine;-TeamsISO.Engine.NdiInterop"
+ -assemblyfilters:"+Dragon-ISO.Engine;-Dragon-ISO.Engine.NdiInterop"
- name: Enforce coverage threshold (80%)
run: |
diff --git a/.gitignore b/.gitignore
index b50fcb5..fc9d3d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,9 @@ Thumbs.db
# Local Claude session metadata
.claude/
+
+# Build / test output logs
+*.log
+full-output.txt
+test-output.txt
+test-run.txt
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 63b0c80..6f91c19 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,62 +1,62 @@
-# Changelog
+# Changelog
-All notable changes to TeamsISO are documented here. The format follows
+All notable changes to Dragon-ISO 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).
-## [1.0.0] — 2026-05-17
+## [1.0.0] — 2026-05-17
First general release. Windows-only, .NET 8 WPF, NDI 6.
### Engine
-- **Participant discovery** over NDI with name cleanup — strips the
+- **Participant discovery** over NDI with name cleanup — strips the
"MS Teams - " / "(Teams) " prefixes and surfaces the operator-friendly
display name.
- **Per-participant ISO outputs** with normalized framerate, resolution,
aspect mode, and audio routing. Each ISO is an individually-addressable
NDI source.
-- **NDI Groups** support — discovery and sender. One-click "Apply
+- **NDI Groups** support — discovery and sender. One-click "Apply
transcoder topology" pins Teams' raw broadcasts to a private
- `teamsiso-input` group while TeamsISO re-emits on `Public`.
-- **Self-healing finder** — if the NDI runtime stalls (zero discovered
+ `Dragon-ISO-input` group while Dragon-ISO re-emits on `Public`.
+- **Self-healing finder** — if the NDI runtime stalls (zero discovered
sources past a startup grace period, or sources go from present to
empty and stay that way), the engine rebuilds the finder automatically.
-- **Real-time recording** — per-output raw BGRA stream + `manifest.json`
+- **Real-time recording** — per-output raw BGRA stream + `manifest.json`
+ an FFmpeg `convert.cmd` script for post-production conversion to
H.264 MKV. Recording is opt-in globally and per-participant.
-### UI — "Studio Terminal"
+### UI — "Studio Terminal"
- **Dark and light themes** with a runtime swap and a system-follow mode.
The Wild Dragon mark, the participants-grid watermark, and every accent
brush respond to the active theme.
- **Header**: brand mark, theme toggle, settings gear.
- **Transport strip**: session timer, participant count, live ISO count,
- control-surface URL — at-a-glance status.
+ control-surface URL — at-a-glance status.
- **Participants table**: 24px state LED, 106px live thumbnail preview,
name + caption, 5-bar audio meter, **inline-editable output name**,
CFG button (per-row override editor), ISO enable pill.
-- **Settings drawer** — slide-over from the right with OUTPUT / NETWORK /
+- **Settings drawer** — slide-over from the right with OUTPUT / NETWORK /
APP tabs.
-- **Ctrl+K command palette** — fuzzy search across Quick / Teams /
+- **Ctrl+K command palette** — fuzzy search across Quick / Teams /
Presets / Output / Network / App categories.
-- **Live preview thumbnails** in the participants table; right-click →
- Open preview… spawns a non-modal floating window suitable for a
+- **Live preview thumbnails** in the participants table; right-click →
+ Open preview… spawns a non-modal floating window suitable for a
secondary monitor.
### Output name template
- New default: **the speaker's display name** (`{name}`). Per-participant
overrides are inline-editable in the table. Empty-name fallback to
- `TEAMSISO_{guid}` keeps the NDI sender uniquely identifiable while a
+ `Dragon-ISO_{guid}` keeps the NDI sender uniquely identifiable while a
participant's display name resolves upstream.
- Available tokens: `{name}`, `{guid}`, `{machine}`, `{timestamp}`.
### Operator presets
- Save current per-participant ISO assignments + custom output names to
- `%LOCALAPPDATA%\TeamsISO\presets.json`. Optional auto-apply on next
+ `%LOCALAPPDATA%\Dragon-ISO\presets.json`. Optional auto-apply on next
launch.
### Teams orchestration
@@ -71,16 +71,16 @@ First general release. Windows-only, .NET 8 WPF, NDI 6.
- REST + WebSocket on `127.0.0.1:9755` for Bitfocus Companion / Stream
Deck / custom controllers.
- OSC on UDP `127.0.0.1:9000` for TouchOSC.
-- Self-contained HTML control panel at `/ui` — open from any phone on
+- Self-contained HTML control panel at `/ui` — open from any phone on
the LAN.
### Diagnostics & installer
-- Rolling daily Serilog logs under `%LOCALAPPDATA%\TeamsISO\logs\`.
-- Diagnostic bundle export — zips logs + config + presets for bug reports.
+- Rolling daily Serilog logs under `%LOCALAPPDATA%\Dragon-ISO\logs\`.
+- Diagnostic bundle export — zips logs + config + presets for bug reports.
- Forgejo-backed update check (manual or silent-on-launch, throttled to
24h).
- WiX MSI installer with proper Add/Remove Programs metadata, Start Menu
+ Desktop shortcuts, and in-place upgrade.
-[1.0.0]: https://forge.wilddragon.net/zgaetano/teamsiso/releases/tag/v1.0.0
+[1.0.0]: https://forge.wilddragon.net/zgaetano/Dragon-ISO/releases/tag/v1.0.0
diff --git a/Dragon-ISO.Linux.slnf b/Dragon-ISO.Linux.slnf
new file mode 100644
index 0000000..d939629
--- /dev/null
+++ b/Dragon-ISO.Linux.slnf
@@ -0,0 +1,12 @@
+{
+ "solution": {
+ "path": "Dragon-ISO.sln",
+ "projects": [
+ "src/Dragon-ISO.Engine/Dragon-ISO.Engine.csproj",
+ "src/Dragon-ISO.Engine.NdiInterop/Dragon-ISO.Engine.NdiInterop.csproj",
+ "src/Dragon-ISO.Console/Dragon-ISO.Console.csproj",
+ "src/tests/Dragon-ISO.Engine.Tests/Dragon-ISO.Engine.Tests.csproj",
+ "src/tests/Dragon-ISO.Engine.IntegrationTests/Dragon-ISO.Engine.IntegrationTests.csproj"
+ ]
+ }
+}
diff --git a/Dragon-ISO.Windows.slnf b/Dragon-ISO.Windows.slnf
new file mode 100644
index 0000000..2ae1d64
--- /dev/null
+++ b/Dragon-ISO.Windows.slnf
@@ -0,0 +1,14 @@
+{
+ "solution": {
+ "path": "Dragon-ISO.sln",
+ "projects": [
+ "src\\Dragon-ISO.Engine\\Dragon-ISO.Engine.csproj",
+ "src\\Dragon-ISO.Engine.NdiInterop\\Dragon-ISO.Engine.NdiInterop.csproj",
+ "src\\Dragon-ISO.Console\\Dragon-ISO.Console.csproj",
+ "src\\Dragon-ISO.App\\Dragon-ISO.App.csproj",
+ "src\\tests\\Dragon-ISO.Engine.Tests\\Dragon-ISO.Engine.Tests.csproj",
+ "src\\tests\\Dragon-ISO.Engine.IntegrationTests\\Dragon-ISO.Engine.IntegrationTests.csproj",
+ "src\\tests\\Dragon-ISO.App.Tests\\Dragon-ISO.App.Tests.csproj"
+ ]
+ }
+}
diff --git a/TeamsISO.sln b/Dragon-ISO.sln
similarity index 74%
rename from TeamsISO.sln
rename to Dragon-ISO.sln
index 3093684..8f5bd7b 100644
--- a/TeamsISO.sln
+++ b/Dragon-ISO.sln
@@ -1,72 +1,72 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.0.31903.59
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{46E05E34-8A87-4986-87D3-FE0DE4E05F44}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamsISO.Engine", "src\TeamsISO.Engine\TeamsISO.Engine.csproj", "{F0D24EAE-9225-4DC4-B3D2-6966077287A0}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamsISO.Engine.NdiInterop", "src\TeamsISO.Engine.NdiInterop\TeamsISO.Engine.NdiInterop.csproj", "{E737E54B-73DE-4F74-909C-1F0F5CF82AC6}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{DBDF4A1D-4215-42D5-B456-2CE7159DF848}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamsISO.Engine.Tests", "src\tests\TeamsISO.Engine.Tests\TeamsISO.Engine.Tests.csproj", "{F8DBD7AB-E160-4B75-88FC-BAECDD4D44E8}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamsISO.App", "src\TeamsISO.App\TeamsISO.App.csproj", "{80DCE039-3BBC-4D3F-B44B-51F324591C29}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamsISO.Engine.IntegrationTests", "src\tests\TeamsISO.Engine.IntegrationTests\TeamsISO.Engine.IntegrationTests.csproj", "{A85E331D-026E-4BDE-B89C-0CC4C95001CE}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamsISO.Console", "src\TeamsISO.Console\TeamsISO.Console.csproj", "{C3254998-9428-4264-A8FB-EAC9E1F9F432}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamsISO.App.Tests", "src\tests\TeamsISO.App.Tests\TeamsISO.App.Tests.csproj", "{B5A6F1E7-3D2C-4F89-9A55-7E1B2A4C8D6F}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {F0D24EAE-9225-4DC4-B3D2-6966077287A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F0D24EAE-9225-4DC4-B3D2-6966077287A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F0D24EAE-9225-4DC4-B3D2-6966077287A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F0D24EAE-9225-4DC4-B3D2-6966077287A0}.Release|Any CPU.Build.0 = Release|Any CPU
- {E737E54B-73DE-4F74-909C-1F0F5CF82AC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E737E54B-73DE-4F74-909C-1F0F5CF82AC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E737E54B-73DE-4F74-909C-1F0F5CF82AC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E737E54B-73DE-4F74-909C-1F0F5CF82AC6}.Release|Any CPU.Build.0 = Release|Any CPU
- {F8DBD7AB-E160-4B75-88FC-BAECDD4D44E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F8DBD7AB-E160-4B75-88FC-BAECDD4D44E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F8DBD7AB-E160-4B75-88FC-BAECDD4D44E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F8DBD7AB-E160-4B75-88FC-BAECDD4D44E8}.Release|Any CPU.Build.0 = Release|Any CPU
- {80DCE039-3BBC-4D3F-B44B-51F324591C29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {80DCE039-3BBC-4D3F-B44B-51F324591C29}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {80DCE039-3BBC-4D3F-B44B-51F324591C29}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {80DCE039-3BBC-4D3F-B44B-51F324591C29}.Release|Any CPU.Build.0 = Release|Any CPU
- {A85E331D-026E-4BDE-B89C-0CC4C95001CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A85E331D-026E-4BDE-B89C-0CC4C95001CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A85E331D-026E-4BDE-B89C-0CC4C95001CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A85E331D-026E-4BDE-B89C-0CC4C95001CE}.Release|Any CPU.Build.0 = Release|Any CPU
- {C3254998-9428-4264-A8FB-EAC9E1F9F432}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C3254998-9428-4264-A8FB-EAC9E1F9F432}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C3254998-9428-4264-A8FB-EAC9E1F9F432}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C3254998-9428-4264-A8FB-EAC9E1F9F432}.Release|Any CPU.Build.0 = Release|Any CPU
- {B5A6F1E7-3D2C-4F89-9A55-7E1B2A4C8D6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B5A6F1E7-3D2C-4F89-9A55-7E1B2A4C8D6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B5A6F1E7-3D2C-4F89-9A55-7E1B2A4C8D6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B5A6F1E7-3D2C-4F89-9A55-7E1B2A4C8D6F}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {F0D24EAE-9225-4DC4-B3D2-6966077287A0} = {46E05E34-8A87-4986-87D3-FE0DE4E05F44}
- {E737E54B-73DE-4F74-909C-1F0F5CF82AC6} = {46E05E34-8A87-4986-87D3-FE0DE4E05F44}
- {DBDF4A1D-4215-42D5-B456-2CE7159DF848} = {46E05E34-8A87-4986-87D3-FE0DE4E05F44}
- {F8DBD7AB-E160-4B75-88FC-BAECDD4D44E8} = {DBDF4A1D-4215-42D5-B456-2CE7159DF848}
- {80DCE039-3BBC-4D3F-B44B-51F324591C29} = {46E05E34-8A87-4986-87D3-FE0DE4E05F44}
- {A85E331D-026E-4BDE-B89C-0CC4C95001CE} = {DBDF4A1D-4215-42D5-B456-2CE7159DF848}
- {C3254998-9428-4264-A8FB-EAC9E1F9F432} = {46E05E34-8A87-4986-87D3-FE0DE4E05F44}
- {B5A6F1E7-3D2C-4F89-9A55-7E1B2A4C8D6F} = {DBDF4A1D-4215-42D5-B456-2CE7159DF848}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{46E05E34-8A87-4986-87D3-FE0DE4E05F44}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dragon-ISO.Engine", "src\Dragon-ISO.Engine\Dragon-ISO.Engine.csproj", "{F0D24EAE-9225-4DC4-B3D2-6966077287A0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dragon-ISO.Engine.NdiInterop", "src\Dragon-ISO.Engine.NdiInterop\Dragon-ISO.Engine.NdiInterop.csproj", "{E737E54B-73DE-4F74-909C-1F0F5CF82AC6}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{DBDF4A1D-4215-42D5-B456-2CE7159DF848}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dragon-ISO.Engine.Tests", "src\tests\Dragon-ISO.Engine.Tests\Dragon-ISO.Engine.Tests.csproj", "{F8DBD7AB-E160-4B75-88FC-BAECDD4D44E8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dragon-ISO.App", "src\Dragon-ISO.App\Dragon-ISO.App.csproj", "{80DCE039-3BBC-4D3F-B44B-51F324591C29}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dragon-ISO.Engine.IntegrationTests", "src\tests\Dragon-ISO.Engine.IntegrationTests\Dragon-ISO.Engine.IntegrationTests.csproj", "{A85E331D-026E-4BDE-B89C-0CC4C95001CE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dragon-ISO.Console", "src\Dragon-ISO.Console\Dragon-ISO.Console.csproj", "{C3254998-9428-4264-A8FB-EAC9E1F9F432}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dragon-ISO.App.Tests", "src\tests\Dragon-ISO.App.Tests\Dragon-ISO.App.Tests.csproj", "{B5A6F1E7-3D2C-4F89-9A55-7E1B2A4C8D6F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F0D24EAE-9225-4DC4-B3D2-6966077287A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F0D24EAE-9225-4DC4-B3D2-6966077287A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F0D24EAE-9225-4DC4-B3D2-6966077287A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F0D24EAE-9225-4DC4-B3D2-6966077287A0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E737E54B-73DE-4F74-909C-1F0F5CF82AC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E737E54B-73DE-4F74-909C-1F0F5CF82AC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E737E54B-73DE-4F74-909C-1F0F5CF82AC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E737E54B-73DE-4F74-909C-1F0F5CF82AC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F8DBD7AB-E160-4B75-88FC-BAECDD4D44E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F8DBD7AB-E160-4B75-88FC-BAECDD4D44E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F8DBD7AB-E160-4B75-88FC-BAECDD4D44E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F8DBD7AB-E160-4B75-88FC-BAECDD4D44E8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {80DCE039-3BBC-4D3F-B44B-51F324591C29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {80DCE039-3BBC-4D3F-B44B-51F324591C29}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {80DCE039-3BBC-4D3F-B44B-51F324591C29}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {80DCE039-3BBC-4D3F-B44B-51F324591C29}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A85E331D-026E-4BDE-B89C-0CC4C95001CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A85E331D-026E-4BDE-B89C-0CC4C95001CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A85E331D-026E-4BDE-B89C-0CC4C95001CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A85E331D-026E-4BDE-B89C-0CC4C95001CE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C3254998-9428-4264-A8FB-EAC9E1F9F432}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C3254998-9428-4264-A8FB-EAC9E1F9F432}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C3254998-9428-4264-A8FB-EAC9E1F9F432}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C3254998-9428-4264-A8FB-EAC9E1F9F432}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B5A6F1E7-3D2C-4F89-9A55-7E1B2A4C8D6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B5A6F1E7-3D2C-4F89-9A55-7E1B2A4C8D6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B5A6F1E7-3D2C-4F89-9A55-7E1B2A4C8D6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B5A6F1E7-3D2C-4F89-9A55-7E1B2A4C8D6F}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {F0D24EAE-9225-4DC4-B3D2-6966077287A0} = {46E05E34-8A87-4986-87D3-FE0DE4E05F44}
+ {E737E54B-73DE-4F74-909C-1F0F5CF82AC6} = {46E05E34-8A87-4986-87D3-FE0DE4E05F44}
+ {DBDF4A1D-4215-42D5-B456-2CE7159DF848} = {46E05E34-8A87-4986-87D3-FE0DE4E05F44}
+ {F8DBD7AB-E160-4B75-88FC-BAECDD4D44E8} = {DBDF4A1D-4215-42D5-B456-2CE7159DF848}
+ {80DCE039-3BBC-4D3F-B44B-51F324591C29} = {46E05E34-8A87-4986-87D3-FE0DE4E05F44}
+ {A85E331D-026E-4BDE-B89C-0CC4C95001CE} = {DBDF4A1D-4215-42D5-B456-2CE7159DF848}
+ {C3254998-9428-4264-A8FB-EAC9E1F9F432} = {46E05E34-8A87-4986-87D3-FE0DE4E05F44}
+ {B5A6F1E7-3D2C-4F89-9A55-7E1B2A4C8D6F} = {DBDF4A1D-4215-42D5-B456-2CE7159DF848}
+ EndGlobalSection
+EndGlobal
diff --git a/TeamsISO.Linux.slnf b/TeamsISO.Linux.slnf
deleted file mode 100644
index 8b9ed27..0000000
--- a/TeamsISO.Linux.slnf
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "solution": {
- "path": "TeamsISO.sln",
- "projects": [
- "src/TeamsISO.Engine/TeamsISO.Engine.csproj",
- "src/TeamsISO.Engine.NdiInterop/TeamsISO.Engine.NdiInterop.csproj",
- "src/TeamsISO.Console/TeamsISO.Console.csproj",
- "src/tests/TeamsISO.Engine.Tests/TeamsISO.Engine.Tests.csproj",
- "src/tests/TeamsISO.Engine.IntegrationTests/TeamsISO.Engine.IntegrationTests.csproj"
- ]
- }
-}
diff --git a/TeamsISO.Windows.slnf b/TeamsISO.Windows.slnf
deleted file mode 100644
index bc2b109..0000000
--- a/TeamsISO.Windows.slnf
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "solution": {
- "path": "TeamsISO.sln",
- "projects": [
- "src\\TeamsISO.Engine\\TeamsISO.Engine.csproj",
- "src\\TeamsISO.Engine.NdiInterop\\TeamsISO.Engine.NdiInterop.csproj",
- "src\\TeamsISO.Console\\TeamsISO.Console.csproj",
- "src\\TeamsISO.App\\TeamsISO.App.csproj",
- "src\\tests\\TeamsISO.Engine.Tests\\TeamsISO.Engine.Tests.csproj",
- "src\\tests\\TeamsISO.Engine.IntegrationTests\\TeamsISO.Engine.IntegrationTests.csproj",
- "src\\tests\\TeamsISO.App.Tests\\TeamsISO.App.Tests.csproj"
- ]
- }
-}
diff --git a/build-and-test.ps1 b/build-and-test.ps1
index 2a417c8..ada50ea 100644
--- a/build-and-test.ps1
+++ b/build-and-test.ps1
@@ -1,36 +1,29 @@
-# Quick build + test verification for TeamsISO.
-#
-# Run from the repo root:
-# pwsh -ExecutionPolicy Bypass -File .\build-and-test.ps1
-#
-# Builds TeamsISO.Windows.slnf in Release with TreatWarningsAsErrors=true
-# (the Directory.Build.props default), then runs unit tests excluding the
-# requires=ndi tier (those need a live NDI runtime).
-
$ErrorActionPreference = 'Stop'
-if (-not (Test-Path 'TeamsISO.Windows.slnf')) {
- throw "Run from the TeamsISO repo root."
+if (-not (Test-Path 'Dragon-ISO.Windows.slnf')) {
+ throw "Run from the Dragon-ISO repo root."
}
+$env:Path = "C:\Program Files\dotnet;$env:Path"
+
Write-Host "=== dotnet --version ===" -ForegroundColor Cyan
dotnet --version
Write-Host ""
Write-Host "=== Restore ===" -ForegroundColor Cyan
-dotnet restore TeamsISO.Windows.slnf
+dotnet restore Dragon-ISO.Windows.slnf
if ($LASTEXITCODE -ne 0) { throw "Restore failed." }
Write-Host ""
Write-Host "=== Build (Release, TreatWarningsAsErrors=true) ===" -ForegroundColor Cyan
-dotnet build TeamsISO.Windows.slnf --configuration Release --no-restore --nologo
+dotnet build Dragon-ISO.Windows.slnf --configuration Release --no-restore --nologo
if ($LASTEXITCODE -ne 0) {
- throw "Build failed. Most likely cause for this batch: System.Windows.Automation needs an explicit Reference. If so, add to src/TeamsISO.App/TeamsISO.App.csproj inside an : "
+ throw "Build failed. Most likely cause for this batch: System.Windows.Automation needs an explicit Reference. If so, add to src/Dragon-ISO.App/Dragon-ISO.App.csproj inside an : "
}
Write-Host ""
Write-Host "=== Tests (excluding requires=ndi) ===" -ForegroundColor Cyan
-dotnet test TeamsISO.Windows.slnf `
+dotnet test Dragon-ISO.Windows.slnf `
--configuration Release `
--no-build `
--nologo `
diff --git a/docs/CONTROL-SURFACE.md b/docs/CONTROL-SURFACE.md
index 0d8cc7d..57b0641 100644
--- a/docs/CONTROL-SURFACE.md
+++ b/docs/CONTROL-SURFACE.md
@@ -1,17 +1,17 @@
-# TeamsISO Control Surface — REST API
+# Dragon-ISO Control Surface — REST API
-TeamsISO can expose a localhost HTTP server so external controllers
+Dragon-ISO can expose a localhost HTTP server so external controllers
(Bitfocus Companion, Stream Deck plugins, Bome MIDI Translator, custom
node-RED flows, command-line scripts) can drive it without a UI binding.
## Enabling
-1. Open TeamsISO → Settings → DISPLAY tab.
+1. Open Dragon-ISO → Settings → DISPLAY tab.
2. Tick "Control surface (Stream Deck / Companion)".
3. Default port is **9755**; change it via the port textbox if needed.
-4. By default the server binds to `127.0.0.1` only — it is NOT reachable
+4. By default the server binds to `127.0.0.1` only — it is NOT reachable
from the LAN.
-5. To allow other machines on the same network to drive TeamsISO (the
+5. To allow other machines on the same network to drive Dragon-ISO (the
"headless host PC + thin client" scenario), tick the nested
"LAN-reachable" checkbox underneath. The settings panel will display
the LAN URL (e.g. `http://192.168.1.42:9755/ui`) with a Copy button.
@@ -31,20 +31,20 @@ netsh http add urlacl url=http://+:9755/ user=Everyone
```
Also confirm the Windows Firewall is letting inbound traffic to that port
-through — `New-NetFirewallRule -DisplayName "TeamsISO Control Surface" -Direction Inbound -Protocol TCP -LocalPort 9755 -Action Allow`
-in an elevated PowerShell, or add it through Windows Defender Firewall →
-Advanced Settings → Inbound Rules.
+through — `New-NetFirewallRule -DisplayName "Dragon-ISO Control Surface" -Direction Inbound -Protocol TCP -LocalPort 9755 -Action Allow`
+in an elevated PowerShell, or add it through Windows Defender Firewall →
+Advanced Settings → Inbound Rules.
## Authentication
-None — by design. In localhost-only mode, the loopback bind is the
+None — by design. In localhost-only mode, the loopback bind is the
security model: any process on the operator's machine can hit these
endpoints, the same threat model as a Stream Deck's USB connection.
In LAN-reachable mode, the assumption is a closed/trusted network (a
production-control LAN, a dedicated show subnet, a private vlan). Any
machine that can route to the host on the listener port can drive
-TeamsISO. **Do not enable LAN-reachable mode on an untrusted network.**
+Dragon-ISO. **Do not enable LAN-reachable mode on an untrusted network.**
## Response shape
@@ -58,7 +58,7 @@ specific fields. Errors return HTTP 4xx/5xx with `{"error": "..."}`.
### `GET /ui`
Self-contained HTML control panel. Open this in a browser to drive
-TeamsISO from a phone, tablet, or second monitor. Lists participants live
+Dragon-ISO from a phone, tablet, or second monitor. Lists participants live
via the same `/ws` WebSocket the rest of the doc describes, and posts to
the REST endpoints when you click. Single page, no external dependencies,
loads in <50KB.
@@ -70,7 +70,7 @@ alive?" probes.
```json
{
- "product": "TeamsISO",
+ "product": "Dragon-ISO",
"version": "1.0.0.0",
"endpoints": ["GET /participants", "POST /participants/{id}/iso", ...]
}
@@ -89,7 +89,7 @@ Snapshot of the current participant list as the UI sees it.
"isOnline": true,
"isEnabled": false,
"customName": null,
- "stateLabel": "—"
+ "stateLabel": "—"
}
]
}
@@ -103,7 +103,7 @@ Enable or disable an ISO by participant Id. Body or query string:
{ "enabled": true, "customName": "Host" }
```
-`enabled` is optional — omitting it toggles the current state. `customName`
+`enabled` is optional — omitting it toggles the current state. `customName`
is optional and overrides the auto-generated NDI output name.
```sh
@@ -174,7 +174,7 @@ Toggle per-output recording on or off. Body or query string:
```
`directory` is optional when `enabled=false`. Already-running ISOs are not
-retroactively recorded — the operator should disable + re-enable a
+retroactively recorded — the operator should disable + re-enable a
participant to start recording it.
### `POST /recording/marker`
@@ -191,8 +191,8 @@ curl -X POST 'http://127.0.0.1:9755/recording/marker?label=Guest+answer'
### `POST /notes`
Append a timestamped line to today's show-notes file at
-`%LOCALAPPDATA%\TeamsISO\Notes\.md`. Body or query string carries
-`text`. Each line is prefixed with `**HH:mm:ss** —`; the file is markdown so
+`%LOCALAPPDATA%\Dragon-ISO\Notes\.md`. Body or query string carries
+`text`. Each line is prefixed with `**HH:mm:ss** —`; the file is markdown so
it renders nicely in any editor.
```sh
@@ -204,7 +204,7 @@ curl -X POST 'http://127.0.0.1:9755/notes?text=guest+segment+starts'
Roll every active recording into a new chunk. Each running pipeline is
disabled (recorder finalizes its `manifest.json`), waits ~150ms, then re-
enabled (recorder opens a fresh subdirectory keyed by display name +
-timestamp). Useful for chaptering between show segments — a Stream Deck
+timestamp). Useful for chaptering between show segments — a Stream Deck
button mapped to this gives operators "next segment" without losing the
already-recorded footage.
@@ -217,7 +217,7 @@ Response:
{ "ok": true, "action": "roll-recording", "rolled": 4 }
```
-## WebSocket — live state push
+## WebSocket — live state push
For controllers that want to light a button when an ISO goes LIVE without
polling, connect to:
@@ -240,37 +240,37 @@ snapshot is pushed within 250ms. Format:
}
```
-Client→server messages are ignored for v1 — all commands go through REST.
+Client→server messages are ignored for v1 — all commands go through REST.
## OSC over UDP
Same command surface, different transport. Enable the OSC bridge in the
-DISPLAY tab (default port **9000** — TouchOSC's default). Bound to
+DISPLAY tab (default port **9000** — TouchOSC's default). Bound to
`127.0.0.1` by default; honors the same LAN-reachable toggle as the REST
-surface — when LAN mode is on, OSC binds to `0.0.0.0` so a TouchOSC tablet
+surface — when LAN mode is on, OSC binds to `0.0.0.0` so a TouchOSC tablet
on the same network can talk to the host directly.
Address vocabulary:
```
-/teamsiso/iso "DisplayName" {0|1} — toggle/set ISO by display name
-/teamsiso/iso/by-id "guid" {0|1} — toggle/set by Id
-/teamsiso/preset "Name" — apply preset
-/teamsiso/teams/mute — UIA toggle mute
-/teamsiso/teams/camera — UIA toggle camera
-/teamsiso/teams/leave — UIA leave
-/teamsiso/teams/share — UIA share tray
-/teamsiso/teams/raise-hand — UIA raise hand
-/teamsiso/refresh-discovery — rebuild NDI finder
-/teamsiso/stop-all — disable every ISO
-/teamsiso/recording {0|1} — recording on/off (default dir)
-/teamsiso/recording/marker "Label" — drop a marker on every active recording
-/teamsiso/recording/roll — roll every active recording into a new chunk
-/teamsiso/notes "Free-form note" — append a timestamped line to today's notes
+/Dragon-ISO/iso "DisplayName" {0|1} — toggle/set ISO by display name
+/Dragon-ISO/iso/by-id "guid" {0|1} — toggle/set by Id
+/Dragon-ISO/preset "Name" — apply preset
+/Dragon-ISO/teams/mute — UIA toggle mute
+/Dragon-ISO/teams/camera — UIA toggle camera
+/Dragon-ISO/teams/leave — UIA leave
+/Dragon-ISO/teams/share — UIA share tray
+/Dragon-ISO/teams/raise-hand — UIA raise hand
+/Dragon-ISO/refresh-discovery — rebuild NDI finder
+/Dragon-ISO/stop-all — disable every ISO
+/Dragon-ISO/recording {0|1} — recording on/off (default dir)
+/Dragon-ISO/recording/marker "Label" — drop a marker on every active recording
+/Dragon-ISO/recording/roll — roll every active recording into a new chunk
+/Dragon-ISO/notes "Free-form note" — append a timestamped line to today's notes
```
-Companion → Surfaces → "Generic OSC" supports outbound OSC; bind a button
-press to e.g. `/teamsiso/iso "Jane" 1`. TouchOSC layouts can use the same
+Companion → Surfaces → "Generic OSC" supports outbound OSC; bind a button
+press to e.g. `/Dragon-ISO/iso "Jane" 1`. TouchOSC layouts can use the same
addresses on the same UDP port.
## Bitfocus Companion recipe
@@ -292,7 +292,7 @@ on the appropriate endpoint above.
## Future work
-- **HTTPS / token auth** — for deployments that don't have a closed
+- **HTTPS / token auth** — for deployments that don't have a closed
network, layer TLS termination + a shared bearer token in front of the
HttpListener. Out of scope for v1; the LAN-reachable mode is a
trusted-network feature only.
diff --git a/docs/REAL-TIME-RECORDING.md b/docs/REAL-TIME-RECORDING.md
index b78ac16..1163368 100644
--- a/docs/REAL-TIME-RECORDING.md
+++ b/docs/REAL-TIME-RECORDING.md
@@ -1,4 +1,4 @@
-# Real-time H.264 recording
+# Real-time H.264 recording
The default recorder (`RawBgraRecorderSink`) writes uncompressed BGRA to disk
and ships a `convert.cmd` for post-recording FFmpeg encoding. That's safe
@@ -7,32 +7,32 @@ and ships a `convert.cmd` for post-recording FFmpeg encoding. That's safe
For long shows or operators on slower disks, the engine ships a
**`MediaFoundationRecorderSink`** that encodes to H.264 in real time using
-Windows Media Foundation. Inline encoding cuts disk pressure ~10× and
+Windows Media Foundation. Inline encoding cuts disk pressure ~10× and
produces a finished `.mp4` without the convert step.
It's behind a build flag because activating it requires adding a NuGet
dependency. The structural code is already in
-`src/TeamsISO.Engine/Pipeline/MediaFoundationRecorderSink.cs`.
+`src/Dragon-ISO.Engine/Pipeline/MediaFoundationRecorderSink.cs`.
-## Status — May 2026
+## Status — May 2026
**Activation deferred.** The Vortice.MediaFoundation 3.6.2 NuGet package
-is referenced from `TeamsISO.Engine.csproj`, but the `MF_AVAILABLE` symbol
+is referenced from `Dragon-ISO.Engine.csproj`, but the `MF_AVAILABLE` symbol
is *not* defined. The scaffold in
-`src/TeamsISO.Engine/Pipeline/MediaFoundationRecorderSink.cs` was written
+`src/Dragon-ISO.Engine/Pipeline/MediaFoundationRecorderSink.cs` was written
against an older Vortice API and needs a port pass before activation:
-- `MFVersion` → not on `MediaFactory` in 3.6.2; pass the SDK version
+- `MFVersion` → not on `MediaFactory` in 3.6.2; pass the SDK version
directly to `MFStartup`.
-- `MediaFactory.MF_LOW_LATENCY` → relocated to a different attribute
+- `MediaFactory.MF_LOW_LATENCY` → relocated to a different attribute
constants class.
-- `IMFAttributes.SetUINT32` → replaced with a generic `Set` overload.
+- `IMFAttributes.SetUINT32` → replaced with a generic `Set` overload.
- `IMFMediaType.MajorType` / `.SubType` / `.AvgBitrate` properties
- → now use `SetGUID(MFAttributeKeys.MajorType, ...)` etc.
-- `VideoFormatGuids.RGB32` → renamed (likely `Rgb32`).
-- `IMFMediaBuffer.Lock(out IntPtr, out int, out int)` → explicit out-param
+ → now use `SetGUID(MFAttributeKeys.MajorType, ...)` etc.
+- `VideoFormatGuids.RGB32` → renamed (likely `Rgb32`).
+- `IMFMediaBuffer.Lock(out IntPtr, out int, out int)` → explicit out-param
signature, no longer returns a locked-buffer wrapper.
-- `IMFSinkWriter.Finalize_` → renamed (likely `Finalize`).
+- `IMFSinkWriter.Finalize_` → renamed (likely `Finalize`).
Until the port lands, the `RawBgraRecorderSink` is the only IRecorderSink
production uses. The raw recorder is reliable and FFmpeg post-processing
@@ -45,7 +45,7 @@ disk pressure during the show.
reference implementation lives in the Vortice samples repo under
`samples/MediaFoundationSamples`.
-2. **Define the `MF_AVAILABLE` build symbol** in `TeamsISO.Engine.csproj`:
+2. **Define the `MF_AVAILABLE` build symbol** in `Dragon-ISO.Engine.csproj`:
```xml
@@ -71,10 +71,10 @@ disk pressure during the show.
## What the MF recorder produces
For each enabled ISO with recording on:
-- `//output.mp4` — H.264 video at the engine's
+- `//output.mp4` — H.264 video at the engine's
configured resolution / framerate, target bitrate ~0.07 bits/pixel
(~7 Mbps for 1080p30, ~3 Mbps for 720p30).
-- `//markers.txt` — tab-separated marker offsets
+- `//markers.txt` — tab-separated marker offsets
from `IIsoController.AddRecordingMarker`. Manually chapter the .mp4 with
`mp4chaps -c -i markers.txt output.mp4` (mp4chaps from the `mp4v2` tools).
@@ -91,5 +91,5 @@ For each enabled ISO with recording on:
| Reliable on legacy GPUs | Yes | Yes (MF falls back to software encoder if no hw H.264) |
If your target machines have NVIDIA NVENC / Intel QuickSync, MF will use
-the hardware encoder transparently — that's the path that gives you
+the hardware encoder transparently — that's the path that gives you
multi-stream realtime H.264 with low CPU.
diff --git a/docs/RELEASING.md b/docs/RELEASING.md
index a1617d4..f4312ab 100644
--- a/docs/RELEASING.md
+++ b/docs/RELEASING.md
@@ -1,4 +1,4 @@
-# Releasing TeamsISO
+# Releasing Dragon-ISO
The release workflow at `.forgejo/workflows/release.yml` runs on **annotated tag pushes
matching `v*.*.*`**. It builds, tests, publishes, packages an MSI, and uploads the
@@ -11,26 +11,26 @@ MSI as a release asset.
separate Windows runner. Register one with `forgejo-runner register` against a
Windows host that has the .NET 8 SDK + WiX SDK access (the WiX SDK pulls itself
via NuGet at build time, so no separate install).
-- The repository's **Create release on tag push** setting on (default), or skip it —
+- The repository's **Create release on tag push** setting on (default), or skip it —
the workflow will create the release if one doesn't exist.
## Cutting a release
```sh
# Bump the version in Directory.Build.props if you haven't already.
-git tag -a v1.0.0 -m "TeamsISO 1.0.0"
+git tag -a v1.0.0 -m "Dragon-ISO 1.0.0"
git push origin v1.0.0
```
The workflow will:
-1. Restore + build `TeamsISO.Windows.slnf` in Release with the tag's version.
-2. Run unit tests (the `requires=ndi` integration tier is skipped — it needs a
+1. Restore + build `Dragon-ISO.Windows.slnf` in Release with the tag's version.
+2. Run unit tests (the `requires=ndi` integration tier is skipped — it needs a
real NDI runtime which a CI runner won't have).
-3. Publish `TeamsISO.App` and `TeamsISO.Console` for `win-x64`,
+3. Publish `Dragon-ISO.App` and `Dragon-ISO.Console` for `win-x64`,
framework-dependent (.NET 8 Desktop runtime is the user's responsibility).
-4. Build `installer/TeamsISO.Installer.wixproj`, producing
- `TeamsISO-Setup-.msi`.
+4. Build `installer/Dragon-ISO.Installer.wixproj`, producing
+ `Dragon-ISO-Setup-.msi`.
5. Upload the MSI as a workflow artifact (downloadable from the run page).
6. Attach the MSI to the GitHub-style Release for the tag, creating the release
first if it doesn't exist. Pre-release flag is set automatically when the
@@ -39,13 +39,13 @@ The workflow will:
## Code signing
The release workflow has optional signtool integration. It runs only when the
-signing-cert secrets are configured on the repository — without them, builds
+signing-cert secrets are configured on the repository — without them, builds
remain unsigned and produce a SmartScreen warning on first launch.
### Enabling signing
-Set these secrets on `forge.wilddragon.net/zgaetano/teamsiso`
-→ Settings → Actions → Secrets:
+Set these secrets on `forge.wilddragon.net/zgaetano/Dragon-ISO`
+→ Settings → Actions → Secrets:
| Secret | Required | Notes |
| --- | --- | --- |
@@ -56,7 +56,7 @@ Set these secrets on `forge.wilddragon.net/zgaetano/teamsiso`
When all three are present, the workflow:
1. Decodes the PFX to a temp file on the runner before building.
-2. Signs `publish/TeamsISO/TeamsISO.exe` after publish, before MSI build, so the
+2. Signs `publish/Dragon-ISO/Dragon-ISO.exe` after publish, before MSI build, so the
binary embedded in the MSI is signed too.
3. Signs the produced MSI itself after WiX builds it.
4. Wipes the temp PFX from disk.
@@ -70,7 +70,7 @@ which is what current Microsoft / SmartScreen guidance requires.
per-publisher over time; brand-new OV certs still trip the warning until
enough downloads accumulate.
- **EV (Extended Validation, ~$300/yr, hardware token).** SmartScreen-trusted
- immediately. Token-based — to use one in CI you'll need to either (a) keep
+ immediately. Token-based — to use one in CI you'll need to either (a) keep
the runner on a host with the token plugged in, or (b) move to a cloud
signing service like Azure Trusted Signing or DigiCert KeyLocker.
diff --git a/src/TeamsISO.App/AboutWindow.xaml b/src/Dragon-ISO.App/AboutWindow.xaml
similarity index 96%
rename from src/TeamsISO.App/AboutWindow.xaml
rename to src/Dragon-ISO.App/AboutWindow.xaml
index 2a06d13..9a2535d 100644
--- a/src/TeamsISO.App/AboutWindow.xaml
+++ b/src/Dragon-ISO.App/AboutWindow.xaml
@@ -1,9 +1,9 @@
-
-
@@ -62,7 +62,7 @@
Margin="0,0,0,16"
RenderOptions.BitmapScalingMode="HighQuality"/>
-
@@ -146,12 +146,12 @@
Click="OnOpenLogs"
Padding="14,6"
Margin="0,0,8,0"
- ToolTip="Open %LOCALAPPDATA%\TeamsISO\Logs in Explorer"/>
+ ToolTip="Open %LOCALAPPDATA%\DragonISO\Logs in Explorer"/>
+ ToolTip="Open %LOCALAPPDATA%\DragonISO\Notes in Explorer"/>
diff --git a/src/TeamsISO.App/AboutWindow.xaml.cs b/src/Dragon-ISO.App/AboutWindow.xaml.cs
similarity index 89%
rename from src/TeamsISO.App/AboutWindow.xaml.cs
rename to src/Dragon-ISO.App/AboutWindow.xaml.cs
index 110334e..078a17a 100644
--- a/src/TeamsISO.App/AboutWindow.xaml.cs
+++ b/src/Dragon-ISO.App/AboutWindow.xaml.cs
@@ -1,13 +1,13 @@
-using System.Diagnostics;
+using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Versioning;
using System.Windows;
using System.Windows.Navigation;
-using TeamsISO.App.Services;
-using TeamsISO.Engine.NdiInterop;
+using DragonISO.App.Services;
+using DragonISO.Engine.NdiInterop;
-namespace TeamsISO.App;
+namespace DragonISO.App;
///
/// Modal "About" dialog. Surfaces enough info that a user filing a support ticket
@@ -65,7 +65,7 @@ public partial class AboutWindow : Window
///
/// Quick-jump: open a path in Explorer. Creates the directory if missing
/// (operator might click "Recordings" before any have been made). Best-
- /// effort — Explorer launch failures don't surface a dialog.
+ /// effort — Explorer launch failures don't surface a dialog.
///
private static void OpenInExplorer(string path)
{
@@ -87,18 +87,18 @@ public partial class AboutWindow : Window
private void OnOpenLogs(object sender, RoutedEventArgs e) =>
OpenInExplorer(Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
- "TeamsISO", "Logs"));
+ "Dragon-ISO", "Logs"));
- // OnOpenRecordings removed — recording feature axed.
+ // OnOpenRecordings removed — recording feature axed.
private void OnOpenNotes(object sender, RoutedEventArgs e) =>
OpenInExplorer(Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
- "TeamsISO", "Notes"));
+ "Dragon-ISO", "Notes"));
///
/// Build the diagnostic bundle and tell the operator where it landed. The
- /// bundle is just zipped logs / config / presets — no screenshots, no
+ /// bundle is just zipped logs / config / presets — no screenshots, no
/// memory dumps. Intended to be attached to a bug report.
///
private void OnExportDiagnostics(object sender, RoutedEventArgs e)
@@ -109,7 +109,7 @@ public partial class AboutWindow : Window
var open = MessageBox.Show(
this,
$"Diagnostic bundle written to:\n\n{path}\n\nOpen the containing folder?",
- "TeamsISO — Diagnostics exported",
+ "Dragon-ISO — Diagnostics exported",
MessageBoxButton.YesNo,
MessageBoxImage.Information);
if (open == MessageBoxResult.Yes)
@@ -131,7 +131,7 @@ public partial class AboutWindow : Window
MessageBox.Show(
this,
$"Diagnostic export failed.\n\n{ex.Message}",
- "TeamsISO — Diagnostic export",
+ "Dragon-ISO — Diagnostic export",
MessageBoxButton.OK,
MessageBoxImage.Warning);
}
@@ -158,7 +158,7 @@ public partial class AboutWindow : Window
$"{result.Message}\n\n" +
$"You're on {result.CurrentVersion}; latest is {result.LatestTag}.\n\n" +
"Open the releases page to download the new MSI?",
- "TeamsISO — Update available",
+ "Dragon-ISO — Update available",
MessageBoxButton.YesNo,
MessageBoxImage.Information);
if (open == MessageBoxResult.Yes)
@@ -169,7 +169,7 @@ public partial class AboutWindow : Window
MessageBox.Show(
this,
result.Message ?? "You're on the latest release.",
- "TeamsISO — Up to date",
+ "Dragon-ISO — Up to date",
MessageBoxButton.OK,
MessageBoxImage.Information);
break;
@@ -179,7 +179,7 @@ public partial class AboutWindow : Window
MessageBox.Show(
this,
$"Couldn't check for updates.\n\n{result.Message}",
- "TeamsISO — Update check failed",
+ "Dragon-ISO — Update check failed",
MessageBoxButton.OK,
MessageBoxImage.Warning);
break;
@@ -193,7 +193,7 @@ public partial class AboutWindow : Window
///
/// Open the company site in the default browser. We intentionally use the
- /// shell's URL handler rather than a tab inside the app — this is a
+ /// shell's URL handler rather than a tab inside the app — this is a
/// "tell me more" link, not a workflow.
///
private void OnWebsiteClick(object sender, RoutedEventArgs e)
diff --git a/src/TeamsISO.App/App.Bootstrap.cs b/src/Dragon-ISO.App/App.Bootstrap.cs
similarity index 89%
rename from src/TeamsISO.App/App.Bootstrap.cs
rename to src/Dragon-ISO.App/App.Bootstrap.cs
index 87b06f7..e8b55d6 100644
--- a/src/TeamsISO.App/App.Bootstrap.cs
+++ b/src/Dragon-ISO.App/App.Bootstrap.cs
@@ -1,16 +1,16 @@
-using System.IO;
+using System.IO;
using System.Windows;
using System.Windows.Interop;
using Microsoft.Extensions.Logging;
-using TeamsISO.App.Services;
-using TeamsISO.App.ViewModels;
-using TeamsISO.Engine.Controller;
-using TeamsISO.Engine.Interop;
-using TeamsISO.Engine.NdiInterop;
-using TeamsISO.Engine.Persistence;
-using TeamsISO.Engine.Pipeline;
+using DragonISO.App.Services;
+using DragonISO.App.ViewModels;
+using DragonISO.Engine.Controller;
+using DragonISO.Engine.Interop;
+using DragonISO.Engine.NdiInterop;
+using DragonISO.Engine.Persistence;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.App;
+namespace DragonISO.App;
// Linear bootstrap steps that OnStartup walks through, extracted so the
// main file reads as a wiring pipeline rather than a single 200-line
@@ -19,10 +19,10 @@ namespace TeamsISO.App;
public partial class App
{
///
- /// Acquire the per-user named mutex that gates a single TeamsISO
- /// instance per Windows user. Two TeamsISOs on the same machine for
+ /// Acquire the per-user named mutex that gates a single Dragon-ISO
+ /// instance per Windows user. Two Dragon-ISOs on the same machine for
/// the same user race over the NDI finder, the NDI senders, and
- /// %APPDATA%\TeamsISO\config.json — none of those are safe to share.
+ /// %APPDATA%\Dragon-ISO\config.json — none of those are safe to share.
///
/// On loss: broadcast the bring-to-front message to wake the existing
/// instance and signal the caller to
@@ -36,7 +36,7 @@ public partial class App
_ownsSingleInstanceMutex = createdNew;
if (!createdNew)
{
- var bringToFront = RegisterWindowMessageW("WildDragon.TeamsISO.BringToFront");
+ var bringToFront = RegisterWindowMessageW("WildDragon.DragonISO.BringToFront");
if (bringToFront != 0)
SendNotifyMessageW(HWND_BROADCAST, bringToFront, IntPtr.Zero, IntPtr.Zero);
return false;
@@ -46,7 +46,7 @@ public partial class App
// *subsequent* launch that broadcasts our bring-to-front message
// surfaces our window. Hold the delegate in a field so OnExit can
// unsubscribe cleanly (ComponentDispatcher is process-static).
- var bringToFrontMsg = RegisterWindowMessageW("WildDragon.TeamsISO.BringToFront");
+ var bringToFrontMsg = RegisterWindowMessageW("WildDragon.DragonISO.BringToFront");
_bringToFrontHandler = (ref MSG msg, ref bool handled) =>
{
if (msg.message == (int)bringToFrontMsg && MainWindow is not null)
@@ -80,10 +80,10 @@ public partial class App
catch (Exception ex)
{
MessageBox.Show(
- "TeamsISO could not initialize the NDI runtime.\n\n" +
+ "Dragon-ISO could not initialize the NDI runtime.\n\n" +
"Install the NDI Runtime from https://ndi.video/tools/ and try again.\n\n" +
"Details: " + ex.Message,
- "TeamsISO — NDI runtime missing",
+ "Dragon-ISO — NDI runtime missing",
MessageBoxButton.OK,
MessageBoxImage.Error);
return false;
@@ -92,7 +92,7 @@ public partial class App
///
/// Wire the engine: configstore, NDI runtime probe, frame scaler,
- /// pipeline factory, IsoController. Doesn't start the engine — that's
+ /// pipeline factory, IsoController. Doesn't start the engine — that's
/// MainViewModel.InitializeAsync's job.
///
private void BootstrapEngine()
@@ -101,7 +101,7 @@ public partial class App
var configPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
- "TeamsISO", "config.json");
+ "Dragon-ISO", "config.json");
var configStore = new ConfigStore(configPath, _loggerFactory.CreateLogger());
var probe = new NdiRuntimeProbe(_interop, NdiVersion.ExpectedRuntimeVersionPrefix);
@@ -141,7 +141,7 @@ public partial class App
/// REST + WebSocket control surface for Stream Deck / Companion and
/// the OSC bridge. Created always; only Started if the operator had
/// the toggle on in the previous session (the settings VM's setter
- /// handles the in-session flip path). Failures log + toast — we don't
+ /// handles the in-session flip path). Failures log + toast — we don't
/// want a port-bind error to block app start.
///
private void BootstrapControlSurfaceServices()
@@ -209,8 +209,8 @@ public partial class App
///
/// Auto-launch Teams in the background if the operator opted in.
/// Combined with AutoHideTeamsWindows this gives the "I only see
- /// TeamsISO" experience. Fire-and-forget — a slow Teams launch must
- /// not delay TeamsISO's own window from appearing.
+ /// Dragon-ISO" experience. Fire-and-forget — a slow Teams launch must
+ /// not delay Dragon-ISO's own window from appearing.
///
private void TryAutoLaunchTeams(ILogger logger)
{
@@ -242,7 +242,7 @@ public partial class App
else if (settings.AutoHideTeamsWindows && TeamsLauncher.IsRunning())
{
// Teams is already up from a previous session. If auto-hide is
- // on, hide it now so the operator's "I only see TeamsISO" rule
+ // on, hide it now so the operator's "I only see Dragon-ISO" rule
// applies even when Teams was launched externally.
_ = TeamsLauncher.AutoHideAfterLaunchAsync();
}
diff --git a/src/TeamsISO.App/App.CrashHandlers.cs b/src/Dragon-ISO.App/App.CrashHandlers.cs
similarity index 77%
rename from src/TeamsISO.App/App.CrashHandlers.cs
rename to src/Dragon-ISO.App/App.CrashHandlers.cs
index b300e14..327c24d 100644
--- a/src/TeamsISO.App/App.CrashHandlers.cs
+++ b/src/Dragon-ISO.App/App.CrashHandlers.cs
@@ -1,17 +1,17 @@
-using System.IO;
+using System.IO;
using System.Windows;
using System.Windows.Threading;
using Microsoft.Extensions.Logging;
-namespace TeamsISO.App;
+namespace DragonISO.App;
-// Crash diagnostics — the three exception channels WPF leaves open by
+// Crash diagnostics — the three exception channels WPF leaves open by
// default, wired to a single handler that logs Fatal to Serilog (rolling
-// daily file at %LOCALAPPDATA%\TeamsISO\Logs) and then shows the user a
+// daily file at %LOCALAPPDATA%\Dragon-ISO\Logs) and then shows the user a
// dialog with the log path so they can attach it to a bug report.
//
// We deliberately don't catch StackOverflowException or
-// ExecutionEngineException — both are uncatchable in modern .NET; if one
+// ExecutionEngineException — both are uncatchable in modern .NET; if one
// fires the OS Watson dialog takes it from here.
public partial class App
{
@@ -23,11 +23,11 @@ public partial class App
private static string LogDirectory =>
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
- "TeamsISO", "Logs");
+ "Dragon-ISO", "Logs");
private void OnAppDomainUnhandled(object sender, UnhandledExceptionEventArgs e)
{
- // IsTerminating is almost always true here — finalizers and
+ // IsTerminating is almost always true here — finalizers and
// managed-thread top-frames don't have a graceful path back. Log
// + show a dialog inline since the process will exit either way.
var ex = e.ExceptionObject as Exception;
@@ -40,7 +40,7 @@ public partial class App
TryLogFatal("Dispatcher.UnhandledException", e.Exception);
TryShowCrashDialog(e.Exception, terminating: false);
// Mark Handled so a single bad UI thunk doesn't take the whole app
- // down — the user has the dialog and the log; they can choose to
+ // down — the user has the dialog and the log; they can choose to
// keep going.
e.Handled = true;
}
@@ -48,7 +48,7 @@ public partial class App
private void OnUnobservedTaskException(object? sender, System.Threading.Tasks.UnobservedTaskExceptionEventArgs e)
{
TryLogFatal("TaskScheduler.UnobservedTaskException", e.Exception);
- // Don't show a dialog here — these fire from the finalizer thread
+ // Don't show a dialog here — these fire from the finalizer thread
// and tend to be cleanup-time noise, not user-actionable. Log only.
e.SetObserved();
}
@@ -62,7 +62,7 @@ public partial class App
}
catch
{
- // Logger itself failed (rare — disk full, permission denied).
+ // Logger itself failed (rare — disk full, permission denied).
// Swallow: nothing useful to do, and re-throwing during crash
// handling makes things worse.
}
@@ -73,15 +73,15 @@ public partial class App
try
{
var heading = terminating
- ? "TeamsISO encountered an unrecoverable error and will exit."
- : "TeamsISO encountered an error.";
+ ? "Dragon-ISO encountered an unrecoverable error and will exit."
+ : "Dragon-ISO encountered an error.";
var details = ex?.GetType().Name + ": " + (ex?.Message ?? "(no details)");
var body =
heading + "\n\n" +
details + "\n\n" +
$"A full diagnostic log has been written to:\n{LogDirectory}\n\n" +
"Attach the most recent file from that directory to your bug report.";
- MessageBox.Show(body, "TeamsISO — Error",
+ MessageBox.Show(body, "Dragon-ISO — Error",
MessageBoxButton.OK, MessageBoxImage.Error);
}
catch
diff --git a/src/TeamsISO.App/App.UpdateCheckBootstrap.cs b/src/Dragon-ISO.App/App.UpdateCheckBootstrap.cs
similarity index 93%
rename from src/TeamsISO.App/App.UpdateCheckBootstrap.cs
rename to src/Dragon-ISO.App/App.UpdateCheckBootstrap.cs
index 1d22d3a..75b65af 100644
--- a/src/TeamsISO.App/App.UpdateCheckBootstrap.cs
+++ b/src/Dragon-ISO.App/App.UpdateCheckBootstrap.cs
@@ -1,7 +1,7 @@
-using Microsoft.Extensions.Logging;
-using TeamsISO.App.Services;
+using Microsoft.Extensions.Logging;
+using DragonISO.App.Services;
-namespace TeamsISO.App;
+namespace DragonISO.App;
// Background update check, throttled to once per 24h. Fire-and-forget
// so a slow / offline update server never delays startup. Surfaces a
diff --git a/src/TeamsISO.App/App.xaml b/src/Dragon-ISO.App/App.xaml
similarity index 96%
rename from src/TeamsISO.App/App.xaml
rename to src/Dragon-ISO.App/App.xaml
index 76d6e06..bd77109 100644
--- a/src/TeamsISO.App/App.xaml
+++ b/src/Dragon-ISO.App/App.xaml
@@ -1,4 +1,4 @@
-
diff --git a/src/TeamsISO.App/App.xaml.cs b/src/Dragon-ISO.App/App.xaml.cs
similarity index 80%
rename from src/TeamsISO.App/App.xaml.cs
rename to src/Dragon-ISO.App/App.xaml.cs
index 5f67f3f..15710e6 100644
--- a/src/TeamsISO.App/App.xaml.cs
+++ b/src/Dragon-ISO.App/App.xaml.cs
@@ -1,51 +1,51 @@
-using System.IO;
+using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using Microsoft.Extensions.Logging;
-using TeamsISO.App.ViewModels;
-using TeamsISO.Engine.Controller;
-using TeamsISO.Engine.Logging;
-using TeamsISO.Engine.NdiInterop;
+using DragonISO.App.ViewModels;
+using DragonISO.Engine.Controller;
+using DragonISO.Engine.Logging;
+using DragonISO.Engine.NdiInterop;
// Application + MessageBox aliases live in GlobalUsings.cs (project-wide).
-// Don't redeclare here — Roslyn errors with CS1537 on duplicate alias.
+// Don't redeclare here — Roslyn errors with CS1537 on duplicate alias.
-namespace TeamsISO.App;
+namespace DragonISO.App;
// Split across partial files by responsibility:
-// • App.xaml.cs — class skeleton, OnStartup (the wiring
+// • App.xaml.cs — class skeleton, OnStartup (the wiring
// pipeline that calls into the partials),
// OnExit, CLI arg parser.
-// • App.Bootstrap.cs — the linear setup steps OnStartup walks
+// • App.Bootstrap.cs — the linear setup steps OnStartup walks
// (single-instance gate, NDI interop, engine,
// main window, control surface, tray icon,
// onboarding, Teams auto-launch).
-// • App.CrashHandlers.cs — AppDomain / Dispatcher / Task exception
+// • App.CrashHandlers.cs — AppDomain / Dispatcher / Task exception
// handlers + crash dialog + LogDirectory.
-// • App.UpdateCheckBootstrap.cs — the background update-checker
+// • App.UpdateCheckBootstrap.cs — the background update-checker
// kickoff (24h-throttled).
public partial class App : Application
{
///
/// Per-user mutex name. Including the username (acting as a SID proxy) ensures two
- /// different Windows users can each run TeamsISO on the same machine, while one
+ /// different Windows users can each run Dragon-ISO on the same machine, while one
/// user can't spawn duplicate instances that would contend over the NDI runtime
- /// and the shared %APPDATA%\TeamsISO\config.json.
+ /// and the shared %APPDATA%\Dragon-ISO\config.json.
///
/// The "Global\" prefix puts the named object in the system-wide namespace
/// (not session-local or integrity-isolated). This matters because when an
/// admin user has UAC effectively disabled, launches from different parents
/// (elevated File Explorer, non-elevated shell, etc.) can land in slightly
/// different security contexts. A "Local\" mutex was being created in
- /// different views per integrity level on some boxes, letting two TeamsISO
- /// instances run concurrently — the second's REST surface couldn't bind port
+ /// different views per integrity level on some boxes, letting two Dragon-ISO
+ /// instances run concurrently — the second's REST surface couldn't bind port
/// 9755 (already held) and its Serilog file sink couldn't open the daily log
/// (already held with shared=false), producing a window that looked like
/// the app but had no engine attached. Global\ closes that gap.
///
private static readonly string SingleInstanceMutexName =
- $"Global\\WildDragon.TeamsISO.SingleInstance.{Environment.UserName}";
+ $"Global\\WildDragon.DragonISO.SingleInstance.{Environment.UserName}";
private System.Threading.Mutex? _singleInstanceMutex;
private bool _ownsSingleInstanceMutex;
@@ -54,23 +54,23 @@ public partial class App : Application
private NdiInteropPInvoke? _interop;
private IsoController? _controller;
private MainViewModel? _viewModel;
- private TeamsISO.App.Services.ControlSurfaceServer? _controlSurface;
- private TeamsISO.App.Services.OscBridge? _oscBridge;
- // _diskSpaceWatcher removed — only existed to auto-disable recording at low free space.
- private TeamsISO.App.Services.TrayIconHost? _trayIcon;
+ private DragonISO.App.Services.ControlSurfaceServer? _controlSurface;
+ private DragonISO.App.Services.OscBridge? _oscBridge;
+ // _diskSpaceWatcher removed — only existed to auto-disable recording at low free space.
+ private DragonISO.App.Services.TrayIconHost? _trayIcon;
///
/// REST control surface lifetime. Lives on App so the settings VM can flip
/// it on/off without us plumbing yet another DI dependency through MainViewModel.
/// Null between process startup and the OnStartup wire-up, and after OnExit.
///
- internal TeamsISO.App.Services.ControlSurfaceServer? ControlSurface => _controlSurface;
+ internal DragonISO.App.Services.ControlSurfaceServer? ControlSurface => _controlSurface;
- /// OSC bridge (UDP) lifetime — same lifecycle pattern as the REST surface.
- internal TeamsISO.App.Services.OscBridge? OscBridge => _oscBridge;
+ /// OSC bridge (UDP) lifetime — same lifecycle pattern as the REST surface.
+ internal DragonISO.App.Services.OscBridge? OscBridge => _oscBridge;
/// Tray-icon host. Exposed so the settings VM can flip the minimize-to-tray toggle.
- internal TeamsISO.App.Services.TrayIconHost? TrayIcon => _trayIcon;
+ internal DragonISO.App.Services.TrayIconHost? TrayIcon => _trayIcon;
[DllImport("user32.dll")]
private static extern uint RegisterWindowMessageW(string lpString);
@@ -82,10 +82,10 @@ public partial class App : Application
protected override async void OnStartup(StartupEventArgs e)
{
- // RAW TRACE — captures startup BEFORE Serilog comes up. Helps diagnose
+ // RAW TRACE — captures startup BEFORE Serilog comes up. Helps diagnose
// launches where the Serilog log stays empty (silent file-sink failure,
// pre-logger crash, weird parent-spawn environment, etc.). Writes to
- // %LOCALAPPDATA%\TeamsISO\startup-trace.log.
+ // %LOCALAPPDATA%\Dragon-ISO\startup-trace.log.
var parentName = "(unknown)";
try { parentName = TryGetParentProcessName() ?? "(null)"; } catch { }
StartupTrace.Write($"OnStartup ENTER. exe={Environment.ProcessPath} parent={parentName} args=[{string.Join(' ', e.Args)}]");
@@ -101,9 +101,9 @@ public partial class App : Application
StartupTrace.Write("base.OnStartup returned");
// De-elevation via runas /trustlevel:0x20000 was tried (commits 191b2c5,
- // 54ee578) on the theory that elevated TeamsISO can't discover NDI
- // sources. THAT THEORY WAS WRONG — verified 2026-05-16 that elevated
- // TeamsISO discovers NDI sources fine. The SAFER-restricted token
+ // 54ee578) on the theory that elevated Dragon-ISO can't discover NDI
+ // sources. THAT THEORY WAS WRONG — verified 2026-05-16 that elevated
+ // Dragon-ISO discovers NDI sources fine. The SAFER-restricted token
// produced by runas /trustlevel was the ACTUAL cause of every "no
// participants" report: it breaks .NET 8 WPF startup such that the
// process appears alive with a window but the managed code never gets
@@ -113,14 +113,14 @@ public partial class App : Application
if (Array.IndexOf(e.Args, "--keep-elevation") >= 0)
StartupTrace.Write("--keep-elevation flag present (no-op now; de-elevation removed)");
- // Crash diagnostics — wire the three exception channels WPF leaves open by
+ // Crash diagnostics — wire the three exception channels WPF leaves open by
// default to a single handler that logs Fatal to Serilog.
AppDomain.CurrentDomain.UnhandledException += OnAppDomainUnhandled;
DispatcherUnhandledException += OnDispatcherUnhandled;
System.Threading.Tasks.TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
StartupTrace.Write("crash handlers registered");
- try { TeamsISO.App.Services.ThemeManager.Current.Apply(); StartupTrace.Write("ThemeManager.Apply OK"); }
+ try { DragonISO.App.Services.ThemeManager.Current.Apply(); StartupTrace.Write("ThemeManager.Apply OK"); }
catch (Exception ex) { StartupTrace.Write($"ThemeManager.Apply THREW: {ex}"); }
// Single-instance gate. Trace the mutex acquisition.
@@ -129,7 +129,7 @@ public partial class App : Application
StartupTrace.Write($"TryAcquireSingleInstance returned: {acquired}");
if (!acquired)
{
- StartupTrace.Write("not first instance — Shutdown(0)");
+ StartupTrace.Write("not first instance — Shutdown(0)");
Shutdown(0);
return;
}
@@ -141,14 +141,14 @@ public partial class App : Application
StartupTrace.Write("EngineLogging.CreateDefault OK");
var logger = _loggerFactory.CreateLogger();
logger.LogInformation(
- "TeamsISO.App starting up. Build: {Version}. Process: {Pid}.",
+ "DragonISO.App starting up. Build: {Version}. Process: {Pid}.",
typeof(App).Assembly.GetName().Version,
Environment.ProcessId);
StartupTrace.Write("Serilog first write attempted");
if (!TryBootstrapNdiInterop())
{
- StartupTrace.Write("TryBootstrapNdiInterop returned false — Shutdown(2)");
+ StartupTrace.Write("TryBootstrapNdiInterop returned false — Shutdown(2)");
Shutdown(2);
return;
}
@@ -176,7 +176,7 @@ public partial class App : Application
StartBackgroundUpdateCheck(logger);
StartupTrace.Write("OnStartup COMPLETE");
- // 5-second post-init participant probe — tells us whether discovery
+ // 5-second post-init participant probe — tells us whether discovery
// is actually producing rows once the engine is up.
_ = Task.Run(async () =>
{
@@ -195,8 +195,8 @@ public partial class App : Application
try { _loggerFactory?.CreateLogger().LogCritical(ex, "OnStartup failed before main loop"); }
catch { /* defensive */ }
MessageBox.Show(
- "TeamsISO failed to start.\n\nDetails: " + ex,
- "TeamsISO — startup error",
+ "Dragon-ISO failed to start.\n\nDetails: " + ex,
+ "Dragon-ISO — startup error",
MessageBoxButton.OK,
MessageBoxImage.Error);
Shutdown(1);
@@ -204,7 +204,7 @@ public partial class App : Application
}
// De-elevation helpers (ShouldDeElevate, TryDeElevateAndExit, the
- // TEAMSISO_RELAUNCHED env var) were removed 2026-05-16. The whole
+ // Dragon-ISO_RELAUNCHED env var) were removed 2026-05-16. The whole
// pattern was treating a symptom that wasn't actually the problem
// (elevation does NOT break NDI Find); the SAFER token produced by
// runas /trustlevel:0x20000 broke .NET 8 WPF startup itself, so the
@@ -237,10 +237,10 @@ public partial class App : Application
///
/// Parse the supported CLI flags. Currently:
- /// --apply-preset NAME — apply the named preset once participants
- /// populate. Equivalent to running TeamsISO and clicking Presets → select →
+ /// --apply-preset NAME — apply the named preset once participants
+ /// populate. Equivalent to running Dragon-ISO and clicking Presets → select →
/// Apply, but driven from a desktop shortcut.
- /// Unrecognized flags are silently ignored — operators using shortcut.lnk
+ /// Unrecognized flags are silently ignored — operators using shortcut.lnk
/// files don't need to fight argument parsers.
///
private void ApplyCommandLineArgs(string[] args)
diff --git a/src/TeamsISO.App/Assets/teamsiso.ico b/src/Dragon-ISO.App/Assets/Dragon-ISO.ico
similarity index 100%
rename from src/TeamsISO.App/Assets/teamsiso.ico
rename to src/Dragon-ISO.App/Assets/Dragon-ISO.ico
diff --git a/src/TeamsISO.App/Assets/Fonts/Inter.ttf b/src/Dragon-ISO.App/Assets/Fonts/Inter.ttf
similarity index 100%
rename from src/TeamsISO.App/Assets/Fonts/Inter.ttf
rename to src/Dragon-ISO.App/Assets/Fonts/Inter.ttf
diff --git a/src/TeamsISO.App/Assets/Fonts/JetBrainsMono.ttf b/src/Dragon-ISO.App/Assets/Fonts/JetBrainsMono.ttf
similarity index 100%
rename from src/TeamsISO.App/Assets/Fonts/JetBrainsMono.ttf
rename to src/Dragon-ISO.App/Assets/Fonts/JetBrainsMono.ttf
diff --git a/src/TeamsISO.App/Assets/_recolor_dragon.py b/src/Dragon-ISO.App/Assets/_recolor_dragon.py
similarity index 100%
rename from src/TeamsISO.App/Assets/_recolor_dragon.py
rename to src/Dragon-ISO.App/Assets/_recolor_dragon.py
diff --git a/src/TeamsISO.App/Assets/dragon-mark-black.png b/src/Dragon-ISO.App/Assets/dragon-mark-black.png
similarity index 100%
rename from src/TeamsISO.App/Assets/dragon-mark-black.png
rename to src/Dragon-ISO.App/Assets/dragon-mark-black.png
diff --git a/src/TeamsISO.App/Assets/dragon-mark-white.png b/src/Dragon-ISO.App/Assets/dragon-mark-white.png
similarity index 100%
rename from src/TeamsISO.App/Assets/dragon-mark-white.png
rename to src/Dragon-ISO.App/Assets/dragon-mark-white.png
diff --git a/src/TeamsISO.App/Assets/dragon-mark.png b/src/Dragon-ISO.App/Assets/dragon-mark.png
similarity index 100%
rename from src/TeamsISO.App/Assets/dragon-mark.png
rename to src/Dragon-ISO.App/Assets/dragon-mark.png
diff --git a/src/TeamsISO.App/Assets/wild-dragon-wordmark.png b/src/Dragon-ISO.App/Assets/wild-dragon-wordmark.png
similarity index 100%
rename from src/TeamsISO.App/Assets/wild-dragon-wordmark.png
rename to src/Dragon-ISO.App/Assets/wild-dragon-wordmark.png
diff --git a/src/TeamsISO.App/Converters/BoolToVisibilityConverter.cs b/src/Dragon-ISO.App/Converters/BoolToVisibilityConverter.cs
similarity index 90%
rename from src/TeamsISO.App/Converters/BoolToVisibilityConverter.cs
rename to src/Dragon-ISO.App/Converters/BoolToVisibilityConverter.cs
index fc5cd96..06f071a 100644
--- a/src/TeamsISO.App/Converters/BoolToVisibilityConverter.cs
+++ b/src/Dragon-ISO.App/Converters/BoolToVisibilityConverter.cs
@@ -1,8 +1,8 @@
-using System.Globalization;
+using System.Globalization;
using System.Windows;
using System.Windows.Data;
-namespace TeamsISO.App.Converters;
+namespace DragonISO.App.Converters;
[ValueConversion(typeof(bool), typeof(Visibility))]
public sealed class BoolToVisibilityConverter : IValueConverter
diff --git a/src/TeamsISO.App/Converters/CountToVisibilityConverter.cs b/src/Dragon-ISO.App/Converters/CountToVisibilityConverter.cs
similarity index 94%
rename from src/TeamsISO.App/Converters/CountToVisibilityConverter.cs
rename to src/Dragon-ISO.App/Converters/CountToVisibilityConverter.cs
index dae52e0..cdee56e 100644
--- a/src/TeamsISO.App/Converters/CountToVisibilityConverter.cs
+++ b/src/Dragon-ISO.App/Converters/CountToVisibilityConverter.cs
@@ -1,9 +1,9 @@
-using System.Collections;
+using System.Collections;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
-namespace TeamsISO.App.Converters;
+namespace DragonISO.App.Converters;
///
/// Maps a collection (or its count) to . Pass
diff --git a/src/TeamsISO.App/Converters/EnumDescriptionConverter.cs b/src/Dragon-ISO.App/Converters/EnumDescriptionConverter.cs
similarity index 90%
rename from src/TeamsISO.App/Converters/EnumDescriptionConverter.cs
rename to src/Dragon-ISO.App/Converters/EnumDescriptionConverter.cs
index 00f86ea..b58c1af 100644
--- a/src/TeamsISO.App/Converters/EnumDescriptionConverter.cs
+++ b/src/Dragon-ISO.App/Converters/EnumDescriptionConverter.cs
@@ -1,8 +1,8 @@
-using System.Globalization;
+using System.Globalization;
using System.Windows.Data;
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.App.Converters;
+namespace DragonISO.App.Converters;
///
/// Renders engine enum values into operator-friendly strings.
@@ -39,7 +39,7 @@ public sealed class EnumDescriptionConverter : IValueConverter
},
AudioMode m => m switch
{
- AudioMode.Auto => "Auto (isolated → mixed fallback)",
+ AudioMode.Auto => "Auto (isolated → mixed fallback)",
AudioMode.Isolated => "Isolated",
AudioMode.Mixed => "Mixed",
_ => m.ToString()
diff --git a/src/TeamsISO.App/Converters/InitialsConverter.cs b/src/Dragon-ISO.App/Converters/InitialsConverter.cs
similarity index 76%
rename from src/TeamsISO.App/Converters/InitialsConverter.cs
rename to src/Dragon-ISO.App/Converters/InitialsConverter.cs
index 448c807..3c5d51e 100644
--- a/src/TeamsISO.App/Converters/InitialsConverter.cs
+++ b/src/Dragon-ISO.App/Converters/InitialsConverter.cs
@@ -1,26 +1,26 @@
-using System.Globalization;
+using System.Globalization;
using System.Windows.Data;
-namespace TeamsISO.App.Converters;
+namespace DragonISO.App.Converters;
///
/// Converts a display name to up to two uppercase initials for an avatar bubble.
-/// "Brendon Power" → "BP". "(Local)" → "L". Falls back to "·" for empty inputs.
+/// "Brendon Power" → "BP". "(Local)" → "L". Falls back to "·" for empty inputs.
///
public sealed class InitialsConverter : IValueConverter
{
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
var s = value as string;
- if (string.IsNullOrWhiteSpace(s)) return "·";
+ if (string.IsNullOrWhiteSpace(s)) return "·";
// Strip surrounding parens / punctuation that would otherwise become
// useless initials (e.g. "(Local)" should yield "L", not "(").
var cleaned = new string(s.Where(c => char.IsLetterOrDigit(c) || char.IsWhiteSpace(c)).ToArray()).Trim();
- if (cleaned.Length == 0) return "·";
+ if (cleaned.Length == 0) return "·";
var parts = cleaned.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
- if (parts.Length == 0) return "·";
+ if (parts.Length == 0) return "·";
if (parts.Length == 1) return char.ToUpperInvariant(parts[0][0]).ToString();
return $"{char.ToUpperInvariant(parts[0][0])}{char.ToUpperInvariant(parts[^1][0])}";
}
diff --git a/src/TeamsISO.App/Converters/LevelThresholdConverter.cs b/src/Dragon-ISO.App/Converters/LevelThresholdConverter.cs
similarity index 87%
rename from src/TeamsISO.App/Converters/LevelThresholdConverter.cs
rename to src/Dragon-ISO.App/Converters/LevelThresholdConverter.cs
index f53630d..c5397d8 100644
--- a/src/TeamsISO.App/Converters/LevelThresholdConverter.cs
+++ b/src/Dragon-ISO.App/Converters/LevelThresholdConverter.cs
@@ -1,10 +1,10 @@
-using System.Globalization;
+using System.Globalization;
using System.Windows.Data;
-namespace TeamsISO.App.Converters;
+namespace DragonISO.App.Converters;
///
-/// Maps an audio level (0.0–1.0) to an opacity for a single audio-meter
+/// Maps an audio level (0.0–1.0) to an opacity for a single audio-meter
/// segment. The XAML binds five copies, each with a different
/// threshold (0.2, 0.4, 0.6,
/// 0.8, 1.0). A segment renders at full opacity when the live level
@@ -21,7 +21,7 @@ public sealed class LevelThresholdConverter : IValueConverter
/// Opacity for an above-threshold segment. Defaults to 1.0.
public double ActiveOpacity { get; set; } = 1.0;
- /// Opacity for a below-threshold segment. Defaults to 0.18 — visible enough to read the segment shape but clearly off.
+ /// Opacity for a below-threshold segment. Defaults to 0.18 — visible enough to read the segment shape but clearly off.
public double InactiveOpacity { get; set; } = 0.18;
public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture)
diff --git a/src/TeamsISO.App/Converters/NullToCollapsedConverter.cs b/src/Dragon-ISO.App/Converters/NullToCollapsedConverter.cs
similarity index 83%
rename from src/TeamsISO.App/Converters/NullToCollapsedConverter.cs
rename to src/Dragon-ISO.App/Converters/NullToCollapsedConverter.cs
index e24a8c9..c062470 100644
--- a/src/TeamsISO.App/Converters/NullToCollapsedConverter.cs
+++ b/src/Dragon-ISO.App/Converters/NullToCollapsedConverter.cs
@@ -1,11 +1,11 @@
-using System.Globalization;
+using System.Globalization;
using System.Windows;
using System.Windows.Data;
-namespace TeamsISO.App.Converters;
+namespace DragonISO.App.Converters;
///
-/// Tiny utility converter — null or empty string ⇒ Collapsed, otherwise
+/// Tiny utility converter — null or empty string ⇒ Collapsed, otherwise
/// Visible. Used by the v2 command palette's optional shortcut chip
/// (e.g. "Ctrl+R") so rows without a bound shortcut don't render the
/// empty pill outline.
diff --git a/src/TeamsISO.App/TeamsISO.App.csproj b/src/Dragon-ISO.App/Dragon-ISO.App.csproj
similarity index 72%
rename from src/TeamsISO.App/TeamsISO.App.csproj
rename to src/Dragon-ISO.App/Dragon-ISO.App.csproj
index 90cb57d..ac0a955 100644
--- a/src/TeamsISO.App/TeamsISO.App.csproj
+++ b/src/Dragon-ISO.App/Dragon-ISO.App.csproj
@@ -1,64 +1,64 @@
-
+WinExenet8.0-windowstruetrue
- TeamsISO.App
- TeamsISO
+ DragonISO.App
+ DragonISOtrue
- Assets\teamsiso.ico
+ Assets\Dragon-ISO.icotrue
-
-
+
+
- <_Parameter1>TeamsISO.App.Tests
+ <_Parameter1>Dragon-ISO.App.Tests
- TeamsISO.App.Properties.Strings.resources
+ Dragon-ISO.App.Properties.Strings.resources
-
+
@@ -67,12 +67,12 @@
a single Wd.BrandMark.Image resource key. The dark theme picks the white
dragon (visible on #0A0A0A), the light theme picks the black dragon
(visible on #FAFAFB). Generated from dragon-mark.png via
- Assets/_recolor_dragon.py — re-run if the source mark ever changes.
+ Assets/_recolor_dragon.py — re-run if the source mark ever changes.
-->
-
+
-
-
+
-
+
-
+
-
+
@@ -197,7 +197,7 @@
Foreground="{DynamicResource Wd.Accent.Cyan}"
TextDecorations="None"
Click="OnDocsClick">
- forge.wilddragon.net/zgaetano/teamsiso
+ forge.wilddragon.net/zgaetano/DragonISO
diff --git a/src/TeamsISO.App/HelpWindow.xaml.cs b/src/Dragon-ISO.App/HelpWindow.xaml.cs
similarity index 91%
rename from src/TeamsISO.App/HelpWindow.xaml.cs
rename to src/Dragon-ISO.App/HelpWindow.xaml.cs
index 5a79f40..e9c462c 100644
--- a/src/TeamsISO.App/HelpWindow.xaml.cs
+++ b/src/Dragon-ISO.App/HelpWindow.xaml.cs
@@ -1,7 +1,7 @@
-using System.Diagnostics;
+using System.Diagnostics;
using System.Windows;
-namespace TeamsISO.App;
+namespace DragonISO.App;
///
/// F1 cheat-sheet dialog. Lists keyboard shortcuts, file locations, and a
@@ -20,7 +20,7 @@ public partial class HelpWindow : Window
{
Process.Start(new ProcessStartInfo
{
- FileName = "https://forge.wilddragon.net/zgaetano/teamsiso",
+ FileName = "https://forge.wilddragon.net/zgaetano/Dragon-ISO",
UseShellExecute = true,
});
}
diff --git a/src/TeamsISO.App/MainWindow.xaml b/src/Dragon-ISO.App/MainWindow.xaml
similarity index 99%
rename from src/TeamsISO.App/MainWindow.xaml
rename to src/Dragon-ISO.App/MainWindow.xaml
index b5e0df9..b655fd4 100644
--- a/src/TeamsISO.App/MainWindow.xaml
+++ b/src/Dragon-ISO.App/MainWindow.xaml
@@ -1,12 +1,12 @@
-
+
@@ -208,7 +208,7 @@
Style="{StaticResource Wd.Text.Body}"
FontSize="12"
Foreground="{DynamicResource Wd.Text.Secondary}"
- Text="To use TeamsISO as your only window: tick both 'Launch Microsoft Teams on TeamsISO startup' and 'Auto-hide Teams windows when launched' under Settings → DISPLAY. Teams runs in the background; the IN-CALL bar shows the meeting state (READY / IN CALL · meeting title), the Mute/Camera/Share/Leave buttons drive Teams via UIAutomation, and the URL paste-box joins meetings directly. Use the eye-icon button in the left rail to manually restore Teams' windows when you need them."/>
+ Text="To use DragonISO as your only window: tick both 'Launch Microsoft Teams on DragonISO startup' and 'Auto-hide Teams windows when launched' under Settings → DISPLAY. Teams runs in the background; the IN-CALL bar shows the meeting state (READY / IN CALL · meeting title), the Mute/Camera/Share/Leave buttons drive Teams via UIAutomation, and the URL paste-box joins meetings directly. Use the eye-icon button in the left rail to manually restore Teams' windows when you need them."/>
@@ -236,7 +236,7 @@
Style="{StaticResource Wd.Text.Body}"
FontSize="12"
Foreground="{DynamicResource Wd.Text.Secondary}"
- Text="For headless host PC + thin-client setups: tick 'Control surface' then 'LAN-reachable' under DISPLAY. TeamsISO listens on http://<your-lan-ip>:9755/ui — open that URL from any browser on the LAN. First-time use needs a one-shot 'netsh http add urlacl url=http://+:9755/ user=Everyone' in an Administrator PowerShell."/>
+ Text="For headless host PC + thin-client setups: tick 'Control surface' then 'LAN-reachable' under DISPLAY. DragonISO listens on http://<your-lan-ip>:9755/ui — open that URL from any browser on the LAN. First-time use needs a one-shot 'netsh http add urlacl url=http://+:9755/ user=Everyone' in an Administrator PowerShell."/>
@@ -264,7 +264,7 @@
Style="{StaticResource Wd.Text.Body}"
FontSize="12"
Foreground="{DynamicResource Wd.Text.Secondary}"
- Text="Diagnostic logs roll daily under %LOCALAPPDATA%\TeamsISO\Logs. Settings live at %APPDATA%\TeamsISO\config.json; presets at %LOCALAPPDATA%\TeamsISO\presets.json. Attach the most recent log when filing an issue at forge.wilddragon.net/zgaetano/teamsiso."/>
+ Text="Diagnostic logs roll daily under %LOCALAPPDATA%\DragonISO\Logs. Settings live at %APPDATA%\DragonISO\config.json; presets at %LOCALAPPDATA%\DragonISO\presets.json. Attach the most recent log when filing an issue at forge.wilddragon.net/zgaetano/DragonISO."/>
diff --git a/src/TeamsISO.App/OnboardingWindow.xaml.cs b/src/Dragon-ISO.App/OnboardingWindow.xaml.cs
similarity index 79%
rename from src/TeamsISO.App/OnboardingWindow.xaml.cs
rename to src/Dragon-ISO.App/OnboardingWindow.xaml.cs
index e4bcab9..6857056 100644
--- a/src/TeamsISO.App/OnboardingWindow.xaml.cs
+++ b/src/Dragon-ISO.App/OnboardingWindow.xaml.cs
@@ -1,7 +1,7 @@
-using System.IO;
+using System.IO;
using System.Windows;
-namespace TeamsISO.App;
+namespace DragonISO.App;
///
/// First-launch welcome dialog. Walks the user through the once-per-machine
@@ -10,8 +10,8 @@ namespace TeamsISO.App;
/// presets live for later self-service.
///
/// Suppression is governed by a marker file at
-/// %LOCALAPPDATA%\TeamsISO\onboarding.flag. The presence of the file —
-/// regardless of contents — means "don't show again." The user can restore
+/// %LOCALAPPDATA%\Dragon-ISO\onboarding.flag. The presence of the file —
+/// regardless of contents — means "don't show again." The user can restore
/// the dialog by deleting that file.
///
public partial class OnboardingWindow : Window
@@ -19,7 +19,7 @@ public partial class OnboardingWindow : Window
private static string FlagPath =>
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
- "TeamsISO", "onboarding.flag");
+ "Dragon-ISO", "onboarding.flag");
public OnboardingWindow() => InitializeComponent();
@@ -30,7 +30,7 @@ public partial class OnboardingWindow : Window
public static bool ShouldShow()
{
try { return !File.Exists(FlagPath); }
- catch { return false; } // permission errors → assume already shown
+ catch { return false; } // permission errors → assume already shown
}
private void OnDismiss(object sender, RoutedEventArgs e)
@@ -47,7 +47,7 @@ public partial class OnboardingWindow : Window
}
catch
{
- // Disk full / permission denied — show the dialog again next launch
+ // Disk full / permission denied — show the dialog again next launch
// rather than fail noisily.
}
}
diff --git a/src/TeamsISO.App/PresetsDialog.xaml b/src/Dragon-ISO.App/PresetsDialog.xaml
similarity index 99%
rename from src/TeamsISO.App/PresetsDialog.xaml
rename to src/Dragon-ISO.App/PresetsDialog.xaml
index 188c1e3..33049fe 100644
--- a/src/TeamsISO.App/PresetsDialog.xaml
+++ b/src/Dragon-ISO.App/PresetsDialog.xaml
@@ -1,9 +1,9 @@
-
/// Modal dialog for saving and loading operator presets. Owned by
@@ -101,7 +101,7 @@ public partial class PresetsDialog : Window
var confirm = MessageBox.Show(
this,
$"A preset named \"{name}\" already exists. Overwrite it?",
- "TeamsISO — Overwrite preset",
+ "Dragon-ISO — Overwrite preset",
MessageBoxButton.YesNo,
MessageBoxImage.Question,
MessageBoxResult.No);
@@ -122,7 +122,7 @@ public partial class PresetsDialog : Window
MessageBox.Show(
this,
$"Could not save preset.\n\n{ex.Message}",
- "TeamsISO — Save preset",
+ "Dragon-ISO — Save preset",
MessageBoxButton.OK,
MessageBoxImage.Warning);
}
@@ -130,7 +130,7 @@ public partial class PresetsDialog : Window
///
/// Apply the selected preset: walks the current participants list, matching
- /// by display name (the only stable join key across meetings — Ids are
+ /// by display name (the only stable join key across meetings — Ids are
/// regenerated each meeting). For each match, set the custom output name and
/// reconcile its enabled state with the preset by calling EnableIsoAsync /
/// DisableIsoAsync as needed. Participants in the preset who aren't in the
@@ -143,15 +143,15 @@ public partial class PresetsDialog : Window
ApplyButton.IsEnabled = false;
try
{
- // PresetApplier owns the apply loop — same code path the REST control
+ // PresetApplier owns the apply loop — same code path the REST control
// surface and auto-apply-on-launch use. Dialog passes null dispatcher
// since OnApply already runs on the UI thread.
var result = await PresetApplier.ApplyAsync(
row.Preset, _participants, _controller, dispatcher: null);
var summary = result.Skipped > 0
- ? $"Applied \"{row.Name}\" — {result.Changed} change(s); {result.Skipped} not in meeting"
- : $"Applied \"{row.Name}\" — {result.Changed} change(s)";
+ ? $"Applied \"{row.Name}\" — {result.Changed} change(s); {result.Skipped} not in meeting"
+ : $"Applied \"{row.Name}\" — {result.Changed} change(s)";
_toast?.Show(summary);
DialogResult = true;
Close();
@@ -184,14 +184,14 @@ public partial class PresetsDialog : Window
var confirm = MessageBox.Show(
this,
$"A preset named \"{newName}\" already exists. Overwrite it?",
- "TeamsISO — Duplicate preset",
+ "Dragon-ISO — Duplicate preset",
MessageBoxButton.YesNo,
MessageBoxImage.Question,
MessageBoxResult.No);
if (confirm != MessageBoxResult.Yes) return;
}
- // Re-using Save() with a fresh SavedAt timestamp — Save's overwrite
+ // Re-using Save() with a fresh SavedAt timestamp — Save's overwrite
// semantics handle the name-collision case cleanly.
OperatorPresetStore.Save(new OperatorPresetStore.Preset(
Name: newName,
@@ -204,14 +204,14 @@ public partial class PresetsDialog : Window
{
MessageBox.Show(this,
$"Could not duplicate preset.\n\n{ex.Message}",
- "TeamsISO — Duplicate preset",
+ "Dragon-ISO — Duplicate preset",
MessageBoxButton.OK,
MessageBoxImage.Warning);
}
}
///
- /// Suggest a name for a copy: "Foo" → "Foo (copy)", "Foo (copy)" → "Foo (copy 2)".
+ /// Suggest a name for a copy: "Foo" → "Foo (copy)", "Foo (copy)" → "Foo (copy 2)".
/// Bumps the digit if the operator iterates from a copy.
///
private static string SuggestCopyName(string original)
@@ -275,7 +275,7 @@ public partial class PresetsDialog : Window
var confirm = MessageBox.Show(
this,
$"Delete preset \"{row.Name}\"? This cannot be undone.",
- "TeamsISO — Delete preset",
+ "Dragon-ISO — Delete preset",
MessageBoxButton.YesNo,
MessageBoxImage.Warning,
MessageBoxResult.No);
@@ -292,7 +292,7 @@ public partial class PresetsDialog : Window
MessageBox.Show(
this,
$"Could not delete preset.\n\n{ex.Message}",
- "TeamsISO — Delete preset",
+ "Dragon-ISO — Delete preset",
MessageBoxButton.OK,
MessageBoxImage.Warning);
}
@@ -313,9 +313,9 @@ public partial class PresetsDialog : Window
{
var dlg = new Microsoft.Win32.SaveFileDialog
{
- Title = "Export TeamsISO presets",
- FileName = $"teamsiso-presets-{DateTimeOffset.Now:yyyy-MM-dd}.json",
- Filter = "TeamsISO preset bundle (*.json)|*.json",
+ Title = "Export Dragon-ISO presets",
+ FileName = $"Dragon-ISO-presets-{DateTimeOffset.Now:yyyy-MM-dd}.json",
+ Filter = "Dragon-ISO preset bundle (*.json)|*.json",
DefaultExt = "json",
};
if (dlg.ShowDialog(this) != true) return;
@@ -330,7 +330,7 @@ public partial class PresetsDialog : Window
{
MessageBox.Show(this,
$"Could not export presets.\n\n{ex.Message}",
- "TeamsISO — Export presets",
+ "Dragon-ISO — Export presets",
MessageBoxButton.OK,
MessageBoxImage.Warning);
}
@@ -338,7 +338,7 @@ public partial class PresetsDialog : Window
///
/// Load a bundle from a path the user picks. On name collision we ask once
- /// (covering all collisions) whether to overwrite — a per-preset prompt would
+ /// (covering all collisions) whether to overwrite — a per-preset prompt would
/// be exhausting for a 20-preset bundle. The Y/N here drives the overwrite
/// flag passed to .
///
@@ -346,8 +346,8 @@ public partial class PresetsDialog : Window
{
var dlg = new Microsoft.Win32.OpenFileDialog
{
- Title = "Import TeamsISO presets",
- Filter = "TeamsISO preset bundle (*.json)|*.json|All files (*.*)|*.*",
+ Title = "Import Dragon-ISO presets",
+ Filter = "Dragon-ISO preset bundle (*.json)|*.json|All files (*.*)|*.*",
};
if (dlg.ShowDialog(this) != true) return;
@@ -357,7 +357,7 @@ public partial class PresetsDialog : Window
{
MessageBox.Show(this,
$"Could not read the file.\n\n{ex.Message}",
- "TeamsISO — Import presets",
+ "Dragon-ISO — Import presets",
MessageBoxButton.OK,
MessageBoxImage.Warning);
return;
@@ -369,8 +369,8 @@ public partial class PresetsDialog : Window
catch
{
MessageBox.Show(this,
- "That file isn't a valid TeamsISO preset bundle.",
- "TeamsISO — Import presets",
+ "That file isn't a valid Dragon-ISO preset bundle.",
+ "Dragon-ISO — Import presets",
MessageBoxButton.OK,
MessageBoxImage.Warning);
return;
@@ -379,7 +379,7 @@ public partial class PresetsDialog : Window
{
MessageBox.Show(this,
"The bundle is empty.",
- "TeamsISO — Import presets",
+ "Dragon-ISO — Import presets",
MessageBoxButton.OK,
MessageBoxImage.Information);
return;
@@ -398,7 +398,7 @@ public partial class PresetsDialog : Window
$"{collisions} preset name(s) in this bundle already exist on this machine.\n\n" +
"Yes = overwrite local copies with the bundle's versions.\n" +
"No = keep local copies; only import new presets.",
- "TeamsISO — Import presets",
+ "Dragon-ISO — Import presets",
MessageBoxButton.YesNoCancel,
MessageBoxImage.Question,
MessageBoxResult.No);
@@ -411,13 +411,13 @@ public partial class PresetsDialog : Window
{
MessageBox.Show(this,
$"Import failed.\n\n{result.Error}",
- "TeamsISO — Import presets",
+ "Dragon-ISO — Import presets",
MessageBoxButton.OK,
MessageBoxImage.Warning);
return;
}
- var summary = $"Imported — {result.Added} new";
+ var summary = $"Imported — {result.Added} new";
if (result.Overwritten > 0) summary += $", {result.Overwritten} overwritten";
if (result.Skipped > 0) summary += $", {result.Skipped} skipped";
_toast?.Show(summary);
diff --git a/src/TeamsISO.App/PreviewWindow.xaml b/src/Dragon-ISO.App/PreviewWindow.xaml
similarity index 97%
rename from src/TeamsISO.App/PreviewWindow.xaml
rename to src/Dragon-ISO.App/PreviewWindow.xaml
index 8d390ab..952e026 100644
--- a/src/TeamsISO.App/PreviewWindow.xaml
+++ b/src/Dragon-ISO.App/PreviewWindow.xaml
@@ -1,9 +1,9 @@
-
/// Non-modal floating preview window for a single participant. Shows the
/// engine's most recent at a higher refresh
/// rate (~20Hz) than the participants DataGrid thumbnails (1Hz). Multi-
/// monitor friendly: operator drags it to a second display, leaves the
-/// main TeamsISO window on the primary.
+/// main Dragon-ISO window on the primary.
///
/// Uses with
-/// — the engine produces full-resolution BGRA frames so we can write them
+/// — the engine produces full-resolution BGRA frames so we can write them
/// straight into the bitmap without scaling. WPF's Image control with
/// Stretch=Uniform handles aspect-correct fit to the window size.
///
@@ -71,12 +71,12 @@ public partial class PreviewWindow : Window
PreviewImage.Source = _bitmap;
_lastWidth = frame.Width;
_lastHeight = frame.Height;
- ResolutionText.Text = $"{frame.Width}×{frame.Height}";
+ ResolutionText.Text = $"{frame.Width}×{frame.Height}";
}
// WritePixels takes a buffer + stride + rect. Stride = width * 4 for
// BGRA. We slice the ProcessedFrame's ReadOnlyMemory via .Span
- // and use the IntPtr overload via MemoryMarshal — but the
+ // and use the IntPtr overload via MemoryMarshal — but the
// byte-array overload is simpler and the compiler picks the right
// ToArray-free path because the engine already allocates a fresh
// array per frame.
diff --git a/src/TeamsISO.App/Properties/Strings.Designer.cs b/src/Dragon-ISO.App/Properties/Strings.Designer.cs
similarity index 85%
rename from src/TeamsISO.App/Properties/Strings.Designer.cs
rename to src/Dragon-ISO.App/Properties/Strings.Designer.cs
index fc74b0d..067daa7 100644
--- a/src/TeamsISO.App/Properties/Strings.Designer.cs
+++ b/src/Dragon-ISO.App/Properties/Strings.Designer.cs
@@ -1,21 +1,21 @@
-// Hand-written strongly-typed accessor for Properties/Strings.resx. Kept
+// Hand-written strongly-typed accessor for Properties/Strings.resx. Kept
// out of Visual Studio's "ResXFileCodeGenerator" auto-regeneration loop
// so the .csproj stays simple and the file doesn't churn on every save.
// If you add a key in Strings.resx, add a matching property here.
// The compiler treats `*.Designer.cs` as auto-generated and refuses
-// nullable annotations without an explicit directive — opt in.
+// nullable annotations without an explicit directive — opt in.
#nullable enable
using System.Globalization;
using System.Resources;
-namespace TeamsISO.App.Properties;
+namespace DragonISO.App.Properties;
internal static class Strings
{
private static readonly ResourceManager ResourceManager = new(
- baseName: "TeamsISO.App.Properties.Strings",
+ baseName: "DragonISO.App.Properties.Strings",
assembly: typeof(Strings).Assembly);
public static CultureInfo? Culture { get; set; }
diff --git a/src/TeamsISO.App/Properties/Strings.resx b/src/Dragon-ISO.App/Properties/Strings.resx
similarity index 100%
rename from src/TeamsISO.App/Properties/Strings.resx
rename to src/Dragon-ISO.App/Properties/Strings.resx
diff --git a/src/TeamsISO.App/Services/ControlPanelHtml.cs b/src/Dragon-ISO.App/Services/ControlPanelHtml.cs
similarity index 91%
rename from src/TeamsISO.App/Services/ControlPanelHtml.cs
rename to src/Dragon-ISO.App/Services/ControlPanelHtml.cs
index 64a0d2e..e3867e3 100644
--- a/src/TeamsISO.App/Services/ControlPanelHtml.cs
+++ b/src/Dragon-ISO.App/Services/ControlPanelHtml.cs
@@ -1,8 +1,8 @@
-namespace TeamsISO.App.Services;
+namespace DragonISO.App.Services;
///
/// The HTML / CSS / JS for the embedded control panel served at
-/// GET /ui. Single self-contained string — no external CDN deps, no
+/// GET /ui. Single self-contained string — no external CDN deps, no
/// build step, no React. Phone-friendly remote that connects via WebSocket
/// to /ws and posts to the existing REST endpoints.
///
@@ -10,7 +10,7 @@ namespace TeamsISO.App.Services;
/// - Live preview tiles per participant via GET /participants/{id}/thumbnail.jpg
/// (engine encodes the latest ProcessedFrame as a 192-wide JPEG; refreshed
/// ~1Hz alongside the WebSocket state push).
-/// - Topology toggle card — shows whether raw Teams NDI sources are
+/// - Topology toggle card — shows whether raw Teams NDI sources are
/// hidden from the LAN, with Apply / Restore buttons that hit the
/// /topology/apply + /topology/restore REST endpoints. Operator still
/// has to restart Teams afterward, surfaced in a banner on apply.
@@ -22,7 +22,7 @@ internal static class ControlPanelHtml
-TeamsISO Control
+Dragon-ISO Control
-
TeamsISO control surface
+
Dragon-ISO control surface
- connecting…
+ connecting…
@@ -156,7 +156,7 @@ internal static class ControlPanelHtml
Network topology
- —
+ —
@@ -173,7 +173,7 @@ internal static class ControlPanelHtml
-
+
@@ -226,20 +226,20 @@ function paintTopology(t) {
topoLabel.textContent = 'Teams hidden from LAN';
} else if (t.mode === 'public') {
topoDot.className = 'dot amber';
- topoLabel.textContent = 'Public — raw Teams visible';
+ topoLabel.textContent = 'Public — raw Teams visible';
} else {
topoDot.className = 'dot gray';
topoLabel.textContent = 'Unknown';
}
- const sends = (t.senders || []).join(', ') || '—';
- const recvs = (t.receivers || []).join(', ') || '—';
- topoDetail.textContent = 'send: ' + sends + ' · recv: ' + recvs;
+ const sends = (t.senders || []).join(', ') || '—';
+ const recvs = (t.receivers || []).join(', ') || '—';
+ topoDetail.textContent = 'send: ' + sends + ' · recv: ' + recvs;
}
async function applyTopology() {
const r = await post('/topology/apply');
if (r && r.ok) {
- topoBanner.textContent = '✓ ' + (r.note || 'Applied. Restart Microsoft Teams for it to take effect.');
+ topoBanner.textContent = '✓ ' + (r.note || 'Applied. Restart Microsoft Teams for it to take effect.');
topoBanner.classList.add('show');
setTimeout(() => topoBanner.classList.remove('show'), 8000);
}
@@ -250,7 +250,7 @@ async function restoreTopology() {
if (!confirm('Restore default NDI groups? Teams will broadcast on public again after you restart it.')) return;
const r = await post('/topology/restore');
if (r && r.ok) {
- topoBanner.textContent = '✓ Defaults restored. Restart Microsoft Teams for it to take effect.';
+ topoBanner.textContent = '✓ Defaults restored. Restart Microsoft Teams for it to take effect.';
topoBanner.classList.add('show');
setTimeout(() => topoBanner.classList.remove('show'), 8000);
}
@@ -282,15 +282,15 @@ const openPanels = new Set();
function shortFps(v) {
for (const [k, label] of FRAMERATE_OPTS) if (k === v) return label;
- return v || '—';
+ return v || '—';
}
function shortRes(v) {
for (const [k, label] of RESOLUTION_OPTS) if (k === v) return label;
- return v || '—';
+ return v || '—';
}
function shortAudio(v) {
for (const [k, label] of AUDIO_OPTS) if (k === v) return label;
- return v || '—';
+ return v || '—';
}
function buildSelect(opts, current) {
@@ -323,21 +323,21 @@ function render(participants) {
const row = document.createElement('div');
row.className = 'participant-row';
const stateColor = p.isEnabled ? 'cyan' : (p.isOnline ? 'gray' : 'coral');
- // Live preview tile — cache-bust with a 1s-bucket query param so the
+ // Live preview tile — cache-bust with a 1s-bucket query param so the
// browser refreshes the image without flickering on every WS message.
const bust = Math.floor(Date.now() / 1000);
const previewUrl = '/participants/' + p.id + '/thumbnail.jpg?t=' + bust;
row.innerHTML =
"""" +
"""" +
- ""
—
"" +
+ ""
—
"" +
""
"" +
"""" +
"""" +
""
"" +
""
"" +
"""" +
- """" +
+ """" +
"""" +
""
"";
const img = row.querySelector('img.preview');
@@ -346,7 +346,7 @@ function render(participants) {
const subEl = row.querySelector('.sub');
subEl.textContent =
(p.stateLabel || (p.isOnline ? 'online' : 'offline')) +
- (p.customName ? ' · ' + p.customName : '');
+ (p.customName ? ' · ' + p.customName : '');
if (isOverride) {
const pill = document.createElement('span');
pill.className = 'ovr-pill';
@@ -354,10 +354,10 @@ function render(participants) {
subEl.appendChild(pill);
}
row.querySelector('.cfg-caption').textContent =
- shortFps(eff.framerate) + ' · ' + shortRes(eff.resolution) + ' · ' + shortAudio(eff.audio);
+ shortFps(eff.framerate) + ' · ' + shortRes(eff.resolution) + ' · ' + shortAudio(eff.audio);
const enableBtn = row.querySelector('.enable-btn');
enableBtn.className = 'enable-btn ' + (p.isEnabled ? 'live' : '');
- enableBtn.textContent = p.isEnabled ? '● LIVE' : 'Enable';
+ enableBtn.textContent = p.isEnabled ? 'â— LIVE' : 'Enable';
enableBtn.onclick = () => post('/participants/iso', {
displayName: p.displayName,
enabled: !p.isEnabled,
@@ -419,7 +419,7 @@ function render(participants) {
}
function connect() {
- setConn('gray', 'connecting…');
+ setConn('gray', 'connecting…');
const ws = new WebSocket(
(location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host + '/ws');
ws.onopen = () => { setConn('green', 'live'); fetchTopology(); };
@@ -430,7 +430,7 @@ function connect() {
} catch (e) { console.warn(e); }
};
ws.onclose = () => {
- setConn('coral', 'disconnected — retry in 3s');
+ setConn('coral', 'disconnected — retry in 3s');
setTimeout(connect, 3000);
};
ws.onerror = () => setConn('coral', 'error');
@@ -438,7 +438,7 @@ function connect() {
connect();
// Re-poll topology every 30s in case the operator changes the machine NDI
-// config externally (NDI Access Manager, manual edit). Cheap — one HTTP GET.
+// config externally (NDI Access Manager, manual edit). Cheap — one HTTP GET.
setInterval(fetchTopology, 30000);
diff --git a/src/TeamsISO.App/Services/ControlSurface/Endpoints/HomeEndpoints.cs b/src/Dragon-ISO.App/Services/ControlSurface/Endpoints/HomeEndpoints.cs
similarity index 88%
rename from src/TeamsISO.App/Services/ControlSurface/Endpoints/HomeEndpoints.cs
rename to src/Dragon-ISO.App/Services/ControlSurface/Endpoints/HomeEndpoints.cs
index bacab7e..dfb0608 100644
--- a/src/TeamsISO.App/Services/ControlSurface/Endpoints/HomeEndpoints.cs
+++ b/src/Dragon-ISO.App/Services/ControlSurface/Endpoints/HomeEndpoints.cs
@@ -1,19 +1,19 @@
-namespace TeamsISO.App.Services;
+namespace DragonISO.App.Services;
-// GET / — server info + endpoint catalogue. Returned as the JSON
+// GET / — server info + endpoint catalogue. Returned as the JSON
// homepage when a Companion / Stream Deck plugin first probes the
// surface; humans see it via curl http://127.0.0.1:9755/.
public sealed partial class ControlSurfaceServer
{
private object GetServerInfo()
{
- // Best-effort engine snapshot — wrapped in TryRead so a transient
+ // Best-effort engine snapshot — wrapped in TryRead so a transient
// controller error doesn't 500 the homepage poll.
var settings = TryRead(() => _controller.GlobalSettings);
var groups = TryRead(() => _controller.GroupSettings);
return new
{
- product = "TeamsISO",
+ product = "Dragon-ISO",
version = typeof(ControlSurfaceServer).Assembly.GetName().Version?.ToString() ?? "unknown",
engine = new
{
diff --git a/src/TeamsISO.App/Services/ControlSurface/Endpoints/NotesEndpoints.cs b/src/Dragon-ISO.App/Services/ControlSurface/Endpoints/NotesEndpoints.cs
similarity index 67%
rename from src/TeamsISO.App/Services/ControlSurface/Endpoints/NotesEndpoints.cs
rename to src/Dragon-ISO.App/Services/ControlSurface/Endpoints/NotesEndpoints.cs
index 3060ffd..b8b5cde 100644
--- a/src/TeamsISO.App/Services/ControlSurface/Endpoints/NotesEndpoints.cs
+++ b/src/Dragon-ISO.App/Services/ControlSurface/Endpoints/NotesEndpoints.cs
@@ -1,11 +1,11 @@
-using System.Collections.Specialized;
+using System.Collections.Specialized;
using System.Text.Json;
-namespace TeamsISO.App.Services;
+namespace DragonISO.App.Services;
-// /notes/* route handlers — append-only operator show-notes file.
+// /notes/* route handlers — append-only operator show-notes file.
//
-// POST /notes (body: { "text": "..." }) → AppendNote
+// POST /notes (body: { "text": "..." }) → AppendNote
public sealed partial class ControlSurfaceServer
{
private object AppendNote(JsonElement body, NameValueCollection query)
diff --git a/src/TeamsISO.App/Services/ControlSurface/Endpoints/ParticipantsEndpoints.cs b/src/Dragon-ISO.App/Services/ControlSurface/Endpoints/ParticipantsEndpoints.cs
similarity index 91%
rename from src/TeamsISO.App/Services/ControlSurface/Endpoints/ParticipantsEndpoints.cs
rename to src/Dragon-ISO.App/Services/ControlSurface/Endpoints/ParticipantsEndpoints.cs
index 4c7232d..d7752bd 100644
--- a/src/TeamsISO.App/Services/ControlSurface/Endpoints/ParticipantsEndpoints.cs
+++ b/src/Dragon-ISO.App/Services/ControlSurface/Endpoints/ParticipantsEndpoints.cs
@@ -1,24 +1,24 @@
-using System.Collections.Specialized;
+using System.Collections.Specialized;
using System.Text.Json;
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.App.Services;
+namespace DragonISO.App.Services;
// /participants/* route handlers. Anything that reads or writes
// participant + per-pipeline state lives here.
//
-// GET /participants → GetParticipants
-// POST /participants/{id}/iso → ToggleIsoByIdAsync
-// POST /participants/iso → ToggleIsoByNameAsync
-// POST /participants/{id}/override → SetIsoOverrideByIdAsync
-// DELETE /participants/{id}/override → ClearIsoOverrideByIdAsync
+// GET /participants → GetParticipants
+// POST /participants/{id}/iso → ToggleIsoByIdAsync
+// POST /participants/iso → ToggleIsoByNameAsync
+// POST /participants/{id}/override → SetIsoOverrideByIdAsync
+// DELETE /participants/{id}/override → ClearIsoOverrideByIdAsync
public sealed partial class ControlSurfaceServer
{
private object GetParticipants()
{
var vm = _viewModel();
if (vm is null) return new { participants = Array.Empty
+
+
+
+
+
+
+
+
+
+ <_Parameter1>Dragon-ISO.Engine.Tests
+
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
diff --git a/src/TeamsISO.Engine.NdiInterop/NdiInteropPInvoke.cs b/src/Dragon-ISO.Engine.NdiInterop/NdiInteropPInvoke.cs
similarity index 94%
rename from src/TeamsISO.Engine.NdiInterop/NdiInteropPInvoke.cs
rename to src/Dragon-ISO.Engine.NdiInterop/NdiInteropPInvoke.cs
index 9eb4298..811136b 100644
--- a/src/TeamsISO.Engine.NdiInterop/NdiInteropPInvoke.cs
+++ b/src/Dragon-ISO.Engine.NdiInterop/NdiInteropPInvoke.cs
@@ -1,10 +1,10 @@
-using System.Runtime.InteropServices;
+using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Microsoft.Extensions.Logging;
-using TeamsISO.Engine.Interop;
-using TeamsISO.Engine.Pipeline;
+using DragonISO.Engine.Interop;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.Engine.NdiInterop;
+namespace DragonISO.Engine.NdiInterop;
///
/// Production implementation backed by the NDI 6 SDK.
@@ -42,10 +42,10 @@ public sealed class NdiInteropPInvoke : INdiInterop, IDisposable
/// **NDI group names are case-sensitive in the runtime.** "Public" matches; "public"
/// does NOT. The default group an unconfigured NDI Sender broadcasts to is "Public"
/// (capital P). Operators who type "public" into the discovery groups field then see
- /// zero sources and report the app as broken — that's how this normalizer came to
- /// exist (2026-05-16 dev session, ~6h of misdiagnosis). We special-case "public" →
+ /// zero sources and report the app as broken — that's how this normalizer came to
+ /// exist (2026-05-16 dev session, ~6h of misdiagnosis). We special-case "public" →
/// "Public" to match the most common operator footgun. Other group names are
- /// passed through verbatim — custom groups like "teamsiso-input" are
+ /// passed through verbatim — custom groups like "Dragon-ISO-input" are
/// intentionally lowercase and must round-trip unchanged.
///
/// Marked internal so the test project can cover the lookup table directly.
@@ -74,7 +74,7 @@ public sealed class NdiInteropPInvoke : INdiInterop, IDisposable
//
// Memory ownership: the NDI SDK's NDIlib_find_create_v2 (and _send_create,
// _recv_create_v3) copy the strings out of the settings struct synchronously
- // before returning — they don't retain pointers into our buffers. This is the
+ // before returning — they don't retain pointers into our buffers. This is the
// same lifetime contract CreateReceiver / CreateSender below have relied on
// since Phase B-2; if it ever turns out to be wrong, those will fail too. The
// loopback discovery integration test would catch a regression here.
@@ -142,7 +142,7 @@ public sealed class NdiInteropPInvoke : INdiInterop, IDisposable
public NdiReceiverHandle CreateReceiver(string sourceFullName)
{
var nameUtf8 = Marshal.StringToHGlobalAnsi(sourceFullName);
- var recvNameUtf8 = Marshal.StringToHGlobalAnsi("TeamsISO");
+ var recvNameUtf8 = Marshal.StringToHGlobalAnsi("Dragon-ISO");
try
{
var settings = new NdiNative.RecvCreateV3Settings
@@ -173,7 +173,7 @@ public sealed class NdiInteropPInvoke : INdiInterop, IDisposable
/// Pulls one audio frame and returns its peak amplitude in [0,1], or null
/// if the timeout elapsed without an audio frame arriving. Uses the same
/// underlying NDIlib_recv_capture_v3 the video path does, but binds the
- /// audio output slot only — the receiver's internal queue serves video
+ /// audio output slot only — the receiver's internal queue serves video
/// and audio independently, so this can be polled from a separate thread
/// without contending with the video capture loop.
///
@@ -190,7 +190,7 @@ public sealed class NdiInteropPInvoke : INdiInterop, IDisposable
if (frameType != NdiNative.FrameType.Audio || nativeAudio.p_data == IntPtr.Zero)
{
// Free defensively on the off-chance an audio struct was partially
- // populated despite the wrong frame-type return — the SDK's free
+ // populated despite the wrong frame-type return — the SDK's free
// is a no-op on a zero pointer.
if (nativeAudio.p_data != IntPtr.Zero)
NdiNative.RecvFreeAudioV3(pInvokeReceiver.Native, ref nativeAudio);
@@ -212,7 +212,7 @@ public sealed class NdiInteropPInvoke : INdiInterop, IDisposable
Marshal.Copy(nativeAudio.p_data, managed, 0, totalBytes);
var totalSamples = nativeAudio.no_channels * nativeAudio.no_samples;
- return TeamsISO.Engine.Pipeline.AudioPeakComputer.ComputePeak(
+ return DragonISO.Engine.Pipeline.AudioPeakComputer.ComputePeak(
managed, nativeAudio.FourCC, totalSamples);
}
finally
diff --git a/src/TeamsISO.Engine.NdiInterop/NdiNative.cs b/src/Dragon-ISO.Engine.NdiInterop/NdiNative.cs
similarity index 97%
rename from src/TeamsISO.Engine.NdiInterop/NdiNative.cs
rename to src/Dragon-ISO.Engine.NdiInterop/NdiNative.cs
index 609d4a0..4780389 100644
--- a/src/TeamsISO.Engine.NdiInterop/NdiNative.cs
+++ b/src/Dragon-ISO.Engine.NdiInterop/NdiNative.cs
@@ -1,13 +1,13 @@
-using System.Runtime.InteropServices;
+using System.Runtime.InteropServices;
-namespace TeamsISO.Engine.NdiInterop;
+namespace DragonISO.Engine.NdiInterop;
///
/// P/Invoke declarations for the NewTek/Vizrt NDI SDK 6 native library.
/// On Windows the import target is Processing.NDI.Lib.x64.dll. Resolution of
/// the DLL is handled by , which loads it from
/// the NDI Runtime installation directory exposed by the
-/// NDI_RUNTIME_DIR_V<n> environment variables — the NDI installer sets
+/// NDI_RUNTIME_DIR_V<n> environment variables — the NDI installer sets
/// these but does not always add the runtime directory to PATH, so a default
/// loader-based resolution would fail with 0x8007007E on otherwise correctly
/// installed machines.
@@ -205,7 +205,7 @@ internal static class NdiNative
/// distinguishes the sample format; for NDI 6 the only common value is
/// FLTP (32-bit float, planar, one channel-plane after another).
/// channel_stride_in_bytes is the byte distance between the start
- /// of channel N and channel N+1 — for FLTP that's no_samples * 4.
+ /// of channel N and channel N+1 — for FLTP that's no_samples * 4.
/// Total buffer size = no_channels * channel_stride_in_bytes.
///
[StructLayout(LayoutKind.Sequential)]
diff --git a/src/TeamsISO.Engine.NdiInterop/NdiNativeLibraryResolver.cs b/src/Dragon-ISO.Engine.NdiInterop/NdiNativeLibraryResolver.cs
similarity index 90%
rename from src/TeamsISO.Engine.NdiInterop/NdiNativeLibraryResolver.cs
rename to src/Dragon-ISO.Engine.NdiInterop/NdiNativeLibraryResolver.cs
index 26ada5c..b7a51e5 100644
--- a/src/TeamsISO.Engine.NdiInterop/NdiNativeLibraryResolver.cs
+++ b/src/Dragon-ISO.Engine.NdiInterop/NdiNativeLibraryResolver.cs
@@ -1,7 +1,7 @@
-using System.Reflection;
+using System.Reflection;
using System.Runtime.InteropServices;
-namespace TeamsISO.Engine.NdiInterop;
+namespace DragonISO.Engine.NdiInterop;
///
/// Resolves the NDI native library (Processing.NDI.Lib.x64.dll) from the
@@ -27,8 +27,8 @@ internal static class NdiNativeLibraryResolver
///
/// NDI runtime install-dir environment variables, in preference order.
- /// V6 is what TeamsISO is built against; V5/V4 are listed as graceful fallbacks
- /// for installs that pre-date V6 — the runtime probe will still report a
+ /// V6 is what Dragon-ISO is built against; V5/V4 are listed as graceful fallbacks
+ /// for installs that pre-date V6 — the runtime probe will still report a
/// version mismatch, but at least the DLL will load and the engine can surface
/// a clear alert instead of dying with DllNotFoundException.
///
@@ -59,7 +59,7 @@ internal static class NdiNativeLibraryResolver
return handle;
}
- // Fall through to default loader (PATH, app dir, etc.) — preserves the
+ // Fall through to default loader (PATH, app dir, etc.) — preserves the
// chance that someone added the NDI dir to PATH manually.
return IntPtr.Zero;
}
diff --git a/src/TeamsISO.Engine.NdiInterop/NdiPInvokeHandles.cs b/src/Dragon-ISO.Engine.NdiInterop/NdiPInvokeHandles.cs
similarity index 94%
rename from src/TeamsISO.Engine.NdiInterop/NdiPInvokeHandles.cs
rename to src/Dragon-ISO.Engine.NdiInterop/NdiPInvokeHandles.cs
index ae67830..dfe6ad0 100644
--- a/src/TeamsISO.Engine.NdiInterop/NdiPInvokeHandles.cs
+++ b/src/Dragon-ISO.Engine.NdiInterop/NdiPInvokeHandles.cs
@@ -1,6 +1,6 @@
-using TeamsISO.Engine.Interop;
+using DragonISO.Engine.Interop;
-namespace TeamsISO.Engine.NdiInterop;
+namespace DragonISO.Engine.NdiInterop;
internal sealed class NdiPInvokeFindHandle : NdiFindHandle
{
diff --git a/src/TeamsISO.Engine.NdiInterop/NdiVersion.cs b/src/Dragon-ISO.Engine.NdiInterop/NdiVersion.cs
similarity index 95%
rename from src/TeamsISO.Engine.NdiInterop/NdiVersion.cs
rename to src/Dragon-ISO.Engine.NdiInterop/NdiVersion.cs
index b2d1d2b..a62b981 100644
--- a/src/TeamsISO.Engine.NdiInterop/NdiVersion.cs
+++ b/src/Dragon-ISO.Engine.NdiInterop/NdiVersion.cs
@@ -1,10 +1,10 @@
-namespace TeamsISO.Engine.NdiInterop;
+namespace DragonISO.Engine.NdiInterop;
///
/// Constants describing the NDI SDK version this build was compiled against.
/// The runtime version reported by is compared against
/// by the engine's runtime probe to detect
-/// installations that pre-date or post-date the SDK headers (per spec §6).
+/// installations that pre-date or post-date the SDK headers (per spec §6).
///
public static class NdiVersion
{
diff --git a/src/TeamsISO.Engine.NdiInterop/Placeholder.cs b/src/Dragon-ISO.Engine.NdiInterop/Placeholder.cs
similarity index 82%
rename from src/TeamsISO.Engine.NdiInterop/Placeholder.cs
rename to src/Dragon-ISO.Engine.NdiInterop/Placeholder.cs
index 08eb145..c5b11dd 100644
--- a/src/TeamsISO.Engine.NdiInterop/Placeholder.cs
+++ b/src/Dragon-ISO.Engine.NdiInterop/Placeholder.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.NdiInterop;
+namespace DragonISO.Engine.NdiInterop;
///
/// Phase A placeholder. The production P/Invoke implementations of INdiInterop
diff --git a/src/TeamsISO.Engine/Controller/IIsoController.cs b/src/Dragon-ISO.Engine/Controller/IIsoController.cs
similarity index 93%
rename from src/TeamsISO.Engine/Controller/IIsoController.cs
rename to src/Dragon-ISO.Engine/Controller/IIsoController.cs
index 0ba1eb1..652310c 100644
--- a/src/TeamsISO.Engine/Controller/IIsoController.cs
+++ b/src/Dragon-ISO.Engine/Controller/IIsoController.cs
@@ -1,6 +1,6 @@
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Controller;
+namespace DragonISO.Engine.Controller;
///
/// Top-of-engine API the WPF host (Phase C) and any future control APIs (OSC / WebSocket in v2.0)
@@ -55,7 +55,7 @@ public interface IIsoController : IAsyncDisposable
///
/// The per-participant override for this pipeline's
/// , or null when the participant
- /// is following global settings. Reads are unsynchronized snapshots —
+ /// is following global settings. Reads are unsynchronized snapshots —
/// safe for UI consumption but don't rely on equality with the value
/// that a concurrent just wrote.
///
@@ -66,7 +66,7 @@ public interface IIsoController : IAsyncDisposable
/// = null removes the override (pipeline
/// reverts to global settings). If a pipeline for the participant is
/// currently running, it's stopped and restarted with the new
- /// settings — the operator sees a brief signal drop during the swap.
+ /// settings — the operator sees a brief signal drop during the swap.
/// Persists alongside the assignment to config.json so the override
/// survives process restarts.
///
@@ -74,7 +74,7 @@ public interface IIsoController : IAsyncDisposable
///
/// Updates the NDI group configuration and persists it. Group changes apply on next process
- /// restart — rebuilding finder/sender handles mid-flight would orphan running pipelines.
+ /// restart — rebuilding finder/sender handles mid-flight would orphan running pipelines.
///
Task SetGroupSettingsAsync(NdiGroupSettings groupSettings, CancellationToken cancellationToken);
@@ -90,7 +90,7 @@ public interface IIsoController : IAsyncDisposable
/// Per-output recording on/off. When enabled, each subsequently-started ISO writes
/// its normalized output to /<display-name>/.
/// Already-running ISOs are not retroactively recorded (would require restarting
- /// their pipelines, which can hiccup live output) — the operator should disable +
+ /// their pipelines, which can hiccup live output) — the operator should disable +
/// re-enable a participant to start recording it.
///
void SetRecording(bool enabled, string? outputDirectory);
diff --git a/src/TeamsISO.Engine/Controller/IsoController.cs b/src/Dragon-ISO.Engine/Controller/IsoController.cs
similarity index 94%
rename from src/TeamsISO.Engine/Controller/IsoController.cs
rename to src/Dragon-ISO.Engine/Controller/IsoController.cs
index 689c27f..ab02643 100644
--- a/src/TeamsISO.Engine/Controller/IsoController.cs
+++ b/src/Dragon-ISO.Engine/Controller/IsoController.cs
@@ -1,14 +1,14 @@
-using System.Reactive.Linq;
+using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading.Channels;
using Microsoft.Extensions.Logging;
-using TeamsISO.Engine.Discovery;
-using TeamsISO.Engine.Domain;
-using TeamsISO.Engine.Interop;
-using TeamsISO.Engine.Persistence;
-using TeamsISO.Engine.Pipeline;
+using DragonISO.Engine.Discovery;
+using DragonISO.Engine.Domain;
+using DragonISO.Engine.Interop;
+using DragonISO.Engine.Persistence;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.Engine.Controller;
+namespace DragonISO.Engine.Controller;
///
/// Default implementation of .
@@ -36,7 +36,7 @@ public sealed class IsoController : IIsoController
// marker-drop API which needs to fan out to every running recorder.
private readonly Dictionary _recorders = new();
// Per-participant FrameProcessingSettings overrides. Null entry / missing
- // key → use global settings. Set entry → that pipeline runs at the
+ // key → use global settings. Set entry → that pipeline runs at the
// override values regardless of global. Persisted to config.json alongside
// the IsoAssignment record so it survives process restarts.
private readonly Dictionary _overrides = new();
@@ -103,7 +103,7 @@ public sealed class IsoController : IIsoController
throw new InvalidOperationException("Controller already started.");
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
- // Runtime probe — surface alert if mismatch but don't fail startup.
+ // Runtime probe — surface alert if mismatch but don't fail startup.
var probeResult = _runtimeProbe.Probe();
if (probeResult is NdiRuntimeProbeResult.Mismatch mismatch)
{
@@ -180,7 +180,7 @@ public sealed class IsoController : IIsoController
IRecorderSink? recorder = null;
if (shouldRecord)
{
- // Per-pipeline recorder instance — each ISO writes to its own
+ // Per-pipeline recorder instance — each ISO writes to its own
// subdirectory keyed by display name. Wrapping in try/catch so a
// recorder construction failure (no logger, weird platform) never
// takes down EnableIsoAsync.
@@ -199,7 +199,7 @@ public sealed class IsoController : IIsoController
OutputGroups = outputGroups,
Recorder = recorder,
// Pass the directory whenever we have a recorder, regardless of the
- // global flag — the per-call override may have forced one even when
+ // global flag — the per-call override may have forced one even when
// global recording is off.
RecordingOutputDirectory = recorder is not null ? recordingDirectory : null,
RecorderDisplayName = p.DisplayName,
@@ -263,7 +263,7 @@ public sealed class IsoController : IIsoController
wasRunning = _pipelines.ContainsKey(participantId);
// Custom name lives on the assignment; for now there's only ever
// one in-flight name (the one passed to EnableIsoAsync), and we
- // don't track that — so the restart path uses the default name.
+ // don't track that — so the restart path uses the default name.
// OK for v2; per-pipeline custom names can be retrofitted later.
customName = null;
}
@@ -282,7 +282,7 @@ public sealed class IsoController : IIsoController
}
else
{
- // Pipeline not running — just persist the override so it takes
+ // Pipeline not running — just persist the override so it takes
// effect the NEXT time the operator enables this participant.
await PersistAssignmentsAsync(cancellationToken);
}
@@ -290,7 +290,7 @@ public sealed class IsoController : IIsoController
///
/// Updates the NDI group configuration. Note: existing finder/sender handles aren't
- /// rebuilt — group changes take effect on the next process restart, since rebuilding
+ /// rebuilt — group changes take effect on the next process restart, since rebuilding
/// the live finder mid-flight would orphan in-flight participants. The settings
/// panel surfaces this caveat to the user.
///
@@ -399,7 +399,7 @@ public sealed class IsoController : IIsoController
}
private static string DefaultOutputName(Guid participantId) =>
- $"TEAMSISO_{participantId.ToString("N")[..8].ToUpperInvariant()}";
+ $"Dragon-ISO_{participantId.ToString("N")[..8].ToUpperInvariant()}";
public async ValueTask DisposeAsync()
{
diff --git a/src/TeamsISO.Engine/Discovery/DiscoveryEvent.cs b/src/Dragon-ISO.Engine/Discovery/DiscoveryEvent.cs
similarity index 71%
rename from src/TeamsISO.Engine/Discovery/DiscoveryEvent.cs
rename to src/Dragon-ISO.Engine/Discovery/DiscoveryEvent.cs
index eb3fd2b..7be12fd 100644
--- a/src/TeamsISO.Engine/Discovery/DiscoveryEvent.cs
+++ b/src/Dragon-ISO.Engine/Discovery/DiscoveryEvent.cs
@@ -1,6 +1,6 @@
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Discovery;
+namespace DragonISO.Engine.Discovery;
public abstract record DiscoveryEvent
{
diff --git a/src/TeamsISO.Engine/Discovery/NdiDiscoveryService.cs b/src/Dragon-ISO.Engine/Discovery/NdiDiscoveryService.cs
similarity index 93%
rename from src/TeamsISO.Engine/Discovery/NdiDiscoveryService.cs
rename to src/Dragon-ISO.Engine/Discovery/NdiDiscoveryService.cs
index 67dda9c..4a0e4a2 100644
--- a/src/TeamsISO.Engine/Discovery/NdiDiscoveryService.cs
+++ b/src/Dragon-ISO.Engine/Discovery/NdiDiscoveryService.cs
@@ -1,8 +1,8 @@
-using System.Threading.Channels;
+using System.Threading.Channels;
using Microsoft.Extensions.Logging;
-using TeamsISO.Engine.Interop;
+using DragonISO.Engine.Interop;
-namespace TeamsISO.Engine.Discovery;
+namespace DragonISO.Engine.Discovery;
///
/// Polls at a fixed cadence, diffs the
@@ -35,11 +35,11 @@ public sealed class NdiDiscoveryService
///
/// Request that the next poll tick rebuild the underlying NDI finder. Useful right
/// after the operator changes discovery groups or applies a new transcoder topology
- /// — without this, the finder is bound to the groups it was created with and never
+ /// — without this, the finder is bound to the groups it was created with and never
/// sees new sources from the just-configured group. Honored on the next
/// tick: the old finder is disposed, a fresh one is created,
/// and the seen-set is cleared so all currently-visible sources re-fire as
- /// . Cheap (idempotent) — extra Refresh calls
+ /// . Cheap (idempotent) — extra Refresh calls
/// while a refresh is already pending are coalesced.
///
public void RequestRefresh() => Interlocked.Exchange(ref _refreshRequested, 1);
@@ -94,14 +94,14 @@ public sealed class NdiDiscoveryService
/// AND it's been >10s since the last rebuild.
///
/// Both rules apply backoff so we don't churn during legitimate empty
- /// periods (no meeting active, etc.) — the rebuild is cheap but the log
+ /// periods (no meeting active, etc.) — the rebuild is cheap but the log
/// noise isn't useful.
///
public async Task RunAsync(TimeSpan pollInterval, CancellationToken cancellationToken)
{
try
{
- // Immediate first poll — PeriodicTimer.WaitForNextTickAsync would
+ // Immediate first poll — PeriodicTimer.WaitForNextTickAsync would
// wait the full interval otherwise, costing us 200-500ms at cold
// start when operators are most impatient.
try { PollOnce(); } catch (Exception ex) { _logger.LogWarning(ex, "Initial discovery poll failed."); }
@@ -127,7 +127,7 @@ public sealed class NdiDiscoveryService
RebuildFinder("operator request");
lastRebuildAt = now;
}
- // Auto-healing rebuilds — see ShouldAutoRebuild.
+ // Auto-healing rebuilds — see ShouldAutoRebuild.
else if (_previous.Count == 0)
{
var decision = ShouldAutoRebuild(
@@ -160,7 +160,7 @@ public sealed class NdiDiscoveryService
/// finder alone." Caller is responsible for tracking the timestamps and
/// updating lastRebuildAt after the rebuild.
///
- /// Public + static for unit-testability — the time-based rules are easy to
+ /// Public + static for unit-testability — the time-based rules are easy to
/// regress and hard to spot in integration testing.
///
/// Rules:
diff --git a/src/TeamsISO.Engine/Discovery/NdiSourceParser.cs b/src/Dragon-ISO.Engine/Discovery/NdiSourceParser.cs
similarity index 81%
rename from src/TeamsISO.Engine/Discovery/NdiSourceParser.cs
rename to src/Dragon-ISO.Engine/Discovery/NdiSourceParser.cs
index dbf2a24..d71714a 100644
--- a/src/TeamsISO.Engine/Discovery/NdiSourceParser.cs
+++ b/src/Dragon-ISO.Engine/Discovery/NdiSourceParser.cs
@@ -1,6 +1,6 @@
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Discovery;
+namespace DragonISO.Engine.Discovery;
///
/// Parses NDI source strings emitted by Microsoft Teams.
@@ -9,17 +9,17 @@ namespace TeamsISO.Engine.Discovery;
/// outputs. Both are recognized.
///
/// Legacy (older Teams desktop):
-/// "MACHINE (Teams)" — auto-mixed active-speaker output
-/// "MACHINE (Teams Audio)" — audio-only mix
-/// "MACHINE (Teams Screen Share)" — screen share
-/// "MACHINE (Teams - Display Name)" — per-participant
+/// "MACHINE (Teams)" — auto-mixed active-speaker output
+/// "MACHINE (Teams Audio)" — audio-only mix
+/// "MACHINE (Teams Screen Share)" — screen share
+/// "MACHINE (Teams - Display Name)" — per-participant
///
/// Current (the new Microsoft Teams desktop client, observed 2026):
-/// "MACHINE (MS Teams - Active Speaker)" — auto-mixed active-speaker output
-/// "MACHINE (MS Teams - Audio Mix)" — audio-only mix
-/// "MACHINE (MS Teams - Screen Share)" — screen share
-/// "MACHINE (MS Teams - (Local))" — the local user's own preview
-/// "MACHINE (MS Teams - Display Name)" — per-participant
+/// "MACHINE (MS Teams - Active Speaker)" — auto-mixed active-speaker output
+/// "MACHINE (MS Teams - Audio Mix)" — audio-only mix
+/// "MACHINE (MS Teams - Screen Share)" — screen share
+/// "MACHINE (MS Teams - (Local))" — the local user's own preview
+/// "MACHINE (MS Teams - Display Name)" — per-participant
///
/// "Microsoft Teams" is also accepted as a defensive future-proof brand prefix.
///
@@ -77,7 +77,7 @@ public static class NdiSourceParser
var rest = inner[brand.Length..].TrimStart();
- // Legacy "MACHINE (Teams)" — bare brand, no suffix → active speaker.
+ // Legacy "MACHINE (Teams)" — bare brand, no suffix → active speaker.
if (rest.Length == 0)
return new NdiSource(fullName, machine, NdiSourceKind.ActiveSpeaker, DisplayName: null);
diff --git a/src/TeamsISO.Engine/Discovery/ParticipantTracker.cs b/src/Dragon-ISO.Engine/Discovery/ParticipantTracker.cs
similarity index 97%
rename from src/TeamsISO.Engine/Discovery/ParticipantTracker.cs
rename to src/Dragon-ISO.Engine/Discovery/ParticipantTracker.cs
index a3c0fe3..47bc747 100644
--- a/src/TeamsISO.Engine/Discovery/ParticipantTracker.cs
+++ b/src/Dragon-ISO.Engine/Discovery/ParticipantTracker.cs
@@ -1,6 +1,6 @@
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Discovery;
+namespace DragonISO.Engine.Discovery;
///
/// Maintains the operator-facing participant list, applying the rename heuristic
@@ -140,7 +140,7 @@ public sealed class ParticipantTracker
///
/// Removes the synthetic auto-mix row's CurrentSource. Crucially does NOT add to
- /// — the auto-mix row's identity is already stable
+ /// — the auto-mix row's identity is already stable
/// via the deterministic v5 GUID, so re-add restores it without needing the
/// rename-window heuristic, and we must not let an active-speaker disappearance
/// poison the rename matcher for a Participant joining the same machine within
diff --git a/src/TeamsISO.Engine/Domain/EngineAlert.cs b/src/Dragon-ISO.Engine/Domain/EngineAlert.cs
similarity index 82%
rename from src/TeamsISO.Engine/Domain/EngineAlert.cs
rename to src/Dragon-ISO.Engine/Domain/EngineAlert.cs
index b9189cd..d77453c 100644
--- a/src/TeamsISO.Engine/Domain/EngineAlert.cs
+++ b/src/Dragon-ISO.Engine/Domain/EngineAlert.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Domain;
+namespace DragonISO.Engine.Domain;
///
/// Structured engine alerts for UI banner display and ops logging.
@@ -9,7 +9,7 @@ public abstract record EngineAlert(string Message)
: EngineAlert($"NDI runtime version mismatch: detected {DetectedVersion}, expected {ExpectedVersion}.");
public sealed record OutputNameCollision(string Name)
- : EngineAlert($"Another TeamsISO instance on the LAN is emitting an output named '{Name}'.");
+ : EngineAlert($"Another Dragon-ISO instance on the LAN is emitting an output named '{Name}'.");
public sealed record PipelineError(Guid ParticipantId, string Reason)
: EngineAlert($"Pipeline {ParticipantId} entered Error: {Reason}");
diff --git a/src/TeamsISO.Engine/Domain/EngineConfig.cs b/src/Dragon-ISO.Engine/Domain/EngineConfig.cs
similarity index 93%
rename from src/TeamsISO.Engine/Domain/EngineConfig.cs
rename to src/Dragon-ISO.Engine/Domain/EngineConfig.cs
index eb2a09c..a56bc00 100644
--- a/src/TeamsISO.Engine/Domain/EngineConfig.cs
+++ b/src/Dragon-ISO.Engine/Domain/EngineConfig.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Domain;
+namespace DragonISO.Engine.Domain;
public sealed record EngineConfig(
FrameProcessingSettings Global,
diff --git a/src/TeamsISO.Engine/Domain/Enums.cs b/src/Dragon-ISO.Engine/Domain/Enums.cs
similarity index 93%
rename from src/TeamsISO.Engine/Domain/Enums.cs
rename to src/Dragon-ISO.Engine/Domain/Enums.cs
index e18418b..ce1ee85 100644
--- a/src/TeamsISO.Engine/Domain/Enums.cs
+++ b/src/Dragon-ISO.Engine/Domain/Enums.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Domain;
+namespace DragonISO.Engine.Domain;
public enum NdiSourceKind
{
diff --git a/src/TeamsISO.Engine/Domain/FrameProcessingSettings.cs b/src/Dragon-ISO.Engine/Domain/FrameProcessingSettings.cs
similarity index 97%
rename from src/TeamsISO.Engine/Domain/FrameProcessingSettings.cs
rename to src/Dragon-ISO.Engine/Domain/FrameProcessingSettings.cs
index 8ac57f5..d675978 100644
--- a/src/TeamsISO.Engine/Domain/FrameProcessingSettings.cs
+++ b/src/Dragon-ISO.Engine/Domain/FrameProcessingSettings.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Domain;
+namespace DragonISO.Engine.Domain;
public sealed record FrameProcessingSettings(
TargetFramerate Framerate,
diff --git a/src/TeamsISO.Engine/Domain/IsoAssignment.cs b/src/Dragon-ISO.Engine/Domain/IsoAssignment.cs
similarity index 83%
rename from src/TeamsISO.Engine/Domain/IsoAssignment.cs
rename to src/Dragon-ISO.Engine/Domain/IsoAssignment.cs
index 612f4bc..c00f6e8 100644
--- a/src/TeamsISO.Engine/Domain/IsoAssignment.cs
+++ b/src/Dragon-ISO.Engine/Domain/IsoAssignment.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Domain;
+namespace DragonISO.Engine.Domain;
///
/// Operator's intent for an ISO output. Persisted to config.json.
@@ -7,7 +7,7 @@ namespace TeamsISO.Engine.Domain;
/// that takes precedence over the global
/// defaults for THIS participant only. null means "follow global settings"
/// (the common case). Non-null lets the operator run a 30 fps 720p Mixed
-/// pipeline next to a 60 fps 1080p Isolated one — useful when downstream
+/// pipeline next to a 60 fps 1080p Isolated one — useful when downstream
/// switchers expect specific formats per source slot.
///
public sealed record IsoAssignment(
diff --git a/src/TeamsISO.Engine/Domain/IsoHealthStats.cs b/src/Dragon-ISO.Engine/Domain/IsoHealthStats.cs
similarity index 90%
rename from src/TeamsISO.Engine/Domain/IsoHealthStats.cs
rename to src/Dragon-ISO.Engine/Domain/IsoHealthStats.cs
index 335043c..57b3c68 100644
--- a/src/TeamsISO.Engine/Domain/IsoHealthStats.cs
+++ b/src/Dragon-ISO.Engine/Domain/IsoHealthStats.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Domain;
+namespace DragonISO.Engine.Domain;
public sealed record IsoHealthStats(
long FramesIn,
@@ -25,7 +25,7 @@ public sealed record IsoHealthStats(
/// 1.0 is full-scale clip. The UI typically displays this as a decaying
/// VU bar in the participants DataGrid.
///
- /// Currently always 0.0 — the engine's NDI receiver doesn't capture audio
+ /// Currently always 0.0 — the engine's NDI receiver doesn't capture audio
/// frames yet (video-only). The field exists so the UI scaffolding is
/// in place; the audio capture path is a focused engine follow-up that
/// adds NdiReceiver audio-frame handling, peak computation, and
diff --git a/src/TeamsISO.Engine/Domain/IsoOutput.cs b/src/Dragon-ISO.Engine/Domain/IsoOutput.cs
similarity index 78%
rename from src/TeamsISO.Engine/Domain/IsoOutput.cs
rename to src/Dragon-ISO.Engine/Domain/IsoOutput.cs
index 4a660f4..65f9e52 100644
--- a/src/TeamsISO.Engine/Domain/IsoOutput.cs
+++ b/src/Dragon-ISO.Engine/Domain/IsoOutput.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Domain;
+namespace DragonISO.Engine.Domain;
public sealed record IsoOutput(
Guid ParticipantId,
diff --git a/src/TeamsISO.Engine/Domain/NdiGroupSettings.cs b/src/Dragon-ISO.Engine/Domain/NdiGroupSettings.cs
similarity index 71%
rename from src/TeamsISO.Engine/Domain/NdiGroupSettings.cs
rename to src/Dragon-ISO.Engine/Domain/NdiGroupSettings.cs
index 3ae230a..dc4de57 100644
--- a/src/TeamsISO.Engine/Domain/NdiGroupSettings.cs
+++ b/src/Dragon-ISO.Engine/Domain/NdiGroupSettings.cs
@@ -1,9 +1,9 @@
-namespace TeamsISO.Engine.Domain;
+namespace DragonISO.Engine.Domain;
///
-/// Network-layer NDI configuration. Lets the operator place TeamsISO inside an NDI
+/// Network-layer NDI configuration. Lets the operator place Dragon-ISO inside an NDI
/// "transcoder" topology where the upstream (Teams) outputs are confined to a private
-/// group so they don't pollute the production network, while TeamsISO's own normalized
+/// group so they don't pollute the production network, while Dragon-ISO's own normalized
/// outputs broadcast on the standard "Public" group consumed by the switcher.
///
/// Both fields are comma-separated lists of NDI group names. Whitespace around commas
@@ -13,11 +13,11 @@ namespace TeamsISO.Engine.Domain;
///
/// Groups the engine's finder subscribes to when enumerating sources. Set this to
/// the private group your Teams machine is configured to broadcast on (e.g.
-/// "teamsiso-input") when you want to hide raw Teams outputs from the rest of
+/// "Dragon-ISO-input") when you want to hide raw Teams outputs from the rest of
/// the network.
///
///
-/// Groups TeamsISO's own ISO senders broadcast on. Leave at the default for the
+/// Groups Dragon-ISO's own ISO senders broadcast on. Leave at the default for the
/// normal case where downstream switchers receive over the standard
/// "Public" group; override only for split-audience setups.
///
diff --git a/src/TeamsISO.Engine/Domain/NdiSource.cs b/src/Dragon-ISO.Engine/Domain/NdiSource.cs
similarity index 86%
rename from src/TeamsISO.Engine/Domain/NdiSource.cs
rename to src/Dragon-ISO.Engine/Domain/NdiSource.cs
index 2394db0..31f37ff 100644
--- a/src/TeamsISO.Engine/Domain/NdiSource.cs
+++ b/src/Dragon-ISO.Engine/Domain/NdiSource.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Domain;
+namespace DragonISO.Engine.Domain;
///
/// Raw discovery record parsed from an NDI source string emitted by Microsoft Teams.
diff --git a/src/TeamsISO.Engine/Domain/Participant.cs b/src/Dragon-ISO.Engine/Domain/Participant.cs
similarity index 89%
rename from src/TeamsISO.Engine/Domain/Participant.cs
rename to src/Dragon-ISO.Engine/Domain/Participant.cs
index 2a38b67..ec85954 100644
--- a/src/TeamsISO.Engine/Domain/Participant.cs
+++ b/src/Dragon-ISO.Engine/Domain/Participant.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Domain;
+namespace DragonISO.Engine.Domain;
///
/// Operator-facing identity for a single human in the meeting.
diff --git a/src/TeamsISO.Engine/TeamsISO.Engine.csproj b/src/Dragon-ISO.Engine/Dragon-ISO.Engine.csproj
similarity index 81%
rename from src/TeamsISO.Engine/TeamsISO.Engine.csproj
rename to src/Dragon-ISO.Engine/Dragon-ISO.Engine.csproj
index 848fc51..7f58117 100644
--- a/src/TeamsISO.Engine/TeamsISO.Engine.csproj
+++ b/src/Dragon-ISO.Engine/Dragon-ISO.Engine.csproj
@@ -1,14 +1,14 @@
-
+net8.0
-
@@ -24,7 +24,7 @@
-
+
diff --git a/src/TeamsISO.Engine/Interop/INdiInterop.cs b/src/Dragon-ISO.Engine/Interop/INdiInterop.cs
similarity index 93%
rename from src/TeamsISO.Engine/Interop/INdiInterop.cs
rename to src/Dragon-ISO.Engine/Interop/INdiInterop.cs
index 045052a..4778c63 100644
--- a/src/TeamsISO.Engine/Interop/INdiInterop.cs
+++ b/src/Dragon-ISO.Engine/Interop/INdiInterop.cs
@@ -1,6 +1,6 @@
-using TeamsISO.Engine.Pipeline;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.Engine.Interop;
+namespace DragonISO.Engine.Interop;
///
/// Test seam over the NDI SDK. Production: P/Invoke shim. Tests: FakeNdiInterop.
@@ -38,7 +38,7 @@ public interface INdiInterop
/// audio is queued (a polling caller drives a UI VU bar; we don't want it
/// to block on a video-only sender).
///
- /// Default implementation returns null — the
+ /// Default implementation returns null — the
/// in tests doesn't simulate audio; the production
/// NdiInteropPInvoke overrides this with the real read.
///
diff --git a/src/TeamsISO.Engine/Interop/NdiFindHandle.cs b/src/Dragon-ISO.Engine/Interop/NdiFindHandle.cs
similarity index 81%
rename from src/TeamsISO.Engine/Interop/NdiFindHandle.cs
rename to src/Dragon-ISO.Engine/Interop/NdiFindHandle.cs
index fec94a6..b34151b 100644
--- a/src/TeamsISO.Engine/Interop/NdiFindHandle.cs
+++ b/src/Dragon-ISO.Engine/Interop/NdiFindHandle.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Interop;
+namespace DragonISO.Engine.Interop;
/// Opaque handle to an NDI Find instance. Implementation-private.
public abstract class NdiFindHandle : IDisposable
diff --git a/src/TeamsISO.Engine/Interop/NdiReceiverHandle.cs b/src/Dragon-ISO.Engine/Interop/NdiReceiverHandle.cs
similarity index 70%
rename from src/TeamsISO.Engine/Interop/NdiReceiverHandle.cs
rename to src/Dragon-ISO.Engine/Interop/NdiReceiverHandle.cs
index c988da6..17dca7e 100644
--- a/src/TeamsISO.Engine/Interop/NdiReceiverHandle.cs
+++ b/src/Dragon-ISO.Engine/Interop/NdiReceiverHandle.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Interop;
+namespace DragonISO.Engine.Interop;
public abstract class NdiReceiverHandle : IDisposable
{
diff --git a/src/TeamsISO.Engine/Interop/NdiRuntimeProbe.cs b/src/Dragon-ISO.Engine/Interop/NdiRuntimeProbe.cs
similarity index 97%
rename from src/TeamsISO.Engine/Interop/NdiRuntimeProbe.cs
rename to src/Dragon-ISO.Engine/Interop/NdiRuntimeProbe.cs
index ed2278a..1ef30f2 100644
--- a/src/TeamsISO.Engine/Interop/NdiRuntimeProbe.cs
+++ b/src/Dragon-ISO.Engine/Interop/NdiRuntimeProbe.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Interop;
+namespace DragonISO.Engine.Interop;
///
/// Result of an NDI runtime version check.
diff --git a/src/TeamsISO.Engine/Interop/NdiSenderHandle.cs b/src/Dragon-ISO.Engine/Interop/NdiSenderHandle.cs
similarity index 70%
rename from src/TeamsISO.Engine/Interop/NdiSenderHandle.cs
rename to src/Dragon-ISO.Engine/Interop/NdiSenderHandle.cs
index ad8f645..0d30a42 100644
--- a/src/TeamsISO.Engine/Interop/NdiSenderHandle.cs
+++ b/src/Dragon-ISO.Engine/Interop/NdiSenderHandle.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Interop;
+namespace DragonISO.Engine.Interop;
public abstract class NdiSenderHandle : IDisposable
{
diff --git a/src/TeamsISO.Engine/Logging/EngineLogging.cs b/src/Dragon-ISO.Engine/Logging/EngineLogging.cs
similarity index 84%
rename from src/TeamsISO.Engine/Logging/EngineLogging.cs
rename to src/Dragon-ISO.Engine/Logging/EngineLogging.cs
index c5952aa..db38d22 100644
--- a/src/TeamsISO.Engine/Logging/EngineLogging.cs
+++ b/src/Dragon-ISO.Engine/Logging/EngineLogging.cs
@@ -1,44 +1,44 @@
-using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Extensions.Logging;
-namespace TeamsISO.Engine.Logging;
+namespace DragonISO.Engine.Logging;
///
/// Convenience factory for an wired to Serilog. Two flavors:
/// for headless / Console-mode use (writes only to stdout),
/// and for the WPF host (writes to stdout AND to a rolling
-/// daily file under %LOCALAPPDATA%\TeamsISO\Logs so support has something to ask for
+/// daily file under %LOCALAPPDATA%\Dragon-ISO\Logs so support has something to ask for
/// when things break).
///
public static class EngineLogging
{
///
/// Default filename for the rolling-file sink. Serilog rotates on size and date with
- /// the suffix it inserts before the extension, so "teamsiso.log" becomes
- /// "teamsiso20260508.log", "teamsiso20260508_001.log", etc.
+ /// the suffix it inserts before the extension, so "DragonISO.log" becomes
+ /// "Dragon-ISO20260508.log", "Dragon-ISO20260508_001.log", etc.
///
- private const string LogFileName = "teamsiso.log";
+ private const string LogFileName = "DragonISO.log";
///
/// Default directory for the rolling-file sink:
- /// %LOCALAPPDATA%\TeamsISO\Logs\. Created on first write if it doesn't exist.
+ /// %LOCALAPPDATA%\Dragon-ISO\Logs\. Created on first write if it doesn't exist.
///
public static string DefaultLogDirectory =>
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
- "TeamsISO",
+ "Dragon-ISO",
"Logs");
///
- /// Console-only factory. Used by TeamsISO.Console where stdout is the right surface
+ /// Console-only factory. Used by DragonISO.Console where stdout is the right surface
/// and a file sink would be redundant with shell redirection.
///
public static ILoggerFactory CreateConsole(LogLevel minimum = LogLevel.Information)
{
var serilog = new LoggerConfiguration()
.MinimumLevel.Is(MapLevel(minimum))
- .Enrich.WithProperty("Component", "TeamsISO.Engine")
+ .Enrich.WithProperty("Component", "DragonISO.Engine")
.WriteTo.Console(outputTemplate:
"[{Timestamp:HH:mm:ss} {Level:u3}] [{Component}] {Message:lj}{NewLine}{Exception}")
.CreateLogger();
@@ -62,7 +62,7 @@ public static class EngineLogging
var serilog = new LoggerConfiguration()
.MinimumLevel.Is(MapLevel(minimum))
- .Enrich.WithProperty("Component", "TeamsISO.Engine")
+ .Enrich.WithProperty("Component", "DragonISO.Engine")
.WriteTo.Console(outputTemplate:
"[{Timestamp:HH:mm:ss} {Level:u3}] [{Component}] {Message:lj}{NewLine}{Exception}")
.WriteTo.File(
@@ -84,7 +84,7 @@ public static class EngineLogging
// the injected ILogger, not Serilog.Log.* directly.
var factory = new SerilogLoggerFactory(serilog, dispose: true);
// Surface the path at startup so support has it without digging.
- factory.CreateLogger("TeamsISO.Engine")
+ factory.CreateLogger("DragonISO.Engine")
.LogInformation("Diagnostic logs writing to: {LogDirectory}", dir);
return factory;
}
diff --git a/src/TeamsISO.Engine/Persistence/ConfigStore.cs b/src/Dragon-ISO.Engine/Persistence/ConfigStore.cs
similarity index 94%
rename from src/TeamsISO.Engine/Persistence/ConfigStore.cs
rename to src/Dragon-ISO.Engine/Persistence/ConfigStore.cs
index 13fef05..64a5f59 100644
--- a/src/TeamsISO.Engine/Persistence/ConfigStore.cs
+++ b/src/Dragon-ISO.Engine/Persistence/ConfigStore.cs
@@ -1,9 +1,9 @@
-using System.Text.Json;
+using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Logging;
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Persistence;
+namespace DragonISO.Engine.Persistence;
///
/// Loads and saves as JSON.
diff --git a/src/TeamsISO.Engine/Pipeline/AudioPeakComputer.cs b/src/Dragon-ISO.Engine/Pipeline/AudioPeakComputer.cs
similarity index 84%
rename from src/TeamsISO.Engine/Pipeline/AudioPeakComputer.cs
rename to src/Dragon-ISO.Engine/Pipeline/AudioPeakComputer.cs
index b603b87..c011ff8 100644
--- a/src/TeamsISO.Engine/Pipeline/AudioPeakComputer.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/AudioPeakComputer.cs
@@ -1,16 +1,16 @@
-using System.Runtime.InteropServices;
+using System.Runtime.InteropServices;
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Computes a single peak amplitude (in [0.0, 1.0]) from one NDI audio frame.
///
-/// NDI 6's preferred audio format is NDIlib_FourCC_audio_type_FLTP —
+/// NDI 6's preferred audio format is NDIlib_FourCC_audio_type_FLTP —
/// 32-bit IEEE float, planar (one contiguous chunk per channel). Values are
/// nominally normalized to [-1, 1]; brief excursions past 1 during transient
/// clipping are clamped here. We compute a max-absolute peak across every
/// sample of every channel rather than RMS so the UI VU bar reads
-/// "loudest part of the buffer" — the same convention OBS / Resolve / Studio
+/// "loudest part of the buffer" — the same convention OBS / Resolve / Studio
/// Monitor use for their meters.
///
/// Pulled out of so the math is unit-testable
@@ -20,10 +20,10 @@ namespace TeamsISO.Engine.Pipeline;
///
public static class AudioPeakComputer
{
- /// FourCC for FLTP — 32-bit float, planar layout. 'F','L','T','p'.
+ /// FourCC for FLTP — 32-bit float, planar layout. 'F','L','T','p'.
public const uint FourCC_FLTP = 0x70544c46;
- /// FourCC for FLT — 32-bit float, interleaved. 'F','L','T',' '. Rarely seen but cheap to handle.
+ /// FourCC for FLT — 32-bit float, interleaved. 'F','L','T',' '. Rarely seen but cheap to handle.
public const uint FourCC_FLT = 0x20544c46;
/// FourCC for PCM 16-bit signed integer, interleaved. Some legacy senders use this. 'P','C','M','s'.
@@ -38,7 +38,7 @@ public static class AudioPeakComputer
/// The NDI audio FourCC (see the constants on this class).
///
/// Total sample count across all channels (e.g. no_samples * no_channels
- /// for FLTP — channels are concatenated planes, but every sample contributes).
+ /// for FLTP — channels are concatenated planes, but every sample contributes).
///
public static double ComputePeak(ReadOnlySpan data, uint fourCC, int totalSamples)
{
@@ -48,7 +48,7 @@ public static class AudioPeakComputer
{
FourCC_FLTP or FourCC_FLT => ComputePeakFloat32(data, totalSamples),
FourCC_PCMs16 => ComputePeakInt16(data, totalSamples),
- _ => 0.0, // unknown format — surface silence rather than throw
+ _ => 0.0, // unknown format — surface silence rather than throw
};
}
@@ -56,7 +56,7 @@ public static class AudioPeakComputer
{
// 4 bytes per sample. Cap by what's actually in the buffer in case
// the caller's totalSamples disagrees with the byte length (defensive
- // — a misreporting source shouldn't take down the receiver loop).
+ // — a misreporting source shouldn't take down the receiver loop).
var available = Math.Min(totalSamples, data.Length / 4);
if (available <= 0) return 0.0;
diff --git a/src/TeamsISO.Engine/Pipeline/ExponentialBackoff.cs b/src/Dragon-ISO.Engine/Pipeline/ExponentialBackoff.cs
similarity index 97%
rename from src/TeamsISO.Engine/Pipeline/ExponentialBackoff.cs
rename to src/Dragon-ISO.Engine/Pipeline/ExponentialBackoff.cs
index 5e6da15..5caf2f9 100644
--- a/src/TeamsISO.Engine/Pipeline/ExponentialBackoff.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/ExponentialBackoff.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Exponential backoff policy used by 's restart supervisor.
diff --git a/src/TeamsISO.Engine/Pipeline/FrameProcessor.cs b/src/Dragon-ISO.Engine/Pipeline/FrameProcessor.cs
similarity index 97%
rename from src/TeamsISO.Engine/Pipeline/FrameProcessor.cs
rename to src/Dragon-ISO.Engine/Pipeline/FrameProcessor.cs
index 7da6f9d..73d66cb 100644
--- a/src/TeamsISO.Engine/Pipeline/FrameProcessor.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/FrameProcessor.cs
@@ -1,8 +1,8 @@
-using System.Threading.Channels;
+using System.Threading.Channels;
using Microsoft.Extensions.Logging;
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Per-ISO frame timing engine. Implements closest-frame strategy: at each tick,
diff --git a/src/TeamsISO.Engine/Pipeline/IFrameClock.cs b/src/Dragon-ISO.Engine/Pipeline/IFrameClock.cs
similarity index 79%
rename from src/TeamsISO.Engine/Pipeline/IFrameClock.cs
rename to src/Dragon-ISO.Engine/Pipeline/IFrameClock.cs
index b7980e7..cf179ba 100644
--- a/src/TeamsISO.Engine/Pipeline/IFrameClock.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/IFrameClock.cs
@@ -1,8 +1,8 @@
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Test seam over the wall clock. Production: .
-/// Tests: FakeFrameClock in TeamsISO.Engine.Tests.
+/// Tests: FakeFrameClock in DragonISO.Engine.Tests.
///
public interface IFrameClock
{
diff --git a/src/TeamsISO.Engine/Pipeline/IFrameScaler.cs b/src/Dragon-ISO.Engine/Pipeline/IFrameScaler.cs
similarity index 68%
rename from src/TeamsISO.Engine/Pipeline/IFrameScaler.cs
rename to src/Dragon-ISO.Engine/Pipeline/IFrameScaler.cs
index 925b385..e241c93 100644
--- a/src/TeamsISO.Engine/Pipeline/IFrameScaler.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/IFrameScaler.cs
@@ -1,6 +1,6 @@
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
public interface IFrameScaler
{
diff --git a/src/TeamsISO.Engine/Pipeline/IRecorderSink.cs b/src/Dragon-ISO.Engine/Pipeline/IRecorderSink.cs
similarity index 88%
rename from src/TeamsISO.Engine/Pipeline/IRecorderSink.cs
rename to src/Dragon-ISO.Engine/Pipeline/IRecorderSink.cs
index 9004f66..afa0517 100644
--- a/src/TeamsISO.Engine/Pipeline/IRecorderSink.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/IRecorderSink.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Tap point for per-ISO output recording. Each can be
@@ -12,7 +12,7 @@ namespace TeamsISO.Engine.Pipeline;
/// 3. is called once when the pipeline stops or fails.
///
/// Implementations must be tolerant of out-of-order calls (Close before Open,
-/// double Close, WriteFrame after Close) — the supervisor's restart logic can
+/// double Close, WriteFrame after Close) — the supervisor's restart logic can
/// race in unusual ways. The simplest correct implementation is to track an
/// _isOpen flag and short-circuit when not open.
///
@@ -32,7 +32,7 @@ public interface IRecorderSink : IAsyncDisposable
void Open(string participantDisplayName, string outputDirectory, int width, int height, double fps);
///
- /// Write one processed frame. Implementations should not block — if encoding is
+ /// Write one processed frame. Implementations should not block — if encoding is
/// expensive, queue the frame to a worker thread and return promptly. Returning
/// false means the recorder dropped the frame (disk full, queue overflow); the
/// pipeline carries on regardless so a recorder failure never kills the live ISO.
@@ -49,8 +49,8 @@ public interface IRecorderSink : IAsyncDisposable
///
/// Drop a timestamped marker into the recording. Used by the operator to
- /// chapter a recording in real time — "host intro starts here", "guest
- /// answer", etc. — so post-production can jump to the right moment without
+ /// chapter a recording in real time — "host intro starts here", "guest
+ /// answer", etc. — so post-production can jump to the right moment without
/// scrubbing through the raw stream. The label is free-form; an empty
/// label means "unnamed marker." No-op when not recording.
///
diff --git a/src/TeamsISO.Engine/Pipeline/IsoPipeline.cs b/src/Dragon-ISO.Engine/Pipeline/IsoPipeline.cs
similarity index 97%
rename from src/TeamsISO.Engine/Pipeline/IsoPipeline.cs
rename to src/Dragon-ISO.Engine/Pipeline/IsoPipeline.cs
index 3bd064d..a7f8dba 100644
--- a/src/TeamsISO.Engine/Pipeline/IsoPipeline.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/IsoPipeline.cs
@@ -1,10 +1,10 @@
-using System.IO;
+using System.IO;
using System.Threading.Channels;
using Microsoft.Extensions.Logging;
-using TeamsISO.Engine.Domain;
-using TeamsISO.Engine.Interop;
+using DragonISO.Engine.Domain;
+using DragonISO.Engine.Interop;
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Per-ISO unit. Owns one capture loop, one frame processor, one send loop, and the
@@ -37,7 +37,7 @@ public sealed class IsoPipeline : IAsyncDisposable
private DateTimeOffset? _lastReceivedAt;
// Most recent ProcessedFrame, for the UI thumbnail. We hold a reference (not a
- // copy) — the FrameProcessor allocates new arrays per frame so the captured
+ // copy) — the FrameProcessor allocates new arrays per frame so the captured
// ReadOnlyMemory stays valid until GC reclaims it. UI consumers read
// this lazily at ~1Hz; transient null reads (between supervisor restarts)
// are handled at the call site.
@@ -106,7 +106,7 @@ public sealed class IsoPipeline : IAsyncDisposable
IncomingHeight: h)
{
State = State,
- // Peak is the high-water mark since the last GetStats() call —
+ // Peak is the high-water mark since the last GetStats() call —
// ConsumeAudioPeak resets it to 0 atomically, so the next read
// reflects only what arrived in the next polling interval.
// 0.0 means silence, no audio yet, or the sender is video-only.
@@ -164,7 +164,7 @@ public sealed class IsoPipeline : IAsyncDisposable
/// Test ctor. The caller supplies the inner runner directly so failures and lifetimes
/// can be controlled from a unit test.
///
- internal IsoPipeline(
+ public IsoPipeline(
Guid participantId,
Func runInner,
ExponentialBackoff backoff,
@@ -217,7 +217,7 @@ public sealed class IsoPipeline : IAsyncDisposable
},
onFrame: frame =>
{
- // Snapshot dimensions only — don't hold the RawFrame reference past
+ // Snapshot dimensions only — don't hold the RawFrame reference past
// the channel write so the GC can reclaim it on schedule, and so a
// late stats read can never resurrect a dropped frame's pixel buffer.
Volatile.Write(ref _lastWidth, frame.Width);
@@ -275,7 +275,7 @@ public sealed class IsoPipeline : IAsyncDisposable
try
{
await _runInner(ct);
- // Inner exited normally (typically only on cancellation) — leave the loop.
+ // Inner exited normally (typically only on cancellation) — leave the loop.
break;
}
catch (OperationCanceledException)
@@ -313,7 +313,7 @@ public sealed class IsoPipeline : IAsyncDisposable
}
///
- /// Default inner pipeline: spins up receiver → processor → sender on bounded channels
+ /// Default inner pipeline: spins up receiver → processor → sender on bounded channels
/// and awaits all three. Throws if any of them throws.
///
/// The optional / /
@@ -431,7 +431,7 @@ public sealed class IsoPipeline : IAsyncDisposable
///
/// Channel-writer wrapper that feeds every successfully-written
/// to an . Opens the
- /// recorder lazily on the first frame (so we know the actual width/height —
+ /// recorder lazily on the first frame (so we know the actual width/height —
/// the FrameProcessor resolves the resolution enum to concrete dimensions
/// only after the first scale, and that's what shows up in the ProcessedFrame).
///
@@ -464,7 +464,7 @@ public sealed class IsoPipeline : IAsyncDisposable
// Lazy-open after the first successful write so we have concrete
// dimensions. We deliberately try-catch here: a recorder failure
// (disk full, permission denied) must NOT prevent the live ISO from
- // continuing — the user's downstream switcher is the production
+ // continuing — the user's downstream switcher is the production
// surface, the recording is the archive copy.
try
{
diff --git a/src/TeamsISO.Engine/Pipeline/IsoPipelineConfig.cs b/src/Dragon-ISO.Engine/Pipeline/IsoPipelineConfig.cs
similarity index 86%
rename from src/TeamsISO.Engine/Pipeline/IsoPipelineConfig.cs
rename to src/Dragon-ISO.Engine/Pipeline/IsoPipelineConfig.cs
index 1968d33..71680a6 100644
--- a/src/TeamsISO.Engine/Pipeline/IsoPipelineConfig.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/IsoPipelineConfig.cs
@@ -1,9 +1,9 @@
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
-/// Per-pipeline configuration — identifies the participant, the source it captures,
+/// Per-pipeline configuration — identifies the participant, the source it captures,
/// the output it emits, and the global processing settings to apply.
///
public sealed record IsoPipelineConfig(
@@ -12,7 +12,7 @@ public sealed record IsoPipelineConfig(
string OutputName,
FrameProcessingSettings Settings)
{
- /// Default no-signal threshold per spec §4.
+ /// Default no-signal threshold per spec §4.
public TimeSpan SlateThreshold { get; init; } = TimeSpan.FromSeconds(2.5);
/// Bounded raw-frame channel capacity (drop-oldest backpressure).
@@ -47,7 +47,7 @@ public sealed record IsoPipelineConfig(
///
/// Operator-facing display name; used by the recorder to derive the filename.
/// Distinct from (the NDI source name, which is for
- /// machine consumption) — the recorder wants something human-readable.
+ /// machine consumption) — the recorder wants something human-readable.
///
public string? RecorderDisplayName { get; init; }
}
diff --git a/src/TeamsISO.Engine/Pipeline/ManagedNearestNeighborFrameScaler.cs b/src/Dragon-ISO.Engine/Pipeline/ManagedNearestNeighborFrameScaler.cs
similarity index 90%
rename from src/TeamsISO.Engine/Pipeline/ManagedNearestNeighborFrameScaler.cs
rename to src/Dragon-ISO.Engine/Pipeline/ManagedNearestNeighborFrameScaler.cs
index 0b93dbf..cae2a6b 100644
--- a/src/TeamsISO.Engine/Pipeline/ManagedNearestNeighborFrameScaler.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/ManagedNearestNeighborFrameScaler.cs
@@ -1,10 +1,10 @@
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Pure-managed BGRA frame scaler with nearest-neighbor sampling and aspect-mode handling.
-/// Suitable for v1.0 ship; libyuv is a v1.5 perf optimization (per spec §6 deferred items).
+/// Suitable for v1.0 ship; libyuv is a v1.5 perf optimization (per spec §6 deferred items).
///
public sealed class ManagedNearestNeighborFrameScaler : IFrameScaler
{
@@ -34,7 +34,7 @@ public sealed class ManagedNearestNeighborFrameScaler : IFrameScaler
// Nearest-neighbor scale into the (drawX, drawY, drawW, drawH) region.
for (var dy = 0; dy < drawH; dy++)
{
- // Map dest-row inside drawn rect → source row
+ // Map dest-row inside drawn rect → source row
var sy = (int)((long)dy * source.Height / drawH);
if (sy >= source.Height) sy = source.Height - 1;
var srcRowStart = sy * source.Width * 4;
@@ -66,20 +66,20 @@ public sealed class ManagedNearestNeighborFrameScaler : IFrameScaler
case AspectMode.Pillarbox:
case AspectMode.Letterbox:
{
- // Both modes preserve aspect ratio and fit within the destination — the difference is
+ // Both modes preserve aspect ratio and fit within the destination — the difference is
// descriptive (which dimension gets bars), but the math is the same: scale to fit.
var srcAspect = (double)srcW / srcH;
var dstAspect = (double)dstW / dstH;
int w, h;
if (srcAspect > dstAspect)
{
- // Source is wider → letterbox (fill width, bars top/bottom).
+ // Source is wider → letterbox (fill width, bars top/bottom).
w = dstW;
h = (int)Math.Round(dstW / srcAspect);
}
else
{
- // Source is taller/narrower → pillarbox (fill height, bars left/right).
+ // Source is taller/narrower → pillarbox (fill height, bars left/right).
h = dstH;
w = (int)Math.Round(dstH * srcAspect);
}
diff --git a/src/TeamsISO.Engine/Pipeline/MediaFoundationRecorderSink.cs b/src/Dragon-ISO.Engine/Pipeline/MediaFoundationRecorderSink.cs
similarity index 90%
rename from src/TeamsISO.Engine/Pipeline/MediaFoundationRecorderSink.cs
rename to src/Dragon-ISO.Engine/Pipeline/MediaFoundationRecorderSink.cs
index 579ba98..00ed11d 100644
--- a/src/TeamsISO.Engine/Pipeline/MediaFoundationRecorderSink.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/MediaFoundationRecorderSink.cs
@@ -1,14 +1,14 @@
-// Real-time H.264 recorder using Windows Media Foundation's SinkWriter.
+// Real-time H.264 recorder using Windows Media Foundation's SinkWriter.
// Gated behind MF_AVAILABLE because activating it requires:
//
-// 1. `dotnet add src/TeamsISO.Engine package Vortice.MediaFoundation --version 3.6.x`
+// 1. `dotnet add src/DragonISO.Engine package Vortice.MediaFoundation --version 3.6.x`
// 2. Add `$(DefineConstants);MF_AVAILABLE`
-// to `TeamsISO.Engine.csproj`
+// to `DragonISO.Engine.csproj`
// 3. Swap the `RawBgraRecorderSink` instantiation in `IsoController.EnableIsoAsync`
// for `MediaFoundationRecorderSink`
//
// This file is here so the swap is one line + a NuGet add when an operator is
-// ready to trade off the dependency for ~10× smaller recordings (1080p60 raw
+// ready to trade off the dependency for ~10× smaller recordings (1080p60 raw
// BGRA = ~500 MB/s; H.264 at the same input ~50 MB/s).
//
// We write to .mp4 (H.264 + AAC) rather than .mkv because Media Foundation's
@@ -21,12 +21,12 @@ using Microsoft.Extensions.Logging;
using Vortice.MediaFoundation;
using static Vortice.MediaFoundation.MediaFactory;
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// that encodes incoming
/// stream to H.264 in an .mp4 container via Windows Media Foundation's
-/// SinkWriter API. Inline encoder — no subprocess, no FFmpeg, no extra disk
+/// SinkWriter API. Inline encoder — no subprocess, no FFmpeg, no extra disk
/// passes.
///
/// Lifecycle matches the contract documented on :
@@ -73,11 +73,11 @@ public sealed class MediaFoundationRecorderSink : IRecorderSink
_writer = MFCreateSinkWriterFromURL(_outputPath, null, attrs);
- // Output type — H.264 baseline, target bitrate scaled by resolution.
+ // Output type — H.264 baseline, target bitrate scaled by resolution.
var outType = MFCreateMediaType();
outType.MajorType = MediaTypeGuids.Video;
outType.SubType = VideoFormatGuids.H264;
- outType.AvgBitrate = (uint)(width * height * fps * 0.07); // ~0.07 bits/pixel — decent quality
+ outType.AvgBitrate = (uint)(width * height * fps * 0.07); // ~0.07 bits/pixel — decent quality
outType.Set(MediaTypeAttributeKeys.InterlaceMode, (uint)VideoInterlaceMode.Progressive);
outType.Set(MediaTypeAttributeKeys.FrameSize, ((long)width << 32) | (uint)height);
outType.Set(MediaTypeAttributeKeys.FrameRate, ((long)(fps * 1000) << 32) | 1000U);
@@ -85,7 +85,7 @@ public sealed class MediaFoundationRecorderSink : IRecorderSink
_streamIndex = _writer.AddStream(outType);
- // Input type — BGRA32. MF will internally convert to NV12 for the H.264 encoder.
+ // Input type — BGRA32. MF will internally convert to NV12 for the H.264 encoder.
var inType = MFCreateMediaType();
inType.MajorType = MediaTypeGuids.Video;
inType.SubType = VideoFormatGuids.RGB32;
@@ -103,7 +103,7 @@ public sealed class MediaFoundationRecorderSink : IRecorderSink
_framesWritten = 0;
_framesDropped = 0;
IsRecording = true;
- _logger?.LogInformation("MF recorder open: {Path} ({W}×{H}@{Fps:F2})", _outputPath, width, height, fps);
+ _logger?.LogInformation("MF recorder open: {Path} ({W}×{H}@{Fps:F2})", _outputPath, width, height, fps);
}
public bool WriteFrame(ProcessedFrame frame)
diff --git a/src/TeamsISO.Engine/Pipeline/NdiReceiver.cs b/src/Dragon-ISO.Engine/Pipeline/NdiReceiver.cs
similarity index 93%
rename from src/TeamsISO.Engine/Pipeline/NdiReceiver.cs
rename to src/Dragon-ISO.Engine/Pipeline/NdiReceiver.cs
index 9997ded..40861fa 100644
--- a/src/TeamsISO.Engine/Pipeline/NdiReceiver.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/NdiReceiver.cs
@@ -1,8 +1,8 @@
-using System.Threading.Channels;
+using System.Threading.Channels;
using Microsoft.Extensions.Logging;
-using TeamsISO.Engine.Interop;
+using DragonISO.Engine.Interop;
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Wraps an receiver handle and pushes captured frames into a
@@ -24,7 +24,7 @@ public sealed class NdiReceiver : IDisposable
// - Audio frames arrive at ~50Hz (1024-sample blocks @ 48kHz).
// - UI stats polling reads at 1Hz.
// If we only published the most recent buffer's peak, the UI would see
- // exactly one of every ~50 audio frames per second — loud transients
+ // exactly one of every ~50 audio frames per second — loud transients
// between reads would be invisible. By keeping the running max and
// consuming it on read, the UI sees the true peak across the entire
// polling interval, which is the actual behavior of a peak VU meter.
@@ -52,7 +52,7 @@ public sealed class NdiReceiver : IDisposable
///
/// Reads the peak audio amplitude (in [0.0, 1.0]) seen since the last
/// call and resets the high-water mark to zero. The reset semantics are
- /// what makes this a true peak meter — between two consecutive reads
+ /// what makes this a true peak meter — between two consecutive reads
/// the caller sees the loudest sample that crossed the receiver, not
/// just whatever the latest buffer happened to contain.
///
@@ -69,7 +69,7 @@ public sealed class NdiReceiver : IDisposable
///
/// Non-consuming peek at the current peak high-water mark. Useful for
/// observability paths that need to read the value without affecting the
- /// max-since-last-read behavior — for example, an external diagnostics
+ /// max-since-last-read behavior — for example, an external diagnostics
/// dashboard that polls more often than the UI.
///
public double PeekAudioPeak()
@@ -94,7 +94,7 @@ public sealed class NdiReceiver : IDisposable
/// updates the high-water peak. Test seam mirroring .
/// The CAS loop is needed because two writers (this method, called from
/// the audio capture thread) and one reader (,
- /// called from the UI poll thread) compete for the same field — a plain
+ /// called from the UI poll thread) compete for the same field — a plain
/// Volatile.Write would lose updates if Consume fires between our read
/// and write.
///
@@ -107,7 +107,7 @@ public sealed class NdiReceiver : IDisposable
do
{
current = Volatile.Read(ref _audioPeakBits);
- // If our peak is no louder than what's already there, leave it —
+ // If our peak is no louder than what's already there, leave it —
// somebody else (the audio thread itself, on a previous frame)
// already published a higher max.
if (peak.Value <= BitConverter.Int64BitsToDouble(current)) return;
@@ -146,10 +146,10 @@ public sealed class NdiReceiver : IDisposable
{
// Audio frames arrive at the source's frame rate (typically
// 48kHz delivered in 1024-sample chunks ~= 50Hz). A 50ms
- // poll matches that cadence — we won't miss frames and we
+ // poll matches that cadence — we won't miss frames and we
// won't busy-spin if the source is video-only.
//
- // Audio loop failures are logged but never re-thrown — a
+ // Audio loop failures are logged but never re-thrown — a
// misbehaving audio path must NEVER tear down the live
// video pipeline. The UI VU bar will simply freeze at its
// last value.
diff --git a/src/TeamsISO.Engine/Pipeline/NdiSender.cs b/src/Dragon-ISO.Engine/Pipeline/NdiSender.cs
similarity index 95%
rename from src/TeamsISO.Engine/Pipeline/NdiSender.cs
rename to src/Dragon-ISO.Engine/Pipeline/NdiSender.cs
index 97d463d..259186a 100644
--- a/src/TeamsISO.Engine/Pipeline/NdiSender.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/NdiSender.cs
@@ -1,8 +1,8 @@
-using System.Threading.Channels;
+using System.Threading.Channels;
using Microsoft.Extensions.Logging;
-using TeamsISO.Engine.Interop;
+using DragonISO.Engine.Interop;
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Pulls processed frames from a channel and forwards them to .
diff --git a/src/TeamsISO.Engine/Pipeline/PassthroughFrameScaler.cs b/src/Dragon-ISO.Engine/Pipeline/PassthroughFrameScaler.cs
similarity index 90%
rename from src/TeamsISO.Engine/Pipeline/PassthroughFrameScaler.cs
rename to src/Dragon-ISO.Engine/Pipeline/PassthroughFrameScaler.cs
index a26c5e4..fcfceea 100644
--- a/src/TeamsISO.Engine/Pipeline/PassthroughFrameScaler.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/PassthroughFrameScaler.cs
@@ -1,6 +1,6 @@
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Phase A scaler. Copies the source frame's pixel buffer through unchanged and tags the
diff --git a/src/TeamsISO.Engine/Pipeline/PeriodicTimerFrameClock.cs b/src/Dragon-ISO.Engine/Pipeline/PeriodicTimerFrameClock.cs
similarity index 94%
rename from src/TeamsISO.Engine/Pipeline/PeriodicTimerFrameClock.cs
rename to src/Dragon-ISO.Engine/Pipeline/PeriodicTimerFrameClock.cs
index cfacce9..c9d4b79 100644
--- a/src/TeamsISO.Engine/Pipeline/PeriodicTimerFrameClock.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/PeriodicTimerFrameClock.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
public sealed class PeriodicTimerFrameClock : IFrameClock, IDisposable
{
diff --git a/src/TeamsISO.Engine/Pipeline/ProcessedFrame.cs b/src/Dragon-ISO.Engine/Pipeline/ProcessedFrame.cs
similarity index 86%
rename from src/TeamsISO.Engine/Pipeline/ProcessedFrame.cs
rename to src/Dragon-ISO.Engine/Pipeline/ProcessedFrame.cs
index 25300d7..a7cb559 100644
--- a/src/TeamsISO.Engine/Pipeline/ProcessedFrame.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/ProcessedFrame.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// A frame after framerate, resolution, and aspect normalization. Ready to send.
diff --git a/src/TeamsISO.Engine/Pipeline/RawBgraRecorderSink.cs b/src/Dragon-ISO.Engine/Pipeline/RawBgraRecorderSink.cs
similarity index 93%
rename from src/TeamsISO.Engine/Pipeline/RawBgraRecorderSink.cs
rename to src/Dragon-ISO.Engine/Pipeline/RawBgraRecorderSink.cs
index 8140858..5e121ed 100644
--- a/src/TeamsISO.Engine/Pipeline/RawBgraRecorderSink.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/RawBgraRecorderSink.cs
@@ -1,9 +1,9 @@
-using System.IO;
+using System.IO;
using System.Text.Json;
using System.Threading.Channels;
using Microsoft.Extensions.Logging;
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Concrete that writes the processed BGRA stream to
@@ -15,10 +15,10 @@ namespace TeamsISO.Engine.Pipeline;
///
/// Files produced under <outputDir>/<sanitized-display-name>/:
///
-/// video.bgra — raw concatenated frames at width*height*4 bytes each.
-/// manifest.json — width, height, fps, format, started/ended timestamps,
+/// video.bgra — raw concatenated frames at width*height*4 bytes each.
+/// manifest.json — width, height, fps, format, started/ended timestamps,
/// frame count. Lets a post-processor reconstruct timing without parsing the .bgra.
-/// convert.cmd — one-liner that pipes the .bgra into ffmpeg to produce
+/// convert.cmd — one-liner that pipes the .bgra into ffmpeg to produce
/// a final output.mkv at H.264. Operators just double-click.
///
///
@@ -26,7 +26,7 @@ namespace TeamsISO.Engine.Pipeline;
/// recording at the default 720p30 takes ~150 GB. Operators should record at the
/// lowest acceptable resolution / framerate, or enable recording only on the
/// participants they intend to keep. A future MediaFoundationRecorderSink
-/// would compress in-process and reduce this 10× — see _NEXT.md.
+/// would compress in-process and reduce this 10× — see _NEXT.md.
///
/// Threading: writes are serialized through a single bounded channel so the
/// pipeline's processor thread never blocks on disk I/O. If the disk can't keep
@@ -63,8 +63,8 @@ public sealed class RawBgraRecorderSink : IRecorderSink
{
_logger = logger;
// Bounded queue with DropOldest: if the disk falls behind, lose the
- // oldest frames and keep recording — better than blocking the pipeline.
- // 240 frames ≈ 4 seconds @ 60 fps; gives us a buffer for transient
+ // oldest frames and keep recording — better than blocking the pipeline.
+ // 240 frames ≈ 4 seconds @ 60 fps; gives us a buffer for transient
// disk hiccups without unbounded RAM growth on a stuck volume.
_queue = Channel.CreateBounded(new BoundedChannelOptions(240)
{
@@ -196,7 +196,7 @@ public sealed class RawBgraRecorderSink : IRecorderSink
var manifest = new
{
- schema = "teamsiso-recorder/v1",
+ schema = "Dragon-ISO-recorder/v1",
participantDisplayName = _displayName,
width = _width,
height = _height,
diff --git a/src/TeamsISO.Engine/Pipeline/RawFrame.cs b/src/Dragon-ISO.Engine/Pipeline/RawFrame.cs
similarity index 84%
rename from src/TeamsISO.Engine/Pipeline/RawFrame.cs
rename to src/Dragon-ISO.Engine/Pipeline/RawFrame.cs
index 417d06b..cac9679 100644
--- a/src/TeamsISO.Engine/Pipeline/RawFrame.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/RawFrame.cs
@@ -1,7 +1,7 @@
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
-/// A frame as captured from an NDI receiver. Pixel buffer is opaque to the engine — its
+/// A frame as captured from an NDI receiver. Pixel buffer is opaque to the engine — its
/// shape is determined by the NDI receive format. Timestamp is the source's reported time.
///
public sealed record RawFrame(
diff --git a/src/TeamsISO.Engine/Pipeline/SolidFrameRenderer.cs b/src/Dragon-ISO.Engine/Pipeline/SolidFrameRenderer.cs
similarity index 93%
rename from src/TeamsISO.Engine/Pipeline/SolidFrameRenderer.cs
rename to src/Dragon-ISO.Engine/Pipeline/SolidFrameRenderer.cs
index 7457d82..3fd18f5 100644
--- a/src/TeamsISO.Engine/Pipeline/SolidFrameRenderer.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/SolidFrameRenderer.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Generates a solid-color BGRA frame for use as a "no signal" slate.
diff --git a/src/TeamsISO.Engine/Pipeline/TestPatternGenerator.cs b/src/Dragon-ISO.Engine/Pipeline/TestPatternGenerator.cs
similarity index 90%
rename from src/TeamsISO.Engine/Pipeline/TestPatternGenerator.cs
rename to src/Dragon-ISO.Engine/Pipeline/TestPatternGenerator.cs
index 831baa6..802a38b 100644
--- a/src/TeamsISO.Engine/Pipeline/TestPatternGenerator.cs
+++ b/src/Dragon-ISO.Engine/Pipeline/TestPatternGenerator.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.Engine.Pipeline;
+namespace DragonISO.Engine.Pipeline;
///
/// Generates synthetic BGRA test-pattern frames for diagnosing NDI setups
@@ -6,12 +6,12 @@ namespace TeamsISO.Engine.Pipeline;
/// moving sweep band and a small frame-counter readout in the corner so
/// the operator can visually confirm frames are flowing in real time.
///
-/// Static stateless API — caller bumps the frame counter each tick. Each
+/// Static stateless API — caller bumps the frame counter each tick. Each
/// call allocates a fresh BGRA byte[] so the caller can hand it straight
/// to via a wrapper
/// without holding shared buffers.
///
-/// Used by TeamsISO.Console --test-pattern; could also be wired
+/// Used by DragonISO.Console --test-pattern; could also be wired
/// into the WPF host as a "synthetic source" toggle for demoing.
///
public static class TestPatternGenerator
@@ -54,7 +54,7 @@ public static class TestPatternGenerator
var (b, g, r) = BarColors[barIdx];
if (isSweep)
{
- // Brighten the bar 32 BGR units (clamped) — visible moving band.
+ // Brighten the bar 32 BGR units (clamped) — visible moving band.
b = (byte)Math.Min(255, b + 32);
g = (byte)Math.Min(255, g + 32);
r = (byte)Math.Min(255, r + 32);
diff --git a/src/TeamsISO.App/Services/ControlSurface/Endpoints/TeamsEndpoints.cs b/src/TeamsISO.App/Services/ControlSurface/Endpoints/TeamsEndpoints.cs
deleted file mode 100644
index 12068b8..0000000
--- a/src/TeamsISO.App/Services/ControlSurface/Endpoints/TeamsEndpoints.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace TeamsISO.App.Services;
-
-// /teams/* route handlers — UIAutomation-driven in-call controls.
-//
-// POST /teams/mute → InvokeTeams(ToggleMute, "mute")
-// POST /teams/camera → InvokeTeams(ToggleCamera, "camera")
-// POST /teams/leave → InvokeTeams(LeaveCall, "leave")
-// POST /teams/share → InvokeTeams(OpenShareTray, "share")
-// POST /teams/raise-hand → InvokeTeams(ToggleRaiseHand, "raise-hand")
-public sealed partial class ControlSurfaceServer
-{
- private object InvokeTeams(Func invoke, string action)
- {
- var result = invoke();
- return new
- {
- ok = result == TeamsControlBridge.InvokeResult.Invoked,
- action,
- result = result.ToString(),
- };
- }
-}
diff --git a/src/tests/TeamsISO.App.Tests/TeamsISO.App.Tests.csproj b/src/tests/Dragon-ISO.App.Tests/Dragon-ISO.App.Tests.csproj
similarity index 83%
rename from src/tests/TeamsISO.App.Tests/TeamsISO.App.Tests.csproj
rename to src/tests/Dragon-ISO.App.Tests/Dragon-ISO.App.Tests.csproj
index 579bc21..ad8ac34 100644
--- a/src/tests/TeamsISO.App.Tests/TeamsISO.App.Tests.csproj
+++ b/src/tests/Dragon-ISO.App.Tests/Dragon-ISO.App.Tests.csproj
@@ -1,14 +1,14 @@
-
+
@@ -39,7 +39,7 @@
-
+
diff --git a/src/tests/TeamsISO.App.Tests/Fakes/StubIsoController.cs b/src/tests/Dragon-ISO.App.Tests/Fakes/StubIsoController.cs
similarity index 95%
rename from src/tests/TeamsISO.App.Tests/Fakes/StubIsoController.cs
rename to src/tests/Dragon-ISO.App.Tests/Fakes/StubIsoController.cs
index 20a2a05..8129c69 100644
--- a/src/tests/TeamsISO.App.Tests/Fakes/StubIsoController.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Fakes/StubIsoController.cs
@@ -1,10 +1,10 @@
-using System.Reactive.Linq;
+using System.Reactive.Linq;
using System.Reactive.Subjects;
-using TeamsISO.Engine.Controller;
-using TeamsISO.Engine.Domain;
-using TeamsISO.Engine.Pipeline;
+using DragonISO.Engine.Controller;
+using DragonISO.Engine.Domain;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.App.Tests.Fakes;
+namespace DragonISO.App.Tests.Fakes;
// Minimal IIsoController stub for tests that need to instantiate
// services in the App layer (ControlSurfaceServer, OscBridge, etc.)
diff --git a/src/tests/TeamsISO.App.Tests/Integration/IntegrationTests.cs b/src/tests/Dragon-ISO.App.Tests/Integration/IntegrationTests.cs
similarity index 87%
rename from src/tests/TeamsISO.App.Tests/Integration/IntegrationTests.cs
rename to src/tests/Dragon-ISO.App.Tests/Integration/IntegrationTests.cs
index a848472..a887347 100644
--- a/src/tests/TeamsISO.App.Tests/Integration/IntegrationTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Integration/IntegrationTests.cs
@@ -1,32 +1,32 @@
-using System.Net;
+using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Text.Json;
using System.Windows;
using System.Windows.Media;
using FluentAssertions;
-using TeamsISO.App.Services;
-using TeamsISO.App.Tests.Fakes;
-using TeamsISO.App.ViewModels;
-using TeamsISO.Engine.Domain;
+using DragonISO.App.Services;
+using DragonISO.App.Tests.Fakes;
+using DragonISO.App.ViewModels;
+using DragonISO.Engine.Domain;
using Xunit;
-namespace TeamsISO.App.Tests.Integration;
+namespace DragonISO.App.Tests.Integration;
// End-to-end-ish integration tests that need a live WPF Application +
// STA dispatcher. All three live in one class + share a
// WpfHostFixture so Application is created exactly once for the
-// suite (Application is one-per-AppDomain — multiple test classes
+// suite (Application is one-per-AppDomain — multiple test classes
// trying to construct it independently collide).
//
// Coverage per the punch list:
-// • App-startup headless smoke — construct App's bootstrap layers
+// • App-startup headless smoke — construct App's bootstrap layers
// on STA, verify XAML resource resolution + theme apply + VM
// wiring + MainWindow construction.
-// • ControlSurface integration — boot the server on an ephemeral
+// • ControlSurface integration — boot the server on an ephemeral
// port, populate a real view-model, hit /participants, verify
// the JSON includes the live participant.
-// • Theme swap — Dark → Light dictionary swap, brush key resolves
+// • Theme swap — Dark → Light dictionary swap, brush key resolves
// to a different value afterward.
[Collection(WpfHostCollection.Name)]
public sealed class IntegrationTests
@@ -51,7 +51,7 @@ public sealed class IntegrationTests
dicts.Clear();
dicts.Add(new ResourceDictionary
{
- Source = new Uri("pack://application:,,,/TeamsISO;component/Themes/Theme.Dark.xaml", UriKind.Absolute),
+ Source = new Uri("pack://application:,,,/DragonISO;component/Themes/Theme.Dark.xaml", UriKind.Absolute),
});
});
}
@@ -63,7 +63,7 @@ public sealed class IntegrationTests
// production code path) and that the two theme files
// produce different brushes for the same key. End-to-end
// exercise of the resource pipeline that doesn't depend on
- // Application.Resources global state — both dicts are
+ // Application.Resources global state — both dicts are
// loaded fresh in this call.
//
// We don't test ThemeManager.SwapColorDictionary here
@@ -79,13 +79,13 @@ public sealed class IntegrationTests
var darkDict = new ResourceDictionary
{
Source = new Uri(
- "pack://application:,,,/TeamsISO;component/Themes/Theme.Dark.xaml",
+ "pack://application:,,,/DragonISO;component/Themes/Theme.Dark.xaml",
UriKind.Absolute),
};
var lightDict = new ResourceDictionary
{
Source = new Uri(
- "pack://application:,,,/TeamsISO;component/Themes/Theme.Light.xaml",
+ "pack://application:,,,/DragonISO;component/Themes/Theme.Light.xaml",
UriKind.Absolute),
};
@@ -115,7 +115,7 @@ public sealed class IntegrationTests
_wpf.Application.Resources.MergedDictionaries.Add(new ResourceDictionary
{
Source = new Uri(
- "pack://application:,,,/TeamsISO;component/Themes/WildDragonTheme.xaml",
+ "pack://application:,,,/DragonISO;component/Themes/WildDragonTheme.xaml",
UriKind.Absolute),
});
});
diff --git a/src/tests/TeamsISO.App.Tests/Integration/WpfHostFixture.cs b/src/tests/Dragon-ISO.App.Tests/Integration/WpfHostFixture.cs
similarity index 97%
rename from src/tests/TeamsISO.App.Tests/Integration/WpfHostFixture.cs
rename to src/tests/Dragon-ISO.App.Tests/Integration/WpfHostFixture.cs
index 5351ac9..77de28a 100644
--- a/src/tests/TeamsISO.App.Tests/Integration/WpfHostFixture.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Integration/WpfHostFixture.cs
@@ -1,8 +1,8 @@
-using System.Threading;
+using System.Threading;
using System.Windows;
using System.Windows.Threading;
-namespace TeamsISO.App.Tests.Integration;
+namespace DragonISO.App.Tests.Integration;
///
/// Shared WPF Application + STA dispatcher fixture. Created once for
diff --git a/src/tests/TeamsISO.App.Tests/MeetingTitleExtractionTests.cs b/src/tests/Dragon-ISO.App.Tests/MeetingTitleExtractionTests.cs
similarity index 90%
rename from src/tests/TeamsISO.App.Tests/MeetingTitleExtractionTests.cs
rename to src/tests/Dragon-ISO.App.Tests/MeetingTitleExtractionTests.cs
index 083fc79..4ff78ce 100644
--- a/src/tests/TeamsISO.App.Tests/MeetingTitleExtractionTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/MeetingTitleExtractionTests.cs
@@ -1,11 +1,11 @@
-using TeamsISO.App.ViewModels;
+using DragonISO.App.ViewModels;
using Xunit;
-namespace TeamsISO.App.Tests;
+namespace DragonISO.App.Tests;
///
/// Validates the title-stripping heuristic used by the IN-CALL bar pill.
-/// Teams' raw window title is the format the user actually sees (or doesn't —
+/// Teams' raw window title is the format the user actually sees (or doesn't —
/// when auto-hide is on); we want to surface the meaningful meeting-name
/// portion without the "| Microsoft Teams" suffix bloating the pill.
///
@@ -36,7 +36,7 @@ public class MeetingTitleExtractionTests
[Fact]
public void BareAppTitle_ReturnsEmpty()
{
- // "Microsoft Teams" alone means no meeting context — pill should
+ // "Microsoft Teams" alone means no meeting context — pill should
// stay at plain "IN CALL" rather than appending a meaningless title.
Assert.Equal(string.Empty, MainViewModel.ExtractMeetingTitle("Microsoft Teams"));
}
@@ -47,7 +47,7 @@ public class MeetingTitleExtractionTests
var long_ = new string('A', 100) + " | Microsoft Teams";
var result = MainViewModel.ExtractMeetingTitle(long_);
Assert.True(result.Length <= 50);
- Assert.EndsWith("…", result);
+ Assert.EndsWith("…", result);
}
[Fact]
diff --git a/src/tests/TeamsISO.App.Tests/Services/ControlSurfaceServerTests.cs b/src/tests/Dragon-ISO.App.Tests/Services/ControlSurfaceServerTests.cs
similarity index 90%
rename from src/tests/TeamsISO.App.Tests/Services/ControlSurfaceServerTests.cs
rename to src/tests/Dragon-ISO.App.Tests/Services/ControlSurfaceServerTests.cs
index af96675..3882165 100644
--- a/src/tests/TeamsISO.App.Tests/Services/ControlSurfaceServerTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Services/ControlSurfaceServerTests.cs
@@ -1,21 +1,21 @@
-using System.Net;
+using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using FluentAssertions;
-using TeamsISO.App.Services;
-using TeamsISO.App.Tests.Fakes;
+using DragonISO.App.Services;
+using DragonISO.App.Tests.Fakes;
-namespace TeamsISO.App.Tests.Services;
+namespace DragonISO.App.Tests.Services;
// End-to-end-ish smoke tests for ControlSurfaceServer. Each test boots
-// the server on an OS-assigned free port (127.0.0.1 only — no urlacl
+// the server on an OS-assigned free port (127.0.0.1 only — no urlacl
// required), makes a real HTTP request via HttpClient, and asserts
// against the response. The tests share a StubIsoController and a
-// null view-model — endpoints that need a UI dispatcher degrade
+// null view-model — endpoints that need a UI dispatcher degrade
// gracefully (return empty arrays) which is enough to verify the
// route table.
//
-// We don't exercise the WebSocket path here — ClientWebSocket adds
+// We don't exercise the WebSocket path here — ClientWebSocket adds
// non-trivial timing complexity and the upgrade is verified by the
// 426/101 status arc of `/ws` on a non-WS GET (we hit it and confirm
// the server doesn't 500).
@@ -52,7 +52,7 @@ public sealed class ControlSurfaceServerTests
res.StatusCode.Should().Be(HttpStatusCode.OK);
var body = await res.Content.ReadAsStringAsync();
- body.Should().Contain("\"product\":\"TeamsISO\"");
+ body.Should().Contain("\"product\":\"Dragon-ISO\"");
body.Should().Contain("\"endpoints\"");
}
finally
@@ -69,7 +69,7 @@ public sealed class ControlSurfaceServerTests
// object {error:"not found"}) rather than null, so the response
// pipeline writes 200 OK with that body instead of branching to
// 404. The body is the disambiguator, matching the rest of the
- // surface's "200 + {ok:false,error:…}" convention. Pinning this
+ // surface's "200 + {ok:false,error:…}" convention. Pinning this
// so a deliberate move to a true 404 is a conscious decision,
// not an accident.
var (server, client, _) = await BootAsync();
@@ -91,7 +91,7 @@ public sealed class ControlSurfaceServerTests
[Fact]
public async Task GetParticipants_Returns200_WithEmptyListWhenNoViewModel()
{
- // No dispatcher / no view-model in tests — the endpoint should
+ // No dispatcher / no view-model in tests — the endpoint should
// gracefully return participants=[] rather than throwing.
var (server, client, _) = await BootAsync();
try
@@ -134,7 +134,7 @@ public sealed class ControlSurfaceServerTests
[Fact]
public async Task PostPresetApply_MissingPreset_RespondsWithOkFalseAndPresetNotFound()
{
- // Preset name that demonstrably doesn't exist on disk → endpoint
+ // Preset name that demonstrably doesn't exist on disk → endpoint
// returns 200 with {"ok":false,"error":"preset not found",...}.
// We don't 404 on missing presets because the operator may have
// typed the wrong name; clearer payload is friendlier.
diff --git a/src/tests/TeamsISO.App.Tests/Services/NotesServiceTests.cs b/src/tests/Dragon-ISO.App.Tests/Services/NotesServiceTests.cs
similarity index 80%
rename from src/tests/TeamsISO.App.Tests/Services/NotesServiceTests.cs
rename to src/tests/Dragon-ISO.App.Tests/Services/NotesServiceTests.cs
index a37821c..6bcc947 100644
--- a/src/tests/TeamsISO.App.Tests/Services/NotesServiceTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Services/NotesServiceTests.cs
@@ -1,12 +1,12 @@
-using System.IO;
+using System.IO;
using FluentAssertions;
-using TeamsISO.App.Services;
+using DragonISO.App.Services;
-namespace TeamsISO.App.Tests.Services;
+namespace DragonISO.App.Tests.Services;
-// Unit tests for NotesService — the append-only show-notes log.
+// Unit tests for NotesService — the append-only show-notes log.
// Uses the DirectoryOverride seam so writes land in a tempdir and
-// don't pollute the dev's real %LOCALAPPDATA%\TeamsISO\Notes folder.
+// don't pollute the dev's real %LOCALAPPDATA%\Dragon-ISO\Notes folder.
//
// Shares NotesStateCollection with any sibling class that mutates
// NotesService.DirectoryOverride (the same static-state-shared-via-
@@ -19,7 +19,7 @@ public sealed class NotesServiceTests : IDisposable
public NotesServiceTests()
{
- _tempDir = Path.Combine(Path.GetTempPath(), $"teamsiso-notes-{Guid.NewGuid():N}");
+ _tempDir = Path.Combine(Path.GetTempPath(), $"Dragon-ISO-notes-{Guid.NewGuid():N}");
_previousOverride = NotesService.DirectoryOverride;
NotesService.DirectoryOverride = _tempDir;
}
@@ -39,8 +39,8 @@ public sealed class NotesServiceTests : IDisposable
ok.Should().BeTrue();
File.Exists(NotesService.TodayPath).Should().BeTrue();
var content = File.ReadAllText(NotesService.TodayPath);
- content.Should().StartWith("# TeamsISO show notes — ");
- content.Should().Contain("— first note");
+ content.Should().StartWith("# Dragon-ISO show notes — ");
+ content.Should().Contain("— first note");
}
[Fact]
@@ -49,9 +49,9 @@ public sealed class NotesServiceTests : IDisposable
NotesService.Append("checkpoint");
var content = File.ReadAllText(NotesService.TodayPath);
- // Each appended line follows "- **HH:mm:ss** — " so a
+ // Each appended line follows "- **HH:mm:ss** — " so a
// reader can scan the file as Markdown without preprocessing.
- content.Should().MatchRegex(@"- \*\*\d{2}:\d{2}:\d{2}\*\* — checkpoint");
+ content.Should().MatchRegex(@"- \*\*\d{2}:\d{2}:\d{2}\*\* — checkpoint");
}
[Fact]
@@ -66,7 +66,7 @@ public sealed class NotesServiceTests : IDisposable
content.Should().Contain("beta");
content.Should().Contain("gamma");
// Header written exactly once, not before every line.
- var headerCount = content.Split("# TeamsISO show notes —").Length - 1;
+ var headerCount = content.Split("# Dragon-ISO show notes —").Length - 1;
headerCount.Should().Be(1);
}
@@ -76,7 +76,7 @@ public sealed class NotesServiceTests : IDisposable
NotesService.Append(" padded ");
var content = File.ReadAllText(NotesService.TodayPath);
- content.Should().Contain("— padded");
+ content.Should().Contain("— padded");
content.Should().NotContain(" padded "); // leading-whitespace gone
}
diff --git a/src/tests/TeamsISO.App.Tests/Services/NotesStateCollection.cs b/src/tests/Dragon-ISO.App.Tests/Services/NotesStateCollection.cs
similarity index 91%
rename from src/tests/TeamsISO.App.Tests/Services/NotesStateCollection.cs
rename to src/tests/Dragon-ISO.App.Tests/Services/NotesStateCollection.cs
index 8e8c25b..92d8bea 100644
--- a/src/tests/TeamsISO.App.Tests/Services/NotesStateCollection.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Services/NotesStateCollection.cs
@@ -1,4 +1,4 @@
-namespace TeamsISO.App.Tests.Services;
+namespace DragonISO.App.Tests.Services;
///
/// Serializes any test class that mutates
diff --git a/src/tests/TeamsISO.App.Tests/Services/OperatorPresetStoreTests.cs b/src/tests/Dragon-ISO.App.Tests/Services/OperatorPresetStoreTests.cs
similarity index 96%
rename from src/tests/TeamsISO.App.Tests/Services/OperatorPresetStoreTests.cs
rename to src/tests/Dragon-ISO.App.Tests/Services/OperatorPresetStoreTests.cs
index 86519fd..5d5d44d 100644
--- a/src/tests/TeamsISO.App.Tests/Services/OperatorPresetStoreTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Services/OperatorPresetStoreTests.cs
@@ -1,18 +1,18 @@
-using System.IO;
+using System.IO;
using FluentAssertions;
-using TeamsISO.App.Services;
+using DragonISO.App.Services;
-namespace TeamsISO.App.Tests.Services;
+namespace DragonISO.App.Tests.Services;
///
/// Unit tests for . Each test redirects
/// the store's file path to a per-test temp path via the internal
/// PathOverride hook so the operator's real
-/// %LOCALAPPDATA%\TeamsISO\presets.json is never touched.
+/// %LOCALAPPDATA%\Dragon-ISO\presets.json is never touched.
///
/// IDisposable on the test class cleans up the temp path after each
/// test. Shares with any other
-/// class that mutates —
+/// class that mutates —
/// xUnit's parallel execution would otherwise let a sibling class's
/// ctor clobber our path mid-test.
///
@@ -28,7 +28,7 @@ public sealed class OperatorPresetStoreTests : IDisposable
// without creating it, and let OperatorPresetStore.Save() create as needed.
_tempPath = Path.Combine(
Path.GetTempPath(),
- $"teamsiso-presets-test-{Guid.NewGuid():N}.json");
+ $"Dragon-ISO-presets-test-{Guid.NewGuid():N}.json");
OperatorPresetStore.PathOverride = _tempPath;
}
@@ -197,7 +197,7 @@ public sealed class OperatorPresetStoreTests : IDisposable
{
OperatorPresetStore.Save(MakePreset("ShowA", ("Jane", true)));
var bundle = OperatorPresetStore.ExportAllAsJson();
- // Modify in-memory: change Jane → Bob, then import without overwrite.
+ // Modify in-memory: change Jane → Bob, then import without overwrite.
OperatorPresetStore.Save(MakePreset("ShowA", ("Bob", true)));
var result = OperatorPresetStore.ImportBundle(bundle, overwrite: false);
diff --git a/src/tests/TeamsISO.App.Tests/Services/OscBridgeDispatchTests.cs b/src/tests/Dragon-ISO.App.Tests/Services/OscBridgeDispatchTests.cs
similarity index 81%
rename from src/tests/TeamsISO.App.Tests/Services/OscBridgeDispatchTests.cs
rename to src/tests/Dragon-ISO.App.Tests/Services/OscBridgeDispatchTests.cs
index f44bb7c..51ed6a3 100644
--- a/src/tests/TeamsISO.App.Tests/Services/OscBridgeDispatchTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Services/OscBridgeDispatchTests.cs
@@ -1,21 +1,21 @@
-using System.IO;
+using System.IO;
using FluentAssertions;
-using TeamsISO.App.Services;
-using TeamsISO.App.Tests.Fakes;
+using DragonISO.App.Services;
+using DragonISO.App.Tests.Fakes;
-namespace TeamsISO.App.Tests.Services;
+namespace DragonISO.App.Tests.Services;
// Tests for the OscBridge.DispatchAsync routing. We construct
// OscMessage instances directly (skipping the UDP receive loop) and
// assert that the right address resolves to the right controller call.
//
// The toggle / preset paths require Application.Current.Dispatcher,
-// which doesn't exist in xUnit's default execution context — those
+// which doesn't exist in xUnit's default execution context — those
// paths return early on the null check, so we verify the bail rather
// than the happy path. The full toggle path is covered in branch 11's
// integration test that boots a real dispatcher.
//
-// Shares NotesStateCollection with NotesServiceTests — both classes
+// Shares NotesStateCollection with NotesServiceTests — both classes
// mutate NotesService.DirectoryOverride and would otherwise race.
[Collection(NotesStateCollection.Name)]
public sealed class OscBridgeDispatchTests : IDisposable
@@ -25,7 +25,7 @@ public sealed class OscBridgeDispatchTests : IDisposable
public OscBridgeDispatchTests()
{
- _tempNotesDir = Path.Combine(Path.GetTempPath(), $"teamsiso-osc-{Guid.NewGuid():N}");
+ _tempNotesDir = Path.Combine(Path.GetTempPath(), $"Dragon-ISO-osc-{Guid.NewGuid():N}");
_previousNotesOverride = NotesService.DirectoryOverride;
NotesService.DirectoryOverride = _tempNotesDir;
}
@@ -40,7 +40,7 @@ public sealed class OscBridgeDispatchTests : IDisposable
private static (OscBridge Bridge, StubIsoController Controller) NewBridge()
{
var controller = new StubIsoController();
- // OscBridge takes Func — returning null exercises
+ // OscBridge takes Func — returning null exercises
// the "no VM yet" graceful path in handlers that need it.
var bridge = new OscBridge(controller, () => null, logger: null);
return (bridge, controller);
@@ -51,7 +51,7 @@ public sealed class OscBridgeDispatchTests : IDisposable
{
var (bridge, controller) = NewBridge();
- await bridge.DispatchAsync(new OscMessage { Address = "/teamsiso/refresh-discovery" });
+ await bridge.DispatchAsync(new OscMessage { Address = "/Dragon-ISO/refresh-discovery" });
controller.RefreshDiscoveryCalled.Should().BeTrue();
}
@@ -61,7 +61,7 @@ public sealed class OscBridgeDispatchTests : IDisposable
{
var (bridge, controller) = NewBridge();
- await bridge.DispatchAsync(new OscMessage { Address = "/teamsiso/nope/never" });
+ await bridge.DispatchAsync(new OscMessage { Address = "/Dragon-ISO/nope/never" });
controller.RefreshDiscoveryCalled.Should().BeFalse();
controller.EnableCalls.Should().BeEmpty();
@@ -75,7 +75,7 @@ public sealed class OscBridgeDispatchTests : IDisposable
await bridge.DispatchAsync(new OscMessage
{
- Address = "/teamsiso/notes",
+ Address = "/Dragon-ISO/notes",
TypeTag = ",s",
Args = new object[] { "tracked through OSC" },
});
@@ -89,10 +89,10 @@ public sealed class OscBridgeDispatchTests : IDisposable
{
// Without a view-model, the stop-all path returns before touching
// the controller. The point of this test is to pin that the bail
- // is clean — no thrown exception, no controller traffic.
+ // is clean — no thrown exception, no controller traffic.
var (bridge, controller) = NewBridge();
- await bridge.DispatchAsync(new OscMessage { Address = "/teamsiso/stop-all" });
+ await bridge.DispatchAsync(new OscMessage { Address = "/Dragon-ISO/stop-all" });
controller.DisableCalls.Should().BeEmpty();
}
@@ -100,14 +100,14 @@ public sealed class OscBridgeDispatchTests : IDisposable
[Fact]
public async Task IsoByNameAddress_NoOpsWhenViewModelIsNull()
{
- // /teamsiso/iso "Jane" 1 — verifies the bail when no VM is
+ // /Dragon-ISO/iso "Jane" 1 — verifies the bail when no VM is
// wired; doesn't fire EnableIsoAsync. The dispatcher-equipped
// version of this round-trip lives in branch 11.
var (bridge, controller) = NewBridge();
await bridge.DispatchAsync(new OscMessage
{
- Address = "/teamsiso/iso",
+ Address = "/Dragon-ISO/iso",
TypeTag = ",sT",
Args = new object[] { "Jane", true },
});
diff --git a/src/tests/TeamsISO.App.Tests/Services/OscMessageTests.cs b/src/tests/Dragon-ISO.App.Tests/Services/OscMessageTests.cs
similarity index 92%
rename from src/tests/TeamsISO.App.Tests/Services/OscMessageTests.cs
rename to src/tests/Dragon-ISO.App.Tests/Services/OscMessageTests.cs
index be7361b..6a0eee1 100644
--- a/src/tests/TeamsISO.App.Tests/Services/OscMessageTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Services/OscMessageTests.cs
@@ -1,9 +1,9 @@
-using System.IO;
+using System.IO;
using System.Text;
using FluentAssertions;
-using TeamsISO.App.Services;
+using DragonISO.App.Services;
-namespace TeamsISO.App.Tests.Services;
+namespace DragonISO.App.Tests.Services;
///
/// Tests for the minimal OSC 1.0 parser inside .
@@ -22,7 +22,7 @@ public class OscMessageTests
[Fact]
public void TryParse_BundleMarker_ReturnsNull()
{
- // Bundles start with "#bundle\0..." — we don't support them.
+ // Bundles start with "#bundle\0..." — we don't support them.
var bytes = Encoding.ASCII.GetBytes("#bundle\0");
OscMessage.TryParse(bytes).Should().BeNull();
}
@@ -30,7 +30,7 @@ public class OscMessageTests
[Fact]
public void TryParse_AddressOnly_ParsesAddress()
{
- // "/foo\0\0\0\0" — 4-char address + null + 3 pad = 8 bytes
+ // "/foo\0\0\0\0" — 4-char address + null + 3 pad = 8 bytes
var bytes = OscPacket("/foo");
var msg = OscMessage.TryParse(bytes);
msg.Should().NotBeNull();
@@ -47,10 +47,10 @@ public class OscMessageTests
[Fact]
public void TryParse_StringArg_RoundTrips()
{
- var bytes = OscPacket("/teamsiso/iso", ",s", "Jane");
+ var bytes = OscPacket("/Dragon-ISO/iso", ",s", "Jane");
var msg = OscMessage.TryParse(bytes);
msg.Should().NotBeNull();
- msg!.Address.Should().Be("/teamsiso/iso");
+ msg!.Address.Should().Be("/Dragon-ISO/iso");
msg.GetStringArg(0).Should().Be("Jane");
}
@@ -118,7 +118,7 @@ public class OscMessageTests
[Fact]
public void TryParse_StringPlusInt_BothParse()
{
- var bytes = OscPacket("/teamsiso/iso", ",si", "Jane", 1);
+ var bytes = OscPacket("/Dragon-ISO/iso", ",si", "Jane", 1);
var msg = OscMessage.TryParse(bytes);
msg.Should().NotBeNull();
msg!.GetStringArg(0).Should().Be("Jane");
@@ -136,7 +136,7 @@ public class OscMessageTests
[Fact]
public void TryParse_MissingTypeTagComma_ReturnsNull()
{
- // Type tag must start with ','. "ix" has no leading comma — invalid.
+ // Type tag must start with ','. "ix" has no leading comma — invalid.
var bytes = OscPacket("/x", "ix");
OscMessage.TryParse(bytes).Should().BeNull();
}
@@ -190,7 +190,7 @@ public class OscMessageTests
case 's': WriteOscString(ms, (string)args[argIdx++]); break;
case 'T': case 'F': break; // no payload
default:
- // Unknown tag — emit no payload. Mirrors how a hostile sender
+ // Unknown tag — emit no payload. Mirrors how a hostile sender
// might construct a malformed packet; the parser should reject.
break;
}
diff --git a/src/tests/TeamsISO.App.Tests/Services/OutputNameTemplateTests.cs b/src/tests/Dragon-ISO.App.Tests/Services/OutputNameTemplateTests.cs
similarity index 80%
rename from src/tests/TeamsISO.App.Tests/Services/OutputNameTemplateTests.cs
rename to src/tests/Dragon-ISO.App.Tests/Services/OutputNameTemplateTests.cs
index 368952f..c197141 100644
--- a/src/tests/TeamsISO.App.Tests/Services/OutputNameTemplateTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Services/OutputNameTemplateTests.cs
@@ -1,7 +1,7 @@
-using FluentAssertions;
-using TeamsISO.App.Services;
+using FluentAssertions;
+using DragonISO.App.Services;
-namespace TeamsISO.App.Tests.Services;
+namespace DragonISO.App.Tests.Services;
///
/// Token-expansion + sanitization tests for .
@@ -18,9 +18,9 @@ public class OutputNameTemplateTests
public void Render_DefaultTemplate_RendersSpeakerDisplayName()
{
var name = OutputNameTemplate.Render(OutputNameTemplate.DefaultTemplate, TestId, "Jane");
- // Default is "{name}" since 0.9.0-rc19 — produces the speaker name
+ // Default is "{name}" since 0.9.0-rc19 — produces the speaker name
// directly so downstream switchers see human-readable identifiers.
- // Previously was "TEAMSISO_{guid}"; see DefaultTemplate's xmldoc.
+ // Previously was "Dragon-ISO_{guid}"; see DefaultTemplate's xmldoc.
name.Should().Be("Jane");
}
@@ -30,27 +30,27 @@ public class OutputNameTemplateTests
// The "{name}" default would render to an empty string for a
// participant with no display name yet (Teams sometimes delivers
// DisplayName a tick after the join event). The empty-name
- // fallback substitutes TEAMSISO_{guid} so the NDI sender is
+ // fallback substitutes Dragon-ISO_{guid} so the NDI sender is
// always uniquely identifiable. Without this, the engine would
// throw on an empty sender name.
var name = OutputNameTemplate.Render(OutputNameTemplate.DefaultTemplate, TestId, "");
- name.Should().Be("TEAMSISO_11223344");
+ name.Should().Be("Dragon-ISO_11223344");
}
[Fact]
public void Render_DefaultTemplate_WhitespaceName_FallsBackToGuidPrefix()
{
- // Mirror of the empty-name case — whitespace-only display names
+ // Mirror of the empty-name case — whitespace-only display names
// sanitize down to empty and should trigger the same fallback.
var name = OutputNameTemplate.Render(OutputNameTemplate.DefaultTemplate, TestId, " ");
- name.Should().Be("TEAMSISO_11223344");
+ name.Should().Be("Dragon-ISO_11223344");
}
[Fact]
public void Render_NameToken_UsesSanitizedDisplayName()
{
- var name = OutputNameTemplate.Render("TEAMSISO_{name}", TestId, "Jane Doe");
- name.Should().Be("TEAMSISO_Jane_Doe", because: "spaces become underscores in the sanitizer");
+ var name = OutputNameTemplate.Render("Dragon-ISO_{name}", TestId, "Jane Doe");
+ name.Should().Be("Dragon-ISO_Jane_Doe", because: "spaces become underscores in the sanitizer");
}
[Fact]
@@ -59,12 +59,12 @@ public class OutputNameTemplateTests
// NDI accepts more chars than we allow, but we keep it conservative
// (alphanumeric + underscore + hyphen + period). Anything else is dropped
// or converted to underscore (whitespace).
- var name = OutputNameTemplate.Render("{name}", TestId, "Jane (PM) — Lead!");
- // Expect: "Jane_PM__Lead" — parens dropped, em-dash dropped, exclamation dropped.
+ var name = OutputNameTemplate.Render("{name}", TestId, "Jane (PM) — Lead!");
+ // Expect: "Jane_PM__Lead" — parens dropped, em-dash dropped, exclamation dropped.
// Whitespace runs collapse into adjacent underscores.
name.Should().NotContain("(");
name.Should().NotContain(")");
- name.Should().NotContain("—");
+ name.Should().NotContain("—");
name.Should().NotContain("!");
name.Should().Contain("Jane");
name.Should().Contain("Lead");
@@ -84,7 +84,7 @@ public class OutputNameTemplateTests
// Sanitization may transform spaces in machine names, so just assert non-empty
// and that it contains the machine name's alphanumeric-ish chars.
name.Should().NotBeNullOrEmpty();
- // MachineName itself is sanitized in render — equality check would be brittle.
+ // MachineName itself is sanitized in render — equality check would be brittle.
}
[Fact]
@@ -92,7 +92,7 @@ public class OutputNameTemplateTests
{
var name = OutputNameTemplate.Render("session_{timestamp}", TestId, "Jane");
// yyyyMMdd_HHmmss is 15 chars + underscore separator = 16.
- // Combined with "session_" prefix → length should be at least 23.
+ // Combined with "session_" prefix → length should be at least 23.
name.Should().StartWith("session_");
name.Length.Should().BeGreaterThan("session_".Length + 14);
}
diff --git a/src/tests/TeamsISO.App.Tests/Services/PresetApplierTests.cs b/src/tests/Dragon-ISO.App.Tests/Services/PresetApplierTests.cs
similarity index 93%
rename from src/tests/TeamsISO.App.Tests/Services/PresetApplierTests.cs
rename to src/tests/Dragon-ISO.App.Tests/Services/PresetApplierTests.cs
index 95150f0..25d6583 100644
--- a/src/tests/TeamsISO.App.Tests/Services/PresetApplierTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Services/PresetApplierTests.cs
@@ -1,15 +1,15 @@
-using System.IO;
+using System.IO;
using FluentAssertions;
-using TeamsISO.App.Services;
-using TeamsISO.App.Tests.Fakes;
-using TeamsISO.App.ViewModels;
-using TeamsISO.Engine.Domain;
+using DragonISO.App.Services;
+using DragonISO.App.Tests.Fakes;
+using DragonISO.App.ViewModels;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.App.Tests.Services;
+namespace DragonISO.App.Tests.Services;
// PresetApplier reconciles a saved preset's per-display-name assignments
// against the live participant view-model list. Tests pin the four
-// transitions (enable→stay, disable→stay, off→enable, on→disable) plus
+// transitions (enable→stay, disable→stay, off→enable, on→disable) plus
// the partial-meeting path where the preset references participants
// who aren't currently present.
//
@@ -25,7 +25,7 @@ public sealed class PresetApplierTests : IDisposable
public PresetApplierTests()
{
- _tempPresets = Path.Combine(Path.GetTempPath(), $"teamsiso-presets-{Guid.NewGuid():N}.json");
+ _tempPresets = Path.Combine(Path.GetTempPath(), $"Dragon-ISO-presets-{Guid.NewGuid():N}.json");
_previousPresetOverride = OperatorPresetStore.PathOverride;
OperatorPresetStore.PathOverride = _tempPresets;
}
@@ -106,7 +106,7 @@ public sealed class PresetApplierTests : IDisposable
result.Matched.Should().Be(1);
result.Changed.Should().Be(0,
- "the participant is already enabled; preset says enabled — no controller traffic");
+ "the participant is already enabled; preset says enabled — no controller traffic");
controller.EnableCalls.Should().BeEmpty();
controller.DisableCalls.Should().BeEmpty();
}
diff --git a/src/tests/TeamsISO.App.Tests/Services/PresetStoreCollection.cs b/src/tests/Dragon-ISO.App.Tests/Services/PresetStoreCollection.cs
similarity index 75%
rename from src/tests/TeamsISO.App.Tests/Services/PresetStoreCollection.cs
rename to src/tests/Dragon-ISO.App.Tests/Services/PresetStoreCollection.cs
index 0428c82..743b4ea 100644
--- a/src/tests/TeamsISO.App.Tests/Services/PresetStoreCollection.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Services/PresetStoreCollection.cs
@@ -1,8 +1,8 @@
-namespace TeamsISO.App.Tests.Services;
+namespace DragonISO.App.Tests.Services;
///
/// Serializes any test class that mutates
-/// OperatorPresetStore.PathOverride — without this, xUnit runs
+/// OperatorPresetStore.PathOverride — without this, xUnit runs
/// fixtures in parallel across the assembly and a sibling class can
/// clobber the path mid-test, leading to flakes that look like data
/// corruption.
diff --git a/src/tests/TeamsISO.App.Tests/Services/ThemeManagerTests.cs b/src/tests/Dragon-ISO.App.Tests/Services/ThemeManagerTests.cs
similarity index 91%
rename from src/tests/TeamsISO.App.Tests/Services/ThemeManagerTests.cs
rename to src/tests/Dragon-ISO.App.Tests/Services/ThemeManagerTests.cs
index 1a02596..c582ed3 100644
--- a/src/tests/TeamsISO.App.Tests/Services/ThemeManagerTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Services/ThemeManagerTests.cs
@@ -1,9 +1,9 @@
-using FluentAssertions;
-using TeamsISO.App.Services;
+using FluentAssertions;
+using DragonISO.App.Services;
-namespace TeamsISO.App.Tests.Services;
+namespace DragonISO.App.Tests.Services;
-// Unit tests for ThemeManager — exercise the resolve / set / toggle
+// Unit tests for ThemeManager — exercise the resolve / set / toggle
// state machine behind the test-only constructor that takes stub seams
// instead of touching HKCU and %LOCALAPPDATA%. Apply() and the
// SystemEvents subscription are intentionally NOT exercised here:
@@ -51,7 +51,7 @@ public sealed class ThemeManagerTests
[Fact]
public void Toggle_FromSystemDark_PinsToOppositeOfCurrent()
{
- // System currently resolves to Dark → toggle should flip
+ // System currently resolves to Dark → toggle should flip
// *preference* to Light (the opposite of the currently-displayed
// theme), not back to System. The point of the click is a
// visible change.
@@ -96,7 +96,7 @@ public sealed class ThemeManagerTests
[Theory]
[InlineData("invalid")]
- [InlineData("dark")] // case-sensitive — we accept exactly Dark
+ [InlineData("dark")] // case-sensitive — we accept exactly Dark
[InlineData("LIGHT")]
[InlineData("")]
public void Set_RejectsInvalidPreferenceWithArgumentException(string bad)
@@ -124,7 +124,7 @@ public sealed class ThemeManagerTests
public void Constructor_DefaultsToSystem_WhenLoadReturnsInvalidValue()
{
// A prefs file written by a future version with an unknown
- // value mustn't poison the in-memory state — invalid loads
+ // value mustn't poison the in-memory state — invalid loads
// fall back to the default, same as a missing file.
var tm = NewManager(initialPreference: "Rainbow");
diff --git a/src/tests/TeamsISO.App.Tests/Services/UpdateCheckerTests.cs b/src/tests/Dragon-ISO.App.Tests/Services/UpdateCheckerTests.cs
similarity index 87%
rename from src/tests/TeamsISO.App.Tests/Services/UpdateCheckerTests.cs
rename to src/tests/Dragon-ISO.App.Tests/Services/UpdateCheckerTests.cs
index 4771b63..024f86e 100644
--- a/src/tests/TeamsISO.App.Tests/Services/UpdateCheckerTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Services/UpdateCheckerTests.cs
@@ -1,16 +1,16 @@
-using System.IO;
+using System.IO;
using FluentAssertions;
-using TeamsISO.App.Services;
+using DragonISO.App.Services;
-namespace TeamsISO.App.Tests.Services;
+namespace DragonISO.App.Tests.Services;
// UpdateChecker unit tests.
//
-// We don't exercise CheckAsync (the real HTTP call against Forgejo) —
+// We don't exercise CheckAsync (the real HTTP call against Forgejo) —
// tests must not depend on the network. Coverage instead:
-// • TryParseSemVer: version-comparison parsing across the inputs the
+// • TryParseSemVer: version-comparison parsing across the inputs the
// real release stream produces.
-// • CheckIfDueAsync throttle: a recent cooldown stamp short-circuits
+// • CheckIfDueAsync throttle: a recent cooldown stamp short-circuits
// and returns null *before* CheckAsync runs (which would otherwise
// fire an HTTP request).
public sealed class UpdateCheckerTests : IDisposable
@@ -20,7 +20,7 @@ public sealed class UpdateCheckerTests : IDisposable
public UpdateCheckerTests()
{
- _tempDir = Path.Combine(Path.GetTempPath(), $"teamsiso-update-{Guid.NewGuid():N}");
+ _tempDir = Path.Combine(Path.GetTempPath(), $"Dragon-ISO-update-{Guid.NewGuid():N}");
Directory.CreateDirectory(_tempDir);
_previousOverride = UpdateChecker.StateDirectoryOverride;
UpdateChecker.StateDirectoryOverride = _tempDir;
@@ -57,7 +57,7 @@ public sealed class UpdateCheckerTests : IDisposable
[Fact]
public void TryParseSemVer_OrderingIsSemantic()
{
- // The CheckAsync comparison is "latest > current" — pin the
+ // The CheckAsync comparison is "latest > current" — pin the
// ordering across the version arc the release process actually
// produces.
var older = UpdateChecker.TryParseSemVer("v0.1.0")!;
@@ -88,7 +88,7 @@ public sealed class UpdateCheckerTests : IDisposable
[Fact]
public async Task CheckIfDueAsync_ReturnsNull_WhenStampIsOldButCooldownIsLargerThanGap()
{
- // Edge case: stamp 1h old, cooldown 24h → still suppressed.
+ // Edge case: stamp 1h old, cooldown 24h → still suppressed.
File.WriteAllText(
Path.Combine(_tempDir, "last-update-check.txt"),
DateTimeOffset.UtcNow.AddHours(-1).ToString("o"));
@@ -101,7 +101,7 @@ public sealed class UpdateCheckerTests : IDisposable
[Fact]
public void LaunchCheckEnabled_RoundTrips()
{
- // Default (no flag file) → enabled.
+ // Default (no flag file) → enabled.
UpdateChecker.LaunchCheckEnabled.Should().BeTrue();
UpdateChecker.LaunchCheckEnabled = false;
diff --git a/src/tests/TeamsISO.App.Tests/Services/WindowStateStoreTests.cs b/src/tests/Dragon-ISO.App.Tests/Services/WindowStateStoreTests.cs
similarity index 86%
rename from src/tests/TeamsISO.App.Tests/Services/WindowStateStoreTests.cs
rename to src/tests/Dragon-ISO.App.Tests/Services/WindowStateStoreTests.cs
index e61aeda..f16c5ac 100644
--- a/src/tests/TeamsISO.App.Tests/Services/WindowStateStoreTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/Services/WindowStateStoreTests.cs
@@ -1,10 +1,10 @@
-using System.IO;
+using System.IO;
using System.Text.Json;
using System.Windows;
using FluentAssertions;
-using TeamsISO.App.Services;
+using DragonISO.App.Services;
-namespace TeamsISO.App.Tests.Services;
+namespace DragonISO.App.Tests.Services;
// Round-trip tests for WindowStateStore.Save / TryApply. Constructing a
// real WPF Window inside an xUnit fact is awkward (no Application.Run,
@@ -15,7 +15,7 @@ namespace TeamsISO.App.Tests.Services;
// shape WindowStateStore writes.
//
// The full Window.Left/Width property writes inside TryApply aren't
-// covered here — they require a WPF Window instance, which means an
+// covered here — they require a WPF Window instance, which means an
// Application.Current + dispatcher. We instead cover the bail paths
// (file missing, too-small, off-screen) which is where regressions
// typically land.
@@ -26,7 +26,7 @@ public sealed class WindowStateStoreTests : IDisposable
public WindowStateStoreTests()
{
- _tempPath = Path.Combine(Path.GetTempPath(), $"teamsiso-window-{Guid.NewGuid():N}.json");
+ _tempPath = Path.Combine(Path.GetTempPath(), $"Dragon-ISO-window-{Guid.NewGuid():N}.json");
_previousOverride = WindowStateStore.PathOverride;
WindowStateStore.PathOverride = _tempPath;
}
@@ -49,7 +49,7 @@ public sealed class WindowStateStoreTests : IDisposable
// Write a Snapshot record through the same JsonSerializer.Serialize
// call WindowStateStore.Save uses; read it back and verify all
// five fields survive. Coverage gap (Save's own Window reads)
- // intentional — see file header.
+ // intentional — see file header.
var snap = new WindowStateStore.Snapshot(
Left: 120, Top: 80, Width: 1024, Height: 768, State: WindowState.Maximized);
WriteSnapshot(_tempPath, snap);
@@ -72,7 +72,7 @@ public sealed class WindowStateStoreTests : IDisposable
// We can't construct a Window without STA; we *can* exercise
// the bail path that returns before any Window property is
// touched by passing null and catching the NRE through the
- // store's own try/catch — which makes TryApply return false.
+ // store's own try/catch — which makes TryApply return false.
var result = WindowStateStore.TryApply(null!);
result.Should().BeFalse();
@@ -81,7 +81,7 @@ public sealed class WindowStateStoreTests : IDisposable
[Fact]
public void TryApply_TooSmallSnapshot_RejectsBeforeTouchingWindow()
{
- // 100×100 is below the 320×240 floor. TryApply should return
+ // 100×100 is below the 320×240 floor. TryApply should return
// false without throwing on the null window.
WriteSnapshot(_tempPath, new WindowStateStore.Snapshot(0, 0, 100, 100, WindowState.Normal));
@@ -93,7 +93,7 @@ public sealed class WindowStateStoreTests : IDisposable
[Fact]
public void TryApply_AbsurdlyLargeSnapshot_RejectsBeforeTouchingWindow()
{
- // 20000×20000 is above the safety ceiling. Again no throw.
+ // 20000×20000 is above the safety ceiling. Again no throw.
WriteSnapshot(_tempPath, new WindowStateStore.Snapshot(0, 0, 20000, 20000, WindowState.Normal));
var result = WindowStateStore.TryApply(null!);
@@ -104,7 +104,7 @@ public sealed class WindowStateStoreTests : IDisposable
[Fact]
public void TryApply_FullyOffScreenSnapshot_RejectsBeforeTouchingWindow()
{
- // Way off the virtual screen — no corner falls inside any
+ // Way off the virtual screen — no corner falls inside any
// monitor's working area.
WriteSnapshot(_tempPath, new WindowStateStore.Snapshot(
Left: -99999, Top: -99999, Width: 800, Height: 600, State: WindowState.Normal));
diff --git a/src/tests/TeamsISO.App.Tests/ViewModels/CommandPaletteMatchesTests.cs b/src/tests/Dragon-ISO.App.Tests/ViewModels/CommandPaletteMatchesTests.cs
similarity index 88%
rename from src/tests/TeamsISO.App.Tests/ViewModels/CommandPaletteMatchesTests.cs
rename to src/tests/Dragon-ISO.App.Tests/ViewModels/CommandPaletteMatchesTests.cs
index 466bbd3..3577f87 100644
--- a/src/tests/TeamsISO.App.Tests/ViewModels/CommandPaletteMatchesTests.cs
+++ b/src/tests/Dragon-ISO.App.Tests/ViewModels/CommandPaletteMatchesTests.cs
@@ -1,14 +1,14 @@
-using FluentAssertions;
-using TeamsISO.App.ViewModels;
+using FluentAssertions;
+using DragonISO.App.ViewModels;
-namespace TeamsISO.App.Tests.ViewModels;
+namespace DragonISO.App.Tests.ViewModels;
-// Unit tests for the CommandPaletteViewModel.Matches predicate — the
+// Unit tests for the CommandPaletteViewModel.Matches predicate — the
// case-insensitive Contains check across Label / Category / Keywords
// that powers the v2 Ctrl+K filter.
//
// We don't build a full CommandPaletteViewModel here (that requires a
-// MainViewModel + IIsoController fake — out of scope). Matches is the
+// MainViewModel + IIsoController fake — out of scope). Matches is the
// behaviorally-relevant unit; pinning it across a representative
// query set guards against accidental regressions when someone adds a
// scoring algorithm or swaps Contains for StartsWith.
@@ -18,19 +18,19 @@ public sealed class CommandPaletteMatchesTests
new(category, label, keywords, Shortcut: null, Invoke: () => { });
[Theory]
- // Label substrings — the dominant match path
+ // Label substrings — the dominant match path
[InlineData("Quick", "Stop all ISOs", null, "stop", true)]
[InlineData("Quick", "Stop all ISOs", null, "STOP", true)] // case-insensitive
[InlineData("Quick", "Stop all ISOs", null, "all", true)]
[InlineData("Quick", "Stop all ISOs", null, "ISO", true)]
- // Category match — operator types the section name
+ // Category match — operator types the section name
[InlineData("Teams", "Mute / unmute", null, "teams", true)]
[InlineData("App", "Help", null, "app", true)]
- // Keywords match — synonym path. The Network/topology command has
+ // Keywords match — synonym path. The Network/topology command has
// "ndi groups isolate" in its keywords blob.
[InlineData("Network", "Apply transcoder topology", "ndi groups isolate", "ndi", true)]
[InlineData("Network", "Apply transcoder topology", "ndi groups isolate", "isolate", true)]
- // No-match — none of label/category/keywords contain the query
+ // No-match — none of label/category/keywords contain the query
[InlineData("Quick", "Stop all ISOs", null, "espresso", false)]
[InlineData("Teams", "Mute / unmute", "microphone audio toggle", "monitor", false)]
public void Matches_Predicate(string category, string label, string? keywords, string query, bool expected)
@@ -43,7 +43,7 @@ public sealed class CommandPaletteMatchesTests
public void Matches_OperatorTypingShortToken_HitsExpectedCategorySpread()
{
// "mute" should match the Teams command but not the App theme
- // commands — pins the cross-category selectivity that makes
+ // commands — pins the cross-category selectivity that makes
// the palette useful at all. If a future change makes Matches
// too permissive (e.g. by indexing the Invoke delegate's
// method name), the second assertion catches it.
@@ -70,7 +70,7 @@ public sealed class CommandPaletteMatchesTests
Cmd("Teams", "Mute / unmute", "microphone audio silence toggle"),
Cmd("Teams", "Toggle camera", "video webcam on off"),
Cmd("Teams", "Leave call", "exit end disconnect quit"),
- Cmd("Network", "Apply transcoder topology", "ndi groups isolate teamsiso-input private"),
+ Cmd("Network", "Apply transcoder topology", "ndi groups isolate Dragon-ISO-input private"),
Cmd("App", "Theme: dark", "appearance night mode"),
Cmd("App", "Theme: light", "appearance day mode bright"),
Cmd("App", "Theme: follow Windows", "system auto"),
@@ -83,7 +83,7 @@ public sealed class CommandPaletteMatchesTests
Hits("stop").Should().Be(1);
Hits("ndi").Should().Be(2, "Refresh discovery (NDI in keywords) + Apply transcoder topology");
// "App" matches case-insensitively against the four App-category
- // commands AND substring-matches inside "Apply transcoder topology" —
+ // commands AND substring-matches inside "Apply transcoder topology" —
// a real operator typing "app" would see five rows, which is
// exactly what Contains delivers. Pinning this so a future move
// to a stricter (StartsWith / token-boundary) algorithm has to
diff --git a/src/tests/TeamsISO.Engine.IntegrationTests/TeamsISO.Engine.IntegrationTests.csproj b/src/tests/Dragon-ISO.Engine.IntegrationTests/Dragon-ISO.Engine.IntegrationTests.csproj
similarity index 74%
rename from src/tests/TeamsISO.Engine.IntegrationTests/TeamsISO.Engine.IntegrationTests.csproj
rename to src/tests/Dragon-ISO.Engine.IntegrationTests/Dragon-ISO.Engine.IntegrationTests.csproj
index b85c9ae..f7daf1a 100644
--- a/src/tests/TeamsISO.Engine.IntegrationTests/TeamsISO.Engine.IntegrationTests.csproj
+++ b/src/tests/Dragon-ISO.Engine.IntegrationTests/Dragon-ISO.Engine.IntegrationTests.csproj
@@ -1,29 +1,29 @@
-
-
-
- net8.0
- enable
- enable
-
- false
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/tests/TeamsISO.Engine.IntegrationTests/IntegrationTestsScaffold.cs b/src/tests/Dragon-ISO.Engine.IntegrationTests/IntegrationTestsScaffold.cs
similarity index 82%
rename from src/tests/TeamsISO.Engine.IntegrationTests/IntegrationTestsScaffold.cs
rename to src/tests/Dragon-ISO.Engine.IntegrationTests/IntegrationTestsScaffold.cs
index 05ebdf6..f658279 100644
--- a/src/tests/TeamsISO.Engine.IntegrationTests/IntegrationTestsScaffold.cs
+++ b/src/tests/Dragon-ISO.Engine.IntegrationTests/IntegrationTestsScaffold.cs
@@ -1,13 +1,13 @@
-using System.Runtime.Versioning;
+using System.Runtime.Versioning;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
-using TeamsISO.Engine.Interop;
-using TeamsISO.Engine.NdiInterop;
+using DragonISO.Engine.Interop;
+using DragonISO.Engine.NdiInterop;
-namespace TeamsISO.Engine.IntegrationTests;
+namespace DragonISO.Engine.IntegrationTests;
///
-/// Integration tests that talk to a real NDI runtime — gated behind
+/// Integration tests that talk to a real NDI runtime — gated behind
/// requires=ndi so the default CI run skips them. Run locally with:
/// dotnet test --filter requires=ndi
///
@@ -44,7 +44,7 @@ public class NdiInteropIntegrationTests
using (var finder = interop.CreateFinder())
{
finder.Should().NotBeNull(because: "default-group finder must construct successfully");
- // Snapshot any visible sources — exercises the path; we don't assert on count
+ // Snapshot any visible sources — exercises the path; we don't assert on count
// because the test environment's NDI sources are unknowable.
_ = interop.GetCurrentSources(finder);
}
@@ -52,9 +52,9 @@ public class NdiInteropIntegrationTests
[Theory]
[Trait("requires", "ndi")]
- [InlineData("teamsiso-test-input")]
- [InlineData("teamsiso-test-input,production")]
- [InlineData(" teamsiso-test-input ")]
+ [InlineData("Dragon-ISO-test-input")]
+ [InlineData("Dragon-ISO-test-input,production")]
+ [InlineData(" Dragon-ISO-test-input ")]
public void Finder_CustomGroups_DoesNotThrow(string groups)
{
using var interop = NewInterop();
@@ -74,7 +74,7 @@ public class NdiInteropIntegrationTests
{
using var interop = NewInterop();
- using (var sender = interop.CreateSender("TEAMSISO_TEST_DEFAULT"))
+ using (var sender = interop.CreateSender("Dragon-ISO_TEST_DEFAULT"))
{
sender.Should().NotBeNull();
}
@@ -86,7 +86,7 @@ public class NdiInteropIntegrationTests
{
using var interop = NewInterop();
- using (var sender = interop.CreateSender("TEAMSISO_TEST_GROUPED", "teamsiso-test-output"))
+ using (var sender = interop.CreateSender("Dragon-ISO_TEST_GROUPED", "Dragon-ISO-test-output"))
{
sender.Should().NotBeNull();
}
@@ -101,7 +101,7 @@ public class NdiInteropIntegrationTests
// network-layer regressions (firewall, mDNS, multicast disable).
using var interop = NewInterop();
- var uniqueName = $"TEAMSISO_LOOP_{Guid.NewGuid().ToString("N")[..8].ToUpperInvariant()}";
+ var uniqueName = $"Dragon-ISO_LOOP_{Guid.NewGuid().ToString("N")[..8].ToUpperInvariant()}";
using var sender = interop.CreateSender(uniqueName);
using var finder = interop.CreateFinder();
diff --git a/src/tests/TeamsISO.Engine.IntegrationTests/PipelineFrameRoundTripTests.cs b/src/tests/Dragon-ISO.Engine.IntegrationTests/PipelineFrameRoundTripTests.cs
similarity index 70%
rename from src/tests/TeamsISO.Engine.IntegrationTests/PipelineFrameRoundTripTests.cs
rename to src/tests/Dragon-ISO.Engine.IntegrationTests/PipelineFrameRoundTripTests.cs
index 0f8c84e..66c3a15 100644
--- a/src/tests/TeamsISO.Engine.IntegrationTests/PipelineFrameRoundTripTests.cs
+++ b/src/tests/Dragon-ISO.Engine.IntegrationTests/PipelineFrameRoundTripTests.cs
@@ -1,18 +1,18 @@
-using System.Runtime.Versioning;
+using System.Runtime.Versioning;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
-using TeamsISO.Engine.Domain;
-using TeamsISO.Engine.NdiInterop;
-using TeamsISO.Engine.Pipeline;
+using DragonISO.Engine.Domain;
+using DragonISO.Engine.NdiInterop;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.Engine.IntegrationTests;
+namespace DragonISO.Engine.IntegrationTests;
///
/// End-to-end pipeline test: synthesize a fake Teams source, run an
/// against it, and assert the resulting normalized
/// output stream yields frames at the configured 1080p target size. This is
/// the closest unit-test analog to "did the engine actually do its job?"
-/// — exercises NdiReceiver, FrameProcessor, ManagedNearestNeighborFrameScaler,
+/// — exercises NdiReceiver, FrameProcessor, ManagedNearestNeighborFrameScaler,
/// and NdiSender as a single chain through the production P/Invoke shim.
///
/// Marked [Trait("requires","ndi")] so default CI skips it; run locally with
@@ -25,13 +25,13 @@ public class PipelineFrameRoundTripTests
[Trait("requires", "ndi")]
public async Task Pipeline_ReceivesFromTeamsLikeSource_AndEmitsAt1080pTarget()
{
- // ─── 1. Source pump ─────────────────────────────────────────────────
+ // ─── 1. Source pump ─────────────────────────────────────────────────
// Spin up an NDI sender broadcasting an unambiguous, unique source
// name. We use the literal "Teams - " form so this works even
// if a parallel test happens to be running at the same time.
var token = Guid.NewGuid().ToString("N")[..6].ToUpperInvariant();
var sourceShortName = $"Teams - FrameRT_{token}";
- var outputName = $"TEAMSISO_RT_{token}";
+ var outputName = $"Dragon-ISO_RT_{token}";
using var interop = new NdiInteropPInvoke(NullLogger.Instance);
using var fakeSender = interop.CreateSender(sourceShortName);
@@ -40,14 +40,14 @@ public class PipelineFrameRoundTripTests
// something obviously-not-zero to pick up. Pump at ~30 fps; the engine
// is configured for 59.94 fps target so it'll either re-emit our
// frames (slate threshold not yet reached) or interpolate via the
- // last-frame re-emit path — either is fine for the dimensions check.
+ // last-frame re-emit path — either is fine for the dimensions check.
const int srcW = 640, srcH = 360;
var pixelBuffer = new byte[srcW * srcH * 4];
for (var i = 0; i < pixelBuffer.Length; i += 4)
{
pixelBuffer[i + 0] = 0xF0; // B
pixelBuffer[i + 1] = 0xED; // G
- pixelBuffer[i + 2] = 0x97; // R → ~Wild Dragon cyan #97EDF0 in BGRA
+ pixelBuffer[i + 2] = 0x97; // R → ~Wild Dragon cyan #97EDF0 in BGRA
pixelBuffer[i + 3] = 0xFF; // A
}
@@ -66,13 +66,13 @@ public class PipelineFrameRoundTripTests
try
{
- // ─── 2. Wait for our fake source to be discoverable ─────────────
+ // ─── 2. Wait for our fake source to be discoverable ─────────────
using var finder = interop.CreateFinder();
var fullSourceName = await WaitForSourceAsync(interop, finder, sourceShortName, TimeSpan.FromSeconds(5));
fullSourceName.Should().NotBeNullOrEmpty(
because: "fake Teams sender should be visible to a same-process finder within 5s");
- // ─── 3. Build the production IsoPipeline against it ────────────
+ // ─── 3. Build the production IsoPipeline against it ────────────
var settings = FrameProcessingSettings.Default; // 1080p, 59.94 fps, Pillarbox
var clock = new PeriodicTimerFrameClock(settings.FramerateHz);
var scaler = new ManagedNearestNeighborFrameScaler();
@@ -85,12 +85,12 @@ public class PipelineFrameRoundTripTests
NullLoggerFactory.Instance);
await pipeline.StartAsync();
- // ─── 4. Wait for the pipeline's output sender to appear ────────
+ // ─── 4. Wait for the pipeline's output sender to appear ────────
var outputFullName = await WaitForSourceAsync(interop, finder, outputName, TimeSpan.FromSeconds(5));
outputFullName.Should().NotBeNullOrEmpty(
- because: "IsoPipeline must broadcast a TEAMSISO_* sender within 5s of StartAsync");
+ because: "IsoPipeline must broadcast a Dragon-ISO_* sender within 5s of StartAsync");
- // ─── 5. Receive a frame from the normalized output ─────────────
+ // ─── 5. Receive a frame from the normalized output ─────────────
using var receiver = interop.CreateReceiver(outputFullName!);
RawFrame? captured = null;
var captureDeadline = DateTime.UtcNow.AddSeconds(8);
@@ -104,13 +104,13 @@ public class PipelineFrameRoundTripTests
captured.Should().NotBeNull(
because: "the pipeline output must yield at least one normalized frame within 8s");
- // ─── 6. Assert the normalized dimensions match the target ──────
+ // ─── 6. Assert the normalized dimensions match the target ──────
var (expectedW, expectedH) = settings.ResolutionSize;
captured!.Width.Should().Be(expectedW,
because: $"the pipeline normalizes to {expectedW}x{expectedH} per FrameProcessingSettings.Default");
captured.Height.Should().Be(expectedH);
- // ─── 7. Stop pipeline cleanly ──────────────────────────────────
+ // ─── 7. Stop pipeline cleanly ──────────────────────────────────
await pipeline.StopAsync();
}
finally
@@ -128,7 +128,7 @@ public class PipelineFrameRoundTripTests
///
private static async Task WaitForSourceAsync(
NdiInteropPInvoke interop,
- TeamsISO.Engine.Interop.NdiFindHandle finder,
+ DragonISO.Engine.Interop.NdiFindHandle finder,
string needle,
TimeSpan timeout)
{
diff --git a/src/tests/TeamsISO.Engine.Tests/Controller/IsoControllerTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Controller/IsoControllerTests.cs
similarity index 89%
rename from src/tests/TeamsISO.Engine.Tests/Controller/IsoControllerTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Controller/IsoControllerTests.cs
index 700e3ee..1a12319 100644
--- a/src/tests/TeamsISO.Engine.Tests/Controller/IsoControllerTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Controller/IsoControllerTests.cs
@@ -1,13 +1,13 @@
-using System.Reactive.Linq;
+using System.Reactive.Linq;
using Microsoft.Extensions.Logging.Abstractions;
-using TeamsISO.Engine.Controller;
-using TeamsISO.Engine.Domain;
-using TeamsISO.Engine.Interop;
-using TeamsISO.Engine.Persistence;
-using TeamsISO.Engine.Pipeline;
-using TeamsISO.Engine.Tests.Fakes;
+using DragonISO.Engine.Controller;
+using DragonISO.Engine.Domain;
+using DragonISO.Engine.Interop;
+using DragonISO.Engine.Persistence;
+using DragonISO.Engine.Pipeline;
+using DragonISO.Engine.Tests.Fakes;
-namespace TeamsISO.Engine.Tests.Controller;
+namespace DragonISO.Engine.Tests.Controller;
public class IsoControllerTests : IDisposable
{
@@ -21,7 +21,7 @@ public class IsoControllerTests : IDisposable
public IsoControllerTests()
{
- _dir = Path.Combine(Path.GetTempPath(), $"teamsiso-controller-{Guid.NewGuid():N}");
+ _dir = Path.Combine(Path.GetTempPath(), $"Dragon-ISO-controller-{Guid.NewGuid():N}");
Directory.CreateDirectory(_dir);
_store = new ConfigStore(Path.Combine(_dir, "config.json"), NullLogger.Instance);
_interop = new FakeNdiInterop { RuntimeVersion = "6.0.0" };
@@ -83,10 +83,10 @@ public class IsoControllerTests : IDisposable
_interop.Sources.Add("PC1 (Teams - Jane)");
var pid = await WaitForFirstParticipantAsync(controller);
- await controller.EnableIsoAsync(pid, customName: "TEAMSISO_JANE", CancellationToken.None);
+ await controller.EnableIsoAsync(pid, customName: "Dragon-ISO_JANE", CancellationToken.None);
_factoryCalls.Should().HaveCount(1);
- _factoryCalls[0].OutputName.Should().Be("TEAMSISO_JANE");
+ _factoryCalls[0].OutputName.Should().Be("Dragon-ISO_JANE");
_factoryCalls[0].SourceName.Should().Be("PC1 (Teams - Jane)");
}
@@ -130,12 +130,12 @@ public class IsoControllerTests : IDisposable
_store.Save(new EngineConfig(
FrameProcessingSettings.Default,
Array.Empty(),
- new NdiGroupSettings(DiscoveryGroups: "teamsiso-input", OutputGroups: null)));
+ new NdiGroupSettings(DiscoveryGroups: "Dragon-ISO-input", OutputGroups: null)));
await using var controller = NewController();
- _interop.LastFinderGroups.Should().Be("teamsiso-input");
- controller.GroupSettings.DiscoveryGroups.Should().Be("teamsiso-input");
+ _interop.LastFinderGroups.Should().Be("Dragon-ISO-input");
+ controller.GroupSettings.DiscoveryGroups.Should().Be("Dragon-ISO-input");
}
[Fact]
@@ -162,7 +162,7 @@ public class IsoControllerTests : IDisposable
public async Task SetGroupSettingsAsync_PersistsToConfigStore()
{
await using var controller = NewController();
- var newGroups = new NdiGroupSettings(DiscoveryGroups: "teamsiso-input", OutputGroups: "Public");
+ var newGroups = new NdiGroupSettings(DiscoveryGroups: "Dragon-ISO-input", OutputGroups: "Public");
await controller.SetGroupSettingsAsync(newGroups, CancellationToken.None);
@@ -204,7 +204,7 @@ public class IsoControllerTests : IDisposable
[Fact]
public async Task AddRecordingMarker_NoOpsCleanly_WhenNoActiveRecorders()
{
- // No pipelines have ever started → no recorders are attached.
+ // No pipelines have ever started → no recorders are attached.
// AddRecordingMarker must not throw on the empty-recorder path
// (the UI Ctrl+M binding fires regardless of recording state).
await using var controller = NewController();
@@ -235,7 +235,7 @@ public class IsoControllerTests : IDisposable
var emitsBefore = seenLists.Count;
- // Trigger a refresh — the discovery loop should re-emit. We
+ // Trigger a refresh — the discovery loop should re-emit. We
// don't care exactly how many emissions land, just that the
// observable kept producing rather than stalling.
controller.RefreshDiscovery();
diff --git a/src/tests/TeamsISO.Engine.Tests/Discovery/NdiDiscoveryServiceTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Discovery/NdiDiscoveryServiceTests.cs
similarity index 92%
rename from src/tests/TeamsISO.Engine.Tests/Discovery/NdiDiscoveryServiceTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Discovery/NdiDiscoveryServiceTests.cs
index a8527aa..fb13c11 100644
--- a/src/tests/TeamsISO.Engine.Tests/Discovery/NdiDiscoveryServiceTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Discovery/NdiDiscoveryServiceTests.cs
@@ -1,9 +1,9 @@
-using System.Threading.Channels;
+using System.Threading.Channels;
using Microsoft.Extensions.Logging.Abstractions;
-using TeamsISO.Engine.Discovery;
-using TeamsISO.Engine.Tests.Fakes;
+using DragonISO.Engine.Discovery;
+using DragonISO.Engine.Tests.Fakes;
-namespace TeamsISO.Engine.Tests.Discovery;
+namespace DragonISO.Engine.Tests.Discovery;
public class NdiDiscoveryServiceTests
{
@@ -68,7 +68,7 @@ public class NdiDiscoveryServiceTests
}
// ============================================================
- // ShouldAutoRebuild — pure function gating the auto-heal path
+ // ShouldAutoRebuild — pure function gating the auto-heal path
// ============================================================
//
// Two rules under test:
@@ -101,7 +101,7 @@ public class NdiDiscoveryServiceTests
[Fact]
public void ShouldAutoRebuild_NeverSeenSource_RecentRebuild_HoldsOff()
{
- // sinceStart qualifies, but the last rebuild was 2s ago — back off.
+ // sinceStart qualifies, but the last rebuild was 2s ago — back off.
NdiDiscoveryService.ShouldAutoRebuild(
sinceStart: TimeSpan.FromSeconds(20),
sinceLastSeen: null,
@@ -122,7 +122,7 @@ public class NdiDiscoveryServiceTests
[Fact]
public void ShouldAutoRebuild_HadSources_NowEmpty_Recently_HoldsOff()
{
- // 10s since last source seen — still inside the 15s grace window.
+ // 10s since last source seen — still inside the 15s grace window.
NdiDiscoveryService.ShouldAutoRebuild(
sinceStart: TimeSpan.FromMinutes(5),
sinceLastSeen: TimeSpan.FromSeconds(10),
@@ -133,7 +133,7 @@ public class NdiDiscoveryServiceTests
[Fact]
public void ShouldAutoRebuild_HadSources_NowEmpty_RecentRebuild_HoldsOff()
{
- // Grace window expired, but we just rebuilt 8s ago — back off.
+ // Grace window expired, but we just rebuilt 8s ago — back off.
NdiDiscoveryService.ShouldAutoRebuild(
sinceStart: TimeSpan.FromMinutes(5),
sinceLastSeen: TimeSpan.FromSeconds(30),
diff --git a/src/tests/TeamsISO.Engine.Tests/Discovery/ParticipantTrackerTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Discovery/ParticipantTrackerTests.cs
similarity index 98%
rename from src/tests/TeamsISO.Engine.Tests/Discovery/ParticipantTrackerTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Discovery/ParticipantTrackerTests.cs
index e9268b0..fca5a52 100644
--- a/src/tests/TeamsISO.Engine.Tests/Discovery/ParticipantTrackerTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Discovery/ParticipantTrackerTests.cs
@@ -1,7 +1,7 @@
-using TeamsISO.Engine.Discovery;
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Discovery;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Tests.Discovery;
+namespace DragonISO.Engine.Tests.Discovery;
public class ParticipantTrackerTests
{
@@ -142,7 +142,7 @@ public class ParticipantTrackerTests
// Regression for the discovery-refresh path: when the operator clicks "Refresh"
// we deliberately re-emit Added events for sources that were already known
// (clearing the discovery service's seen-set so it re-fires everything coming
- // back from the rebuilt finder). The tracker must coalesce these — minting a
+ // back from the rebuilt finder). The tracker must coalesce these — minting a
// new Guid would orphan the operator's running ISO and visibly duplicate the
// row in the participants list.
var time = T0;
diff --git a/src/tests/TeamsISO.Engine.Tests/Domain/EnumSanityTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Domain/EnumSanityTests.cs
similarity index 92%
rename from src/tests/TeamsISO.Engine.Tests/Domain/EnumSanityTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Domain/EnumSanityTests.cs
index 1af3d28..e8afb16 100644
--- a/src/tests/TeamsISO.Engine.Tests/Domain/EnumSanityTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Domain/EnumSanityTests.cs
@@ -1,6 +1,6 @@
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Tests.Domain;
+namespace DragonISO.Engine.Tests.Domain;
public class EnumSanityTests
{
diff --git a/src/tests/TeamsISO.Engine.Tests/Domain/NdiSourceParserTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Domain/NdiSourceParserTests.cs
similarity index 91%
rename from src/tests/TeamsISO.Engine.Tests/Domain/NdiSourceParserTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Domain/NdiSourceParserTests.cs
index d9f21f3..8e94111 100644
--- a/src/tests/TeamsISO.Engine.Tests/Domain/NdiSourceParserTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Domain/NdiSourceParserTests.cs
@@ -1,14 +1,14 @@
-using TeamsISO.Engine.Discovery;
-using TeamsISO.Engine.Domain;
+using DragonISO.Engine.Discovery;
+using DragonISO.Engine.Domain;
-namespace TeamsISO.Engine.Tests.Domain;
+namespace DragonISO.Engine.Tests.Domain;
public class NdiSourceParserTests
{
[Theory]
// ----- Legacy "Teams" brand (older Teams desktop) -----
[InlineData("WORKSTATION-01 (Teams - Jane Doe)", "WORKSTATION-01", NdiSourceKind.Participant, "Jane Doe")]
- [InlineData("PROD-PC (Teams - Élise O'Connor)", "PROD-PC", NdiSourceKind.Participant, "Élise O'Connor")]
+ [InlineData("PROD-PC (Teams - Élise O'Connor)", "PROD-PC", NdiSourceKind.Participant, "Élise O'Connor")]
[InlineData("HOST (Teams - Smith, Bob (PM))", "HOST", NdiSourceKind.Participant, "Smith, Bob (PM)")]
// ----- Current "MS Teams" brand (the new Teams desktop client) -----
[InlineData("WOOGLIN (MS Teams - Brendon Power)", "WOOGLIN", NdiSourceKind.Participant, "Brendon Power")]
diff --git a/src/tests/TeamsISO.Engine.Tests/TeamsISO.Engine.Tests.csproj b/src/tests/Dragon-ISO.Engine.Tests/Dragon-ISO.Engine.Tests.csproj
similarity index 74%
rename from src/tests/TeamsISO.Engine.Tests/TeamsISO.Engine.Tests.csproj
rename to src/tests/Dragon-ISO.Engine.Tests/Dragon-ISO.Engine.Tests.csproj
index d4e0928..e543fd9 100644
--- a/src/tests/TeamsISO.Engine.Tests/TeamsISO.Engine.Tests.csproj
+++ b/src/tests/Dragon-ISO.Engine.Tests/Dragon-ISO.Engine.Tests.csproj
@@ -1,34 +1,34 @@
-
-
-
- net8.0
- enable
- enable
-
- false
- true
-
-
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/tests/TeamsISO.Engine.Tests/Fakes/FakeFrameClock.cs b/src/tests/Dragon-ISO.Engine.Tests/Fakes/FakeFrameClock.cs
similarity index 93%
rename from src/tests/TeamsISO.Engine.Tests/Fakes/FakeFrameClock.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Fakes/FakeFrameClock.cs
index e28c94c..b003e51 100644
--- a/src/tests/TeamsISO.Engine.Tests/Fakes/FakeFrameClock.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Fakes/FakeFrameClock.cs
@@ -1,6 +1,6 @@
-using TeamsISO.Engine.Pipeline;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.Engine.Tests.Fakes;
+namespace DragonISO.Engine.Tests.Fakes;
///
/// Manual-tick clock. Tests advance the clock and trigger the awaiter explicitly.
diff --git a/src/tests/TeamsISO.Engine.Tests/Fakes/FakeNdiInterop.cs b/src/tests/Dragon-ISO.Engine.Tests/Fakes/FakeNdiInterop.cs
similarity index 94%
rename from src/tests/TeamsISO.Engine.Tests/Fakes/FakeNdiInterop.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Fakes/FakeNdiInterop.cs
index 394745c..f5e35bb 100644
--- a/src/tests/TeamsISO.Engine.Tests/Fakes/FakeNdiInterop.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Fakes/FakeNdiInterop.cs
@@ -1,8 +1,8 @@
-using System.Collections.Concurrent;
-using TeamsISO.Engine.Interop;
-using TeamsISO.Engine.Pipeline;
+using System.Collections.Concurrent;
+using DragonISO.Engine.Interop;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.Engine.Tests.Fakes;
+namespace DragonISO.Engine.Tests.Fakes;
///
/// In-memory test double for . Tests configure source lists and frame
@@ -51,7 +51,7 @@ public sealed class FakeNdiInterop : INdiInterop
var key = ((FakeReceiverHandle)receiver).Source;
if (ReceiverAudioPeaks.TryGetValue(key, out var q) && q.TryDequeue(out var peak))
return peak;
- return null; // no audio queued — simulate timeout
+ return null; // no audio queued — simulate timeout
}
public NdiSenderHandle CreateSender(string outputName, string? groups = null)
diff --git a/src/tests/TeamsISO.Engine.Tests/GlobalUsings.cs b/src/tests/Dragon-ISO.Engine.Tests/GlobalUsings.cs
similarity index 100%
rename from src/tests/TeamsISO.Engine.Tests/GlobalUsings.cs
rename to src/tests/Dragon-ISO.Engine.Tests/GlobalUsings.cs
diff --git a/src/tests/TeamsISO.Engine.Tests/Interop/NdiInteropNormalizeGroupsTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Interop/NdiInteropNormalizeGroupsTests.cs
similarity index 60%
rename from src/tests/TeamsISO.Engine.Tests/Interop/NdiInteropNormalizeGroupsTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Interop/NdiInteropNormalizeGroupsTests.cs
index f36a4ed..792c348 100644
--- a/src/tests/TeamsISO.Engine.Tests/Interop/NdiInteropNormalizeGroupsTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Interop/NdiInteropNormalizeGroupsTests.cs
@@ -1,18 +1,18 @@
-using System.Runtime.Versioning;
-using TeamsISO.Engine.NdiInterop;
+using System.Runtime.Versioning;
+using DragonISO.Engine.NdiInterop;
-namespace TeamsISO.Engine.Tests.Interop;
+namespace DragonISO.Engine.Tests.Interop;
// NdiInteropPInvoke is marked [SupportedOSPlatform("windows")] because it
// P/Invokes the Windows-only NDI runtime. The pure NormalizeGroups helper
// doesn't actually touch native code, but it inherits the platform tag from
// the enclosing class. Re-declaring SupportedOSPlatform here silences CA1416
-// — these tests still only run on Windows (the Engine.Tests project itself
+// — these tests still only run on Windows (the Engine.Tests project itself
// is platform-agnostic but xunit only schedules them when the OS supports).
[SupportedOSPlatform("windows")]
// NdiInteropPInvoke.NormalizeGroups is internal; the engine tests project has
-// access via InternalsVisibleTo applied to TeamsISO.Engine.NdiInterop.
+// access via InternalsVisibleTo applied to DragonISO.Engine.NdiInterop.
public class NdiInteropNormalizeGroupsTests
{
[Theory]
@@ -23,11 +23,11 @@ public class NdiInteropNormalizeGroupsTests
[InlineData("public", "Public")] // lowercase -> canonical (the bug fix)
[InlineData("PUBLIC", "Public")] // shouty -> canonical
[InlineData("PuBlIc", "Public")] // mixed case -> canonical
- [InlineData("teamsiso-input", "teamsiso-input")] // custom group: pass through
- [InlineData("Public,teamsiso-input", "Public,teamsiso-input")]
- [InlineData("public,teamsiso-input", "Public,teamsiso-input")] // mixed list normalizes the standard one only
- [InlineData("teamsiso-input,PUBLIC", "teamsiso-input,Public")]
- [InlineData(" public , teamsiso-input ", "Public,teamsiso-input")] // whitespace trimmed per part
+ [InlineData("Dragon-ISO-input", "Dragon-ISO-input")] // custom group: pass through
+ [InlineData("Public,Dragon-ISO-input", "Public,Dragon-ISO-input")]
+ [InlineData("public,Dragon-ISO-input", "Public,Dragon-ISO-input")] // mixed list normalizes the standard one only
+ [InlineData("Dragon-ISO-input,PUBLIC", "Dragon-ISO-input,Public")]
+ [InlineData(" public , Dragon-ISO-input ", "Public,Dragon-ISO-input")] // whitespace trimmed per part
public void NormalizeGroups_Maps(string? input, string? expected)
{
NdiInteropPInvoke.NormalizeGroups(input).Should().Be(expected);
diff --git a/src/tests/TeamsISO.Engine.Tests/Interop/NdiRuntimeProbeTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Interop/NdiRuntimeProbeTests.cs
similarity index 88%
rename from src/tests/TeamsISO.Engine.Tests/Interop/NdiRuntimeProbeTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Interop/NdiRuntimeProbeTests.cs
index c4d9258..b989b5f 100644
--- a/src/tests/TeamsISO.Engine.Tests/Interop/NdiRuntimeProbeTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Interop/NdiRuntimeProbeTests.cs
@@ -1,7 +1,7 @@
-using TeamsISO.Engine.Interop;
-using TeamsISO.Engine.Tests.Fakes;
+using DragonISO.Engine.Interop;
+using DragonISO.Engine.Tests.Fakes;
-namespace TeamsISO.Engine.Tests.Interop;
+namespace DragonISO.Engine.Tests.Interop;
public class NdiRuntimeProbeTests
{
diff --git a/src/tests/TeamsISO.Engine.Tests/Logging/EngineLoggingTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Logging/EngineLoggingTests.cs
similarity index 90%
rename from src/tests/TeamsISO.Engine.Tests/Logging/EngineLoggingTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Logging/EngineLoggingTests.cs
index 5c949bc..5585450 100644
--- a/src/tests/TeamsISO.Engine.Tests/Logging/EngineLoggingTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Logging/EngineLoggingTests.cs
@@ -1,8 +1,8 @@
-using FluentAssertions;
+using FluentAssertions;
using Microsoft.Extensions.Logging;
-using TeamsISO.Engine.Logging;
+using DragonISO.Engine.Logging;
-namespace TeamsISO.Engine.Tests.Logging;
+namespace DragonISO.Engine.Tests.Logging;
public class EngineLoggingTests : IDisposable
{
@@ -10,7 +10,7 @@ public class EngineLoggingTests : IDisposable
public EngineLoggingTests()
{
- _dir = Path.Combine(Path.GetTempPath(), $"teamsiso-log-{Guid.NewGuid():N}");
+ _dir = Path.Combine(Path.GetTempPath(), $"Dragon-ISO-log-{Guid.NewGuid():N}");
}
public void Dispose()
@@ -21,7 +21,7 @@ public class EngineLoggingTests : IDisposable
[Fact]
public void CreateDefault_AllLoggers_WriteToFile()
{
- // Multiple ILoggers from the same factory must all land in the file sink —
+ // Multiple ILoggers from the same factory must all land in the file sink —
// catches regressions in CreateDefault wiring (e.g. if SerilogLoggerFactory
// swaps to Log.Logger silently and our static singleton isn't set).
var factory = EngineLogging.CreateDefault(LogLevel.Information, logDirectoryOverride: _dir);
diff --git a/src/tests/TeamsISO.Engine.Tests/Persistence/ConfigStoreTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Persistence/ConfigStoreTests.cs
similarity index 87%
rename from src/tests/TeamsISO.Engine.Tests/Persistence/ConfigStoreTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Persistence/ConfigStoreTests.cs
index fa156e2..528fa6c 100644
--- a/src/tests/TeamsISO.Engine.Tests/Persistence/ConfigStoreTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Persistence/ConfigStoreTests.cs
@@ -1,8 +1,8 @@
-using Microsoft.Extensions.Logging.Abstractions;
-using TeamsISO.Engine.Domain;
-using TeamsISO.Engine.Persistence;
+using Microsoft.Extensions.Logging.Abstractions;
+using DragonISO.Engine.Domain;
+using DragonISO.Engine.Persistence;
-namespace TeamsISO.Engine.Tests.Persistence;
+namespace DragonISO.Engine.Tests.Persistence;
public class ConfigStoreTests : IDisposable
{
@@ -10,7 +10,7 @@ public class ConfigStoreTests : IDisposable
public ConfigStoreTests()
{
- _dir = Path.Combine(Path.GetTempPath(), $"teamsiso-tests-{Guid.NewGuid():N}");
+ _dir = Path.Combine(Path.GetTempPath(), $"Dragon-ISO-tests-{Guid.NewGuid():N}");
Directory.CreateDirectory(_dir);
}
@@ -36,7 +36,7 @@ public class ConfigStoreTests : IDisposable
AspectMode.Letterbox, AudioMode.Isolated),
new[]
{
- new IsoAssignment(Guid.NewGuid(), IsEnabled: true, CustomOutputName: "TEAMSISO_A"),
+ new IsoAssignment(Guid.NewGuid(), IsEnabled: true, CustomOutputName: "Dragon-ISO_A"),
new IsoAssignment(Guid.NewGuid(), IsEnabled: false, CustomOutputName: null),
});
diff --git a/src/tests/TeamsISO.Engine.Tests/Pipeline/AudioPeakComputerTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/AudioPeakComputerTests.cs
similarity index 95%
rename from src/tests/TeamsISO.Engine.Tests/Pipeline/AudioPeakComputerTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Pipeline/AudioPeakComputerTests.cs
index e7e4cfb..382af71 100644
--- a/src/tests/TeamsISO.Engine.Tests/Pipeline/AudioPeakComputerTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/AudioPeakComputerTests.cs
@@ -1,8 +1,8 @@
-using System.Runtime.InteropServices;
-using TeamsISO.Engine.Pipeline;
+using System.Runtime.InteropServices;
+using DragonISO.Engine.Pipeline;
using Xunit;
-namespace TeamsISO.Engine.Tests.Pipeline;
+namespace DragonISO.Engine.Tests.Pipeline;
public class AudioPeakComputerTests
{
@@ -22,7 +22,7 @@ public class AudioPeakComputerTests
[Fact]
public void UnknownFourCC_ReturnsZero_RatherThanThrow()
{
- // Receiver loop must never crash on an unrecognized format — better to
+ // Receiver loop must never crash on an unrecognized format — better to
// show silence on the meter than to take down the pipeline.
var floats = new[] { 0.5f, -0.5f };
var bytes = AsBytes(floats);
@@ -77,7 +77,7 @@ public class AudioPeakComputerTests
public void Fltp_TotalSamplesSmallerThanBuffer_OnlyConsumesReportedRange()
{
// The reported range covers only the first 3 floats. The 4th
- // (largest) is past `totalSamples` and must be ignored — otherwise we'd
+ // (largest) is past `totalSamples` and must be ignored — otherwise we'd
// be reading beyond what the source said it wrote.
var floats = new[] { 0.1f, -0.2f, 0.3f, 0.99f };
var bytes = AsBytes(floats);
@@ -128,7 +128,7 @@ public class AudioPeakComputerTests
var samples = new[] { (short)0, (short)16384, (short)-16383 };
var bytes = AsBytes(samples);
var peak = AudioPeakComputer.ComputePeak(bytes, AudioPeakComputer.FourCC_PCMs16, samples.Length);
- // 16384 / 32767 ≈ 0.500015; tolerate small precision drift.
+ // 16384 / 32767 ≈ 0.500015; tolerate small precision drift.
Assert.InRange(peak, 0.49, 0.51);
}
diff --git a/src/tests/TeamsISO.Engine.Tests/Pipeline/ExponentialBackoffTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/ExponentialBackoffTests.cs
similarity index 92%
rename from src/tests/TeamsISO.Engine.Tests/Pipeline/ExponentialBackoffTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Pipeline/ExponentialBackoffTests.cs
index f182fba..08b19b1 100644
--- a/src/tests/TeamsISO.Engine.Tests/Pipeline/ExponentialBackoffTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/ExponentialBackoffTests.cs
@@ -1,6 +1,6 @@
-using TeamsISO.Engine.Pipeline;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.Engine.Tests.Pipeline;
+namespace DragonISO.Engine.Tests.Pipeline;
public class ExponentialBackoffTests
{
diff --git a/src/tests/TeamsISO.Engine.Tests/Pipeline/FrameProcessorTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/FrameProcessorTests.cs
similarity index 95%
rename from src/tests/TeamsISO.Engine.Tests/Pipeline/FrameProcessorTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Pipeline/FrameProcessorTests.cs
index bd423c9..d3c8c3a 100644
--- a/src/tests/TeamsISO.Engine.Tests/Pipeline/FrameProcessorTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/FrameProcessorTests.cs
@@ -1,10 +1,10 @@
-using System.Threading.Channels;
+using System.Threading.Channels;
using Microsoft.Extensions.Logging.Abstractions;
-using TeamsISO.Engine.Domain;
-using TeamsISO.Engine.Pipeline;
-using TeamsISO.Engine.Tests.Fakes;
+using DragonISO.Engine.Domain;
+using DragonISO.Engine.Pipeline;
+using DragonISO.Engine.Tests.Fakes;
-namespace TeamsISO.Engine.Tests.Pipeline;
+namespace DragonISO.Engine.Tests.Pipeline;
public class FrameProcessorTests
{
diff --git a/src/tests/TeamsISO.Engine.Tests/Pipeline/IsoPipelineStatsTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/IsoPipelineStatsTests.cs
similarity index 95%
rename from src/tests/TeamsISO.Engine.Tests/Pipeline/IsoPipelineStatsTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Pipeline/IsoPipelineStatsTests.cs
index bc6cddf..6a300a0 100644
--- a/src/tests/TeamsISO.Engine.Tests/Pipeline/IsoPipelineStatsTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/IsoPipelineStatsTests.cs
@@ -1,15 +1,15 @@
-using System.Threading.Channels;
+using System.Threading.Channels;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
-using TeamsISO.Engine.Domain;
-using TeamsISO.Engine.Pipeline;
+using DragonISO.Engine.Domain;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.Engine.Tests.Pipeline;
+namespace DragonISO.Engine.Tests.Pipeline;
///
/// Targets the IsoPipeline stats wiring (FPS ring buffer + drops/dups surfaced
/// from FrameProcessor). The production-ctor's runner pumps the receiver in a
-/// background thread, so we drive the FrameProcessor directly here — that's
+/// background thread, so we drive the FrameProcessor directly here — that's
/// where FramesDropped and FramesDuplicated are computed.
///
public class FrameProcessorStatsTests
@@ -52,7 +52,7 @@ public class FrameProcessorStatsTests
[Fact]
public async Task FrameProcessor_DuplicatesLastFrame_WhenNoNewArrival()
{
- // First tick: a single frame. Second tick: nothing new — should re-emit
+ // First tick: a single frame. Second tick: nothing new — should re-emit
// the last frame (within slate threshold) and increment FramesDuplicated.
var raw = Channel.CreateUnbounded();
var processed = Channel.CreateUnbounded();
diff --git a/src/tests/TeamsISO.Engine.Tests/Pipeline/IsoPipelineTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/IsoPipelineTests.cs
similarity index 92%
rename from src/tests/TeamsISO.Engine.Tests/Pipeline/IsoPipelineTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Pipeline/IsoPipelineTests.cs
index 765d844..e9746ed 100644
--- a/src/tests/TeamsISO.Engine.Tests/Pipeline/IsoPipelineTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/IsoPipelineTests.cs
@@ -1,8 +1,8 @@
-using Microsoft.Extensions.Logging.Abstractions;
-using TeamsISO.Engine.Domain;
-using TeamsISO.Engine.Pipeline;
+using Microsoft.Extensions.Logging.Abstractions;
+using DragonISO.Engine.Domain;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.Engine.Tests.Pipeline;
+namespace DragonISO.Engine.Tests.Pipeline;
public class IsoPipelineTests
{
@@ -88,7 +88,7 @@ public class IsoPipelineTests
await pipeline.StartAsync();
- // Wait for supervisor to give up (max 5 attempts × ~1ms delay)
+ // Wait for supervisor to give up (max 5 attempts × ~1ms delay)
var deadline = DateTime.UtcNow.AddSeconds(2);
while (pipeline.State != IsoState.Error && DateTime.UtcNow < deadline)
await Task.Delay(20);
diff --git a/src/tests/TeamsISO.Engine.Tests/Pipeline/ManagedNearestNeighborFrameScalerTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/ManagedNearestNeighborFrameScalerTests.cs
similarity index 95%
rename from src/tests/TeamsISO.Engine.Tests/Pipeline/ManagedNearestNeighborFrameScalerTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Pipeline/ManagedNearestNeighborFrameScalerTests.cs
index 1ab4a1f..589abd0 100644
--- a/src/tests/TeamsISO.Engine.Tests/Pipeline/ManagedNearestNeighborFrameScalerTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/ManagedNearestNeighborFrameScalerTests.cs
@@ -1,7 +1,7 @@
-using TeamsISO.Engine.Domain;
-using TeamsISO.Engine.Pipeline;
+using DragonISO.Engine.Domain;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.Engine.Tests.Pipeline;
+namespace DragonISO.Engine.Tests.Pipeline;
public class ManagedNearestNeighborFrameScalerTests
{
diff --git a/src/tests/TeamsISO.Engine.Tests/Pipeline/NdiReceiverTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/NdiReceiverTests.cs
similarity index 92%
rename from src/tests/TeamsISO.Engine.Tests/Pipeline/NdiReceiverTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Pipeline/NdiReceiverTests.cs
index 3741280..fc7c75c 100644
--- a/src/tests/TeamsISO.Engine.Tests/Pipeline/NdiReceiverTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/NdiReceiverTests.cs
@@ -1,9 +1,9 @@
-using System.Threading.Channels;
+using System.Threading.Channels;
using Microsoft.Extensions.Logging.Abstractions;
-using TeamsISO.Engine.Pipeline;
-using TeamsISO.Engine.Tests.Fakes;
+using DragonISO.Engine.Pipeline;
+using DragonISO.Engine.Tests.Fakes;
-namespace TeamsISO.Engine.Tests.Pipeline;
+namespace DragonISO.Engine.Tests.Pipeline;
public class NdiReceiverTests
{
@@ -88,7 +88,7 @@ public class NdiReceiverTests
// First Consume returns the peak
receiver.ConsumeAudioPeak().Should().BeApproximately(0.42, precision: 0.0001);
- // Second Consume returns 0 — Consume has reset semantics
+ // Second Consume returns 0 — Consume has reset semantics
receiver.ConsumeAudioPeak().Should().Be(0.0);
}
@@ -96,7 +96,7 @@ public class NdiReceiverTests
public void CaptureAudioOnce_KeepsHighWaterMarkAcrossMultipleFrames()
{
// Three frames with peaks 0.3, 0.8, 0.2. Without reset, the receiver
- // must report the loudest (0.8) — that's the whole point of a peak
+ // must report the loudest (0.8) — that's the whole point of a peak
// meter. The "latest peak" naive overwrite would lose the 0.8 if a
// quieter 0.2 frame followed it.
var interop = new FakeNdiInterop();
@@ -120,7 +120,7 @@ public class NdiReceiverTests
{
// Establish a peak, then call CaptureAudioOnce when the fake has no
// queued frames. The high-water mark must NOT be reset just because
- // a polling tick saw nothing — that would defeat the peak-hold
+ // a polling tick saw nothing — that would defeat the peak-hold
// semantic between consumer reads.
var interop = new FakeNdiInterop();
interop.ReceiverAudioPeaks.GetOrAdd(Source, _ => new System.Collections.Concurrent.ConcurrentQueue())
diff --git a/src/tests/TeamsISO.Engine.Tests/Pipeline/NdiSenderTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/NdiSenderTests.cs
similarity index 90%
rename from src/tests/TeamsISO.Engine.Tests/Pipeline/NdiSenderTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Pipeline/NdiSenderTests.cs
index db6aceb..9a7bd9b 100644
--- a/src/tests/TeamsISO.Engine.Tests/Pipeline/NdiSenderTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/NdiSenderTests.cs
@@ -1,13 +1,13 @@
-using System.Threading.Channels;
+using System.Threading.Channels;
using Microsoft.Extensions.Logging.Abstractions;
-using TeamsISO.Engine.Pipeline;
-using TeamsISO.Engine.Tests.Fakes;
+using DragonISO.Engine.Pipeline;
+using DragonISO.Engine.Tests.Fakes;
-namespace TeamsISO.Engine.Tests.Pipeline;
+namespace DragonISO.Engine.Tests.Pipeline;
public class NdiSenderTests
{
- private const string Output = "TEAMSISO_01";
+ private const string Output = "Dragon-ISO_01";
private static ProcessedFrame MakeFrame(long ts) =>
new(1920, 1080, ts, new byte[1920 * 1080 * 4], PixelFormat.Bgra);
diff --git a/src/tests/TeamsISO.Engine.Tests/Pipeline/SolidFrameRendererTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/SolidFrameRendererTests.cs
similarity index 91%
rename from src/tests/TeamsISO.Engine.Tests/Pipeline/SolidFrameRendererTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Pipeline/SolidFrameRendererTests.cs
index 5976e43..689b099 100644
--- a/src/tests/TeamsISO.Engine.Tests/Pipeline/SolidFrameRendererTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/SolidFrameRendererTests.cs
@@ -1,6 +1,6 @@
-using TeamsISO.Engine.Pipeline;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.Engine.Tests.Pipeline;
+namespace DragonISO.Engine.Tests.Pipeline;
public class SolidFrameRendererTests
{
diff --git a/src/tests/TeamsISO.Engine.Tests/Pipeline/TestPatternGeneratorTests.cs b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/TestPatternGeneratorTests.cs
similarity index 91%
rename from src/tests/TeamsISO.Engine.Tests/Pipeline/TestPatternGeneratorTests.cs
rename to src/tests/Dragon-ISO.Engine.Tests/Pipeline/TestPatternGeneratorTests.cs
index b0c7634..aef89b2 100644
--- a/src/tests/TeamsISO.Engine.Tests/Pipeline/TestPatternGeneratorTests.cs
+++ b/src/tests/Dragon-ISO.Engine.Tests/Pipeline/TestPatternGeneratorTests.cs
@@ -1,7 +1,7 @@
-using FluentAssertions;
-using TeamsISO.Engine.Pipeline;
+using FluentAssertions;
+using DragonISO.Engine.Pipeline;
-namespace TeamsISO.Engine.Tests.Pipeline;
+namespace DragonISO.Engine.Tests.Pipeline;
public class TestPatternGeneratorTests
{
@@ -60,8 +60,8 @@ public class TestPatternGeneratorTests
var frame0 = TestPatternGenerator.Render(640, 480, frameNumber: 0, timestampTicks: 0);
var frame100 = TestPatternGenerator.Render(640, 480, frameNumber: 100, timestampTicks: 0);
- // frame0's sweep row is 0 (and ±4 rows). frame100's sweep row is 200.
- // Compare pixel row 200 — frame100 should be brighter at that row.
+ // frame0's sweep row is 0 (and ±4 rows). frame100's sweep row is 200.
+ // Compare pixel row 200 — frame100 should be brighter at that row.
var px0 = frame0.Pixels.Span;
var px100 = frame100.Pixels.Span;
var row = 200;