using System; using System.Collections.Generic; using System.Linq; using Crestron.SimplSharpPro; using PepperDash.Core; using Serilog.Events; namespace PepperDash.Essentials.Core { /// /// Represents a collection of individual route steps between a Source and a Destination device for a specific signal type. /// public class RouteDescriptor { /// /// The destination device (sink or midpoint) for the route. /// public IRoutingInputs Destination { get; private set; } /// /// The specific input port on the destination device used for this route. Can be null if not specified or applicable. /// public RoutingInputPort InputPort { get; private set; } /// /// The source device for the route. /// public IRoutingOutputs Source { get; private set; } /// /// The type of signal being routed (e.g., Audio, Video). This descriptor represents a single signal type. /// public eRoutingSignalType SignalType { get; private set; } /// /// A list of individual switching steps required to establish the route. /// public List Routes { get; private set; } /// /// Initializes a new instance of the class for a route without a specific destination input port. /// /// The source device. /// The destination device. /// The type of signal being routed. public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) : this(source, destination, null, signalType) { } /// /// Initializes a new instance of the class for a route with a specific destination input port. /// /// The source device. /// The destination device. /// The destination input port (optional). /// The signal type for this route. public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, RoutingInputPort inputPort, eRoutingSignalType signalType) { Destination = destination; InputPort = inputPort; Source = source; SignalType = signalType; Routes = new List(); } /// /// Executes all the switching steps defined in the list. /// public void ExecuteRoutes() { foreach (var route in Routes) { Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}", null, route.ToString()); if (route.SwitchingDevice is IRoutingSinkWithSwitching sink) { sink.ExecuteSwitch(route.InputPort.Selector); continue; } if (route.SwitchingDevice is IRouting switchingDevice) { switchingDevice.ExecuteSwitch(route.InputPort.Selector, route.OutputPort.Selector, SignalType); 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); } } } /// /// Releases the usage tracking for the route and optionally clears the route on the switching devices. /// /// If true, attempts to clear the route on the switching devices (e.g., set input to null/0). public void ReleaseRoutes(bool clearRoute = false) { foreach (var route in Routes.Where(r => r.SwitchingDevice is IRouting)) { if (route.SwitchingDevice is IRouting switchingDevice) { if(clearRoute) { try { switchingDevice.ExecuteSwitch(null, route.OutputPort.Selector, SignalType); } catch (Exception e) { Debug.LogError("Error executing switch: {exception}", e.Message); } } if (route.OutputPort == null) { continue; } 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); } else { Debug.LogMessage(LogEventLevel.Error, "InUseTracker is null for OutputPort {0}", null, route.OutputPort.Key); } } } } /// /// Returns a string representation of the route descriptor, including source, destination, and individual route steps. /// /// A string describing the route. public override string ToString() { var routesText = Routes.Select(r => r.ToString()).ToArray(); return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText)); } } /*/// /// Represents an collection of individual route steps between Source and Destination /// public class RouteDescriptor { public IRoutingInputs Destination { get; private set; } public IRoutingOutputs Source { get; private set; } public eRoutingSignalType SignalType { get; private set; } public List> Routes { get; private set; } public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) { Destination = destination; Source = source; SignalType = signalType; Routes = new List>(); } /// /// Executes all routes described in this collection. Typically called via /// extension method IRoutingInputs.ReleaseAndMakeRoute() /// public void ExecuteRoutes() { foreach (var route in Routes) { Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}", null, route.ToString()); if (route.SwitchingDevice is IRoutingSinkWithSwitching sink) { sink.ExecuteSwitch(route.InputPort.Selector); continue; } if (route.SwitchingDevice is IRouting switchingDevice) { switchingDevice.ExecuteSwitch(route.InputPort.Selector, route.OutputPort.Selector, SignalType); 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); } } } /// /// Releases all routes in this collection. Typically called via /// extension method IRoutingInputs.ReleaseAndMakeRoute() /// public void ReleaseRoutes() { foreach (var route in Routes) { if (route.SwitchingDevice is IRouting) { // Pull the route from the port. Whatever is watching the output's in use tracker is // responsible for responding appropriately. 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); } } } public override string ToString() { var routesText = Routes.Select(r => r.ToString()).ToArray(); return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText)); } }*/ }