using System; using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DM; using Crestron.SimplSharpPro.DM.Cards; using Crestron.SimplSharpPro.DM.Endpoints; using Crestron.SimplSharpPro.DM.Endpoints.Receivers; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.DM.Config; namespace PepperDash.Essentials.DM { public class DmpsRoutingController : Device, IRoutingInputsOutputs, IRouting, IHasFeedback { public CrestronControlSystem Dmps { get; set; } public ISystemControl SystemControl { get; private set; } // Feedbacks for EssentialDM public Dictionary VideoOutputFeedbacks { get; private set; } public Dictionary AudioOutputFeedbacks { get; private set; } public Dictionary VideoInputSyncFeedbacks { get; private set; } public Dictionary InputEndpointOnlineFeedbacks { get; private set; } public Dictionary OutputEndpointOnlineFeedbacks { get; private set; } public Dictionary InputNameFeedbacks { get; private set; } public Dictionary OutputNameFeedbacks { get; private set; } public Dictionary OutputVideoRouteNameFeedbacks { get; private set; } public Dictionary OutputAudioRouteNameFeedbacks { get; private set; } public FeedbackCollection Feedbacks { get; private set; } // Need a couple Lists of generic Backplane ports public RoutingPortCollection InputPorts { get; private set; } public RoutingPortCollection OutputPorts { get; private set; } public Dictionary TxDictionary { get; set; } public Dictionary RxDictionary { get; set; } public Dictionary InputNames { get; set; } public Dictionary OutputNames { get; set; } public Dictionary VolumeControls { get; private set; } public const int RouteOffTime = 500; Dictionary RouteOffTimers = new Dictionary(); public static DmpsRoutingController GetDmpsRoutingController(string key, string name, string type, DmpsRoutingPropertiesConfig properties) { try { ISystemControl systemControl = null; type = type.ToLower(); systemControl = Global.ControlSystem.SystemControl as ISystemControl; if (systemControl == null) { return null; } var controller = new DmpsRoutingController(key, name, systemControl); controller.InputNames = properties.InputNames; controller.OutputNames = properties.OutputNames; return controller; } catch (System.Exception e) { Debug.Console(0, "Error getting DMPS Controller:\r{0}", e); } return null; } /// /// /// /// /// /// public DmpsRoutingController(string key, string name, ISystemControl systemControl) : base(key, name) { Dmps = Global.ControlSystem; SystemControl = systemControl; InputPorts = new RoutingPortCollection(); OutputPorts = new RoutingPortCollection(); VolumeControls = new Dictionary(); TxDictionary = new Dictionary(); RxDictionary = new Dictionary(); VideoOutputFeedbacks = new Dictionary(); AudioOutputFeedbacks = new Dictionary(); VideoInputSyncFeedbacks = new Dictionary(); InputNameFeedbacks = new Dictionary(); OutputNameFeedbacks = new Dictionary(); OutputVideoRouteNameFeedbacks = new Dictionary(); OutputAudioRouteNameFeedbacks = new Dictionary(); InputEndpointOnlineFeedbacks = new Dictionary(); OutputEndpointOnlineFeedbacks = new Dictionary(); Dmps.DMInputChange += new DMInputEventHandler(Dmps_DMInputChange); Dmps.DMOutputChange +=new DMOutputEventHandler(Dmps_DMOutputChange); // Default to EnableAudioBreakaway SystemControl.EnableAudioBreakaway.BoolValue = true; for (uint x = 1; x <= Dmps.NumberOfSwitcherOutputs; x++) { var tempX = x; Card.Dmps3OutputBase outputCard = Dmps.SwitcherOutputs[tempX] as Card.Dmps3OutputBase; if (outputCard != null) { VideoOutputFeedbacks[tempX] = new IntFeedback(() => { if(outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number;} else { return 0; }; }); AudioOutputFeedbacks[tempX] = new IntFeedback(() => { if (outputCard.AudioOutFeedback != null) { return (ushort)outputCard.AudioOutFeedback.Number; } else { return 0; }; }); OutputNameFeedbacks[tempX] = new StringFeedback(() => { if (outputCard.NameFeedback.StringValue != null) { return outputCard.NameFeedback.StringValue; } else { return ""; } }); OutputVideoRouteNameFeedbacks[tempX] = new StringFeedback(() => { if (outputCard.VideoOutFeedback != null) { return outputCard.VideoOutFeedback.NameFeedback.StringValue; } else { return ""; } }); OutputAudioRouteNameFeedbacks[tempX] = new StringFeedback(() => { if (outputCard.AudioOutFeedback != null) { return outputCard.AudioOutFeedback.NameFeedback.StringValue; } else { return ""; } }); OutputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => { return outputCard.EndpointOnlineFeedback; }); AddOutputCard(tempX, outputCard); } } for (uint x = 1; x <= Dmps.NumberOfSwitcherInputs; x++) { var tempX = x; DMInput inputCard = Dmps.SwitcherInputs[tempX] as DMInput; if (inputCard != null) { InputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => { return inputCard.EndpointOnlineFeedback; }); VideoInputSyncFeedbacks[tempX] = new BoolFeedback(() => { return inputCard.VideoDetectedFeedback.BoolValue; }); InputNameFeedbacks[tempX] = new StringFeedback(() => { if (inputCard.NameFeedback.StringValue != null) { return inputCard.NameFeedback.StringValue; } else { return ""; } }); } } } public override bool CustomActivate() { if (InputNames != null) foreach (var kvp in InputNames) (Dmps.SwitcherInputs[kvp.Key] as DMInput).Name.StringValue = kvp.Value; if (OutputNames != null) foreach (var kvp in OutputNames) (Dmps.SwitcherOutputs[kvp.Key] as Card.Dmps3OutputBase).Name.StringValue = kvp.Value; return base.CustomActivate(); } /// /// Builds the appropriate ports aand callst the appropreate add port method /// /// /// public void AddInputCard(uint number, DMInput inputCard) { if (inputCard is Card.Dmps3HdmiInputWithoutAnalogAudio) { var hdmiInputCard = inputCard as Card.Dmps3HdmiInput; var cecPort = hdmiInputCard.HdmiInputPort; AddInputPortWithDebug(number, string.Format("hdmiIn{0}", number), eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, cecPort); } else if (inputCard is Card.Dmps3HdmiInput) { var hdmiInputCard = inputCard as Card.Dmps3HdmiInput; var cecPort = hdmiInputCard.HdmiInputPort; AddInputPortWithDebug(number, string.Format("hdmiIn{0}", number), eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, cecPort); AddInputPortWithDebug(number, string.Format("audioIn{1}", number), eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); } else if (inputCard is Card.Dmps3HdmiVgaInput) { // TODO: Build a virtual TX device and assign the ports to it var hdmiVgaInputCard = inputCard as Card.Dmps3HdmiVgaInput; DmpsInternalVirtualHdmiVgaInputController inputCardController = new DmpsInternalVirtualHdmiVgaInputController(Key + string.Format("-input{0}", number), string.Format("InternalInputController-{0}", number), hdmiVgaInputCard); DeviceManager.AddDevice(inputCardController); AddInputPortWithDebug(number, string.Format("input{0}", number), eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.BackplaneOnly); } else if (inputCard is Card.Dmps3HdmiVgaBncInput) { // TODO: Build a virtual TX device and assign the ports to it var hdmiVgaBncInputCard = inputCard as Card.Dmps3HdmiVgaBncInput; DmpsInternalVirtualHdmiVgaBncInputController inputCardController = new DmpsInternalVirtualHdmiVgaBncInputController(Key + string.Format("-input{0}", number), string.Format("InternalInputController-{0}", number), hdmiVgaBncInputCard); DeviceManager.AddDevice(inputCardController); AddInputPortWithDebug(number, string.Format("input{0}", number), eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.BackplaneOnly); } else if (inputCard is Card.Dmps3DmInput) { var hdmiInputCard = inputCard as Card.Dmps3DmInput; var cecPort = hdmiInputCard.DmInputPort; AddInputPortWithDebug(number, string.Format("dmIn{0}", number), eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.DmCat, cecPort); } else if (inputCard is Card.Dmps3AirMediaInput) { var airMediaInputCard = inputCard as Card.Dmps3AirMediaInput; AddInputPortWithDebug(number, string.Format("airMediaIn{0}", number), eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Streaming); } } /// /// Adds InputPort /// void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType) { var portKey = string.Format("inputCard{0}--{1}", cardNum, portName); Debug.Console(2, this, "Adding input port '{0}'", portKey); var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this); InputPorts.Add(inputPort); } /// /// Adds InputPort and sets Port as ICec object /// void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, ICec cecPort) { var portKey = string.Format("inputCard{0}--{1}", cardNum, portName); Debug.Console(2, this, "Adding input port '{0}'", portKey); var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this); if (cecPort != null) inputPort.Port = cecPort; InputPorts.Add(inputPort); } /// /// Builds the appropriate ports and calls the appropriate add port method /// /// /// public void AddOutputCard(uint number, Card.Dmps3OutputBase outputCard) { if (outputCard is Card.Dmps3HdmiOutput) { var hdmiOutputCard = outputCard as Card.Dmps3HdmiOutput; var cecPort = hdmiOutputCard.HdmiOutputPort; AddHdmiOutputPort(number, cecPort); } else if (outputCard is Card.Dmps3DmOutput) { var dmOutputCard = outputCard as Card.Dmps3DmOutput; var cecPort = dmOutputCard.DmOutputPort; AddDmOutputPort(number); } } /// /// Adds an HDMI output port /// /// /// void AddHdmiOutputPort(uint number, ICec cecPort) { AddOutputPortWithDebug(number, string.Format("hdmiOut{0}", number), eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, number, cecPort); } /// /// Adds a DM output port /// /// void AddDmOutputPort(uint number) { AddOutputPortWithDebug(number, string.Format("dmOut{0}", number), eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.DmCat, number); } /// /// Adds OutputPort /// void AddOutputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector) { var portKey = string.Format("outputCard{0}--{1}", cardNum, portName); Debug.Console(2, this, "Adding output port '{0}'", portKey); OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this)); } /// /// Adds OutputPort and sets Port as ICec object /// void AddOutputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector, ICec cecPort) { var portKey = string.Format("outputCard{0}--{1}", cardNum, portName); Debug.Console(2, this, "Adding output port '{0}'", portKey); var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this); if (cecPort != null) outputPort.Port = cecPort; OutputPorts.Add(outputPort); } void Dmps_DMInputChange(Switch device, DMInputEventArgs args) { //Debug.Console(2, this, "DMSwitch:{0} Input:{1} Event:{2}'", this.Name, args.Number, args.EventId.ToString()); switch (args.EventId) { case (DMInputEventIds.OnlineFeedbackEventId): { Debug.Console(2, this, "DMINput OnlineFeedbackEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); break; } case (DMInputEventIds.VideoDetectedEventId): { Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number); VideoInputSyncFeedbacks[args.Number].FireUpdate(); break; } case (DMInputEventIds.InputNameEventId): { Debug.Console(2, this, "DM Input {0} NameFeedbackEventId", args.Number); InputNameFeedbacks[args.Number].FireUpdate(); break; } } } /// /// void Dmps_DMOutputChange(Switch device, DMOutputEventArgs args) { var output = args.Number; Card.Dmps3OutputBase outputCard = Dmps.SwitcherOutputs[output] as Card.Dmps3OutputBase; if (args.EventId == DMOutputEventIds.VolumeEventId && VolumeControls.ContainsKey(output)) { VolumeControls[args.Number].VolumeEventFromChassis(); } else if (args.EventId == DMOutputEventIds.OnlineFeedbackEventId) { OutputEndpointOnlineFeedbacks[output].FireUpdate(); } else if (args.EventId == DMOutputEventIds.VideoOutEventId) { if (outputCard != null && outputCard.VideoOutFeedback != null) { Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, outputCard.VideoOutFeedback.Number, output); } if (VideoOutputFeedbacks.ContainsKey(output)) { VideoOutputFeedbacks[output].FireUpdate(); } if (OutputVideoRouteNameFeedbacks.ContainsKey(output)) { OutputVideoRouteNameFeedbacks[output].FireUpdate(); } } else if (args.EventId == DMOutputEventIds.AudioOutEventId) { if (outputCard != null && outputCard.AudioOutFeedback != null) { Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, outputCard.AudioOutFeedback.Number, output); } if (AudioOutputFeedbacks.ContainsKey(output)) { AudioOutputFeedbacks[output].FireUpdate(); } } else if (args.EventId == DMOutputEventIds.OutputNameEventId) { Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output); OutputNameFeedbacks[output].FireUpdate(); } } /// /// /// /// void StartOffTimer(PortNumberType pnt) { if (RouteOffTimers.ContainsKey(pnt)) return; RouteOffTimers[pnt] = new CTimer(o => { ExecuteSwitch(0, pnt.Number, pnt.Type); }, RouteOffTime); } #region IRouting Members public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType sigType) { Debug.Console(2, this, "Making an awesome DM route from {0} to {1} {2}", inputSelector, outputSelector, sigType); var input = Convert.ToUInt32(inputSelector); // Cast can sometimes fail var output = Convert.ToUInt32(outputSelector); // Check to see if there's an off timer waiting on this and if so, cancel var key = new PortNumberType(output, sigType); if (input == 0) { StartOffTimer(key); } else { if (RouteOffTimers.ContainsKey(key)) { Debug.Console(2, this, "{0} cancelling route off due to new source", output); RouteOffTimers[key].Stop(); RouteOffTimers.Remove(key); } } DMInput inCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput; // NOTE THAT THESE ARE NOTS - TO CATCH THE AudioVideo TYPE if (sigType != eRoutingSignalType.Audio) { SystemControl.VideoEnter.BoolValue = true; (Dmps.SwitcherOutputs[output] as Card.Dmps3OutputBase).VideoOut = inCard; } if (sigType != eRoutingSignalType.Video) { SystemControl.AudioEnter.BoolValue = true; (Dmps.SwitcherOutputs[output] as Card.Dmps3OutputBase).AudioOut = inCard; } } #endregion } }