mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-07 00:35:07 +00:00
Combining repos
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using Crestron.SimplSharp;
|
||||
|
||||
//using PepperDash.Core;
|
||||
|
||||
//namespace PepperDash.Essentials.Core
|
||||
//{
|
||||
// /// <summary>
|
||||
// /// Defines a class that has cards, like a DM chassis controller, where
|
||||
// /// we need to access ports on those cards
|
||||
// /// </summary>
|
||||
// public interface ICardPortsDevice : IKeyed
|
||||
// {
|
||||
// RoutingInputPort GetChildInputPort(string card, string port);
|
||||
// RoutingOutputPort GetChildOutputPort(string card, string port);
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,333 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DM;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions added to any IRoutingInputs classes to provide discovery-based routing
|
||||
/// on those destinations.
|
||||
/// </summary>
|
||||
public static class IRoutingInputsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute
|
||||
/// and then attempts a new Route and if sucessful, stores that RouteDescriptor
|
||||
/// in RouteDescriptorCollection.DefaultCollection
|
||||
/// </summary>
|
||||
public static void ReleaseAndMakeRoute(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType)
|
||||
{
|
||||
destination.ReleaseRoute();
|
||||
|
||||
if (source == null) return;
|
||||
var newRoute = destination.GetRouteToSource(source, signalType);
|
||||
if (newRoute == null) return;
|
||||
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(newRoute);
|
||||
Debug.Console(1, destination, "Executing new route");
|
||||
newRoute.ExecuteRoutes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will release the existing route on the destination, if it is found in
|
||||
/// RouteDescriptorCollection.DefaultCollection
|
||||
/// </summary>
|
||||
/// <param name="destination"></param>
|
||||
public static void ReleaseRoute(this IRoutingInputs destination)
|
||||
{
|
||||
var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination);
|
||||
if (current != null)
|
||||
{
|
||||
Debug.Console(1, destination, "Releasing current route: {0}", current.Source.Key);
|
||||
current.ReleaseRoutes();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a RouteDescriptor that contains the steps necessary to make a route between devices.
|
||||
/// Routes of type AudioVideo will be built as two separate routes, audio and video. If
|
||||
/// a route is discovered, a new RouteDescriptor is returned. If one or both parts
|
||||
/// of an audio/video route are discovered a route descriptor is returned. If no route is
|
||||
/// discovered, then null is returned
|
||||
/// </summary>
|
||||
public static RouteDescriptor GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType)
|
||||
{
|
||||
var routeDescr = new RouteDescriptor(source, destination, signalType);
|
||||
// if it's a single signal type, find the route
|
||||
if (signalType != eRoutingSignalType.AudioVideo)
|
||||
{
|
||||
Debug.Console(1, destination, "Attempting to build source route from {0}", source.Key);
|
||||
if (!destination.GetRouteToSource(source, null, null, signalType, 0, routeDescr))
|
||||
routeDescr = null;
|
||||
}
|
||||
// otherwise, audioVideo needs to be handled as two steps.
|
||||
else
|
||||
{
|
||||
Debug.Console(1, destination, "Attempting to build audio and video routes from {0}", source.Key);
|
||||
var audioSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Audio, 0, routeDescr);
|
||||
if (!audioSuccess)
|
||||
Debug.Console(1, destination, "Cannot find audio route to {0}", source.Key);
|
||||
var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, routeDescr);
|
||||
if (!videoSuccess)
|
||||
Debug.Console(1, destination, "Cannot find video route to {0}", source.Key);
|
||||
if (!audioSuccess && !videoSuccess)
|
||||
routeDescr = null;
|
||||
}
|
||||
|
||||
Debug.Console(1, destination, "Route{0} discovered", routeDescr == null ? " NOT" : "");
|
||||
return routeDescr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The recursive part of this. Will stop on each device, search its inputs for the
|
||||
/// desired source and if not found, invoke this function for the each input port
|
||||
/// hoping to find the source.
|
||||
/// </summary>
|
||||
/// <param name="destination"></param>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="outputPortToUse">The RoutingOutputPort whose link is being checked for a route</param>
|
||||
/// <param name="alreadyCheckedDevices">Prevents Devices from being twice-checked</param>
|
||||
/// <param name="signalType">This recursive function should not be called with AudioVideo</param>
|
||||
/// <param name="cycle">Just an informational counter</param>
|
||||
/// <param name="routeTable">The RouteDescriptor being populated as the route is discovered</param>
|
||||
/// <returns>true if source is hit</returns>
|
||||
static bool GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source,
|
||||
RoutingOutputPort outputPortToUse, List<IRoutingInputsOutputs> alreadyCheckedDevices,
|
||||
eRoutingSignalType signalType, int cycle, RouteDescriptor routeTable)
|
||||
{
|
||||
cycle++;
|
||||
Debug.Console(2, destination, "SelectInput-cycle {1}. Finding {2} route back to {0}", source.Key, cycle, signalType);
|
||||
var destDevInputTies = TieLineCollection.Default.Where(t =>
|
||||
t.DestinationPort.ParentDevice == destination && (t.Type == signalType || t.Type == eRoutingSignalType.AudioVideo));
|
||||
|
||||
// find a direct tie
|
||||
var directTie = destDevInputTies.FirstOrDefault(
|
||||
t => !(t.SourcePort.ParentDevice is IRoutingInputsOutputs)
|
||||
&& t.DestinationPort.ParentDevice == destination
|
||||
&& t.SourcePort.ParentDevice == source);
|
||||
RoutingInputPort goodInputPort = null;
|
||||
if (directTie != null) // Found a tie directly to the source
|
||||
{
|
||||
Debug.Console(2, destination, "Found direct tie to {0}**", source.Key);
|
||||
goodInputPort = directTie.DestinationPort;
|
||||
}
|
||||
else // no direct-connect. Walk back devices.
|
||||
{
|
||||
Debug.Console(2, destination, "is not directly connected to {0}. Walking down tie lines", source.Key);
|
||||
|
||||
// No direct tie? Run back out on the inputs' attached devices...
|
||||
// Only the ones that are routing devices
|
||||
var attachedMidpoints = destDevInputTies.Where(t => t.SourcePort.ParentDevice is IRoutingInputsOutputs);
|
||||
foreach (var inputTieToTry in attachedMidpoints)
|
||||
{
|
||||
Debug.Console(2, destination, "Trying to find route on {0}", inputTieToTry.SourcePort.ParentDevice.Key);
|
||||
var upstreamDeviceOutputPort = inputTieToTry.SourcePort;
|
||||
var upstreamRoutingDevice = upstreamDeviceOutputPort.ParentDevice as IRoutingInputsOutputs;
|
||||
// Check if this previous device has already been walked
|
||||
if (!(alreadyCheckedDevices != null && alreadyCheckedDevices.Contains(upstreamRoutingDevice)))
|
||||
{
|
||||
// haven't seen this device yet. Do it. Pass the output port to the next
|
||||
// level to enable switching on success
|
||||
var upstreamRoutingSuccess = upstreamRoutingDevice.GetRouteToSource(source, upstreamDeviceOutputPort,
|
||||
alreadyCheckedDevices, signalType, cycle, routeTable);
|
||||
if (upstreamRoutingSuccess)
|
||||
{
|
||||
Debug.Console(2, destination, "Upstream device route found");
|
||||
goodInputPort = inputTieToTry.DestinationPort;
|
||||
break; // Stop looping the inputs in this cycle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we have a route on corresponding inputPort. *** Do the route ***
|
||||
if (goodInputPort != null)
|
||||
{
|
||||
Debug.Console(2, destination, "adding RouteDescriptor");
|
||||
if (outputPortToUse == null)
|
||||
{
|
||||
// it's a sink device
|
||||
routeTable.Routes.Add(new RouteSwitchDescriptor(goodInputPort));
|
||||
}
|
||||
else if (destination is IRouting)
|
||||
{
|
||||
routeTable.Routes.Add(new RouteSwitchDescriptor (outputPortToUse, goodInputPort));
|
||||
}
|
||||
else // device is merely IRoutingInputOutputs
|
||||
Debug.Console(2, destination, " No routing. Passthrough device");
|
||||
Debug.Console(2, destination, "Exiting cycle {0}", cycle);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(alreadyCheckedDevices == null)
|
||||
alreadyCheckedDevices = new List<IRoutingInputsOutputs>();
|
||||
alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs);
|
||||
|
||||
Debug.Console(2, destination, "No route found to {0}", source.Key);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A collection of RouteDescriptors - typically the static DefaultCollection is used
|
||||
/// </summary>
|
||||
public class RouteDescriptorCollection
|
||||
{
|
||||
public static RouteDescriptorCollection DefaultCollection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_DefaultCollection == null)
|
||||
_DefaultCollection = new RouteDescriptorCollection();
|
||||
return _DefaultCollection;
|
||||
}
|
||||
}
|
||||
static RouteDescriptorCollection _DefaultCollection;
|
||||
|
||||
List<RouteDescriptor> RouteDescriptors = new List<RouteDescriptor>();
|
||||
|
||||
/// <summary>
|
||||
/// Adds a RouteDescriptor to the list. If an existing RouteDescriptor for the
|
||||
/// destination exists already, it will not be added - in order to preserve
|
||||
/// proper route releasing.
|
||||
/// </summary>
|
||||
/// <param name="descriptor"></param>
|
||||
public void AddRouteDescriptor(RouteDescriptor descriptor)
|
||||
{
|
||||
if (RouteDescriptors.Any(t => t.Destination == descriptor.Destination))
|
||||
{
|
||||
Debug.Console(1, descriptor.Destination,
|
||||
"Route to [{0}] already exists in global routes table", descriptor.Source.Key);
|
||||
return;
|
||||
}
|
||||
RouteDescriptors.Add(descriptor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the RouteDescriptor for a destination
|
||||
/// </summary>
|
||||
/// <returns>null if no RouteDescriptor for a destination exists</returns>
|
||||
public RouteDescriptor GetRouteDescriptorForDestination(IRoutingInputs destination)
|
||||
{
|
||||
return RouteDescriptors.FirstOrDefault(rd => rd.Destination == destination);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the RouteDescriptor for a given destination AND removes it from collection.
|
||||
/// Returns null if no route with the provided destination exists.
|
||||
/// </summary>
|
||||
public RouteDescriptor RemoveRouteDescriptor(IRoutingInputs destination)
|
||||
{
|
||||
var descr = GetRouteDescriptorForDestination(destination);
|
||||
if (descr != null)
|
||||
RouteDescriptors.Remove(descr);
|
||||
return descr;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an collection of individual route steps between Source and Destination
|
||||
/// </summary>
|
||||
public class RouteDescriptor
|
||||
{
|
||||
public IRoutingInputs Destination { get; private set; }
|
||||
public IRoutingOutputs Source { get; private set; }
|
||||
public eRoutingSignalType SignalType { get; private set; }
|
||||
public List<RouteSwitchDescriptor> Routes { get; private set; }
|
||||
|
||||
|
||||
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType)
|
||||
{
|
||||
Destination = destination;
|
||||
Source = source;
|
||||
SignalType = signalType;
|
||||
Routes = new List<RouteSwitchDescriptor>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes all routes described in this collection. Typically called via
|
||||
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
|
||||
/// </summary>
|
||||
public void ExecuteRoutes()
|
||||
{
|
||||
foreach (var route in Routes)
|
||||
{
|
||||
Debug.Console(2, route.ToString());
|
||||
if (route.SwitchingDevice is IRoutingSinkWithSwitching)
|
||||
(route.SwitchingDevice as IRoutingSinkWithSwitching).ExecuteSwitch(route.InputPort.Selector);
|
||||
else if (route.SwitchingDevice is IRouting)
|
||||
{
|
||||
(route.SwitchingDevice as IRouting).ExecuteSwitch(route.InputPort.Selector, route.OutputPort.Selector, SignalType);
|
||||
route.OutputPort.InUseTracker.AddUser(Destination, "destination-" + SignalType);
|
||||
Debug.Console(2, "Port {0} routing. Count={1}", route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases all routes in this collection. Typically called via
|
||||
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
|
||||
/// </summary>
|
||||
public void ReleaseRoutes()
|
||||
{
|
||||
foreach (var route in Routes)
|
||||
{
|
||||
if (route.SwitchingDevice is IRouting)
|
||||
{
|
||||
// Pull the route from the port. Whatever is watching the output's in use tracker is
|
||||
// responsible for responding appropriately.
|
||||
route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType);
|
||||
Debug.Console(2, "Port {0} releasing. Count={1}", route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var routesText = Routes.Select(r => r.ToString()).ToArray();
|
||||
return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an individual link for a route
|
||||
/// </summary>
|
||||
public class RouteSwitchDescriptor
|
||||
{
|
||||
public IRoutingInputs SwitchingDevice { get { return InputPort.ParentDevice; } }
|
||||
public RoutingOutputPort OutputPort { get; set; }
|
||||
public RoutingInputPort InputPort { get; set; }
|
||||
|
||||
public RouteSwitchDescriptor(RoutingInputPort inputPort)
|
||||
{
|
||||
InputPort = inputPort;
|
||||
}
|
||||
|
||||
public RouteSwitchDescriptor(RoutingOutputPort outputPort, RoutingInputPort inputPort)
|
||||
{
|
||||
InputPort = inputPort;
|
||||
OutputPort = outputPort;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if(OutputPort == null) // IRoutingSink
|
||||
return string.Format("{0} switches to input '{1}'", SwitchingDevice.Key, InputPort.Selector);
|
||||
|
||||
return string.Format("{0} switches output '{1}' to input '{2}'", SwitchingDevice.Key, OutputPort.Selector, InputPort.Selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DM;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
//*******************************************************************************************
|
||||
// Interfaces
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Defines a class that has a collection of RoutingInputPorts
|
||||
/// </summary>
|
||||
public interface IRoutingInputs : IKeyed
|
||||
{
|
||||
RoutingPortCollection<RoutingInputPort> InputPorts { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines a class that has a collection of RoutingOutputPorts
|
||||
/// </summary>
|
||||
|
||||
public interface IRoutingOutputs : IKeyed
|
||||
{
|
||||
RoutingPortCollection<RoutingOutputPort> OutputPorts { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For fixed-source endpoint devices
|
||||
/// </summary>
|
||||
public interface IRoutingSinkNoSwitching : IRoutingInputs
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public interface IRoutingSinkWithSwitching : IRoutingSinkNoSwitching
|
||||
{
|
||||
//void ClearRoute();
|
||||
void ExecuteSwitch(object inputSelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For devices like RMCs, baluns, other devices with no switching.
|
||||
/// </summary>
|
||||
public interface IRoutingInputsOutputs : IRoutingInputs, IRoutingOutputs
|
||||
{
|
||||
}
|
||||
|
||||
public interface IRouting : IRoutingInputsOutputs
|
||||
{
|
||||
//void ClearRoute(object outputSelector);
|
||||
void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType);
|
||||
}
|
||||
|
||||
public interface IRoutingSource : IRoutingOutputs
|
||||
{
|
||||
}
|
||||
}
|
||||
200
Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs
Normal file
200
Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for RoutingInput and Output ports
|
||||
/// </summary>
|
||||
public abstract class RoutingPort : IKeyed
|
||||
{
|
||||
public string Key { get; private set; }
|
||||
public eRoutingSignalType Type { get; private set; }
|
||||
public eRoutingPortConnectionType ConnectionType { get; private set; }
|
||||
public readonly object Selector;
|
||||
public bool IsInternal { get; private set; }
|
||||
|
||||
public RoutingPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, object selector, bool isInternal)
|
||||
{
|
||||
Key = key;
|
||||
Type = type;
|
||||
ConnectionType = connType;
|
||||
Selector = selector;
|
||||
IsInternal = IsInternal;
|
||||
}
|
||||
}
|
||||
|
||||
public enum eRoutingSignalType
|
||||
{
|
||||
Audio,
|
||||
Video,
|
||||
AudioVideo
|
||||
}
|
||||
|
||||
public enum eRoutingPortConnectionType
|
||||
{
|
||||
None, BackplaneOnly, DisplayPort, Dvi, Hdmi, Rgb, Vga, LineAudio, DigitalAudio, Sdi,
|
||||
Composite, Component, DmCat, DmMmFiber, DmSmFiber, Speaker
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Basic RoutingInput with no statuses.
|
||||
/// </summary>
|
||||
public class RoutingInputPort : RoutingPort
|
||||
{
|
||||
/// <summary>
|
||||
/// The IRoutingInputs object this lives on
|
||||
/// </summary>
|
||||
public IRoutingInputs ParentDevice { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for a basic RoutingInputPort
|
||||
/// </summary>
|
||||
/// <param name="selector">An object used to refer to this port in the IRouting device's ExecuteSwitch method.
|
||||
/// May be string, number, whatever</param>
|
||||
/// <param name="parent">The IRoutingInputs object this lives on</param>
|
||||
public RoutingInputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType,
|
||||
object selector, IRoutingInputs parent)
|
||||
: this (key, type, connType, selector, parent, false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for a virtual routing input port that lives inside a device. For example
|
||||
/// the ports that link a DM card to a DM matrix bus
|
||||
/// </summary>
|
||||
/// <param name="isInternal">true for internal ports</param>
|
||||
public RoutingInputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType,
|
||||
object selector, IRoutingInputs parent, bool isInternal)
|
||||
: base(key, type, connType, selector, isInternal)
|
||||
{
|
||||
if (parent == null)
|
||||
throw new ArgumentNullException("parent");
|
||||
ParentDevice = parent;
|
||||
}
|
||||
|
||||
|
||||
///// <summary>
|
||||
///// Static method to get a named port from a named device
|
||||
///// </summary>
|
||||
///// <returns>Returns null if device or port doesn't exist</returns>
|
||||
//public static RoutingInputPort GetDevicePort(string deviceKey, string portKey)
|
||||
//{
|
||||
// var sourceDev = DeviceManager.GetDeviceForKey(deviceKey) as IRoutingInputs;
|
||||
// if (sourceDev == null)
|
||||
// return null;
|
||||
// return sourceDev.InputPorts[portKey];
|
||||
//}
|
||||
|
||||
///// <summary>
|
||||
///// Static method to get a named port from a card in a named ICardPortsDevice device
|
||||
///// Uses ICardPortsDevice.GetChildInputPort
|
||||
///// </summary>
|
||||
///// <param name="cardKey">'input-N'</param>
|
||||
///// <returns>null if device, card or port doesn't exist</returns>
|
||||
//public static RoutingInputPort GetDeviceCardPort(string deviceKey, string cardKey, string portKey)
|
||||
//{
|
||||
// var sourceDev = DeviceManager.GetDeviceForKey(deviceKey) as ICardPortsDevice;
|
||||
// if (sourceDev == null)
|
||||
// return null;
|
||||
// return sourceDev.GetChildInputPort(cardKey, portKey);
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A RoutingInputPort for devices like DM-TX and DM input cards.
|
||||
/// Will provide video statistics on connected signals
|
||||
/// </summary>
|
||||
public class RoutingInputPortWithVideoStatuses : RoutingInputPort
|
||||
{
|
||||
/// <summary>
|
||||
/// Video statuses attached to this port
|
||||
/// </summary>
|
||||
public VideoStatusOutputs VideoStatus { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="selector">An object used to refer to this port in the IRouting device's ExecuteSwitch method.
|
||||
/// May be string, number, whatever</param>
|
||||
/// <param name="parent">The IRoutingInputs object this lives on</param>
|
||||
/// <param name="funcs">A VideoStatusFuncsWrapper used to assign the callback funcs that will get
|
||||
/// the values for the various stats</param>
|
||||
public RoutingInputPortWithVideoStatuses(string key,
|
||||
eRoutingSignalType type, eRoutingPortConnectionType connType, object selector,
|
||||
IRoutingInputs parent, VideoStatusFuncsWrapper funcs) :
|
||||
base(key, type, connType, selector, parent)
|
||||
{
|
||||
VideoStatus = new VideoStatusOutputs(funcs);
|
||||
}
|
||||
}
|
||||
|
||||
public class RoutingOutputPort : RoutingPort
|
||||
{
|
||||
/// <summary>
|
||||
/// The IRoutingOutputs object this port lives on
|
||||
/// </summary>
|
||||
public IRoutingOutputs ParentDevice { get; private set; }
|
||||
|
||||
public InUseTracking InUseTracker { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="selector">An object used to refer to this port in the IRouting device's ExecuteSwitch method.
|
||||
/// May be string, number, whatever</param>
|
||||
/// <param name="parent">The IRoutingOutputs object this port lives on</param>
|
||||
public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType,
|
||||
object selector, IRoutingOutputs parent)
|
||||
: this(key, type, connType, selector, parent, false)
|
||||
{
|
||||
}
|
||||
|
||||
public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType,
|
||||
object selector, IRoutingOutputs parent, bool isInternal)
|
||||
: base(key, type, connType, selector, isInternal)
|
||||
{
|
||||
if (parent == null)
|
||||
throw new ArgumentNullException("parent");
|
||||
ParentDevice = parent;
|
||||
InUseTracker = new InUseTracking();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ParentDevice.Key + ":" + Key;
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// Static method to get a named port from a named device
|
||||
///// </summary>
|
||||
///// <returns>Returns null if device or port doesn't exist</returns>
|
||||
//public static RoutingOutputPort GetDevicePort(string deviceKey, string portKey)
|
||||
//{
|
||||
// var sourceDev = DeviceManager.GetDeviceForKey(deviceKey) as IRoutingOutputs;
|
||||
// if (sourceDev == null)
|
||||
// return null;
|
||||
// var port = sourceDev.OutputPorts[portKey];
|
||||
// if (port == null)
|
||||
// Debug.Console(0, "WARNING: Device '{0}' does does not contain output port '{1}'", deviceKey, portKey);
|
||||
// return port;
|
||||
//}
|
||||
|
||||
///// <summary>
|
||||
///// Static method to get a named port from a card in a named ICardPortsDevice device
|
||||
///// Uses ICardPortsDevice.GetChildOutputPort on that device
|
||||
///// </summary>
|
||||
///// <param name="cardKey">'input-N' or 'output-N'</param>
|
||||
///// <returns>null if device, card or port doesn't exist</returns>
|
||||
//public static RoutingOutputPort GetDeviceCardPort(string deviceKey, string cardKey, string portKey)
|
||||
//{
|
||||
// var sourceDev = DeviceManager.GetDeviceForKey(deviceKey) as ICardPortsDevice;
|
||||
// if (sourceDev == null)
|
||||
// return null;
|
||||
// var port = sourceDev.GetChildOutputPort(cardKey, portKey);
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Basically a List , with an indexer to find ports by key name
|
||||
/// </summary>
|
||||
public class RoutingPortCollection<T> : List<T> where T: RoutingPort
|
||||
{
|
||||
/// <summary>
|
||||
/// Case-insensitive port lookup linked to ports' keys
|
||||
/// </summary>
|
||||
public T this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.FirstOrDefault(i => i.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// These should correspond directly with the portNames var in the config tool.
|
||||
/// </summary>
|
||||
public class RoutingPortNames
|
||||
{
|
||||
public const string AntennaIn = "antennaIn";
|
||||
public const string AnyAudioIn = "anyAudioIn";
|
||||
public const string AnyAudioOut = "anyAudioOut";
|
||||
public const string AnyOut = "anyOut";
|
||||
public const string AnyVideoIn = "anyVideoIn";
|
||||
public const string AnyVideoOut = "anyVideoOut";
|
||||
public const string BalancedAudioOut = "balancedAudioOut";
|
||||
public const string ComponentIn = "componentIn";
|
||||
public const string ComponentOut = "componentOut";
|
||||
public const string CompositeIn = "compositeIn";
|
||||
public const string CompositeOut = "compositeOut";
|
||||
public const string DisplayPortIn = "displayPortIn";
|
||||
public const string DisplayPortIn1 = "displayPortIn1";
|
||||
public const string DisplayPortIn2 = "displayPortIn2";
|
||||
public const string DisplayPortIn3 = "displayPortIn3";
|
||||
public const string DisplayPortOut = "displayPortOut";
|
||||
public const string DmIn = "dmIn";
|
||||
public const string DmOut = "dmOut";
|
||||
public const string DviIn = "dviIn";
|
||||
public const string DviOut = "dviOut";
|
||||
public const string HdmiIn = "hdmiIn";
|
||||
public const string HdmiIn1 = "hdmiIn1";
|
||||
public const string HdmiIn2 = "hdmiIn2";
|
||||
public const string HdmiIn3 = "hdmiIn3";
|
||||
public const string HdmiIn4 = "hdmiIn4";
|
||||
public const string HdmiIn5 = "hdmiIn5";
|
||||
public const string HdmiIn6 = "hdmiIn6";
|
||||
public const string HdmiOut = "hdmiOut";
|
||||
public const string RgbIn = "rgbIn";
|
||||
public const string VgaIn = "vgaIn";
|
||||
public const string VgaOut = "vgaOut";
|
||||
}
|
||||
}
|
||||
111
Essentials Core/PepperDashEssentialsBase/Routing/TieLine.cs
Normal file
111
Essentials Core/PepperDashEssentialsBase/Routing/TieLine.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DM;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
public class TieLine
|
||||
{
|
||||
public RoutingOutputPort SourcePort { get; private set; }
|
||||
public RoutingInputPort DestinationPort { get; private set; }
|
||||
//public int InUseCount { get { return DestinationUsingThis.Count; } }
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public eRoutingSignalType Type
|
||||
{
|
||||
get
|
||||
{
|
||||
if (OverrideType.HasValue) return OverrideType.Value;
|
||||
return DestinationPort.Type;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to override the Type property for the destination port. For example,
|
||||
/// when the tie line is type AudioVideo, and the signal flow should be limited to
|
||||
/// Audio-only or Video only, changing this type will alter the signal paths
|
||||
/// available to the routing algorithm without affecting the actual Type
|
||||
/// of the destination port.
|
||||
/// </summary>
|
||||
public eRoutingSignalType? OverrideType { get; set; }
|
||||
|
||||
//List<IRoutingInputs> DestinationUsingThis = new List<IRoutingInputs>();
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
public bool IsInternal { get { return SourcePort.IsInternal && DestinationPort.IsInternal; } }
|
||||
public bool TypeMismatch { get { return SourcePort.Type != DestinationPort.Type; } }
|
||||
public bool ConnectionTypeMismatch { get { return SourcePort.ConnectionType != DestinationPort.ConnectionType; } }
|
||||
public string TypeMismatchNote { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sourcePort"></param>
|
||||
/// <param name="destinationPort"></param>
|
||||
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort)
|
||||
{
|
||||
if (sourcePort == null || destinationPort == null)
|
||||
throw new ArgumentNullException("source or destination port");
|
||||
SourcePort = sourcePort;
|
||||
DestinationPort = destinationPort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a tie line with an overriding Type. See help for OverrideType property for info
|
||||
/// </summary>
|
||||
/// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type</param>
|
||||
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) :
|
||||
this(sourcePort, destinationPort)
|
||||
{
|
||||
OverrideType = overrideType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will link up video status from supporting inputs to connected outputs
|
||||
/// </summary>
|
||||
public void Activate()
|
||||
{
|
||||
// Now does nothing
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
// Now does nothing
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("Tie line: [{0}]{1} --> [{2}]{3}", SourcePort.ParentDevice.Key, SourcePort.Key,
|
||||
DestinationPort.ParentDevice.Key, DestinationPort.Key);
|
||||
}
|
||||
}
|
||||
|
||||
//********************************************************************************
|
||||
|
||||
public class TieLineCollection : List<TieLine>
|
||||
{
|
||||
public static TieLineCollection Default
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Default == null)
|
||||
_Default = new TieLineCollection();
|
||||
return _Default;
|
||||
}
|
||||
}
|
||||
static TieLineCollection _Default;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Config
|
||||
{
|
||||
public class TieLineConfig
|
||||
{
|
||||
public string SourceKey { get; set; }
|
||||
public string SourceCard { get; set; }
|
||||
public string SourcePort { get; set; }
|
||||
public string DestinationKey { get; set; }
|
||||
public string DestinationCard { get; set; }
|
||||
public string DestinationPort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the appropriate tie line for either a card-based device or
|
||||
/// regular device with ports on-device.
|
||||
/// </summary>
|
||||
/// <returns>null if config data does not match ports, cards or devices</returns>
|
||||
public TieLine GetTieLine()
|
||||
{
|
||||
Debug.Console(0, "Build TieLine: {0}", this);
|
||||
// Get the source device
|
||||
var sourceDev = DeviceManager.GetDeviceForKey(SourceKey) as IRoutingOutputs;
|
||||
if (sourceDev == null)
|
||||
{
|
||||
LogError("Routable source not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the destination device
|
||||
var destDev = DeviceManager.GetDeviceForKey(DestinationKey) as IRoutingInputs;
|
||||
if (destDev == null)
|
||||
{
|
||||
LogError("Routable destination not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
//Get the source port
|
||||
RoutingOutputPort sourceOutputPort = null;
|
||||
//// If it's a card-based device, get the card and then the source port
|
||||
//if (sourceDev is ICardPortsDevice)
|
||||
//{
|
||||
// if (SourceCard == null)
|
||||
// {
|
||||
// LogError("Card missing from source device config");
|
||||
// return null;
|
||||
// }
|
||||
// sourceOutputPort = (sourceDev as ICardPortsDevice).GetChildOutputPort(SourceCard, SourcePort);
|
||||
// if (sourceOutputPort == null)
|
||||
// {
|
||||
// LogError("Source card does not contain port");
|
||||
// return null;
|
||||
// }
|
||||
//}
|
||||
//// otherwise it's a normal port device, get the source port
|
||||
//else
|
||||
//{
|
||||
sourceOutputPort = sourceDev.OutputPorts[SourcePort];
|
||||
if (sourceOutputPort == null)
|
||||
{
|
||||
LogError("Source does not contain port");
|
||||
return null;
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
//Get the Destination port
|
||||
RoutingInputPort destinationInputPort = null;
|
||||
//// If it's a card-based device, get the card and then the Destination port
|
||||
//if (destDev is ICardPortsDevice)
|
||||
//{
|
||||
// if (DestinationCard == null)
|
||||
// {
|
||||
// LogError("Card missing from destination device config");
|
||||
// return null;
|
||||
// }
|
||||
// destinationInputPort = (destDev as ICardPortsDevice).GetChildInputPort(DestinationCard, DestinationPort);
|
||||
// if (destinationInputPort == null)
|
||||
// {
|
||||
// LogError("Destination card does not contain port");
|
||||
// return null;
|
||||
// }
|
||||
//}
|
||||
//// otherwise it's a normal port device, get the Destination port
|
||||
//else
|
||||
//{
|
||||
destinationInputPort = destDev.InputPorts[DestinationPort];
|
||||
if (destinationInputPort == null)
|
||||
{
|
||||
LogError("Destination does not contain port");
|
||||
return null;
|
||||
}
|
||||
//}
|
||||
|
||||
return new TieLine(sourceOutputPort, destinationInputPort);
|
||||
}
|
||||
|
||||
void LogError(string msg)
|
||||
{
|
||||
Debug.Console(1, "WARNING: Cannot create tie line: {0}:\r {1}", msg, this);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0}.{1}.{2} --> {3}.{4}.{5}", SourceKey, SourceCard, SourcePort,
|
||||
DestinationKey, DestinationCard, DestinationPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user