Compare commits

..

2 Commits

Author SHA1 Message Date
Andrew Welker
2f3babef91 build(force-patch): add props to package with Essentials version 2025-04-30 11:01:10 -05:00
Andrew Welker
ec1b99498a feat: set base MinimumEssentialsFrameworkVersion to Essentials version 2025-04-30 09:51:55 -05:00
25 changed files with 75 additions and 489 deletions

View File

@@ -1,6 +1,6 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Version>2.4.0-local</Version> <Version>2.4.0-local</Version>
<InformationalVersion>$(Version)</InformationalVersion> <InformationalVersion>$(Version)</InformationalVersion>
<Authors>PepperDash Technology</Authors> <Authors>PepperDash Technology</Authors>
<Company>PepperDash Technology</Company> <Company>PepperDash Technology</Company>
@@ -19,5 +19,6 @@
<ItemGroup> <ItemGroup>
<None Include="..\..\LICENSE.md" Pack="true" PackagePath=""/> <None Include="..\..\LICENSE.md" Pack="true" PackagePath=""/>
<None Include="..\..\README.md" Pack="true" PackagePath=""/> <None Include="..\..\README.md" Pack="true" PackagePath=""/>
<None Include=".\build\**" Pack="true" PackagePath="build"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -196,10 +196,18 @@ namespace PepperDash.Essentials.Core
/// </summary> /// </summary>
public abstract class EssentialsPluginDeviceFactory<T> : EssentialsDeviceFactory<T>, IPluginDeviceFactory where T : EssentialsDevice public abstract class EssentialsPluginDeviceFactory<T> : EssentialsDeviceFactory<T>, IPluginDeviceFactory where T : EssentialsDevice
{ {
#if ESSENTIALS_VERSION
/// <summary>
/// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33")
/// </summary>
public string MinimumEssentialsFrameworkVersion { get; protected set; } = ESSENTIALS_VERSION
#else
/// <summary> /// <summary>
/// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33") /// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33")
/// </summary> /// </summary>
public string MinimumEssentialsFrameworkVersion { get; protected set; } public string MinimumEssentialsFrameworkVersion { get; protected set; }
#endif
} }
public abstract class EssentialsPluginDevelopmentDeviceFactory<T> : EssentialsDeviceFactory<T>, IPluginDevelopmentDeviceFactory where T : EssentialsDevice public abstract class EssentialsPluginDevelopmentDeviceFactory<T> : EssentialsDeviceFactory<T>, IPluginDevelopmentDeviceFactory where T : EssentialsDevice

View File

@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Configurations>Debug;Release;Debug 4.7.2</Configurations> <Configurations>Debug;Release;Debug 4.7.2</Configurations>
<DefineConstants>$(DefineConstants);ESSENTIALS_VERSION=$(Version)</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<TargetFramework>net472</TargetFramework> <TargetFramework>net472</TargetFramework>

View File

@@ -18,15 +18,8 @@ namespace PepperDash.Essentials.Core
/// </summary> /// </summary>
public static class Extensions public static class Extensions
{ {
/// <summary>
/// Stores pending route requests, keyed by the destination device key.
/// Used primarily to handle routing requests while a device is cooling down.
/// </summary>
private static readonly Dictionary<string, RouteRequest> RouteRequests = new Dictionary<string, RouteRequest>(); private static readonly Dictionary<string, RouteRequest> RouteRequests = new Dictionary<string, RouteRequest>();
/// <summary>
/// A queue to process route requests and releases sequentially.
/// </summary>
private static readonly GenericQueue routeRequestQueue = new GenericQueue("routingQueue"); private static readonly GenericQueue routeRequestQueue = new GenericQueue("routingQueue");
/// <summary> /// <summary>
@@ -45,49 +38,16 @@ namespace PepperDash.Essentials.Core
ReleaseAndMakeRoute(destination, source, signalType, inputPort, outputPort); ReleaseAndMakeRoute(destination, source, signalType, inputPort, outputPort);
} }
/// <summary>
/// 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
/// </summary>
/// <param name="destination">destination to clear</param>
public static void ReleaseRoute(this IRoutingInputs destination) public static void ReleaseRoute(this IRoutingInputs destination)
{ {
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty, false)); routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty));
} }
/// <summary>
/// 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
/// </summary>
/// <param name="destination">destination to clear</param>
/// <param name="inputPortKey">Input to use to find existing route</param>
public static void ReleaseRoute(this IRoutingInputs destination, string inputPortKey) public static void ReleaseRoute(this IRoutingInputs destination, string inputPortKey)
{ {
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey, false)); routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey));
} }
/// <summary>
/// Clears the route on the destination. This will remove any routes that are currently in use
/// </summary>
/// <param name="destination">Destination</param>
public static void ClearRoute(this IRoutingInputs destination)
{
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty, true));
}
/// <summary>
/// Clears the route on the destination. This will remove any routes that are currently in use
/// </summary>
/// <param name="destination">destination</param>
/// <param name="inputPortKey">input to use to find existing route</param>
public static void ClearRoute(this IRoutingInputs destination, string inputPortKey)
{
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey, true));
}
/// <summary>
/// Removes the route request for the destination. This will remove any routes that are currently in use
/// </summary>
/// <param name="destinationKey">destination device key</param>
public static void RemoveRouteRequestForDestination(string destinationKey) public static void RemoveRouteRequestForDestination(string destinationKey)
{ {
Debug.LogMessage(LogEventLevel.Information, "Removing route request for {destination}", null, destinationKey); Debug.LogMessage(LogEventLevel.Information, "Removing route request for {destination}", null, destinationKey);
@@ -170,15 +130,6 @@ namespace PepperDash.Essentials.Core
return (audioRouteDescriptor, videoRouteDescriptor); return (audioRouteDescriptor, videoRouteDescriptor);
} }
/// <summary>
/// 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.
/// </summary>
/// <param name="destination">The destination device.</param>
/// <param name="source">The source device.</param>
/// <param name="signalType">The type of signal to route.</param>
/// <param name="destinationPort">The specific destination input port (optional).</param>
/// <param name="sourcePort">The specific source output port (optional).</param>
private static void ReleaseAndMakeRoute(IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort = null, RoutingOutputPort sourcePort = null) private static void ReleaseAndMakeRoute(IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort = null, RoutingOutputPort sourcePort = null)
{ {
if (destination == null) throw new ArgumentNullException(nameof(destination)); if (destination == null) throw new ArgumentNullException(nameof(destination));
@@ -233,16 +184,11 @@ 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); 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, false)); routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination,destinationPort?.Key ?? string.Empty));
routeRequestQueue.Enqueue(new RouteRequestQueueItem(RunRouteRequest, routeRequest)); routeRequestQueue.Enqueue(new RouteRequestQueueItem(RunRouteRequest, routeRequest));
} }
/// <summary>
/// Executes the actual routing based on a <see cref="RouteRequest"/>.
/// Finds the route path, adds it to the collection, and executes the switches.
/// </summary>
/// <param name="request">The route request details.</param>
private static void RunRouteRequest(RouteRequest request) private static void RunRouteRequest(RouteRequest request)
{ {
try try
@@ -270,15 +216,14 @@ namespace PepperDash.Essentials.Core
{ {
Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request); Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request);
} }
} }
/// <summary> /// <summary>
/// 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
/// </summary> /// </summary>
/// <param name="destination"></param> /// <param name="destination"></param>
/// <param name="inputPortKey"> The input port key to use to find the route. If empty, will use the first available input port</param> private static void ReleaseRouteInternal(IRoutingInputs destination, string inputPortKey)
/// <param name="clearRoute"> If true, will clear the route on the destination. This will remove any routes that are currently in use</param>
private static void ReleaseRouteInternal(IRoutingInputs destination, string inputPortKey, bool clearRoute)
{ {
try try
{ {
@@ -297,7 +242,7 @@ namespace PepperDash.Essentials.Core
if (current != null) if (current != null)
{ {
Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key); Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key);
current.ReleaseRoutes(clearRoute); current.ReleaseRoutes();
} }
} catch (Exception ex) } catch (Exception ex)
{ {

View File

@@ -1,7 +1,7 @@
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary> /// <summary>
/// Marker interface to identify a device that acts as the origin of a signal path (<see cref="IRoutingOutputs"/>). /// Defines an IRoutingOutputs devices as being a source - the start of the chain
/// </summary> /// </summary>
public interface IRoutingSource : IRoutingOutputs public interface IRoutingSource : IRoutingOutputs
{ {

View File

@@ -1,8 +1,5 @@
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary>
/// Defines a routing device (<see cref="IRouting"/>) that supports explicitly clearing a route on an output.
/// </summary>
public interface IRoutingWithClear : IRouting public interface IRoutingWithClear : IRouting
{ {
/// <summary> /// <summary>

View File

@@ -3,25 +3,14 @@ using System;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary>
/// Delegate for handling route change events on devices implementing <see cref="IRoutingWithFeedback"/>.
/// </summary>
/// <param name="midpoint">The routing device where the change occurred.</param>
/// <param name="newRoute">A descriptor of the new route that was established.</param>
public delegate void RouteChangedEventHandler(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute); public delegate void RouteChangedEventHandler(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute);
/// <summary> /// <summary>
/// Defines a routing device (<see cref="IRouting"/>) that provides feedback about its current routes. /// Defines an IRouting with a feedback event
/// </summary> /// </summary>
public interface IRoutingWithFeedback : IRouting public interface IRoutingWithFeedback : IRouting
{ {
/// <summary>
/// Gets a list describing the currently active routes on this device.
/// </summary>
List<RouteSwitchDescriptor> CurrentRoutes { get; } List<RouteSwitchDescriptor> CurrentRoutes { get; }
/// <summary>
/// Event triggered when a route changes on this device.
/// </summary>
event RouteChangedEventHandler RouteChanged; event RouteChangedEventHandler RouteChanged;
} }
} }

View File

@@ -1,18 +1,8 @@
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary>
/// Represents a routing device (typically a transmitter or source) that provides numeric feedback for its current route.
/// Extends <see cref="IRoutingNumeric"/>.
/// </summary>
public interface ITxRouting : IRoutingNumeric public interface ITxRouting : IRoutingNumeric
{ {
/// <summary>
/// Feedback indicating the currently routed video source by its numeric identifier.
/// </summary>
IntFeedback VideoSourceNumericFeedback { get; } IntFeedback VideoSourceNumericFeedback { get; }
/// <summary>
/// Feedback indicating the currently routed audio source by its numeric identifier.
/// </summary>
IntFeedback AudioSourceNumericFeedback { get; } IntFeedback AudioSourceNumericFeedback { get; }
} }
} }

View File

@@ -1,5 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Crestron.SimplSharpPro; using Crestron.SimplSharpPro;
@@ -10,63 +9,35 @@ using Serilog.Events;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary> /// <summary>
/// Represents a collection of individual route steps between a Source and a Destination device for a specific signal type. /// Represents an collection of individual route steps between Source and Destination
/// </summary> /// </summary>
public class RouteDescriptor public class RouteDescriptor
{ {
/// <summary>
/// The destination device (sink or midpoint) for the route.
/// </summary>
public IRoutingInputs Destination { get; private set; } 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.
/// </summary>
public RoutingInputPort InputPort { get; private set; } public RoutingInputPort InputPort { get; private set; }
/// <summary>
/// The source device for the route.
/// </summary>
public IRoutingOutputs Source { get; private set; } public IRoutingOutputs Source { get; private set; }
/// <summary>
/// The type of signal being routed (e.g., Audio, Video). This descriptor represents a single signal type.
/// </summary>
public eRoutingSignalType SignalType { get; private set; } public eRoutingSignalType SignalType { get; private set; }
/// <summary>
/// A list of individual switching steps required to establish the route.
/// </summary>
public List<RouteSwitchDescriptor> Routes { get; private set; } public List<RouteSwitchDescriptor> Routes { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="RouteDescriptor"/> class for a route without a specific destination input port.
/// </summary>
/// <param name="source">The source device.</param>
/// <param name="destination">The destination device.</param>
/// <param name="signalType">The type of signal being routed.</param>
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) : this(source, destination, null, signalType) public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) : this(source, destination, null, signalType)
{ {
} }
/// <summary>
/// Initializes a new instance of the <see cref="RouteDescriptor"/> class for a route with a specific destination input port.
/// </summary>
/// <param name="source">The source device.</param>
/// <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)
{ {
Destination = destination; Destination = destination;
InputPort = inputPort;
Source = source; Source = source;
SignalType = signalType; SignalType = signalType;
InputPort = inputPort;
Routes = new List<RouteSwitchDescriptor>(); Routes = new List<RouteSwitchDescriptor>();
} }
/// <summary> /// <summary>
/// Executes all the switching steps defined in the <see cref="Routes"/> list. /// Executes all routes described in this collection. Typically called via
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
/// </summary> /// </summary>
public void ExecuteRoutes() public void ExecuteRoutes()
{ {
@@ -92,27 +63,15 @@ namespace PepperDash.Essentials.Core
} }
/// <summary> /// <summary>
/// Releases the usage tracking for the route and optionally clears the route on the switching devices. /// Releases all routes in this collection. Typically called via
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
/// </summary> /// </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()
public void ReleaseRoutes(bool clearRoute = false)
{ {
foreach (var route in Routes.Where(r => r.SwitchingDevice is IRouting)) foreach (var route in Routes.Where(r => r.SwitchingDevice is IRouting))
{ {
if (route.SwitchingDevice is IRouting switchingDevice) 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) if (route.OutputPort == null)
{ {
continue; continue;
@@ -131,10 +90,6 @@ namespace PepperDash.Essentials.Core
} }
} }
/// <summary>
/// Returns a string representation of the route descriptor, including source, destination, and individual route steps.
/// </summary>
/// <returns>A string describing the route.</returns>
public override string ToString() public override string ToString()
{ {
var routesText = Routes.Select(r => r.ToString()).ToArray(); var routesText = Routes.Select(r => r.ToString()).ToArray();

View File

@@ -4,42 +4,15 @@ using System;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary>
/// Represents a request to establish a route between a source and a destination device.
/// </summary>
public class RouteRequest public class RouteRequest
{ {
/// <summary>
/// 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.
/// </summary>
public RoutingInputPort DestinationPort { get; set; } public RoutingInputPort DestinationPort { get; set; }
/// <summary>
/// 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.
/// </summary>
public RoutingOutputPort SourcePort { get; set; } public RoutingOutputPort SourcePort { get; set; }
/// <summary>
/// The destination device (sink or midpoint) for the route.
/// </summary>
public IRoutingInputs Destination { get; set; } public IRoutingInputs Destination { get; set; }
/// <summary>
/// The source device for the route.
/// </summary>
public IRoutingOutputs Source { get; set; } public IRoutingOutputs Source { get; set; }
/// <summary>
/// The type of signal being routed (e.g., Audio, Video, AudioVideo).
/// </summary>
public eRoutingSignalType SignalType { get; set; } public eRoutingSignalType SignalType { get; set; }
/// <summary>
/// Handles the route request after a device's cooldown period has finished.
/// This method is typically subscribed to the IsCoolingDownFeedback.OutputChange event.
/// </summary>
/// <param name="sender">The object that triggered the event (usually the cooling device).</param>
/// <param name="args">Event arguments indicating the cooldown state change.</param>
public void HandleCooldown(object sender, FeedbackEventArgs args) public void HandleCooldown(object sender, FeedbackEventArgs args)
{ {
try try
@@ -66,10 +39,6 @@ namespace PepperDash.Essentials.Core
} }
} }
/// <summary>
/// Returns a string representation of the route request.
/// </summary>
/// <returns>A string describing the source and destination of the route request.</returns>
public override string ToString() public override string ToString()
{ {
return $"Route {Source?.Key ?? "No Source Device"}:{SourcePort?.Key ?? "auto"} to {Destination?.Key ?? "No Destination Device"}:{DestinationPort?.Key ?? "auto"}"; return $"Route {Source?.Key ?? "No Source Device"}:{SourcePort?.Key ?? "auto"} to {Destination?.Key ?? "No Destination Device"}:{DestinationPort?.Key ?? "auto"}";

View File

@@ -5,34 +5,17 @@ using Serilog.Events;
namespace PepperDash.Essentials.Core.Routing namespace PepperDash.Essentials.Core.Routing
{ {
/// <summary>
/// Represents an item in the route request queue.
/// </summary>
public class RouteRequestQueueItem : IQueueMessage public class RouteRequestQueueItem : IQueueMessage
{ {
/// <summary>
/// The action to perform for the route request.
/// </summary>
private readonly Action<RouteRequest> action; private readonly Action<RouteRequest> action;
/// <summary>
/// The route request data.
/// </summary>
private readonly RouteRequest routeRequest; private readonly RouteRequest routeRequest;
/// <summary>
/// Initializes a new instance of the <see cref="RouteRequestQueueItem"/> class.
/// </summary>
/// <param name="routeAction">The action to perform.</param>
/// <param name="request">The route request data.</param>
public RouteRequestQueueItem(Action<RouteRequest> routeAction, RouteRequest request) public RouteRequestQueueItem(Action<RouteRequest> routeAction, RouteRequest request)
{ {
action = routeAction; action = routeAction;
routeRequest = request; routeRequest = request;
} }
/// <summary>
/// Dispatches the route request action.
/// </summary>
public void Dispatch() public void Dispatch()
{ {
Debug.LogMessage(LogEventLevel.Information, "Dispatching route request {routeRequest}", null, routeRequest); Debug.LogMessage(LogEventLevel.Information, "Dispatching route request {routeRequest}", null, routeRequest);
@@ -40,50 +23,23 @@ namespace PepperDash.Essentials.Core.Routing
} }
} }
/// <summary>
/// Represents an item in the queue for releasing a route.
/// </summary>
public class ReleaseRouteQueueItem : IQueueMessage public class ReleaseRouteQueueItem : IQueueMessage
{ {
/// <summary> private readonly Action<IRoutingInputs, string> action;
/// The action to perform for releasing the route.
/// </summary>
private readonly Action<IRoutingInputs, string, bool> action;
/// <summary>
/// The destination device whose route is being released.
/// </summary>
private readonly IRoutingInputs destination; private readonly IRoutingInputs destination;
/// <summary>
/// The specific input port key on the destination to release, or null/empty for any/default.
/// </summary>
private readonly string inputPortKey; private readonly string inputPortKey;
/// <summary>
/// Indicates whether to clear the route (send null) or just release the usage tracking.
/// </summary>
private readonly bool clearRoute;
/// <summary> public ReleaseRouteQueueItem(Action<IRoutingInputs, string> action, IRoutingInputs destination, string inputPortKey)
/// Initializes a new instance of the <see cref="ReleaseRouteQueueItem"/> class.
/// </summary>
/// <param name="action">The action to perform.</param>
/// <param name="destination">The destination device.</param>
/// <param name="inputPortKey">The input port key.</param>
/// <param name="clearRoute">True to clear the route, false to just release.</param>
public ReleaseRouteQueueItem(Action<IRoutingInputs, string, bool> action, IRoutingInputs destination, string inputPortKey, bool clearRoute)
{ {
this.action = action; this.action = action;
this.destination = destination; this.destination = destination;
this.inputPortKey = inputPortKey; this.inputPortKey = inputPortKey;
this.clearRoute = clearRoute;
} }
/// <summary>
/// Dispatches the release route action.
/// </summary>
public void Dispatch() public void Dispatch()
{ {
Debug.LogMessage(LogEventLevel.Information, "Dispatching release route request for {destination}:{inputPortKey}", null, destination?.Key ?? "no destination", string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey); Debug.LogMessage(LogEventLevel.Information, "Dispatching release route request for {destination}:{inputPortKey}", null, destination?.Key ?? "no destination", string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
action(destination, inputPortKey, clearRoute); action(destination, inputPortKey);
} }
} }
} }

View File

@@ -1,47 +1,25 @@
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary> /// <summary>
/// Represents a single switching step within a larger route, detailing the switching device, input port, and optionally the output port. /// Represents an individual link for a route
/// </summary> /// </summary>
public class RouteSwitchDescriptor public class RouteSwitchDescriptor
{ {
/// <summary>
/// The device performing the switch (derived from the InputPort's parent).
/// </summary>
public IRoutingInputs SwitchingDevice { get { return InputPort?.ParentDevice; } } public IRoutingInputs SwitchingDevice { get { return InputPort?.ParentDevice; } }
/// <summary>
/// The output port being switched from (relevant for matrix switchers). Null for sink devices.
/// </summary>
public RoutingOutputPort OutputPort { get; set; } public RoutingOutputPort OutputPort { get; set; }
/// <summary>
/// The input port being switched to.
/// </summary>
public RoutingInputPort InputPort { get; set; } public RoutingInputPort InputPort { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="RouteSwitchDescriptor"/> class for sink devices (no output port).
/// </summary>
/// <param name="inputPort">The input port being switched to.</param>
public RouteSwitchDescriptor(RoutingInputPort inputPort) public RouteSwitchDescriptor(RoutingInputPort inputPort)
{ {
InputPort = inputPort; InputPort = inputPort;
} }
/// <summary>
/// Initializes a new instance of the <see cref="RouteSwitchDescriptor"/> class for matrix switchers.
/// </summary>
/// <param name="outputPort">The output port being switched from.</param>
/// <param name="inputPort">The input port being switched to.</param>
public RouteSwitchDescriptor(RoutingOutputPort outputPort, RoutingInputPort inputPort) public RouteSwitchDescriptor(RoutingOutputPort outputPort, RoutingInputPort inputPort)
{ {
InputPort = inputPort; InputPort = inputPort;
OutputPort = outputPort; OutputPort = outputPort;
} }
/// <summary>
/// Returns a string representation of the route switch descriptor.
/// </summary>
/// <returns>A string describing the switch operation.</returns>
public override string ToString() public override string ToString()
{ {
if (SwitchingDevice is IRouting) if (SwitchingDevice is IRouting)

View File

@@ -5,17 +5,8 @@ using System.Linq;
namespace PepperDash.Essentials.Core.Routing namespace PepperDash.Essentials.Core.Routing
{ {
/// <summary>
/// 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.
/// </summary>
public class RoutingFeedbackManager:EssentialsDevice public class RoutingFeedbackManager:EssentialsDevice
{ {
/// <summary>
/// Initializes a new instance of the <see cref="RoutingFeedbackManager"/> class.
/// </summary>
/// <param name="key">The unique key for this manager device.</param>
/// <param name="name">The name of this manager device.</param>
public RoutingFeedbackManager(string key, string name): base(key, name) public RoutingFeedbackManager(string key, string name): base(key, name)
{ {
AddPreActivationAction(SubscribeForMidpointFeedback); AddPreActivationAction(SubscribeForMidpointFeedback);
@@ -23,9 +14,6 @@ namespace PepperDash.Essentials.Core.Routing
} }
/// <summary>
/// Subscribes to the RouteChanged event on all devices implementing <see cref="IRoutingWithFeedback"/>.
/// </summary>
private void SubscribeForMidpointFeedback() private void SubscribeForMidpointFeedback()
{ {
var midpointDevices = DeviceManager.AllDevices.OfType<IRoutingWithFeedback>(); var midpointDevices = DeviceManager.AllDevices.OfType<IRoutingWithFeedback>();
@@ -36,9 +24,6 @@ namespace PepperDash.Essentials.Core.Routing
} }
} }
/// <summary>
/// Subscribes to the InputChanged event on all devices implementing <see cref="IRoutingSinkWithSwitchingWithInputPort"/>.
/// </summary>
private void SubscribeForSinkFeedback() private void SubscribeForSinkFeedback()
{ {
var sinkDevices = DeviceManager.AllDevices.OfType<IRoutingSinkWithSwitchingWithInputPort>(); var sinkDevices = DeviceManager.AllDevices.OfType<IRoutingSinkWithSwitchingWithInputPort>();
@@ -49,12 +34,6 @@ namespace PepperDash.Essentials.Core.Routing
} }
} }
/// <summary>
/// Handles the RouteChanged event from a midpoint device.
/// Triggers an update for all sink devices.
/// </summary>
/// <param name="midpoint">The midpoint device that reported a route change.</param>
/// <param name="newRoute">The descriptor of the new route.</param>
private void HandleMidpointUpdate(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute) private void HandleMidpointUpdate(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute)
{ {
try try
@@ -72,12 +51,6 @@ namespace PepperDash.Essentials.Core.Routing
} }
} }
/// <summary>
/// Handles the InputChanged event from a sink device.
/// Triggers an update for the specific sink device.
/// </summary>
/// <param name="sender">The sink device that reported an input change.</param>
/// <param name="currentInputPort">The new input port selected on the sink device.</param>
private void HandleSinkUpdate(IRoutingSinkWithSwitching sender, RoutingInputPort currentInputPort) private void HandleSinkUpdate(IRoutingSinkWithSwitching sender, RoutingInputPort currentInputPort)
{ {
try try
@@ -90,12 +63,6 @@ namespace PepperDash.Essentials.Core.Routing
} }
} }
/// <summary>
/// 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.
/// </summary>
/// <param name="destination">The destination sink device to update.</param>
/// <param name="inputPort">The currently selected input port on the destination device.</param>
private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort) private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort)
{ {
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key); // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key);
@@ -232,12 +199,6 @@ namespace PepperDash.Essentials.Core.Routing
} }
/// <summary>
/// Recursively traces a route back from a given tie line to find the root source tie line.
/// It navigates through midpoint devices (<see cref="IRoutingWithFeedback"/>) by checking their current routes.
/// </summary>
/// <param name="tieLine">The starting tie line (typically connected to a sink or midpoint).</param>
/// <returns>The <see cref="TieLine"/> connected to the original source device, or null if the source cannot be determined.</returns>
private TieLine GetRootTieLine(TieLine tieLine) private TieLine GetRootTieLine(TieLine tieLine)
{ {
TieLine nextTieLine = null; TieLine nextTieLine = null;

View File

@@ -5,7 +5,7 @@ using System;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary> /// <summary>
/// Represents a basic routing input port on a device. /// Basic RoutingInput with no statuses.
/// </summary> /// </summary>
public class RoutingInputPort : RoutingPort public class RoutingInputPort : RoutingPort
{ {
@@ -41,10 +41,6 @@ namespace PepperDash.Essentials.Core
ParentDevice = parent; ParentDevice = parent;
} }
/// <summary>
/// Returns a string representation of the input port.
/// </summary>
/// <returns>A string in the format "ParentDeviceKey|PortKey|SignalType|ConnectionType".</returns>
public override string ToString() public override string ToString()
{ {
return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}"; return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}";

View File

@@ -1,25 +1,24 @@
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary> /// <summary>
/// Represents a routing input port that provides video status feedback (e.g., sync, resolution). /// A RoutingInputPort for devices like DM-TX and DM input cards.
/// Suitable for devices like DM transmitters or DM input cards. /// Will provide video statistics on connected signals
/// </summary> /// </summary>
public class RoutingInputPortWithVideoStatuses : RoutingInputPort public class RoutingInputPortWithVideoStatuses : RoutingInputPort
{ {
/// <summary> /// <summary>
/// Provides feedback outputs for video statuses associated with this port. /// Video statuses attached to this port
/// </summary> /// </summary>
public VideoStatusOutputs VideoStatus { get; private set; } public VideoStatusOutputs VideoStatus { get; private set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RoutingInputPortWithVideoStatuses"/> class. /// Constructor
/// </summary> /// </summary>
/// <param name="key">The unique key for this port.</param> /// <param name="selector">An object used to refer to this port in the IRouting device's ExecuteSwitch method.
/// <param name="type">The signal type supported by this port.</param> /// May be string, number, whatever</param>
/// <param name="connType">The physical connection type of this port.</param> /// <param name="parent">The IRoutingInputs object this lives on</param>
/// <param name="selector">An object used to refer to this port in the parent device's ExecuteSwitch method.</param> /// <param name="funcs">A VideoStatusFuncsWrapper used to assign the callback funcs that will get
/// <param name="parent">The <see cref="IRoutingInputs"/> device this port belongs to.</param> /// the values for the various stats</param>
/// <param name="funcs">A <see cref="VideoStatusFuncsWrapper"/> containing delegates to retrieve video status values.</param>
public RoutingInputPortWithVideoStatuses(string key, public RoutingInputPortWithVideoStatuses(string key,
eRoutingSignalType type, eRoutingPortConnectionType connType, object selector, eRoutingSignalType type, eRoutingPortConnectionType connType, object selector,
IRoutingInputs parent, VideoStatusFuncsWrapper funcs) : IRoutingInputs parent, VideoStatusFuncsWrapper funcs) :

View File

@@ -3,72 +3,32 @@
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary>
/// Provides event arguments for routing changes, potentially including numeric or port object references.
/// </summary>
public class RoutingNumericEventArgs : EventArgs public class RoutingNumericEventArgs : EventArgs
{ {
/// <summary>
/// The numeric representation of the output, if applicable.
/// </summary>
public uint? Output { get; set; } public uint? Output { get; set; }
/// <summary>
/// The numeric representation of the input, if applicable.
/// </summary>
public uint? Input { get; set; } public uint? Input { get; set; }
/// <summary>
/// The type of signal involved in the routing change.
/// </summary>
public eRoutingSignalType SigType { get; set; } public eRoutingSignalType SigType { get; set; }
/// <summary>
/// The input port involved in the routing change, if applicable.
/// </summary>
public RoutingInputPort InputPort { get; set; } public RoutingInputPort InputPort { get; set; }
/// <summary>
/// The output port involved in the routing change, if applicable.
/// </summary>
public RoutingOutputPort OutputPort { get; set; } public RoutingOutputPort OutputPort { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="RoutingNumericEventArgs"/> class using numeric identifiers.
/// </summary>
/// <param name="output">The numeric output identifier.</param>
/// <param name="input">The numeric input identifier.</param>
/// <param name="sigType">The signal type.</param>
public RoutingNumericEventArgs(uint output, uint input, eRoutingSignalType sigType) : this(output, input, null, null, sigType) public RoutingNumericEventArgs(uint output, uint input, eRoutingSignalType sigType) : this(output, input, null, null, sigType)
{ {
} }
/// <summary>
/// Initializes a new instance of the <see cref="RoutingNumericEventArgs"/> class using port objects.
/// </summary>
/// <param name="outputPort">The output port object.</param>
/// <param name="inputPort">The input port object.</param>
/// <param name="sigType">The signal type.</param>
public RoutingNumericEventArgs(RoutingOutputPort outputPort, RoutingInputPort inputPort, public RoutingNumericEventArgs(RoutingOutputPort outputPort, RoutingInputPort inputPort,
eRoutingSignalType sigType) eRoutingSignalType sigType)
: this(null, null, outputPort, inputPort, sigType) : this(null, null, outputPort, inputPort, sigType)
{ {
} }
/// <summary>
/// Initializes a new instance of the <see cref="RoutingNumericEventArgs"/> class with default values.
/// </summary>
public RoutingNumericEventArgs() public RoutingNumericEventArgs()
: this(null, null, null, null, 0) : this(null, null, null, null, 0)
{ {
} }
/// <summary>
/// Initializes a new instance of the <see cref="RoutingNumericEventArgs"/> class with potentially mixed identifiers.
/// </summary>
/// <param name="output">The numeric output identifier (optional).</param>
/// <param name="input">The numeric input identifier (optional).</param>
/// <param name="outputPort">The output port object (optional).</param>
/// <param name="inputPort">The input port object (optional).</param>
/// <param name="sigType">The signal type.</param>
public RoutingNumericEventArgs(uint? output, uint? input, RoutingOutputPort outputPort, public RoutingNumericEventArgs(uint? output, uint? input, RoutingOutputPort outputPort,
RoutingInputPort inputPort, eRoutingSignalType sigType) RoutingInputPort inputPort, eRoutingSignalType sigType)
{ {

View File

@@ -4,46 +4,29 @@ using System;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary>
/// Represents a basic routing output port on a device.
/// </summary>
public class RoutingOutputPort : RoutingPort public class RoutingOutputPort : RoutingPort
{ {
/// <summary> /// <summary>
/// The IRoutingOutputs object this port lives on. /// The IRoutingOutputs object this port lives on
/// </summary> /// </summary>
///
[JsonIgnore] [JsonIgnore]
public IRoutingOutputs ParentDevice { get; private set; } public IRoutingOutputs ParentDevice { get; private set; }
/// <summary>
/// Tracks which destinations are currently using this output port.
/// </summary>
public InUseTracking InUseTracker { get; private set; } public InUseTracking InUseTracker { get; private set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RoutingOutputPort"/> class.
/// </summary> /// </summary>
/// <param name="key">The unique key for this port.</param> /// <param name="selector">An object used to refer to this port in the IRouting device's ExecuteSwitch method.
/// <param name="type">The signal type supported by this port.</param> /// May be string, number, whatever</param>
/// <param name="connType">The physical connection type of this port.</param> /// <param name="parent">The IRoutingOutputs object this port lives on</param>
/// <param name="selector">An object used to refer to this port in the parent device's ExecuteSwitch method.</param>
/// <param name="parent">The <see cref="IRoutingOutputs"/> device this port belongs to.</param>
public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType,
object selector, IRoutingOutputs parent) object selector, IRoutingOutputs parent)
: this(key, type, connType, selector, parent, false) : this(key, type, connType, selector, parent, false)
{ {
} }
/// <summary>
/// Initializes a new instance of the <see cref="RoutingOutputPort"/> class, potentially marking it as internal.
/// </summary>
/// <param name="key">The unique key for this port.</param>
/// <param name="type">The signal type supported by this port.</param>
/// <param name="connType">The physical connection type of this port.</param>
/// <param name="selector">An object used to refer to this port in the parent device's ExecuteSwitch method.</param>
/// <param name="parent">The <see cref="IRoutingOutputs"/> device this port belongs to.</param>
/// <param name="isInternal">True if this port represents an internal connection within a device (e.g., card to backplane).</param>
public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType,
object selector, IRoutingOutputs parent, bool isInternal) object selector, IRoutingOutputs parent, bool isInternal)
: base(key, type, connType, selector, isInternal) : base(key, type, connType, selector, isInternal)
@@ -52,10 +35,6 @@ namespace PepperDash.Essentials.Core
InUseTracker = new InUseTracking(); InUseTracker = new InUseTracking();
} }
/// <summary>
/// Returns a string representation of the output port.
/// </summary>
/// <returns>A string in the format "ParentDeviceKey|PortKey|SignalType|ConnectionType".</returns>
public override string ToString() public override string ToString()
{ {
return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}"; return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}";

View File

@@ -4,47 +4,18 @@
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary> /// <summary>
/// Base class for <see cref="RoutingInputPort"/> and <see cref="RoutingOutputPort"/>. /// Base class for RoutingInput and Output ports
/// </summary> /// </summary>
public abstract class RoutingPort : IKeyed public abstract class RoutingPort : IKeyed
{ {
/// <summary>
/// The unique key identifying this port within its parent device.
/// </summary>
public string Key { get; private set; } public string Key { get; private set; }
/// <summary>
/// The type of signal this port handles (e.g., Audio, Video, AudioVideo).
/// </summary>
public eRoutingSignalType Type { get; private set; } public eRoutingSignalType Type { get; private set; }
/// <summary>
/// The physical connection type of this port (e.g., Hdmi, Rca, Dm).
/// </summary>
public eRoutingPortConnectionType ConnectionType { get; private set; } public eRoutingPortConnectionType ConnectionType { get; private set; }
/// <summary>
/// An object (often a number or string) used by the parent routing device to select this port during switching.
/// </summary>
public readonly object Selector; public readonly object Selector;
/// <summary>
/// Indicates if this port represents an internal connection within a device (e.g., card to backplane).
/// </summary>
public bool IsInternal { get; private set; } public bool IsInternal { get; private set; }
/// <summary>
/// An object used to match feedback values to this port, if applicable.
/// </summary>
public object FeedbackMatchObject { get; set; } public object FeedbackMatchObject { get; set; }
/// <summary>
/// A reference to the underlying hardware port object (e.g., SimplSharpPro Port), if applicable.
/// </summary>
public object Port { get; set; } public object Port { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="RoutingPort"/> class.
/// </summary>
/// <param name="key">The unique key for this port.</param>
/// <param name="type">The signal type supported by this port.</param>
/// <param name="connType">The physical connection type of this port.</param>
/// <param name="selector">The selector object for switching.</param>
/// <param name="isInternal">True if this port is internal.</param>
public RoutingPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, object selector, bool isInternal) public RoutingPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, object selector, bool isInternal)
{ {
Key = key; Key = key;

View File

@@ -7,8 +7,7 @@ using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary> /// <summary>
/// Defines constant string values for common routing port keys. /// These should correspond directly with the portNames var in the config tool.
/// These should correspond directly with the portNames var in the config tool.
/// </summary> /// </summary>
public class RoutingPortNames public class RoutingPortNames
{ {

View File

@@ -4,23 +4,14 @@ using System.Collections.Generic;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary>
/// Represents a connection (tie line) between a <see cref="RoutingOutputPort"/> and a <see cref="RoutingInputPort"/>.
/// </summary>
public class TieLine public class TieLine
{ {
/// <summary>
/// The source output port of the tie line.
/// </summary>
public RoutingOutputPort SourcePort { get; private set; } public RoutingOutputPort SourcePort { get; private set; }
/// <summary>
/// The destination input port of the tie line.
/// </summary>
public RoutingInputPort DestinationPort { get; private set; } public RoutingInputPort DestinationPort { get; private set; }
//public int InUseCount { get { return DestinationUsingThis.Count; } } //public int InUseCount { get { return DestinationUsingThis.Count; } }
/// <summary> /// <summary>
/// Gets the type of this tie line. Will either be the type of the destination port /// Gets the type of this tie line. Will either be the type of the desination port
/// or the type of OverrideType when it is set. /// or the type of OverrideType when it is set.
/// </summary> /// </summary>
public eRoutingSignalType Type public eRoutingSignalType Type
@@ -44,27 +35,20 @@ namespace PepperDash.Essentials.Core
//List<IRoutingInputs> DestinationUsingThis = new List<IRoutingInputs>(); //List<IRoutingInputs> DestinationUsingThis = new List<IRoutingInputs>();
/// <summary> /// <summary>
/// Gets a value indicating whether this tie line represents an internal connection within a device (both source and destination ports are internal). /// 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
/// </summary> /// </summary>
public bool IsInternal { get { return SourcePort.IsInternal && DestinationPort.IsInternal; } } public bool IsInternal { get { return SourcePort.IsInternal && DestinationPort.IsInternal; } }
/// <summary>
/// Gets a value indicating whether the signal types of the source and destination ports differ.
/// </summary>
public bool TypeMismatch { get { return SourcePort.Type != DestinationPort.Type; } } public bool TypeMismatch { get { return SourcePort.Type != DestinationPort.Type; } }
/// <summary>
/// Gets a value indicating whether the connection types of the source and destination ports differ.
/// </summary>
public bool ConnectionTypeMismatch { get { return SourcePort.ConnectionType != DestinationPort.ConnectionType; } } public bool ConnectionTypeMismatch { get { return SourcePort.ConnectionType != DestinationPort.ConnectionType; } }
/// <summary>
/// A descriptive note about any type mismatch, if applicable.
/// </summary>
public string TypeMismatchNote { get; set; } public string TypeMismatchNote { get; set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TieLine"/> class. ///
/// </summary> /// </summary>
/// <param name="sourcePort">The source output port.</param> /// <param name="sourcePort"></param>
/// <param name="destinationPort">The destination input port.</param> /// <param name="destinationPort"></param>
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort) public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort)
{ {
if (sourcePort == null || destinationPort == null) if (sourcePort == null || destinationPort == null)
@@ -74,11 +58,9 @@ namespace PepperDash.Essentials.Core
} }
/// <summary> /// <summary>
/// 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
/// </summary> /// </summary>
/// <param name="sourcePort">The source output port.</param> /// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type</param>
/// <param name="destinationPort">The destination input port.</param>
/// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations.</param>
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType? overrideType) : public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType? overrideType) :
this(sourcePort, destinationPort) this(sourcePort, destinationPort)
{ {
@@ -86,11 +68,9 @@ namespace PepperDash.Essentials.Core
} }
/// <summary> /// <summary>
/// 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
/// </summary> /// </summary>
/// <param name="sourcePort">The source output port.</param> /// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type</param>
/// <param name="destinationPort">The destination input port.</param>
/// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations.</param>
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) : public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) :
this(sourcePort, destinationPort) this(sourcePort, destinationPort)
{ {
@@ -98,25 +78,18 @@ namespace PepperDash.Essentials.Core
} }
/// <summary> /// <summary>
/// Will link up video status from supporting inputs to connected outputs. /// Will link up video status from supporting inputs to connected outputs
/// </summary> /// </summary>
public void Activate() public void Activate()
{ {
// Now does nothing // Now does nothing
} }
/// <summary>
/// Deactivates the tie line.
/// </summary>
public void Deactivate() public void Deactivate()
{ {
// Now does nothing // Now does nothing
} }
/// <summary>
/// Returns a string representation of the tie line.
/// </summary>
/// <returns>A string describing the source, destination, and type of the tie line.</returns>
public override string ToString() public override string ToString()
{ {
return string.Format("Tie line: {0}:{1} --> {2}:{3} {4}", SourcePort.ParentDevice.Key, SourcePort.Key, return string.Format("Tie line: {0}:{1} --> {2}:{3} {4}", SourcePort.ParentDevice.Key, SourcePort.Key,
@@ -126,14 +99,8 @@ namespace PepperDash.Essentials.Core
//******************************************************************************** //********************************************************************************
/// <summary>
/// Represents a collection of <see cref="TieLine"/> objects.
/// </summary>
public class TieLineCollection : List<TieLine> public class TieLineCollection : List<TieLine>
{ {
/// <summary>
/// Gets the default singleton instance of the <see cref="TieLineCollection"/>.
/// </summary>
public static TieLineCollection Default public static TieLineCollection Default
{ {
get get
@@ -144,9 +111,6 @@ namespace PepperDash.Essentials.Core
} }
} }
/// <summary>
/// Backing field for the singleton instance.
/// </summary>
[JsonIgnore] [JsonIgnore]
private static TieLineCollection _Default; private static TieLineCollection _Default;
} }

View File

@@ -1,4 +1,6 @@
using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp.CrestronIO;
@@ -13,44 +15,15 @@ using Serilog.Events;
namespace PepperDash.Essentials.Core.Config namespace PepperDash.Essentials.Core.Config
{ {
/// <summary>
/// Represents the configuration data for a single tie line between two routing ports.
/// </summary>
public class TieLineConfig public class TieLineConfig
{ {
/// <summary>
/// The key of the source device.
/// </summary>
public string SourceKey { get; set; } public string SourceKey { get; set; }
/// <summary>
/// The key of the source card (if applicable, e.g., in a modular chassis).
/// </summary>
public string SourceCard { get; set; } public string SourceCard { get; set; }
/// <summary>
/// The key of the source output port.
/// </summary>
public string SourcePort { get; set; } public string SourcePort { get; set; }
/// <summary>
/// The key of the destination device.
/// </summary>
public string DestinationKey { get; set; } public string DestinationKey { get; set; }
/// <summary>
/// The key of the destination card (if applicable).
/// </summary>
public string DestinationCard { get; set; } public string DestinationCard { get; set; }
/// <summary>
/// The key of the destination input port.
/// </summary>
public string DestinationPort { get; set; } public string DestinationPort { get; set; }
/// <summary>
/// Optional override for the signal type of the tie line. If set, this overrides the destination port's type for routing calculations.
/// </summary>
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
public eRoutingSignalType? OverrideType { get; set; } public eRoutingSignalType? OverrideType { get; set; }
@@ -100,19 +73,11 @@ namespace PepperDash.Essentials.Core.Config
return new TieLine(sourceOutputPort, destinationInputPort, OverrideType); return new TieLine(sourceOutputPort, destinationInputPort, OverrideType);
} }
/// <summary>
/// Logs an error message related to creating this tie line configuration.
/// </summary>
/// <param name="msg">The specific error message.</param>
void LogError(string msg) void LogError(string msg)
{ {
Debug.LogMessage(LogEventLevel.Error, "WARNING: Cannot create tie line: {message}:\r {tieLineConfig}",null, msg, this); Debug.LogMessage(LogEventLevel.Error, "WARNING: Cannot create tie line: {message}:\r {tieLineConfig}",null, msg, this);
} }
/// <summary>
/// Returns a string representation of the tie line configuration.
/// </summary>
/// <returns>A string describing the source and destination of the configured tie line.</returns>
public override string ToString() public override string ToString()
{ {
return string.Format("{0}.{1}.{2} --> {3}.{4}.{5}", SourceKey, SourceCard, SourcePort, return string.Format("{0}.{1}.{2} --> {3}.{4}.{5}", SourceKey, SourceCard, SourcePort,

View File

@@ -227,7 +227,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist); SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist);
for (int i = 0; i < joinMap.PresetRecallStart.JoinSpan; i++) for (int i = 0; i < joinMap.NumberOfPresets.JoinSpan; i++)
{ {
int tempNum = i; int tempNum = i;

View File

@@ -7,7 +7,7 @@ using System.Collections.Generic;
namespace PepperDash.Essentials.Devices.Common.Generic namespace PepperDash.Essentials.Devices.Common.Generic
{ {
public class GenericSink : EssentialsDevice, IRoutingSinkWithInputPort public class GenericSink : EssentialsDevice, IRoutingSink
{ {
public GenericSink(string key, string name) : base(key, name) public GenericSink(string key, string name) : base(key, name)
{ {

View File

@@ -8,10 +8,9 @@ using System.Linq;
namespace PepperDash.Essentials.Devices.Common.SoftCodec namespace PepperDash.Essentials.Devices.Common.SoftCodec
{ {
public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingSinkWithSwitchingWithInputPort public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingOutputs, IRoutingSinkWithSwitching
{ {
private RoutingInputPort _currentInputPort; private RoutingInputPort _currentInputPort;
public RoutingInputPort CurrentInputPort { public RoutingInputPort CurrentInputPort {
get => _currentInputPort; get => _currentInputPort;
set set

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project>
<EssentialsVersion>$(Version)</EssentialsVersion>
</Project>