92 lines
3.4 KiB
C#
92 lines
3.4 KiB
C#
|
|
namespace TeamsISO.App.Services;
|
||
|
|
|
||
|
|
// /topology/* route handlers — read + apply / restore the machine NDI
|
||
|
|
// access-manager config so the operator can flip transcoder topology
|
||
|
|
// without leaving the web UI.
|
||
|
|
//
|
||
|
|
// GET /topology → GetTopology
|
||
|
|
// POST /topology/apply → ApplyTopologyAsync
|
||
|
|
// POST /topology/restore → RestoreTopologyAsync
|
||
|
|
public sealed partial class ControlSurfaceServer
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// Report the current NDI machine topology. "mode" is "hidden" when
|
||
|
|
/// local senders are confined to the private group (raw Teams sources
|
||
|
|
/// invisible to the rest of the LAN), "public" otherwise. Reads the
|
||
|
|
/// machine NDI config file directly — no caching, so the result
|
||
|
|
/// reflects whatever state the file is in right now (including
|
||
|
|
/// manual edits).
|
||
|
|
/// </summary>
|
||
|
|
private object GetTopology()
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var (mode, sends, recvs) = NdiAccessManagerConfig.ReadCurrent();
|
||
|
|
return new
|
||
|
|
{
|
||
|
|
mode,
|
||
|
|
senders = sends,
|
||
|
|
receivers = recvs,
|
||
|
|
configPath = NdiAccessManagerConfig.ConfigPath,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
return new { ok = false, error = ex.Message };
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Apply the transcoder topology: machine senders → <c>teamsiso-input</c>,
|
||
|
|
/// receivers → <c>public + teamsiso-input</c>; engine groups updated to
|
||
|
|
/// match (discover from teamsiso-input, broadcast on public). Operator
|
||
|
|
/// MUST restart Teams afterward for it to read the new NDI config.
|
||
|
|
/// </summary>
|
||
|
|
private async Task<object> ApplyTopologyAsync()
|
||
|
|
{
|
||
|
|
var result = NdiAccessManagerConfig.ApplyTranscoderTopology();
|
||
|
|
if (!result.Success)
|
||
|
|
{
|
||
|
|
return new { ok = false, error = result.ErrorMessage, configPath = result.ConfigPath };
|
||
|
|
}
|
||
|
|
// Mirror what the WPF settings VM does so the engine groups +
|
||
|
|
// machine config stay in lockstep.
|
||
|
|
var ourGroups = new TeamsISO.Engine.Domain.NdiGroupSettings(
|
||
|
|
DiscoveryGroups: NdiAccessManagerConfig.TranscoderInputGroup,
|
||
|
|
OutputGroups: "public");
|
||
|
|
await _controller.SetGroupSettingsAsync(ourGroups, CancellationToken.None);
|
||
|
|
return new
|
||
|
|
{
|
||
|
|
ok = true,
|
||
|
|
mode = "hidden",
|
||
|
|
backupPath = result.BackupPath,
|
||
|
|
note = "Restart Microsoft Teams for the new NDI config to take effect there.",
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Restore the machine NDI defaults: senders + receivers both on
|
||
|
|
/// <c>public</c>. Engine groups go back to null/defaults too. Operator
|
||
|
|
/// must restart Teams for it to broadcast on public again.
|
||
|
|
/// </summary>
|
||
|
|
private async Task<object> RestoreTopologyAsync()
|
||
|
|
{
|
||
|
|
var result = NdiAccessManagerConfig.RestoreDefaults();
|
||
|
|
if (!result.Success)
|
||
|
|
{
|
||
|
|
return new { ok = false, error = result.ErrorMessage, configPath = result.ConfigPath };
|
||
|
|
}
|
||
|
|
var ourGroups = new TeamsISO.Engine.Domain.NdiGroupSettings(
|
||
|
|
DiscoveryGroups: null,
|
||
|
|
OutputGroups: null);
|
||
|
|
await _controller.SetGroupSettingsAsync(ourGroups, CancellationToken.None);
|
||
|
|
return new
|
||
|
|
{
|
||
|
|
ok = true,
|
||
|
|
mode = "public",
|
||
|
|
backupPath = result.BackupPath,
|
||
|
|
note = "Restart Microsoft Teams for the new NDI config to take effect there.",
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|