diff --git a/src/PepperDash.Essentials.Core/Routing/Extensions.cs b/src/PepperDash.Essentials.Core/Routing/Extensions.cs
index 1ad4dd7f..f3eec22a 100644
--- a/src/PepperDash.Essentials.Core/Routing/Extensions.cs
+++ b/src/PepperDash.Essentials.Core/Routing/Extensions.cs
@@ -18,8 +18,15 @@ namespace PepperDash.Essentials.Core
///
public static class Extensions
{
+ ///
+ /// Stores pending route requests, keyed by the destination device key.
+ /// Used primarily to handle routing requests while a device is cooling down.
+ ///
private static readonly Dictionary RouteRequests = new Dictionary();
+ ///
+ /// A queue to process route requests and releases sequentially.
+ ///
private static readonly GenericQueue routeRequestQueue = new GenericQueue("routingQueue");
///
@@ -38,16 +45,49 @@ namespace PepperDash.Essentials.Core
ReleaseAndMakeRoute(destination, source, signalType, inputPort, outputPort);
}
+
+ ///
+ /// Will release the existing route to the destination, if a route is found. This does not CLEAR the route, only stop counting usage time on any output ports that have a usage tracker set
+ ///
+ /// destination to clear
public static void ReleaseRoute(this IRoutingInputs destination)
{
- routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty));
+ routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty, false));
}
+ ///
+ /// Will release the existing route to the destination, if a route is found. This does not CLEAR the route, only stop counting usage time on any output ports that have a usage tracker set
+ ///
+ /// destination to clear
+ /// Input to use to find existing route
public static void ReleaseRoute(this IRoutingInputs destination, string inputPortKey)
{
- routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey));
+ routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey, false));
}
+ ///
+ /// Clears the route on the destination. This will remove any routes that are currently in use
+ ///
+ /// Destination
+ public static void ClearRoute(this IRoutingInputs destination)
+ {
+ routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty, true));
+ }
+
+ ///
+ /// Clears the route on the destination. This will remove any routes that are currently in use
+ ///
+ /// destination
+ /// input to use to find existing route
+ public static void ClearRoute(this IRoutingInputs destination, string inputPortKey)
+ {
+ routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey, true));
+ }
+
+ ///
+ /// Removes the route request for the destination. This will remove any routes that are currently in use
+ ///
+ /// destination device key
public static void RemoveRouteRequestForDestination(string destinationKey)
{
Debug.LogMessage(LogEventLevel.Information, "Removing route request for {destination}", null, destinationKey);
@@ -130,6 +170,15 @@ namespace PepperDash.Essentials.Core
return (audioRouteDescriptor, videoRouteDescriptor);
}
+ ///
+ /// Internal method to handle the logic for releasing an existing route and making a new one.
+ /// Handles devices with cooling states by queueing the request.
+ ///
+ /// The destination device.
+ /// The source device.
+ /// The type of signal to route.
+ /// The specific destination input port (optional).
+ /// The specific source output port (optional).
private static void ReleaseAndMakeRoute(IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort = null, RoutingOutputPort sourcePort = null)
{
if (destination == null) throw new ArgumentNullException(nameof(destination));
@@ -184,11 +233,16 @@ namespace PepperDash.Essentials.Core
Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is NOT cooling down. Removing stored route request and routing to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
}
- routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination,destinationPort?.Key ?? string.Empty));
+ routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination,destinationPort?.Key ?? string.Empty, false));
routeRequestQueue.Enqueue(new RouteRequestQueueItem(RunRouteRequest, routeRequest));
}
+ ///
+ /// Executes the actual routing based on a .
+ /// Finds the route path, adds it to the collection, and executes the switches.
+ ///
+ /// The route request details.
private static void RunRouteRequest(RouteRequest request)
{
try
@@ -216,14 +270,15 @@ namespace PepperDash.Essentials.Core
{
Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request);
}
- }
+ }
///
- /// Will release the existing route on the destination, if it is found in
- /// RouteDescriptorCollection.DefaultCollection
+ /// Will release the existing route on the destination, if it is found in RouteDescriptorCollection.DefaultCollection
///
- ///
- private static void ReleaseRouteInternal(IRoutingInputs destination, string inputPortKey)
+ ///
+ /// The input port key to use to find the route. If empty, will use the first available input port
+ /// If true, will clear the route on the destination. This will remove any routes that are currently in use
+ private static void ReleaseRouteInternal(IRoutingInputs destination, string inputPortKey, bool clearRoute)
{
try
{
@@ -242,7 +297,7 @@ namespace PepperDash.Essentials.Core
if (current != null)
{
Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key);
- current.ReleaseRoutes();
+ current.ReleaseRoutes(clearRoute);
}
} catch (Exception ex)
{
diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingSource.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingSource.cs
index d50bcbb0..d3f61e72 100644
--- a/src/PepperDash.Essentials.Core/Routing/IRoutingSource.cs
+++ b/src/PepperDash.Essentials.Core/Routing/IRoutingSource.cs
@@ -1,7 +1,7 @@
namespace PepperDash.Essentials.Core
{
///
- /// Defines an IRoutingOutputs devices as being a source - the start of the chain
+ /// Marker interface to identify a device that acts as the origin of a signal path ().
///
public interface IRoutingSource : IRoutingOutputs
{
diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingWithClear.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingWithClear.cs
index 077d4ecd..407133ef 100644
--- a/src/PepperDash.Essentials.Core/Routing/IRoutingWithClear.cs
+++ b/src/PepperDash.Essentials.Core/Routing/IRoutingWithClear.cs
@@ -1,5 +1,8 @@
namespace PepperDash.Essentials.Core
{
+ ///
+ /// Defines a routing device () that supports explicitly clearing a route on an output.
+ ///
public interface IRoutingWithClear : IRouting
{
///
diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingWithFeedback.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingWithFeedback.cs
index dcf4e423..a328441a 100644
--- a/src/PepperDash.Essentials.Core/Routing/IRoutingWithFeedback.cs
+++ b/src/PepperDash.Essentials.Core/Routing/IRoutingWithFeedback.cs
@@ -3,14 +3,25 @@ using System;
namespace PepperDash.Essentials.Core
{
+ ///
+ /// Delegate for handling route change events on devices implementing .
+ ///
+ /// The routing device where the change occurred.
+ /// A descriptor of the new route that was established.
public delegate void RouteChangedEventHandler(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute);
///
- /// Defines an IRouting with a feedback event
+ /// Defines a routing device () that provides feedback about its current routes.
///
public interface IRoutingWithFeedback : IRouting
{
+ ///
+ /// Gets a list describing the currently active routes on this device.
+ ///
List CurrentRoutes { get; }
+ ///
+ /// Event triggered when a route changes on this device.
+ ///
event RouteChangedEventHandler RouteChanged;
}
}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Routing/ITxRouting.cs b/src/PepperDash.Essentials.Core/Routing/ITxRouting.cs
index 0950e6a6..a157e8d1 100644
--- a/src/PepperDash.Essentials.Core/Routing/ITxRouting.cs
+++ b/src/PepperDash.Essentials.Core/Routing/ITxRouting.cs
@@ -1,8 +1,18 @@
namespace PepperDash.Essentials.Core
{
+ ///
+ /// Represents a routing device (typically a transmitter or source) that provides numeric feedback for its current route.
+ /// Extends .
+ ///
public interface ITxRouting : IRoutingNumeric
{
+ ///
+ /// Feedback indicating the currently routed video source by its numeric identifier.
+ ///
IntFeedback VideoSourceNumericFeedback { get; }
+ ///
+ /// Feedback indicating the currently routed audio source by its numeric identifier.
+ ///
IntFeedback AudioSourceNumericFeedback { get; }
}
}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Routing/RouteDescriptor.cs b/src/PepperDash.Essentials.Core/Routing/RouteDescriptor.cs
index b7dade4c..e02dd30e 100644
--- a/src/PepperDash.Essentials.Core/Routing/RouteDescriptor.cs
+++ b/src/PepperDash.Essentials.Core/Routing/RouteDescriptor.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
using Crestron.SimplSharpPro;
@@ -9,35 +10,63 @@ using Serilog.Events;
namespace PepperDash.Essentials.Core
{
///
- /// Represents an collection of individual route steps between Source and Destination
+ /// 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;
- InputPort = inputPort;
Routes = new List();
}
///
- /// Executes all routes described in this collection. Typically called via
- /// extension method IRoutingInputs.ReleaseAndMakeRoute()
+ /// Executes all the switching steps defined in the list.
///
public void ExecuteRoutes()
{
@@ -63,15 +92,27 @@ namespace PepperDash.Essentials.Core
}
///
- /// Releases all routes in this collection. Typically called via
- /// extension method IRoutingInputs.ReleaseAndMakeRoute()
+ /// Releases the usage tracking for the route and optionally clears the route on the switching devices.
///
- public void ReleaseRoutes()
+ /// 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;
@@ -90,6 +131,10 @@ namespace PepperDash.Essentials.Core
}
}
+ ///
+ /// 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();
diff --git a/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs b/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs
index 19d8655b..a8bdf015 100644
--- a/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs
+++ b/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs
@@ -4,15 +4,42 @@ using System;
namespace PepperDash.Essentials.Core
{
+ ///
+ /// Represents a request to establish a route between a source and a destination device.
+ ///
public class RouteRequest
{
+ ///
+ /// The specific input port on the destination device to use for the route. Can be null if the port should be automatically determined or is not applicable.
+ ///
public RoutingInputPort DestinationPort { get; set; }
+ ///
+ /// The specific output port on the source device to use for the route. Can be null if the port should be automatically determined or is not applicable.
+ ///
public RoutingOutputPort SourcePort { get; set; }
+
+ ///
+ /// The destination device (sink or midpoint) for the route.
+ ///
public IRoutingInputs Destination { get; set; }
+
+ ///
+ /// The source device for the route.
+ ///
public IRoutingOutputs Source { get; set; }
+
+ ///
+ /// The type of signal being routed (e.g., Audio, Video, AudioVideo).
+ ///
public eRoutingSignalType SignalType { get; set; }
+ ///
+ /// Handles the route request after a device's cooldown period has finished.
+ /// This method is typically subscribed to the IsCoolingDownFeedback.OutputChange event.
+ ///
+ /// The object that triggered the event (usually the cooling device).
+ /// Event arguments indicating the cooldown state change.
public void HandleCooldown(object sender, FeedbackEventArgs args)
{
try
@@ -39,6 +66,10 @@ namespace PepperDash.Essentials.Core
}
}
+ ///
+ /// Returns a string representation of the route request.
+ ///
+ /// A string describing the source and destination of the route request.
public override string ToString()
{
return $"Route {Source?.Key ?? "No Source Device"}:{SourcePort?.Key ?? "auto"} to {Destination?.Key ?? "No Destination Device"}:{DestinationPort?.Key ?? "auto"}";
diff --git a/src/PepperDash.Essentials.Core/Routing/RouteRequestQueueItem.cs b/src/PepperDash.Essentials.Core/Routing/RouteRequestQueueItem.cs
index 05681991..07b52c2c 100644
--- a/src/PepperDash.Essentials.Core/Routing/RouteRequestQueueItem.cs
+++ b/src/PepperDash.Essentials.Core/Routing/RouteRequestQueueItem.cs
@@ -5,17 +5,34 @@ using Serilog.Events;
namespace PepperDash.Essentials.Core.Routing
{
+ ///
+ /// Represents an item in the route request queue.
+ ///
public class RouteRequestQueueItem : IQueueMessage
{
+ ///
+ /// The action to perform for the route request.
+ ///
private readonly Action action;
+ ///
+ /// The route request data.
+ ///
private readonly RouteRequest routeRequest;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The action to perform.
+ /// The route request data.
public RouteRequestQueueItem(Action routeAction, RouteRequest request)
{
action = routeAction;
routeRequest = request;
}
+ ///
+ /// Dispatches the route request action.
+ ///
public void Dispatch()
{
Debug.LogMessage(LogEventLevel.Information, "Dispatching route request {routeRequest}", null, routeRequest);
@@ -23,23 +40,50 @@ namespace PepperDash.Essentials.Core.Routing
}
}
+ ///
+ /// Represents an item in the queue for releasing a route.
+ ///
public class ReleaseRouteQueueItem : IQueueMessage
{
- private readonly Action action;
+ ///
+ /// The action to perform for releasing the route.
+ ///
+ private readonly Action action;
+ ///
+ /// The destination device whose route is being released.
+ ///
private readonly IRoutingInputs destination;
+ ///
+ /// The specific input port key on the destination to release, or null/empty for any/default.
+ ///
private readonly string inputPortKey;
+ ///
+ /// Indicates whether to clear the route (send null) or just release the usage tracking.
+ ///
+ private readonly bool clearRoute;
- public ReleaseRouteQueueItem(Action action, IRoutingInputs destination, string inputPortKey)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The action to perform.
+ /// The destination device.
+ /// The input port key.
+ /// True to clear the route, false to just release.
+ public ReleaseRouteQueueItem(Action action, IRoutingInputs destination, string inputPortKey, bool clearRoute)
{
this.action = action;
this.destination = destination;
this.inputPortKey = inputPortKey;
+ this.clearRoute = clearRoute;
}
+ ///
+ /// Dispatches the release route action.
+ ///
public void Dispatch()
{
Debug.LogMessage(LogEventLevel.Information, "Dispatching release route request for {destination}:{inputPortKey}", null, destination?.Key ?? "no destination", string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
- action(destination, inputPortKey);
+ action(destination, inputPortKey, clearRoute);
}
}
}
diff --git a/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs b/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs
index c425d0a4..6394a3bc 100644
--- a/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs
+++ b/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs
@@ -1,25 +1,47 @@
namespace PepperDash.Essentials.Core
{
///
- /// Represents an individual link for a route
+ /// Represents a single switching step within a larger route, detailing the switching device, input port, and optionally the output port.
///
public class RouteSwitchDescriptor
{
+ ///
+ /// The device performing the switch (derived from the InputPort's parent).
+ ///
public IRoutingInputs SwitchingDevice { get { return InputPort?.ParentDevice; } }
+ ///
+ /// The output port being switched from (relevant for matrix switchers). Null for sink devices.
+ ///
public RoutingOutputPort OutputPort { get; set; }
+ ///
+ /// The input port being switched to.
+ ///
public RoutingInputPort InputPort { get; set; }
+ ///
+ /// Initializes a new instance of the class for sink devices (no output port).
+ ///
+ /// The input port being switched to.
public RouteSwitchDescriptor(RoutingInputPort inputPort)
{
InputPort = inputPort;
}
+ ///
+ /// Initializes a new instance of the class for matrix switchers.
+ ///
+ /// The output port being switched from.
+ /// The input port being switched to.
public RouteSwitchDescriptor(RoutingOutputPort outputPort, RoutingInputPort inputPort)
{
InputPort = inputPort;
OutputPort = outputPort;
}
+ ///
+ /// Returns a string representation of the route switch descriptor.
+ ///
+ /// A string describing the switch operation.
public override string ToString()
{
if (SwitchingDevice is IRouting)
diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs b/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs
index 4e2ccc5b..9afdb33d 100644
--- a/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs
+++ b/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs
@@ -5,8 +5,17 @@ using System.Linq;
namespace PepperDash.Essentials.Core.Routing
{
+ ///
+ /// Manages routing feedback by subscribing to route changes on midpoint and sink devices,
+ /// tracing the route back to the original source, and updating the CurrentSourceInfo on sink devices.
+ ///
public class RoutingFeedbackManager:EssentialsDevice
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The unique key for this manager device.
+ /// The name of this manager device.
public RoutingFeedbackManager(string key, string name): base(key, name)
{
AddPreActivationAction(SubscribeForMidpointFeedback);
@@ -14,6 +23,9 @@ namespace PepperDash.Essentials.Core.Routing
}
+ ///
+ /// Subscribes to the RouteChanged event on all devices implementing .
+ ///
private void SubscribeForMidpointFeedback()
{
var midpointDevices = DeviceManager.AllDevices.OfType();
@@ -24,6 +36,9 @@ namespace PepperDash.Essentials.Core.Routing
}
}
+ ///
+ /// Subscribes to the InputChanged event on all devices implementing .
+ ///
private void SubscribeForSinkFeedback()
{
var sinkDevices = DeviceManager.AllDevices.OfType();
@@ -34,6 +49,12 @@ namespace PepperDash.Essentials.Core.Routing
}
}
+ ///
+ /// Handles the RouteChanged event from a midpoint device.
+ /// Triggers an update for all sink devices.
+ ///
+ /// The midpoint device that reported a route change.
+ /// The descriptor of the new route.
private void HandleMidpointUpdate(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute)
{
try
@@ -51,6 +72,12 @@ namespace PepperDash.Essentials.Core.Routing
}
}
+ ///
+ /// Handles the InputChanged event from a sink device.
+ /// Triggers an update for the specific sink device.
+ ///
+ /// The sink device that reported an input change.
+ /// The new input port selected on the sink device.
private void HandleSinkUpdate(IRoutingSinkWithSwitching sender, RoutingInputPort currentInputPort)
{
try
@@ -63,6 +90,12 @@ namespace PepperDash.Essentials.Core.Routing
}
}
+ ///
+ /// Updates the CurrentSourceInfo and CurrentSourceInfoKey properties on a destination (sink) device
+ /// based on its currently selected input port by tracing the route back through tie lines.
+ ///
+ /// The destination sink device to update.
+ /// The currently selected input port on the destination device.
private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort)
{
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key);
@@ -199,6 +232,12 @@ namespace PepperDash.Essentials.Core.Routing
}
+ ///
+ /// Recursively traces a route back from a given tie line to find the root source tie line.
+ /// It navigates through midpoint devices () by checking their current routes.
+ ///
+ /// The starting tie line (typically connected to a sink or midpoint).
+ /// The connected to the original source device, or null if the source cannot be determined.
private TieLine GetRootTieLine(TieLine tieLine)
{
TieLine nextTieLine = null;
diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingInputPort.cs b/src/PepperDash.Essentials.Core/Routing/RoutingInputPort.cs
index 3dbbb6af..c949db4e 100644
--- a/src/PepperDash.Essentials.Core/Routing/RoutingInputPort.cs
+++ b/src/PepperDash.Essentials.Core/Routing/RoutingInputPort.cs
@@ -5,7 +5,7 @@ using System;
namespace PepperDash.Essentials.Core
{
///
- /// Basic RoutingInput with no statuses.
+ /// Represents a basic routing input port on a device.
///
public class RoutingInputPort : RoutingPort
{
@@ -41,6 +41,10 @@ namespace PepperDash.Essentials.Core
ParentDevice = parent;
}
+ ///
+ /// Returns a string representation of the input port.
+ ///
+ /// A string in the format "ParentDeviceKey|PortKey|SignalType|ConnectionType".
public override string ToString()
{
return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}";
diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingInputPortWithVideoStatuses.cs b/src/PepperDash.Essentials.Core/Routing/RoutingInputPortWithVideoStatuses.cs
index bd4dd489..e0c6bba0 100644
--- a/src/PepperDash.Essentials.Core/Routing/RoutingInputPortWithVideoStatuses.cs
+++ b/src/PepperDash.Essentials.Core/Routing/RoutingInputPortWithVideoStatuses.cs
@@ -1,24 +1,25 @@
namespace PepperDash.Essentials.Core
{
///
- /// A RoutingInputPort for devices like DM-TX and DM input cards.
- /// Will provide video statistics on connected signals
+ /// Represents a routing input port that provides video status feedback (e.g., sync, resolution).
+ /// Suitable for devices like DM transmitters or DM input cards.
///
public class RoutingInputPortWithVideoStatuses : RoutingInputPort
{
///
- /// Video statuses attached to this port
+ /// Provides feedback outputs for video statuses associated with this port.
///
public VideoStatusOutputs VideoStatus { get; private set; }
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
- /// An object used to refer to this port in the IRouting device's ExecuteSwitch method.
- /// May be string, number, whatever
- /// The IRoutingInputs object this lives on
- /// A VideoStatusFuncsWrapper used to assign the callback funcs that will get
- /// the values for the various stats
+ /// The unique key for this port.
+ /// The signal type supported by this port.
+ /// The physical connection type of this port.
+ /// An object used to refer to this port in the parent device's ExecuteSwitch method.
+ /// The device this port belongs to.
+ /// A containing delegates to retrieve video status values.
public RoutingInputPortWithVideoStatuses(string key,
eRoutingSignalType type, eRoutingPortConnectionType connType, object selector,
IRoutingInputs parent, VideoStatusFuncsWrapper funcs) :
diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingNumericEventArgs.cs b/src/PepperDash.Essentials.Core/Routing/RoutingNumericEventArgs.cs
index 7ede13c2..a0e706ac 100644
--- a/src/PepperDash.Essentials.Core/Routing/RoutingNumericEventArgs.cs
+++ b/src/PepperDash.Essentials.Core/Routing/RoutingNumericEventArgs.cs
@@ -3,32 +3,72 @@
namespace PepperDash.Essentials.Core
{
+ ///
+ /// Provides event arguments for routing changes, potentially including numeric or port object references.
+ ///
public class RoutingNumericEventArgs : EventArgs
{
-
+ ///
+ /// The numeric representation of the output, if applicable.
+ ///
public uint? Output { get; set; }
+ ///
+ /// The numeric representation of the input, if applicable.
+ ///
public uint? Input { get; set; }
+ ///
+ /// The type of signal involved in the routing change.
+ ///
public eRoutingSignalType SigType { get; set; }
+ ///
+ /// The input port involved in the routing change, if applicable.
+ ///
public RoutingInputPort InputPort { get; set; }
+ ///
+ /// The output port involved in the routing change, if applicable.
+ ///
public RoutingOutputPort OutputPort { get; set; }
+ ///
+ /// Initializes a new instance of the class using numeric identifiers.
+ ///
+ /// The numeric output identifier.
+ /// The numeric input identifier.
+ /// The signal type.
public RoutingNumericEventArgs(uint output, uint input, eRoutingSignalType sigType) : this(output, input, null, null, sigType)
{
}
+ ///
+ /// Initializes a new instance of the class using port objects.
+ ///
+ /// The output port object.
+ /// The input port object.
+ /// The signal type.
public RoutingNumericEventArgs(RoutingOutputPort outputPort, RoutingInputPort inputPort,
eRoutingSignalType sigType)
: this(null, null, outputPort, inputPort, sigType)
{
}
+ ///
+ /// Initializes a new instance of the class with default values.
+ ///
public RoutingNumericEventArgs()
: this(null, null, null, null, 0)
{
}
+ ///
+ /// Initializes a new instance of the class with potentially mixed identifiers.
+ ///
+ /// The numeric output identifier (optional).
+ /// The numeric input identifier (optional).
+ /// The output port object (optional).
+ /// The input port object (optional).
+ /// The signal type.
public RoutingNumericEventArgs(uint? output, uint? input, RoutingOutputPort outputPort,
RoutingInputPort inputPort, eRoutingSignalType sigType)
{
diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingOutputPort.cs b/src/PepperDash.Essentials.Core/Routing/RoutingOutputPort.cs
index fbbd3a22..1cae64c0 100644
--- a/src/PepperDash.Essentials.Core/Routing/RoutingOutputPort.cs
+++ b/src/PepperDash.Essentials.Core/Routing/RoutingOutputPort.cs
@@ -4,29 +4,46 @@ using System;
namespace PepperDash.Essentials.Core
{
+ ///
+ /// Represents a basic routing output port on a device.
+ ///
public class RoutingOutputPort : RoutingPort
{
///
- /// The IRoutingOutputs object this port lives on
+ /// The IRoutingOutputs object this port lives on.
///
- ///
[JsonIgnore]
public IRoutingOutputs ParentDevice { get; private set; }
+ ///
+ /// Tracks which destinations are currently using this output port.
+ ///
public InUseTracking InUseTracker { get; private set; }
///
+ /// Initializes a new instance of the class.
///
- /// An object used to refer to this port in the IRouting device's ExecuteSwitch method.
- /// May be string, number, whatever
- /// The IRoutingOutputs object this port lives on
+ /// The unique key for this port.
+ /// The signal type supported by this port.
+ /// The physical connection type of this port.
+ /// An object used to refer to this port in the parent device's ExecuteSwitch method.
+ /// The device this port belongs to.
public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType,
object selector, IRoutingOutputs parent)
: this(key, type, connType, selector, parent, false)
{
}
+ ///
+ /// Initializes a new instance of the class, potentially marking it as internal.
+ ///
+ /// The unique key for this port.
+ /// The signal type supported by this port.
+ /// The physical connection type of this port.
+ /// An object used to refer to this port in the parent device's ExecuteSwitch method.
+ /// The device this port belongs to.
+ /// True if this port represents an internal connection within a device (e.g., card to backplane).
public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType,
object selector, IRoutingOutputs parent, bool isInternal)
: base(key, type, connType, selector, isInternal)
@@ -35,6 +52,10 @@ namespace PepperDash.Essentials.Core
InUseTracker = new InUseTracking();
}
+ ///
+ /// Returns a string representation of the output port.
+ ///
+ /// A string in the format "ParentDeviceKey|PortKey|SignalType|ConnectionType".
public override string ToString()
{
return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}";
diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs b/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs
index 04e804f1..64fae203 100644
--- a/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs
+++ b/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs
@@ -4,18 +4,47 @@
namespace PepperDash.Essentials.Core
{
///
- /// Base class for RoutingInput and Output ports
+ /// Base class for and .
///
public abstract class RoutingPort : IKeyed
{
+ ///
+ /// The unique key identifying this port within its parent device.
+ ///
public string Key { get; private set; }
+ ///
+ /// The type of signal this port handles (e.g., Audio, Video, AudioVideo).
+ ///
public eRoutingSignalType Type { get; private set; }
+ ///
+ /// The physical connection type of this port (e.g., Hdmi, Rca, Dm).
+ ///
public eRoutingPortConnectionType ConnectionType { get; private set; }
+ ///
+ /// An object (often a number or string) used by the parent routing device to select this port during switching.
+ ///
public readonly object Selector;
+ ///
+ /// Indicates if this port represents an internal connection within a device (e.g., card to backplane).
+ ///
public bool IsInternal { get; private set; }
+ ///
+ /// An object used to match feedback values to this port, if applicable.
+ ///
public object FeedbackMatchObject { get; set; }
+ ///
+ /// A reference to the underlying hardware port object (e.g., SimplSharpPro Port), if applicable.
+ ///
public object Port { get; set; }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The unique key for this port.
+ /// The signal type supported by this port.
+ /// The physical connection type of this port.
+ /// The selector object for switching.
+ /// True if this port is internal.
public RoutingPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, object selector, bool isInternal)
{
Key = key;
diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs b/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs
index 160b4f16..96a2ca32 100644
--- a/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs
+++ b/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs
@@ -7,7 +7,8 @@ using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core
{
///
- /// These should correspond directly with the portNames var in the config tool.
+ /// Defines constant string values for common routing port keys.
+ /// These should correspond directly with the portNames var in the config tool.
///
public class RoutingPortNames
{
diff --git a/src/PepperDash.Essentials.Core/Routing/TieLine.cs b/src/PepperDash.Essentials.Core/Routing/TieLine.cs
index 51968152..f3a2c71d 100644
--- a/src/PepperDash.Essentials.Core/Routing/TieLine.cs
+++ b/src/PepperDash.Essentials.Core/Routing/TieLine.cs
@@ -4,14 +4,23 @@ using System.Collections.Generic;
namespace PepperDash.Essentials.Core
{
+ ///
+ /// Represents a connection (tie line) between a and a .
+ ///
public class TieLine
{
+ ///
+ /// The source output port of the tie line.
+ ///
public RoutingOutputPort SourcePort { get; private set; }
+ ///
+ /// The destination input port of the tie line.
+ ///
public RoutingInputPort DestinationPort { get; private set; }
//public int InUseCount { get { return DestinationUsingThis.Count; } }
///
- /// Gets the type of this tie line. Will either be the type of the desination port
+ /// Gets the type of this tie line. Will either be the type of the destination port
/// or the type of OverrideType when it is set.
///
public eRoutingSignalType Type
@@ -35,20 +44,27 @@ namespace PepperDash.Essentials.Core
//List DestinationUsingThis = new List();
///
- /// For tie lines that represent internal links, like from cards to the matrix in a DM.
- /// This property is true if SourcePort and DestinationPort IsInternal
- /// property are both true
+ /// Gets a value indicating whether this tie line represents an internal connection within a device (both source and destination ports are internal).
///
public bool IsInternal { get { return SourcePort.IsInternal && DestinationPort.IsInternal; } }
+ ///
+ /// Gets a value indicating whether the signal types of the source and destination ports differ.
+ ///
public bool TypeMismatch { get { return SourcePort.Type != DestinationPort.Type; } }
+ ///
+ /// Gets a value indicating whether the connection types of the source and destination ports differ.
+ ///
public bool ConnectionTypeMismatch { get { return SourcePort.ConnectionType != DestinationPort.ConnectionType; } }
+ ///
+ /// A descriptive note about any type mismatch, if applicable.
+ ///
public string TypeMismatchNote { get; set; }
///
- ///
+ /// Initializes a new instance of the class.
///
- ///
- ///
+ /// The source output port.
+ /// The destination input port.
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort)
{
if (sourcePort == null || destinationPort == null)
@@ -58,9 +74,11 @@ namespace PepperDash.Essentials.Core
}
///
- /// Creates a tie line with an overriding Type. See help for OverrideType property for info
+ /// Creates a tie line with an overriding Type. See help for OverrideType property for info.
///
- /// The signal type to limit the link to. Overrides DestinationPort.Type
+ /// The source output port.
+ /// The destination input port.
+ /// The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations.
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType? overrideType) :
this(sourcePort, destinationPort)
{
@@ -68,9 +86,11 @@ namespace PepperDash.Essentials.Core
}
///
- /// Creates a tie line with an overriding Type. See help for OverrideType property for info
+ /// Creates a tie line with an overriding Type. See help for OverrideType property for info.
///
- /// The signal type to limit the link to. Overrides DestinationPort.Type
+ /// The source output port.
+ /// The destination input port.
+ /// The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations.
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) :
this(sourcePort, destinationPort)
{
@@ -78,18 +98,25 @@ namespace PepperDash.Essentials.Core
}
///
- /// Will link up video status from supporting inputs to connected outputs
+ /// Will link up video status from supporting inputs to connected outputs.
///
public void Activate()
{
// Now does nothing
}
+ ///
+ /// Deactivates the tie line.
+ ///
public void Deactivate()
{
// Now does nothing
}
+ ///
+ /// Returns a string representation of the tie line.
+ ///
+ /// A string describing the source, destination, and type of the tie line.
public override string ToString()
{
return string.Format("Tie line: {0}:{1} --> {2}:{3} {4}", SourcePort.ParentDevice.Key, SourcePort.Key,
@@ -99,8 +126,14 @@ namespace PepperDash.Essentials.Core
//********************************************************************************
+ ///
+ /// Represents a collection of objects.
+ ///
public class TieLineCollection : List
{
+ ///
+ /// Gets the default singleton instance of the .
+ ///
public static TieLineCollection Default
{
get
@@ -111,6 +144,9 @@ namespace PepperDash.Essentials.Core
}
}
+ ///
+ /// Backing field for the singleton instance.
+ ///
[JsonIgnore]
private static TieLineCollection _Default;
}
diff --git a/src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs b/src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs
index e7ffb292..5090f9c2 100644
--- a/src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs
+++ b/src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs
@@ -1,6 +1,4 @@
-
-
-using System;
+using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
@@ -15,15 +13,44 @@ using Serilog.Events;
namespace PepperDash.Essentials.Core.Config
{
+ ///
+ /// Represents the configuration data for a single tie line between two routing ports.
+ ///
public class TieLineConfig
{
+ ///
+ /// The key of the source device.
+ ///
public string SourceKey { get; set; }
+
+ ///
+ /// The key of the source card (if applicable, e.g., in a modular chassis).
+ ///
public string SourceCard { get; set; }
+
+ ///
+ /// The key of the source output port.
+ ///
public string SourcePort { get; set; }
+
+ ///
+ /// The key of the destination device.
+ ///
public string DestinationKey { get; set; }
+
+ ///
+ /// The key of the destination card (if applicable).
+ ///
public string DestinationCard { get; set; }
+
+ ///
+ /// The key of the destination input port.
+ ///
public string DestinationPort { get; set; }
+ ///
+ /// Optional override for the signal type of the tie line. If set, this overrides the destination port's type for routing calculations.
+ ///
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
public eRoutingSignalType? OverrideType { get; set; }
@@ -73,11 +100,19 @@ namespace PepperDash.Essentials.Core.Config
return new TieLine(sourceOutputPort, destinationInputPort, OverrideType);
}
+ ///
+ /// Logs an error message related to creating this tie line configuration.
+ ///
+ /// The specific error message.
void LogError(string msg)
{
Debug.LogMessage(LogEventLevel.Error, "WARNING: Cannot create tie line: {message}:\r {tieLineConfig}",null, msg, this);
}
+ ///
+ /// Returns a string representation of the tie line configuration.
+ ///
+ /// A string describing the source and destination of the configured tie line.
public override string ToString()
{
return string.Format("{0}.{1}.{2} --> {3}.{4}.{5}", SourceKey, SourceCard, SourcePort,
diff --git a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs
index cc9bc1e2..618924cd 100644
--- a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs
+++ b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs
@@ -7,7 +7,7 @@ using System.Collections.Generic;
namespace PepperDash.Essentials.Devices.Common.Generic
{
- public class GenericSink : EssentialsDevice, IRoutingSink
+ public class GenericSink : EssentialsDevice, IRoutingSinkWithInputPort
{
public GenericSink(string key, string name) : base(key, name)
{
diff --git a/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs b/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs
index 7fdad9b4..84847f35 100644
--- a/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs
+++ b/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs
@@ -8,9 +8,10 @@ using System.Linq;
namespace PepperDash.Essentials.Devices.Common.SoftCodec
{
- public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingOutputs, IRoutingSinkWithSwitching
+ public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingSinkWithSwitchingWithInputPort
{
private RoutingInputPort _currentInputPort;
+
public RoutingInputPort CurrentInputPort {
get => _currentInputPort;
set