mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-07-02 10:38:16 +00:00
feat: enhance routing functionality with additional parameters in RouteDescriptor and update RouteDescriptorCollection for change notifications
This commit is contained in:
parent
4bb2917b69
commit
fb4ba8ccfa
5 changed files with 171 additions and 200 deletions
|
|
@ -222,7 +222,7 @@ public static class Extensions
|
|||
// if it's a single signal type, find the route
|
||||
if (!signalType.HasFlag(eRoutingSignalType.AudioVideo))
|
||||
{
|
||||
var singleTypeRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, signalType);
|
||||
var singleTypeRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, sourcePort, signalType);
|
||||
Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key, signalType);
|
||||
|
||||
if (!destination.GetRouteToSource(source, null, null, signalType, 0, singleTypeRouteDescriptor, destinationPort, sourcePort))
|
||||
|
|
@ -240,14 +240,14 @@ public static class Extensions
|
|||
|
||||
Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key);
|
||||
|
||||
var audioRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.Audio);
|
||||
var audioRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, sourcePort, eRoutingSignalType.Audio);
|
||||
|
||||
var audioSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Audio, 0, audioRouteDescriptor, destinationPort, sourcePort);
|
||||
|
||||
if (!audioSuccess)
|
||||
Debug.LogMessage(LogEventLevel.Debug, "Cannot find audio route to {0}", destination, source.Key);
|
||||
|
||||
var videoRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.Video);
|
||||
var videoRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, sourcePort, eRoutingSignalType.Video);
|
||||
|
||||
var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, videoRouteDescriptor, destinationPort, sourcePort);
|
||||
|
||||
|
|
@ -366,7 +366,8 @@ public static class Extensions
|
|||
audioOrSingleRoute = audioCollection.Descriptors.FirstOrDefault(d =>
|
||||
d.Source.Key == request.Source.Key &&
|
||||
d.Destination.Key == request.Destination.Key &&
|
||||
(request.DestinationPort == null || d.InputPort?.Key == request.DestinationPort.Key));
|
||||
(request.DestinationPort == null || d.InputPort?.Key == request.DestinationPort.Key) &&
|
||||
(request.SourcePort == null || d.OutputPort?.Key == request.SourcePort.Key));
|
||||
}
|
||||
|
||||
if (RouteDescriptors.TryGetValue(eRoutingSignalType.Video, out RouteDescriptorCollection videoCollection))
|
||||
|
|
@ -374,7 +375,8 @@ public static class Extensions
|
|||
videoRoute = videoCollection.Descriptors.FirstOrDefault(d =>
|
||||
d.Source.Key == request.Source.Key &&
|
||||
d.Destination.Key == request.Destination.Key &&
|
||||
(request.DestinationPort == null || d.InputPort?.Key == request.DestinationPort.Key));
|
||||
(request.DestinationPort == null || d.InputPort?.Key == request.DestinationPort.Key) &&
|
||||
(request.SourcePort == null || d.OutputPort?.Key == request.SourcePort.Key));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -385,7 +387,8 @@ public static class Extensions
|
|||
audioOrSingleRoute = collection.Descriptors.FirstOrDefault(d =>
|
||||
d.Source.Key == request.Source.Key &&
|
||||
d.Destination.Key == request.Destination.Key &&
|
||||
(request.DestinationPort == null || d.InputPort?.Key == request.DestinationPort.Key));
|
||||
(request.DestinationPort == null || d.InputPort?.Key == request.DestinationPort.Key) &&
|
||||
(request.SourcePort == null || d.OutputPort?.Key == request.SourcePort.Key));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,35 +7,40 @@ using PepperDash.Core;
|
|||
using Serilog.Events;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a collection of individual route steps between a Source and a Destination device for a specific signal type.
|
||||
/// </summary>
|
||||
public class RouteDescriptor
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of individual route steps between a Source and a Destination device for a specific signal type.
|
||||
/// </summary>
|
||||
public class RouteDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// The destination device (sink or midpoint) for the route.
|
||||
/// </summary>
|
||||
public IRoutingInputs Destination { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The specific input port on the destination device used for this route. Can be null if not specified or applicable.
|
||||
/// The InputPort on the destination device for this route, if applicable. May be null if the route is not for a specific input port.
|
||||
/// </summary>
|
||||
public RoutingInputPort InputPort { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The source device for the route.
|
||||
/// Gets the source device (sink or midpoint) for the route.
|
||||
/// </summary>
|
||||
public IRoutingOutputs Source { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of signal being routed (e.g., Audio, Video). This descriptor represents a single signal type.
|
||||
/// Gets the OutputPort on the source device for this route, if applicable. May be null if the route is not for a specific output port.
|
||||
/// </summary>
|
||||
public RoutingOutputPort OutputPort { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the signal type for this route.
|
||||
/// </summary>
|
||||
public eRoutingSignalType SignalType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of individual switching steps required to establish the route.
|
||||
/// Gets the collection of route switch descriptors for this route.
|
||||
/// </summary>
|
||||
public List<RouteSwitchDescriptor> Routes { get; private set; }
|
||||
|
||||
|
|
@ -56,23 +61,36 @@ public class RouteDescriptor
|
|||
/// <param name="destination">The destination device.</param>
|
||||
/// <param name="inputPort">The destination input port (optional).</param>
|
||||
/// <param name="signalType">The signal type for this route.</param>
|
||||
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, RoutingInputPort inputPort, eRoutingSignalType signalType)
|
||||
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, RoutingInputPort inputPort, eRoutingSignalType signalType) : this(source, destination, inputPort, null, signalType)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RouteDescriptor"/> class for a route with specific destination input and source output ports.
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="destination"></param>
|
||||
/// <param name="inputPort"></param>
|
||||
/// <param name="outputPort"></param>
|
||||
/// <param name="signalType"></param>
|
||||
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, RoutingInputPort inputPort, RoutingOutputPort outputPort, eRoutingSignalType signalType)
|
||||
{
|
||||
Destination = destination;
|
||||
InputPort = inputPort;
|
||||
Source = source;
|
||||
OutputPort = outputPort;
|
||||
SignalType = signalType;
|
||||
Routes = new List<RouteSwitchDescriptor>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes all the switching steps defined in the <see cref="Routes"/> list.
|
||||
/// ExecuteRoutes method
|
||||
/// </summary>
|
||||
public void ExecuteRoutes()
|
||||
{
|
||||
foreach (var route in Routes)
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}", null, route.ToString());
|
||||
Debug.LogVerbose("ExecuteRoutes: {0}", route.ToString());
|
||||
|
||||
if (route.SwitchingDevice is IRoutingSinkWithFeedback sink)
|
||||
{
|
||||
|
|
@ -86,7 +104,7 @@ public class RouteDescriptor
|
|||
|
||||
route.OutputPort.InUseTracker.AddUser(Destination, "destination-" + SignalType);
|
||||
|
||||
Debug.LogMessage(LogEventLevel.Verbose, "Output port {0} routing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue);
|
||||
Debug.LogVerbose("Output port {0} routing. Count={1}", route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -95,6 +113,8 @@ public class RouteDescriptor
|
|||
/// Releases the usage tracking for the route and optionally clears the route on the switching devices.
|
||||
/// </summary>
|
||||
/// <param name="clearRoute">If true, attempts to clear the route on the switching devices (e.g., set input to null/0).</param>
|
||||
|
||||
|
||||
public void ReleaseRoutes(bool clearRoute = false)
|
||||
{
|
||||
foreach (var route in Routes.Where(r => r.SwitchingDevice is IRoutingMidpointWithFeedback))
|
||||
|
|
@ -110,6 +130,7 @@ public class RouteDescriptor
|
|||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("Error executing switch: {exception}", e.Message);
|
||||
Debug.LogDebug(e, "Stack Trace: ");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,11 +142,11 @@ public class RouteDescriptor
|
|||
if (route.OutputPort.InUseTracker != null)
|
||||
{
|
||||
route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType);
|
||||
Debug.LogMessage(LogEventLevel.Verbose, "Port {0} releasing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue);
|
||||
Debug.LogVerbose("Port {0} releasing. Count={1}", route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Error, "InUseTracker is null for OutputPort {0}", null, route.OutputPort.Key);
|
||||
Debug.LogVerbose("InUseTracker is null for OutputPort {0}", route.OutputPort.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -140,4 +161,6 @@ public class RouteDescriptor
|
|||
var routesText = Routes.Select(r => r.ToString()).ToArray();
|
||||
return $"Route table from {Source.Key} to {Destination.Key} for {SignalType}:\r\n {string.Join("\r\n ", routesText)}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -28,6 +28,9 @@ public class RouteDescriptorCollection
|
|||
|
||||
private readonly List<RouteDescriptor> RouteDescriptors = new List<RouteDescriptor>();
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the collection of RouteDescriptors changes (add/remove). This is useful for updating routing status in the UI, for example.
|
||||
/// </summary>
|
||||
public event EventHandler RouteDescriptorCollectionChanged;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
{
|
||||
/// <summary>
|
||||
/// Represents a RouteSwitchDescriptor
|
||||
/// This represents a switch to be made on an IRoutingInputs device, which could be a matrix switcher or a sink device.
|
||||
/// </summary>
|
||||
public class RouteSwitchDescriptor
|
||||
{
|
||||
|
|
|
|||
|
|
@ -225,6 +225,7 @@ namespace PepperDash.Essentials.Core.Routing
|
|||
try
|
||||
{
|
||||
UpdateDestination(sender, currentInputPort);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -340,11 +341,6 @@ namespace PepperDash.Essentials.Core.Routing
|
|||
inputPort
|
||||
);
|
||||
|
||||
var tempSourceListItem = new SourceListItem
|
||||
{
|
||||
SourceKey = "$transient",
|
||||
Name = inputPort.Key,
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -371,11 +367,15 @@ namespace PepperDash.Essentials.Core.Routing
|
|||
inputPort
|
||||
);
|
||||
|
||||
var tempSourceListItem = new SourceListItem
|
||||
{
|
||||
SourceKey = "$transient",
|
||||
Name = "None",
|
||||
};
|
||||
|
||||
// determine all the tie lines between the source and destination to determine the signal type
|
||||
// the type is the union of all the tie lines between the source and destination
|
||||
|
||||
// For now we assume the type matches the tie line connected to the destination
|
||||
destination.SetCurrentSource(firstTieLine.Type, null);
|
||||
|
||||
// remove existing descriptor if any
|
||||
RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination, inputPort.Key);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -386,83 +386,24 @@ namespace PepperDash.Essentials.Core.Routing
|
|||
return;
|
||||
}
|
||||
|
||||
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root TieLine {tieLine}", this, sourceTieLine);
|
||||
|
||||
// Does not handle combinable scenarios or other scenarios where a display might be part of multiple rooms yet.
|
||||
var room = DeviceManager
|
||||
.AllDevices.OfType<IEssentialsRoom>()
|
||||
.FirstOrDefault(
|
||||
(r) =>
|
||||
{
|
||||
|
||||
if (r is IHasDefaultDisplay roomDefaultDisplay)
|
||||
{
|
||||
return roomDefaultDisplay.DefaultDisplay.Key == destination.Key;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// Get the routes from the destination to the source using the existing GetRouteToSource method
|
||||
var routes = destination.GetRouteToSource(
|
||||
sourceTieLine.SourcePort.ParentDevice as IRoutingOutputs,
|
||||
sourceTieLine.Type,
|
||||
inputPort,
|
||||
sourceTieLine.SourcePort
|
||||
);
|
||||
|
||||
if (room == null)
|
||||
// remove existing descriptor if any
|
||||
RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination, inputPort.Key);
|
||||
|
||||
// Add the new route descriptors to the collection
|
||||
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(routes.Item1);
|
||||
|
||||
if(routes.Item2 != null)
|
||||
{
|
||||
Debug.LogMessage(
|
||||
Serilog.Events.LogEventLevel.Debug,
|
||||
"No room found for display {destination}",
|
||||
this,
|
||||
destination.Key
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found room {room} for destination {destination}", this, room.Key, destination.Key);
|
||||
|
||||
var sourceList = ConfigReader.ConfigObject.GetSourceListForKey(room.SourceListKey);
|
||||
|
||||
if (sourceList == null)
|
||||
{
|
||||
Debug.LogMessage(
|
||||
Serilog.Events.LogEventLevel.Debug,
|
||||
"No source list found for source list key {key}. Unable to find source for tieLine {sourceTieLine}",
|
||||
this,
|
||||
room.SourceListKey,
|
||||
sourceTieLine
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found sourceList for room {room}", this, room.Key);
|
||||
|
||||
var sourceListItem = sourceList.FirstOrDefault(sli =>
|
||||
{
|
||||
//// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose,
|
||||
// "SourceListItem {sourceListItem}:{sourceKey} tieLine sourceport device key {sourcePortDeviceKey}",
|
||||
// this,
|
||||
// sli.Key,
|
||||
// sli.Value.SourceKey,
|
||||
// sourceTieLine.SourcePort.ParentDevice.Key);
|
||||
|
||||
return sli.Value.SourceKey.Equals(
|
||||
sourceTieLine.SourcePort.ParentDevice.Key,
|
||||
StringComparison.InvariantCultureIgnoreCase
|
||||
);
|
||||
});
|
||||
|
||||
var source = sourceListItem.Value;
|
||||
var sourceKey = sourceListItem.Key;
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
Debug.LogMessage(
|
||||
Serilog.Events.LogEventLevel.Debug,
|
||||
"No source found for device {key}. Creating transient source for {destination}",
|
||||
this,
|
||||
sourceTieLine.SourcePort.ParentDevice.Key,
|
||||
destination
|
||||
);
|
||||
|
||||
|
||||
return;
|
||||
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(routes.Item2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue