teamsiso/src/TeamsISO.Engine/Discovery/NdiSourceParser.cs
Zac Gaetano aaf3184a8e
Some checks failed
CI / build-and-test (push) Failing after 22s
feat(discovery): add NdiSource record and Teams source string parser
2026-05-07 15:11:00 +00:00

70 lines
2.6 KiB
C#

using TeamsISO.Engine.Domain;
namespace TeamsISO.Engine.Discovery;
/// <summary>
/// Parses NDI source strings emitted by Microsoft Teams.
///
/// Examples Teams emits:
/// "MACHINE (Teams - Display Name)"
/// "MACHINE (Teams)" — auto-mixed active speaker
/// "MACHINE (Teams Audio)" — audio-only mix
/// "MACHINE (Teams Screen Share)" — screen share
/// </summary>
public static class NdiSourceParser
{
public static NdiSource? Parse(string fullName)
{
if (string.IsNullOrWhiteSpace(fullName))
return null;
// Find the last '(' so machine names can themselves contain parens.
var openParen = fullName.LastIndexOf('(');
if (openParen <= 0 || !fullName.EndsWith(')'))
{
// Try outer parens for cases like "MACHINE (Teams - Smith, Bob (PM))"
// by walking from the first '(' that opens a "Teams" inner.
var firstParen = fullName.IndexOf(" (Teams", StringComparison.Ordinal);
if (firstParen <= 0)
return null;
openParen = firstParen + 1;
if (!fullName.EndsWith(')'))
return null;
}
else
{
// Re-anchor to the first " (Teams" if present, so display names containing
// their own parens (e.g. "Smith, Bob (PM)") don't get truncated.
var firstParen = fullName.IndexOf(" (Teams", StringComparison.Ordinal);
if (firstParen > 0)
openParen = firstParen + 1;
}
var machine = fullName[..openParen].TrimEnd();
if (machine.Length == 0)
return null;
var inner = fullName.Substring(openParen + 1, fullName.Length - openParen - 2).Trim();
if (!inner.StartsWith("Teams", StringComparison.Ordinal))
return null;
if (inner == "Teams")
return new NdiSource(fullName, machine, NdiSourceKind.ActiveSpeaker, DisplayName: null);
if (inner == "Teams Audio")
return new NdiSource(fullName, machine, NdiSourceKind.Audio, DisplayName: null);
if (inner == "Teams Screen Share")
return new NdiSource(fullName, machine, NdiSourceKind.ScreenShare, DisplayName: null);
const string prefix = "Teams - ";
if (inner.StartsWith(prefix, StringComparison.Ordinal))
{
var display = inner[prefix.Length..].Trim();
if (display.Length == 0)
return null;
return new NdiSource(fullName, machine, NdiSourceKind.Participant, display);
}
return null;
}
}