108 lines
4.1 KiB
C#
108 lines
4.1 KiB
C#
|
|
using System.Reactive.Linq;
|
||
|
|
using System.Reactive.Subjects;
|
||
|
|
using TeamsISO.Engine.Controller;
|
||
|
|
using TeamsISO.Engine.Domain;
|
||
|
|
using TeamsISO.Engine.Pipeline;
|
||
|
|
|
||
|
|
namespace TeamsISO.App.Tests.Fakes;
|
||
|
|
|
||
|
|
// Minimal IIsoController stub for tests that need to instantiate
|
||
|
|
// services in the App layer (ControlSurfaceServer, OscBridge, etc.)
|
||
|
|
// without spinning up the real engine + NDI runtime.
|
||
|
|
//
|
||
|
|
// Everything is a sensible no-op default; tests that need a specific
|
||
|
|
// behaviour (e.g. "EnableIsoAsync was called with these args") subclass
|
||
|
|
// or replace methods via the action hooks.
|
||
|
|
internal sealed class StubIsoController : IIsoController
|
||
|
|
{
|
||
|
|
private readonly BehaviorSubject<IReadOnlyList<Participant>> _participants =
|
||
|
|
new(Array.Empty<Participant>());
|
||
|
|
private readonly BehaviorSubject<EngineAlert?> _alerts = new(default);
|
||
|
|
|
||
|
|
public IObservable<IReadOnlyList<Participant>> Participants => _participants;
|
||
|
|
public IObservable<EngineAlert> Alerts => _alerts.Where(a => a is not null)!;
|
||
|
|
|
||
|
|
public FrameProcessingSettings GlobalSettings { get; set; } = new(
|
||
|
|
TargetFramerate.Fps30, TargetResolution.R1080p, AspectMode.Letterbox, AudioMode.Auto);
|
||
|
|
|
||
|
|
public NdiGroupSettings GroupSettings { get; set; } = new(
|
||
|
|
DiscoveryGroups: null, OutputGroups: null);
|
||
|
|
|
||
|
|
public bool RecordingEnabled { get; private set; }
|
||
|
|
public string? RecordingDirectory { get; private set; }
|
||
|
|
|
||
|
|
public Func<Guid, IsoHealthStats>? GetStatsHandler { get; set; }
|
||
|
|
public Func<Guid, ProcessedFrame?>? GetLatestProcessedFrameHandler { get; set; }
|
||
|
|
public Func<Guid, FrameProcessingSettings?>? GetIsoOverrideHandler { get; set; }
|
||
|
|
|
||
|
|
public IsoHealthStats GetStats(Guid participantId) =>
|
||
|
|
GetStatsHandler?.Invoke(participantId) ?? IsoHealthStats.Empty;
|
||
|
|
|
||
|
|
public ProcessedFrame? GetLatestProcessedFrame(Guid participantId) =>
|
||
|
|
GetLatestProcessedFrameHandler?.Invoke(participantId);
|
||
|
|
|
||
|
|
public FrameProcessingSettings? GetIsoOverride(Guid participantId) =>
|
||
|
|
GetIsoOverrideHandler?.Invoke(participantId);
|
||
|
|
|
||
|
|
public List<(Guid Id, string? Name)> EnableCalls { get; } = new();
|
||
|
|
public List<Guid> DisableCalls { get; } = new();
|
||
|
|
|
||
|
|
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||
|
|
|
||
|
|
public Task EnableIsoAsync(Guid participantId, string? customName, CancellationToken cancellationToken)
|
||
|
|
{
|
||
|
|
EnableCalls.Add((participantId, customName));
|
||
|
|
return Task.CompletedTask;
|
||
|
|
}
|
||
|
|
|
||
|
|
public Task EnableIsoAsync(Guid participantId, string? customName, bool? recordOverride, CancellationToken cancellationToken)
|
||
|
|
{
|
||
|
|
EnableCalls.Add((participantId, customName));
|
||
|
|
return Task.CompletedTask;
|
||
|
|
}
|
||
|
|
|
||
|
|
public Task DisableIsoAsync(Guid participantId, CancellationToken cancellationToken)
|
||
|
|
{
|
||
|
|
DisableCalls.Add(participantId);
|
||
|
|
return Task.CompletedTask;
|
||
|
|
}
|
||
|
|
|
||
|
|
public Task SetGlobalSettingsAsync(FrameProcessingSettings settings, CancellationToken cancellationToken)
|
||
|
|
{
|
||
|
|
GlobalSettings = settings;
|
||
|
|
return Task.CompletedTask;
|
||
|
|
}
|
||
|
|
|
||
|
|
public Task SetIsoOverrideAsync(Guid participantId, FrameProcessingSettings? settings, CancellationToken cancellationToken) =>
|
||
|
|
Task.CompletedTask;
|
||
|
|
|
||
|
|
public Task SetGroupSettingsAsync(NdiGroupSettings groupSettings, CancellationToken cancellationToken)
|
||
|
|
{
|
||
|
|
GroupSettings = groupSettings;
|
||
|
|
return Task.CompletedTask;
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool RefreshDiscoveryCalled { get; private set; }
|
||
|
|
public void RefreshDiscovery() => RefreshDiscoveryCalled = true;
|
||
|
|
|
||
|
|
public void SetRecording(bool enabled, string? outputDirectory)
|
||
|
|
{
|
||
|
|
RecordingEnabled = enabled;
|
||
|
|
RecordingDirectory = outputDirectory;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void AddRecordingMarker(string label) { /* no-op for stub */ }
|
||
|
|
|
||
|
|
public ValueTask DisposeAsync()
|
||
|
|
{
|
||
|
|
_participants.Dispose();
|
||
|
|
_alerts.Dispose();
|
||
|
|
return ValueTask.CompletedTask;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Used by tests to push synthetic participant snapshots through the
|
||
|
|
// observable chain.
|
||
|
|
public void PublishParticipants(params Participant[] participants) =>
|
||
|
|
_participants.OnNext(participants);
|
||
|
|
}
|