Skip to content

Commit

Permalink
feat: implement IMatrixRouting
Browse files Browse the repository at this point in the history
  • Loading branch information
andrew-welker committed Mar 19, 2024
1 parent 3bc0a2c commit 596c4d7
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 0 deletions.
74 changes: 74 additions & 0 deletions src/NvxEpi/Features/Routing/NvxGlobalRouter.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
using System;
using System.Collections.Generic;
using PepperDash.Core;
using System.Linq;
using NvxEpi.Abstractions;
using NvxEpi.Services.TieLines;
using NvxEpi.Services.Utilities;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Routing;
using NvxEpi.Abstractions.SecondaryAudio;
using NvxEpi.Devices;

namespace NvxEpi.Features.Routing
{
#if SERIES4
public class NvxGlobalRouter : EssentialsDevice, IRoutingNumeric, IMatrixRouting
#else
public class NvxGlobalRouter : EssentialsDevice, IRoutingNumeric
#endif
{
private static readonly NvxGlobalRouter _instance = new NvxGlobalRouter();

Expand All @@ -31,6 +40,10 @@ private NvxGlobalRouter()
DeviceManager.AddDevice(SecondaryAudioRouter);

AddPostActivationAction(BuildTieLines);

#if SERIES4
AddPostActivationAction(BuildMatrixRouting);
#endif
}

public static NvxGlobalRouter Instance { get { return _instance; } }
Expand Down Expand Up @@ -84,5 +97,66 @@ public void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType
{
throw new NotImplementedException("Execute Numeric Switch");
}

#if SERIES4
public Dictionary<string, IRoutingInputSlot> InputSlots { get; private set; }

public Dictionary<string, IRoutingOutputSlot> OutputSlots { get; private set; }

private void BuildMatrixRouting()
{
InputSlots = DeviceManager.AllDevices
.OfType<NvxBaseDevice>()
.Where(t => t.IsTransmitter)
.Select(t =>
{
return new NvxMatrixInput(t);
})
.ToDictionary(i => i.Key, i => i as IRoutingInputSlot);

OutputSlots = DeviceManager.AllDevices
.OfType<NvxBaseDevice>()
.Where(t => !t.IsTransmitter)
.Select(t => new NvxMatrixOutput(t, this))
.ToDictionary(t => t.Key, t => t as IRoutingOutputSlot);
}

public void Route(string inputSlotKey, string outputSlotKey, eRoutingSignalType type)
{
if(!InputSlots.TryGetValue(inputSlotKey, out var inputSlot))
{
Debug.Console(0, this, "Unable to find input slot with key {0}", inputSlotKey);
return;
}

if(!OutputSlots.TryGetValue(outputSlotKey, out var outputSlot))
{
Debug.Console(0, this, "Unable to find output slot with key {0}", outputSlotKey);
return;
}

var outputDevice = (outputSlot as NvxMatrixOutput).Device;

if (outputDevice == null)
{
Debug.Console(0, this, "Unable to get device to route");
return;
}

if(type.Has(eRoutingSignalType.Video))
{
// using namespace to qualify type as `Route` is a static method
Routing.PrimaryStreamRouter.Route(inputSlot.SlotNumber, outputDevice);
}

if((type.Has(eRoutingSignalType.SecondaryAudio)
|| type.Has(eRoutingSignalType.Audio))
&& outputDevice is ISecondaryAudioStreamWithHardware audioOutput)
{
// using namespace to qualify type as `Route` is a static method
Routing.SecondaryAudioRouter.Route(inputSlot.SlotNumber, audioOutput);
}
}
}
#endif
}
46 changes: 46 additions & 0 deletions src/NvxEpi/Features/Routing/NvxMatrixInput.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using NvxEpi.Abstractions.HdmiInput;
using NvxEpi.Devices;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Routing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NvxEpi.Features.Routing
{
public class NvxMatrixInput : IRoutingInputSlot
{
private readonly NvxBaseDevice _device;

public NvxMatrixInput(NvxBaseDevice device)
{
_device = device;

if(_device is IHdmiInput hdmiInput)
{
foreach(var feedback in hdmiInput.Feedbacks)
{
feedback.OutputChange += (o, a) => VideoSyncChanged?.Invoke(this, new EventArgs());
}
}
}

public string TxDeviceKey => _device.Key;

public int SlotNumber => _device.DeviceId;

public eRoutingSignalType SupportedSignalTypes => eRoutingSignalType.AudioVideo | eRoutingSignalType.UsbInput | eRoutingSignalType.UsbOutput | eRoutingSignalType.SecondaryAudio;

public string Name => _device.Name;

public BoolFeedback IsOnline => _device.IsOnline;

public bool VideoSyncDetected => _device is IHdmiInput inputDevice ? inputDevice.SyncDetected.Any(fb => fb.Value.BoolValue) : false;

public string Key => $"{_device.Key}-matrixInput";

public event EventHandler VideoSyncChanged;
}
}
80 changes: 80 additions & 0 deletions src/NvxEpi/Features/Routing/NvxMatrixOutput.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using NvxEpi.Abstractions.Stream;
using NvxEpi.Devices;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Routing;
using System;
using System.Collections.Generic;
using System.Linq;

namespace NvxEpi.Features.Routing
{
public class NvxMatrixOutput : IRoutingOutputSlot
{
private readonly NvxBaseDevice _device;

public NvxMatrixOutput(NvxBaseDevice device, IMatrixRouting parent)
{
_device = device;

_device.CurrentStreamId.OutputChange += (o, a) =>
{
var inputSlot = parent.InputSlots.Values.FirstOrDefault(input => input.SlotNumber == a.IntValue);

SetInputRoute(eRoutingSignalType.Video, inputSlot);

if (!_device.IsStreamingSecondaryAudio.BoolValue)
{
SetInputRoute(eRoutingSignalType.Audio, inputSlot);
}
};

_device.CurrentSecondaryAudioStreamId.OutputChange += (o, a) =>
{
var inputSlot = parent.InputSlots.Values.FirstOrDefault(input => input.SlotNumber == a.IntValue);

SetInputRoute(eRoutingSignalType.SecondaryAudio, inputSlot);
};
}

public string RxDeviceKey { get; set; }

private readonly Dictionary<eRoutingSignalType, IRoutingInputSlot> currentRoutes = new Dictionary<eRoutingSignalType, IRoutingInputSlot>
{
{eRoutingSignalType.Audio, null },
{eRoutingSignalType.Video, null },
{eRoutingSignalType.UsbInput, null },
{eRoutingSignalType.UsbOutput, null },
{eRoutingSignalType.SecondaryAudio, null },
};

public IStreamWithHardware Device => _device;

private void SetInputRoute(eRoutingSignalType type, IRoutingInputSlot input)
{
if (currentRoutes.ContainsKey(type))
{
currentRoutes[type] = input;

OutputSlotChanged?.Invoke(this, new EventArgs());

return;
}

currentRoutes.Add(type, input);

OutputSlotChanged?.Invoke(this, new EventArgs());
}

public Dictionary<eRoutingSignalType, IRoutingInputSlot> CurrentRoutes => currentRoutes;

public int SlotNumber => _device.DeviceId;

public eRoutingSignalType SupportedSignalTypes => eRoutingSignalType.AudioVideo | eRoutingSignalType.UsbInput | eRoutingSignalType.UsbOutput | eRoutingSignalType.SecondaryAudio;

public string Name => _device.Name;

public string Key => $"{_device.Key}-matrixInput";

public event EventHandler<EventArgs> OutputSlotChanged;
}
}

0 comments on commit 596c4d7

Please sign in to comment.