/// <summary>
        ///
        /// </summary>
        /// <param name="key"></param>
        /// <param name="name"></param>
        /// <param name="chassis"></param>
        public DmChassisController(string key, string name, DmMDMnxn chassis)
            : base(key, name, chassis)
        {
            Chassis                       = chassis;
            InputPorts                    = new RoutingPortCollection <RoutingInputPort>();
            OutputPorts                   = new RoutingPortCollection <RoutingOutputPort>();
            VolumeControls                = new Dictionary <uint, DmCardAudioOutputController>();
            TxDictionary                  = new Dictionary <uint, string>();
            RxDictionary                  = new Dictionary <uint, string>();
            IsOnline.OutputChange        += new EventHandler <FeedbackEventArgs>(IsOnline_OutputChange);
            Chassis.DMInputChange        += new DMInputEventHandler(Chassis_DMInputChange);
            Chassis.DMSystemChange       += new DMSystemEventHandler(Chassis_DMSystemChange);
            Chassis.DMOutputChange       += new DMOutputEventHandler(Chassis_DMOutputChange);
            VideoOutputFeedbacks          = new Dictionary <uint, IntFeedback>();
            AudioOutputFeedbacks          = new Dictionary <uint, IntFeedback>();
            UsbOutputRoutedToFeebacks     = new Dictionary <uint, IntFeedback>();
            UsbInputRoutedToFeebacks      = new Dictionary <uint, IntFeedback>();
            OutputDisabledByHdcpFeedbacks = new Dictionary <uint, BoolFeedback>();
            VideoInputSyncFeedbacks       = new Dictionary <uint, BoolFeedback>();
            InputNameFeedbacks            = new Dictionary <uint, StringFeedback>();
            OutputNameFeedbacks           = new Dictionary <uint, StringFeedback>();
            OutputVideoRouteNameFeedbacks = new Dictionary <uint, StringFeedback>();
            OutputAudioRouteNameFeedbacks = new Dictionary <uint, StringFeedback>();
            InputEndpointOnlineFeedbacks  = new Dictionary <uint, BoolFeedback>();
            OutputEndpointOnlineFeedbacks = new Dictionary <uint, BoolFeedback>();

            SystemIdFeebdack                 = new IntFeedback(() => { return((Chassis as DmMDMnxn).SystemIdFeedback.UShortValue); });
            SystemIdBusyFeedback             = new BoolFeedback(() => { return((Chassis as DmMDMnxn).SystemIdBusy.BoolValue); });
            InputCardHdcpCapabilityFeedbacks = new Dictionary <uint, IntFeedback>();
            InputCardHdcpCapabilityTypes     = new Dictionary <uint, eHdcpCapabilityType>();

            for (uint x = 1; x <= Chassis.NumberOfOutputs; x++)
            {
                var tempX = x;

                if (Chassis.Outputs[tempX] != null)
                {
                    VideoOutputFeedbacks[tempX] = new IntFeedback(() => {
                        if (Chassis.Outputs[tempX].VideoOutFeedback != null)
                        {
                            return((ushort)Chassis.Outputs[tempX].VideoOutFeedback.Number);
                        }

                        return(0);
                    });
                    AudioOutputFeedbacks[tempX] = new IntFeedback(() => {
                        if (Chassis.Outputs[tempX].AudioOutFeedback != null)
                        {
                            return((ushort)Chassis.Outputs[tempX].AudioOutFeedback.Number);
                        }

                        return(0);
                    });
                    UsbOutputRoutedToFeebacks[tempX] = new IntFeedback(() => {
                        if (Chassis.Outputs[tempX].USBRoutedToFeedback != null)
                        {
                            return((ushort)Chassis.Outputs[tempX].USBRoutedToFeedback.Number);
                        }

                        return(0);
                    });

                    OutputNameFeedbacks[tempX] = new StringFeedback(() => {
                        if (Chassis.Outputs[tempX].NameFeedback != null)
                        {
                            return(Chassis.Outputs[tempX].NameFeedback.StringValue);
                        }

                        return("");
                    });
                    OutputVideoRouteNameFeedbacks[tempX] = new StringFeedback(() => {
                        if (Chassis.Outputs[tempX].VideoOutFeedback != null)
                        {
                            return(Chassis.Outputs[tempX].VideoOutFeedback.NameFeedback.StringValue);
                        }

                        return(NoRouteText);
                    });
                    OutputAudioRouteNameFeedbacks[tempX] = new StringFeedback(() => {
                        if (Chassis.Outputs[tempX].AudioOutFeedback != null)
                        {
                            return(Chassis.Outputs[tempX].AudioOutFeedback.NameFeedback.StringValue);
                        }

                        return(NoRouteText);
                    });
                    OutputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => Chassis.Outputs[tempX].EndpointOnlineFeedback);

                    OutputDisabledByHdcpFeedbacks[tempX] = new BoolFeedback(() => {
                        var output = Chassis.Outputs[tempX];

                        var hdmiTxOutput = output as Card.HdmiTx;
                        if (hdmiTxOutput != null)
                        {
                            return(hdmiTxOutput.HdmiOutput.DisabledByHdcp.BoolValue);
                        }

                        var dmHdmiOutput = output as Card.DmHdmiOutput;
                        if (dmHdmiOutput != null)
                        {
                            return(dmHdmiOutput.DisabledByHdcpFeedback.BoolValue);
                        }

                        var dmsDmOutAdvanced = output as Card.DmsDmOutAdvanced;
                        if (dmsDmOutAdvanced != null)
                        {
                            return(dmsDmOutAdvanced.DisabledByHdcpFeedback.BoolValue);
                        }

                        var dmps3HdmiAudioOutput = output as Card.Dmps3HdmiAudioOutput;
                        if (dmps3HdmiAudioOutput != null)
                        {
                            return(dmps3HdmiAudioOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue);
                        }

                        var dmps3HdmiOutput = output as Card.Dmps3HdmiOutput;
                        if (dmps3HdmiOutput != null)
                        {
                            return(dmps3HdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue);
                        }

                        var dmps3HdmiOutputBackend = output as Card.Dmps3HdmiOutputBackend;
                        if (dmps3HdmiOutputBackend != null)
                        {
                            return(dmps3HdmiOutputBackend.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue);
                        }

                        // var hdRx4kX10HdmiOutput = output as HdRx4kX10HdmiOutput;
                        // if (hdRx4kX10HdmiOutput != null)
                        //     return hdRx4kX10HdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue;

                        // var hdMdNxMHdmiOutput = output as HdMdNxMHdmiOutput;
                        // if (hdMdNxMHdmiOutput != null)
                        //     return hdMdNxMHdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue;

                        return(false);
                    });
                }

                if (Chassis.Inputs[tempX] != null)
                {
                    UsbInputRoutedToFeebacks[tempX] = new IntFeedback(() => {
                        if (Chassis.Inputs[tempX].USBRoutedToFeedback != null)
                        {
                            return((ushort)Chassis.Inputs[tempX].USBRoutedToFeedback.Number);
                        }

                        return(0);
                    });
                    VideoInputSyncFeedbacks[tempX] = new BoolFeedback(() => {
                        if (Chassis.Inputs[tempX].VideoDetectedFeedback != null)
                        {
                            return(Chassis.Inputs[tempX].VideoDetectedFeedback.BoolValue);
                        }

                        return(false);
                    });
                    InputNameFeedbacks[tempX] = new StringFeedback(() => {
                        if (Chassis.Inputs[tempX].NameFeedback != null)
                        {
                            return(Chassis.Inputs[tempX].NameFeedback.StringValue);
                        }

                        return("");
                    });

                    InputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => { return(Chassis.Inputs[tempX].EndpointOnlineFeedback); });

                    InputCardHdcpCapabilityFeedbacks[tempX] = new IntFeedback(() => {
                        var inputCard = Chassis.Inputs[tempX];

                        if (inputCard.Card is DmcHd)
                        {
                            InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport;

                            if ((inputCard.Card as DmcHd).HdmiInput.HdcpSupportOnFeedback.BoolValue)
                            {
                                return(1);
                            }
                            return(0);
                        }

                        if (inputCard.Card is DmcHdDsp)
                        {
                            InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport;

                            if ((inputCard.Card as DmcHdDsp).HdmiInput.HdcpSupportOnFeedback.BoolValue)
                            {
                                return(1);
                            }
                            return(0);
                        }
                        if (inputCard.Card is Dmc4kHdBase)
                        {
                            InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.Hdcp2_2Support;
                            return((int)(inputCard.Card as Dmc4kHdBase).HdmiInput.HdcpReceiveCapability);
                        }
                        if (inputCard.Card is Dmc4kCBase)
                        {
                            if (PropertiesConfig.InputSlotSupportsHdcp2[tempX])
                            {
                                InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport;
                                return((int)(inputCard.Card as Dmc4kCBase).DmInput.HdcpReceiveCapability);
                            }

                            if ((inputCard.Card as Dmc4kCBase).DmInput.HdcpSupportOnFeedback.BoolValue)
                            {
                                return(1);
                            }
                            return(0);
                        }
                        if (inputCard.Card is Dmc4kCDspBase)
                        {
                            if (PropertiesConfig.InputSlotSupportsHdcp2[tempX])
                            {
                                InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport;
                                return((int)(inputCard.Card as Dmc4kCDspBase).DmInput.HdcpReceiveCapability);
                            }

                            if ((inputCard.Card as Dmc4kCDspBase).DmInput.HdcpSupportOnFeedback.BoolValue)
                            {
                                return(1);
                            }

                            return(0);
                        }
                        return(0);
                    });
                }
            }
        }
        /// <summary>
        /// Factory method to create a new chassis controller from config data. Limited to 8x8 right now
        /// </summary>
        public static DmChassisController GetDmChassisController(string key, string name,
                                                                 string type, DMChassisPropertiesConfig properties)
        {
            try
            {
                type = type.ToLower();
                uint ipid = properties.Control.IpIdInt;

                DmMDMnxn chassis = null;
                switch (type)
                {
                case "dmmd8x8":
                    chassis = new DmMd8x8(ipid, Global.ControlSystem);
                    break;

                case "dmmd8x8rps":
                    chassis = new DmMd8x8rps(ipid, Global.ControlSystem);
                    break;

                case "dmmd8x8cpu3":
                    chassis = new DmMd8x8Cpu3(ipid, Global.ControlSystem);
                    break;

                case "dmmd8x8cpu3rps":
                    chassis = new DmMd8x8Cpu3rps(ipid, Global.ControlSystem);
                    break;

                case "dmmd16x16":
                    chassis = new DmMd16x16(ipid, Global.ControlSystem);
                    break;

                case "dmmd16x16rps":
                    chassis = new DmMd16x16rps(ipid, Global.ControlSystem);
                    break;

                case "dmmd16x16cpu3":
                    chassis = new DmMd16x16Cpu3(ipid, Global.ControlSystem);
                    break;

                case "dmmd16x16cpu3rps":
                    chassis = new DmMd16x16Cpu3rps(ipid, Global.ControlSystem);
                    break;

                case "dmmd32x32":
                    chassis = new DmMd32x32(ipid, Global.ControlSystem);
                    break;

                case "dmmd32x32rps":
                    chassis = new DmMd32x32rps(ipid, Global.ControlSystem);
                    break;

                case "dmmd32x32cpu3":
                    chassis = new DmMd32x32Cpu3(ipid, Global.ControlSystem);
                    break;

                case "dmmd32x32cpu3rps":
                    chassis = new DmMd32x32Cpu3rps(ipid, Global.ControlSystem);
                    break;
                }

                if (chassis == null)
                {
                    return(null);
                }

                var controller = new DmChassisController(key, name, chassis);

                // add the cards and port names
                foreach (var kvp in properties.InputSlots)
                {
                    controller.AddInputCard(kvp.Value, kvp.Key);
                }

                foreach (var kvp in properties.OutputSlots)
                {
                    controller.AddOutputCard(kvp.Value, kvp.Key);
                }

                foreach (var kvp in properties.VolumeControls)
                {
                    // get the card
                    // check it for an audio-compatible type
                    // make a something-something that will make it work
                    // retire to mountain village
                    var          outNum = kvp.Key;
                    var          card   = controller.Chassis.Outputs[outNum].Card;
                    Audio.Output audio  = null;
                    if (card is DmcHdo)
                    {
                        audio = (card as DmcHdo).Audio;
                    }
                    else if (card is Dmc4kHdo)
                    {
                        audio = (card as Dmc4kHdo).Audio;
                    }
                    if (audio == null)
                    {
                        continue;
                    }

                    // wire up the audio to something here...
                    controller.AddVolumeControl(outNum, audio);
                }

                controller.InputNames  = properties.InputNames;
                controller.OutputNames = properties.OutputNames;

                if (!string.IsNullOrEmpty(properties.NoRouteText))
                {
                    controller.NoRouteText = properties.NoRouteText;
                    Debug.Console(1, controller, "Setting No Route Text value to: {0}", controller.NoRouteText);
                }
                else
                {
                    Debug.Console(1, controller, "NoRouteText not specified.  Defaulting to blank string.", controller.NoRouteText);
                }

                controller.PropertiesConfig = properties;
                return(controller);
            }
            catch (Exception e)
            {
                Debug.Console(0, "Error creating DM chassis:\r{0}", e);
            }

            return(null);
        }