From dc8d0e25d5ae1a9e8cc465dc48e6a2ec5575e6d7 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 22 Jul 2019 17:04:41 -0600 Subject: [PATCH] Adds Virtual Dm Tx Controller classes to handle Dmps inputs with mutliple connectors and auto switching. Completes DmpsRoutingController (requires testing) --- .../Routing/RoutingPort.cs | 2 +- .../DmpsInternalVirtualDmTxController.cs | 400 ++++++++++++++++++ .../Chassis/DmpsRoutingController.cs | 339 ++++++++++++++- .../Essentials DM/Essentials_DM/DmPortName.cs | 3 + .../Transmitters/DmTx401CController.cs | 6 +- .../Essentials_DM/Essentials_DM.csproj | 3 +- .../Essentials_DM/VideoStatusHelpers.cs | 20 + 7 files changed, 762 insertions(+), 11 deletions(-) create mode 100644 essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsInternalVirtualDmTxController.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs index 47e47501..34e9b573 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs @@ -33,7 +33,7 @@ namespace PepperDash.Essentials.Core { Audio = 1, Video = 2, - AudioVideo = 3 + AudioVideo = 4 } public enum eRoutingPortConnectionType diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsInternalVirtualDmTxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsInternalVirtualDmTxController.cs new file mode 100644 index 00000000..767a9ebb --- /dev/null +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsInternalVirtualDmTxController.cs @@ -0,0 +1,400 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro.DM; +using Crestron.SimplSharpPro.DM.Cards; + +using PepperDash.Core; +using PepperDash.Essentials.Core; + + +namespace PepperDash.Essentials.DM +{ + /// + /// + /// + public class DmpsInternalVirtualHdmiVgaInputController : Device, ITxRouting, IHasFeedback + { + public Card.Dmps3HdmiVgaInput InputCard { get; protected set; } + + public eHdcpCapabilityType HdcpSupportCapability { get; protected set; } + public StringFeedback ActiveVideoInputFeedback { get; protected set; } + + public RoutingInputPortWithVideoStatuses HdmiIn { get; protected set; } + public RoutingInputPortWithVideoStatuses VgaIn { get; protected set; } + public RoutingInputPort AudioIn { get; protected set; } + public RoutingInputPortWithVideoStatuses AnyVideoInput { get; protected set; } + + public RoutingOutputPort VirtualDmOut { get; protected set; } + + public IntFeedback VideoSourceNumericFeedback { get; protected set; } + public IntFeedback AudioSourceNumericFeedback { get; protected set; } + public IntFeedback HdmiInHdcpCapabilityFeedback { get; protected set; } + + /// + /// Returns a list containing the Outputs that we want to expose. + /// + public FeedbackCollection Feedbacks { get; private set; } + + public void SetPortHdcpCapability(eHdcpCapabilityType hdcpMode, uint port) { } + + /// + /// Helps get the "real" inputs, including when in Auto + /// + public eDmps3InputVideoSource ActualVideoInput + { + get + { + if (InputCard.VideoSourceFeedback != eDmps3InputVideoSource.Auto) + return InputCard.VideoSourceFeedback; + else // auto + { + if (InputCard.HdmiInputPort.SyncDetectedFeedback.BoolValue) + return eDmps3InputVideoSource.Hdmi; + else if (InputCard.VgaInputPort.SyncDetectedFeedback.BoolValue) + return eDmps3InputVideoSource.Vga; + else + return eDmps3InputVideoSource.Bnc; + } + } + } + + public virtual RoutingPortCollection InputPorts + { + get + { + return new RoutingPortCollection + { + HdmiIn, + VgaIn, + AudioIn, + AnyVideoInput + }; + } + } + + public RoutingPortCollection OutputPorts + { + get + { + return new RoutingPortCollection { VirtualDmOut }; + } + } + + public DmpsInternalVirtualHdmiVgaInputController(string key, string name, DMInput inputCard) + : base(key, name) + { + var hdmiVgaInputCard = inputCard as Card.Dmps3HdmiVgaInput; + + if(hdmiVgaInputCard != null) + { + InputCard = inputCard as Card.Dmps3HdmiVgaInput; + + HdmiIn = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, + eDmps3InputVideoSource.Hdmi, this, VideoStatusHelper.GetHdmiInputStatusFuncs(hdmiVgaInputCard.HdmiInputPort)); + VgaIn = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn, + eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, eDmps3InputVideoSource.Vga, this, + VideoStatusHelper.GetVgaInputStatusFuncs(InputCard.VgaInputPort)); + AudioIn = new RoutingInputPort(DmPortName.AudioIn, eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio, + eDmps3InputAudioSource.Analog, this); + + var combinedFuncs = new VideoStatusFuncsWrapper + { + HdcpActiveFeedbackFunc = () => + (ActualVideoInput == eDmps3InputVideoSource.Hdmi + && InputCard.HdmiInputPort.VideoAttributes.HdcpActiveFeedback.BoolValue), + + HdcpStateFeedbackFunc = () => + { + if (ActualVideoInput == eDmps3InputVideoSource.Hdmi) + return InputCard.HdmiInputPort.VideoAttributes.HdcpStateFeedback.ToString(); + return ""; + }, + + VideoResolutionFeedbackFunc = () => + { + if (ActualVideoInput == eDmps3InputVideoSource.Hdmi) + return InputCard.HdmiInputPort.VideoAttributes.GetVideoResolutionString(); + if (ActualVideoInput == eDmps3InputVideoSource.Vga) + return InputCard.VgaInputPort.VideoAttributes.GetVideoResolutionString(); + return ""; + }, + VideoSyncFeedbackFunc = () => + (ActualVideoInput == eDmps3InputVideoSource.Hdmi + && InputCard.HdmiInputPort.SyncDetectedFeedback.BoolValue) + || (ActualVideoInput == eDmps3InputVideoSource.Vga + && InputCard.VgaInputPort.SyncDetectedFeedback.BoolValue) + }; + + AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn, + eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.None, 0, this, combinedFuncs); + + } + + ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput", () => ActualVideoInput.ToString()); + + VideoSourceNumericFeedback = new IntFeedback(() => + { + return (int)InputCard.VideoSourceFeedback; + }); + AudioSourceNumericFeedback = new IntFeedback(() => + { + return (int)InputCard.AudioSourceFeedback; + }); + + HdmiInHdcpCapabilityFeedback = new IntFeedback("HdmiInHdcpCapability", () => + { + if (InputCard.HdmiInputPort.HdcpSupportOnFeedback.BoolValue) + return 1; + else + return 0; + }); + + if (InputCard.HdmiInputPort.HdcpSupportedLevelFeedback == eHdcpSupportedLevel.Hdcp2xSupport) + HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support; + else if (InputCard.HdmiInputPort.HdcpSupportedLevelFeedback == eHdcpSupportedLevel.Hdcp1xSupport) + HdcpSupportCapability = eHdcpCapabilityType.Hdcp1xSupport; + + VirtualDmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.None, null, this); + + AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback, + AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback, + AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback, + AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiInHdcpCapabilityFeedback); + + // Set Ports for CEC + HdmiIn.Port = InputCard.HdmiInputPort; + } + + public override bool CustomActivate() + { + // Link up all of these damned events to the various RoutingPorts via a helper handler + InputCard.HdmiInputPort.Card.BaseEvent += (o, a) => FowardInputStreamChange(HdmiIn, a.EventId); + InputCard.HdmiInputPort.VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn, a.EventId); + + InputCard.VgaInputPort.Card.BaseEvent += (o, a) => FowardInputStreamChange(VgaIn, a.EventId); + InputCard.VgaInputPort.VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(VgaIn, a.EventId); + + // Base does register and sets up comm monitoring. + return base.CustomActivate(); + } + + /// + /// Relays the input stream change to the appropriate RoutingInputPort. + /// + protected void FowardInputStreamChange(RoutingInputPortWithVideoStatuses inputPort, int eventId) + { + if (eventId == Crestron.SimplSharpPro.DM.DMInputEventIds.SourceSyncEventId) + { + inputPort.VideoStatus.VideoSyncFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.VideoSyncFeedback.FireUpdate(); + } + } + + /// + /// Relays the VideoAttributes change to a RoutingInputPort + /// + protected void ForwardVideoAttributeChange(RoutingInputPortWithVideoStatuses inputPort, int eventId) + { + switch (eventId) + { + case VideoAttributeEventIds.HdcpActiveFeedbackEventId: + inputPort.VideoStatus.HdcpActiveFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.HdcpActiveFeedback.FireUpdate(); + break; + case VideoAttributeEventIds.HdcpStateFeedbackEventId: + inputPort.VideoStatus.HdcpStateFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.HdcpStateFeedback.FireUpdate(); + break; + case VideoAttributeEventIds.HorizontalResolutionFeedbackEventId: + case VideoAttributeEventIds.VerticalResolutionFeedbackEventId: + inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate(); + break; + case VideoAttributeEventIds.FramesPerSecondFeedbackEventId: + inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate(); + break; + } + } + + /// + /// Adds feedback(s) to the list + /// + /// + public void AddToFeedbackList(params Feedback[] newFbs) + { + foreach (var f in newFbs) + { + if (f != null) + { + if (!Feedbacks.Contains(f)) + { + Feedbacks.Add(f); + } + } + } + } + + #region ITxRouting Members + + + public virtual void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type) + { + Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input); + + switch (input) + { + case 0: + { + ExecuteSwitch(eDmps3InputVideoSource.Auto, null, type); + break; + } + case 1: + { + ExecuteSwitch(HdmiIn.Selector, null, type); + break; + } + case 2: + { + ExecuteSwitch(VgaIn.Selector, null, type); + break; + } + } + + } + + #endregion + + #region IRouting Members + + public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) + { + if ((signalType | eRoutingSignalType.Video) == eRoutingSignalType.Video) + InputCard.VideoSource = (eDmps3InputVideoSource)inputSelector; + if ((signalType | eRoutingSignalType.Audio) == eRoutingSignalType.Audio) + InputCard.AudioSource = (eDmps3InputAudioSource)inputSelector; + } + + #endregion + } + + /// + /// + /// + public class DmpsInternalVirtualHdmiVgaBncInputController : DmpsInternalVirtualHdmiVgaInputController + { + public new Card.Dmps3HdmiVgaBncInput InputCard { get; private set; } + + public RoutingInputPortWithVideoStatuses BncIn { get; private set; } + public RoutingInputPort SpdifIn { get; private set; } + + public override RoutingPortCollection InputPorts + { + get + { + return new RoutingPortCollection + { + HdmiIn, + VgaIn, + BncIn, + SpdifIn, + AnyVideoInput + }; + } + } + + public DmpsInternalVirtualHdmiVgaBncInputController(string key, string name, Card.Dmps3HdmiVgaBncInput inputCard) + : base(key, name, inputCard) + { + InputCard = inputCard; + + HdmiIn = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, + eDmps3InputVideoSource.Hdmi, this, VideoStatusHelper.GetHdmiInputStatusFuncs(InputCard.HdmiInputPort)); + VgaIn = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn, + eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, eDmps3InputVideoSource.Vga, this, + VideoStatusHelper.GetVgaInputStatusFuncs(InputCard.VgaInputPort)); + BncIn = new RoutingInputPortWithVideoStatuses(DmPortName.BncIn, eRoutingSignalType.Video, eRoutingPortConnectionType.Component, + eDmps3InputVideoSource.Bnc, this, VideoStatusHelper.GetBncInputStatusFuncs(InputCard.BncInputPort)); + SpdifIn = new RoutingInputPort(DmPortName.SpdifIn, eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio, + eDmps3InputAudioSource.Spdif, this); + + var combinedFuncs = new VideoStatusFuncsWrapper + { + HdcpActiveFeedbackFunc = () => + (ActualVideoInput == eDmps3InputVideoSource.Hdmi + && InputCard.HdmiInputPort.VideoAttributes.HdcpActiveFeedback.BoolValue), + + HdcpStateFeedbackFunc = () => + { + if (ActualVideoInput == eDmps3InputVideoSource.Hdmi) + return InputCard.HdmiInputPort.VideoAttributes.HdcpStateFeedback.ToString(); + return ""; + }, + + VideoResolutionFeedbackFunc = () => + { + if (ActualVideoInput == eDmps3InputVideoSource.Hdmi) + return InputCard.HdmiInputPort.VideoAttributes.GetVideoResolutionString(); + if (ActualVideoInput == eDmps3InputVideoSource.Vga) + return InputCard.VgaInputPort.VideoAttributes.GetVideoResolutionString(); + if (ActualVideoInput == eDmps3InputVideoSource.Bnc) + return InputCard.BncInputPort.VideoAttributes.GetVideoResolutionString(); + return ""; + }, + VideoSyncFeedbackFunc = () => + (ActualVideoInput == eDmps3InputVideoSource.Hdmi + && InputCard.HdmiInputPort.SyncDetectedFeedback.BoolValue) + || (ActualVideoInput == eDmps3InputVideoSource.Vga + && InputCard.VgaInputPort.SyncDetectedFeedback.BoolValue) + || (ActualVideoInput == eDmps3InputVideoSource.Bnc + && InputCard.BncInputPort.VideoDetectedFeedback.BoolValue) + }; + + AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn, + eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.None, 0, this, combinedFuncs); + } + + public override bool CustomActivate() + { + // Link up all of these damned events to the various RoutingPorts via a helper handler + InputCard.BncInputPort.Card.BaseEvent += (o, a) => FowardInputStreamChange(HdmiIn, a.EventId); + InputCard.BncInputPort.VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn, a.EventId); + + // Base does remaining inputs + return base.CustomActivate(); + } + + public override void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type) + { + Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input); + + switch (input) + { + case 0: + { + ExecuteSwitch(eDmps3InputVideoSource.Auto, null, type); + break; + } + case 1: + { + ExecuteSwitch(HdmiIn.Selector, null, type); + break; + } + case 2: + { + ExecuteSwitch(VgaIn.Selector, null, type); + break; + } + case 3: + { + ExecuteSwitch(BncIn.Selector, null, type); + break; + } + } + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index f2870300..0811ee61 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -5,6 +5,7 @@ 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; @@ -31,6 +32,8 @@ namespace PepperDash.Essentials.DM 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; } @@ -107,6 +110,274 @@ namespace PepperDash.Essentials.DM 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) @@ -140,6 +411,9 @@ namespace PepperDash.Essentials.DM 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)) { @@ -151,14 +425,13 @@ namespace PepperDash.Essentials.DM } else if (args.EventId == DMOutputEventIds.VideoOutEventId) { - if (Dmps.SwitcherOutputs[output].VideoOutFeedback != null) + if (outputCard != null && outputCard.VideoOutFeedback != null) { - Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, Chassis.Outputs[output].VideoOutFeedback.Number, output); + 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)) { @@ -167,9 +440,9 @@ namespace PepperDash.Essentials.DM } else if (args.EventId == DMOutputEventIds.AudioOutEventId) { - if (Dmps.SwitcherOutputsoutput].AudioOutFeedback != null) + if (outputCard != null && outputCard.AudioOutFeedback != null) { - Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, Chassis.Outputs[output].AudioOutFeedback.Number, output); + Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, outputCard.AudioOutFeedback.Number, output); } if (AudioOutputFeedbacks.ContainsKey(output)) { @@ -183,5 +456,61 @@ namespace PepperDash.Essentials.DM } } + + /// + /// + /// + /// + 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 } } \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/DmPortName.cs b/essentials-framework/Essentials DM/Essentials_DM/DmPortName.cs index c862f1ed..2c65b3f8 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/DmPortName.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/DmPortName.cs @@ -14,10 +14,12 @@ namespace PepperDash.Essentials.DM public const string AirBoardIn = "AirBoardIn"; public const string AirMediaIn = "AirMediaIn"; public const string AnyVideoIn = "AnyVideoIn"; + public const string AudioIn = "AudioIn"; public const string AudioLoopOut = "AudioLoopOut"; public const string BalancedAudioOut = "BalancedAudioOut"; public const string BalancedAudioOut1 = "BalancedAudioOut1"; public const string BalancedAudioOut2 = "BalancedAudioOut2"; + public const string BncIn = "BncIn"; public const string CompositeIn = "CompositeIn"; public const string DisplayPortIn = "DisplayPortIn"; public const string DmIn = "DmIn"; @@ -32,6 +34,7 @@ namespace PepperDash.Essentials.DM public const string HdmiLoopOut = "HdmiLoopOut"; public const string HdmiOut = "HdmiOut"; public const string Osd = "Osd"; + public const string SpdifIn = "SpdifIn"; public const string VgaIn = "VgaIn"; } } \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs index eb5c10fc..50b5acb7 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs @@ -168,11 +168,9 @@ namespace PepperDash.Essentials.DM && tx.CvbsInput.SyncDetectedFeedback.BoolValue) }; - AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn, - eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.None, 0, this, combinedFuncs); - DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.DmCat, null, this); + DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.DmCat, null, this); AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback, AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/Essentials_DM.csproj index 99350628..f266c842 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/Essentials_DM.csproj @@ -97,9 +97,10 @@ + - + diff --git a/essentials-framework/Essentials DM/Essentials_DM/VideoStatusHelpers.cs b/essentials-framework/Essentials DM/Essentials_DM/VideoStatusHelpers.cs index 096b1e36..50107c37 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/VideoStatusHelpers.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/VideoStatusHelpers.cs @@ -48,6 +48,26 @@ namespace PepperDash.Essentials.DM }; } + public static VideoStatusFuncsWrapper GetVgaInputStatusFuncs(VgaDviInputPort port) + { + return new VideoStatusFuncsWrapper + { + HdcpActiveFeedbackFunc = () => port.VideoAttributes.HdcpActiveFeedback.BoolValue, + HdcpStateFeedbackFunc = () => port.VideoAttributes.HdcpStateFeedback.ToString(), + VideoResolutionFeedbackFunc = () => port.VideoAttributes.GetVideoResolutionString(), + VideoSyncFeedbackFunc = () => port.SyncDetectedFeedback.BoolValue + }; + } + + public static VideoStatusFuncsWrapper GetBncInputStatusFuncs(Component port) + { + return new VideoStatusFuncsWrapper + { + VideoResolutionFeedbackFunc = () => port.VideoAttributes.GetVideoResolutionString(), + VideoSyncFeedbackFunc = () => port.VideoDetectedFeedback.BoolValue + }; + } + public static VideoStatusFuncsWrapper GetDmInputStatusFuncs(DMInputPort port) { return new VideoStatusFuncsWrapper