diff --git a/PepperDashEssentials/PepperDashEssentials.csproj b/PepperDashEssentials/PepperDashEssentials.csproj index cd8062ce..42d0e288 100644 --- a/PepperDashEssentials/PepperDashEssentials.csproj +++ b/PepperDashEssentials/PepperDashEssentials.csproj @@ -71,7 +71,7 @@ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - + False ..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 1b936420..ffc6a4db 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -194,7 +194,7 @@ namespace PepperDash.Essentials var vc = VideoCodec as IHasExternalSourceSwitching; if (vc != null) { - vc.SetSelectedSource(_CurrentSourceInfo.SourceKey); + vc.SetSelectedSource(CurrentSourceInfoKey); } } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 2b45030c..e2e6519e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -83,7 +83,7 @@ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - + False ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 4a439d19..34d1cd60 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -18,14 +18,14 @@ using PepperDash.Essentials.DM.Config; using Feedback = PepperDash.Essentials.Core.Feedback; namespace PepperDash.Essentials.DM -{ +{ public class DmpsRoutingController : EssentialsBridgeableDevice, IRoutingNumericWithFeedback, IHasFeedback { public CrestronControlSystem Dmps { get; set; } - public ISystemControl SystemControl { get; private set; } - - //IroutingNumericEvent - public event EventHandler NumericSwitchChange; + public ISystemControl SystemControl { get; private set; } + + //IroutingNumericEvent + public event EventHandler NumericSwitchChange; // Feedbacks for EssentialDM public Dictionary VideoOutputFeedbacks { get; private set; } @@ -57,16 +57,16 @@ namespace PepperDash.Essentials.DM /// /// Text that represents when an output has no source routed to it /// - public string NoRouteText = ""; - - /// - /// Raise an event when the status of a switch object changes. - /// - /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType - private void OnSwitchChange(RoutingNumericEventArgs e) - { - var newEvent = NumericSwitchChange; - if (newEvent != null) newEvent(this, e); + public string NoRouteText = ""; + + /// + /// Raise an event when the status of a switch object changes. + /// + /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType + private void OnSwitchChange(RoutingNumericEventArgs e) + { + var newEvent = NumericSwitchChange; + if (newEvent != null) newEvent(this, e); } @@ -133,8 +133,8 @@ namespace PepperDash.Essentials.DM OutputEndpointOnlineFeedbacks = new Dictionary(); Debug.Console(1, this, "{0} Switcher Inputs Present.", Dmps.SwitcherInputs.Count); - Debug.Console(1, this, "{0} Switcher Outputs Present.", Dmps.SwitcherOutputs.Count); - + Debug.Console(1, this, "{0} Switcher Outputs Present.", Dmps.SwitcherOutputs.Count); + Debug.Console(1, this, "{0} Inputs in ControlSystem", Dmps.NumberOfSwitcherInputs); Debug.Console(1, this, "{0} Outputs in ControlSystem", Dmps.NumberOfSwitcherOutputs); @@ -155,57 +155,57 @@ namespace PepperDash.Essentials.DM Dmps.DMOutputChange += Dmps_DMOutputChange; return base.CustomActivate(); - } - - private void SetOutputNames() - { - if (OutputNames == null) - { - return; - } - - foreach (var kvp in OutputNames) - { - var output = (Dmps.SwitcherOutputs[kvp.Key] as DMOutput); - if (output != null && output.Name.Type != eSigType.NA) - { - output.Name.StringValue = kvp.Value; - } - } - } - - private void SetInputNames() - { - if (InputNames == null) - { - return; - } - foreach (var kvp in InputNames) - { - var input = (Dmps.SwitcherInputs[kvp.Key] as DMInput); - if (input != null && input.Name.Type != eSigType.NA) - { - input.Name.StringValue = kvp.Value; - } - } - } - + } + + private void SetOutputNames() + { + if (OutputNames == null) + { + return; + } + + foreach (var kvp in OutputNames) + { + var output = (Dmps.SwitcherOutputs[kvp.Key] as DMOutput); + if (output != null && output.Name.Type != eSigType.NA) + { + output.Name.StringValue = kvp.Value; + } + } + } + + private void SetInputNames() + { + if (InputNames == null) + { + return; + } + foreach (var kvp in InputNames) + { + var input = (Dmps.SwitcherInputs[kvp.Key] as DMInput); + if (input != null && input.Name.Type != eSigType.NA) + { + input.Name.StringValue = kvp.Value; + } + } + } + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { + { var joinMap = new DmpsRoutingControllerJoinMap(joinStart); var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); } Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); @@ -214,194 +214,203 @@ namespace PepperDash.Essentials.DM LinkInputsToApi(trilist, joinMap); LinkOutputsToApi(trilist, joinMap); - } - - private void LinkOutputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap) - { - for (uint i = 1; i <= Dmps.SwitcherOutputs.Count; i++) - { - Debug.Console(2, this, "Linking Output Card {0}", i); - - var ioSlot = i; - var ioSlotJoin = ioSlot - 1; - - // Control - trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, - o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video)); - trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + ioSlotJoin, - o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio)); - - trilist.SetStringSigAction(joinMap.OutputNames.JoinNumber + ioSlotJoin, s => - { - var outputCard = Dmps.SwitcherOutputs[ioSlot] as DMOutput; - - //Debug.Console(2, dmpsRouter, "Output Name String Sig Action for Output Card {0}", ioSlot); - - if (outputCard == null) - { - return; - } - //Debug.Console(2, dmpsRouter, "Card Type: {0}", outputCard.CardInputOutputType); - - if (outputCard is Card.Dmps3CodecOutput || outputCard.NameFeedback == null) - { - return; - } - if (string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) - { - return; - } - //Debug.Console(2, dmpsRouter, "NameFeedabck: {0}", outputCard.NameFeedback.StringValue); - - if (outputCard.NameFeedback.StringValue != s && outputCard.Name != null) - { - outputCard.Name.StringValue = s; - } - }); - - // Feedback - if (VideoOutputFeedbacks[ioSlot] != null) - { - VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]); - } - if (AudioOutputFeedbacks[ioSlot] != null) - { - AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]); - } - if (OutputNameFeedbacks[ioSlot] != null) - { - OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); - } - if (OutputVideoRouteNameFeedbacks[ioSlot] != null) - { - OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig( - trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + ioSlotJoin]); - } - if (OutputAudioRouteNameFeedbacks[ioSlot] != null) - { - OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig( - trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + ioSlotJoin]); - } - if (OutputEndpointOnlineFeedbacks[ioSlot] != null) - { - OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( - trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]); - } - } - } - - private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap) - { - for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++) - { - Debug.Console(2, this, "Linking Input Card {0}", i); - - var ioSlot = i; - var ioSlotJoin = ioSlot - 1; - - if (VideoInputSyncFeedbacks[ioSlot] != null) - { - VideoInputSyncFeedbacks[ioSlot].LinkInputSig( - trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); - } - - if (InputNameFeedbacks[ioSlot] != null) - { - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); - } - - trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s => - { - var inputCard = Dmps.SwitcherInputs[ioSlot] as DMInput; - - if (inputCard == null) - { - return; - } - - if (inputCard.NameFeedback == null || string.IsNullOrEmpty(inputCard.NameFeedback.StringValue) || - inputCard.NameFeedback.StringValue == s) - { - return; - } - - if (inputCard.Name != null) - { - inputCard.Name.StringValue = s; - } - }); - - - if (InputEndpointOnlineFeedbacks[ioSlot] != null) - { - InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( - trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]); - } - } - } - - + } + + private void LinkOutputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap) + { + for (uint i = 1; i <= Dmps.SwitcherOutputs.Count; i++) + { + Debug.Console(2, this, "Linking Output Card {0}", i); + + var ioSlot = i; + var ioSlotJoin = ioSlot - 1; + + // Control + trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, + o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video)); + trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + ioSlotJoin, + o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio)); + + trilist.SetStringSigAction(joinMap.OutputNames.JoinNumber + ioSlotJoin, s => + { + var outputCard = Dmps.SwitcherOutputs[ioSlot] as DMOutput; + + //Debug.Console(2, dmpsRouter, "Output Name String Sig Action for Output Card {0}", ioSlot); + + if (outputCard == null) + { + return; + } + //Debug.Console(2, dmpsRouter, "Card Type: {0}", outputCard.CardInputOutputType); + + if (outputCard is Card.Dmps3CodecOutput || outputCard.NameFeedback == null) + { + return; + } + if (string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) + { + return; + } + //Debug.Console(2, dmpsRouter, "NameFeedabck: {0}", outputCard.NameFeedback.StringValue); + + if (outputCard.NameFeedback.StringValue != s && outputCard.Name != null) + { + outputCard.Name.StringValue = s; + } + }); + + // Feedback + if (VideoOutputFeedbacks[ioSlot] != null) + { + VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]); + } + if (AudioOutputFeedbacks[ioSlot] != null) + { + AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]); + } + if (OutputNameFeedbacks[ioSlot] != null) + { + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); + } + if (OutputVideoRouteNameFeedbacks[ioSlot] != null) + { + OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig( + trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + ioSlotJoin]); + } + if (OutputAudioRouteNameFeedbacks[ioSlot] != null) + { + OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig( + trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + ioSlotJoin]); + } + if (OutputEndpointOnlineFeedbacks[ioSlot] != null) + { + OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( + trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]); + } + } + } + + private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap) + { + for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++) + { + Debug.Console(2, this, "Linking Input Card {0}", i); + + var ioSlot = i; + var ioSlotJoin = ioSlot - 1; + + if (VideoInputSyncFeedbacks[ioSlot] != null) + { + VideoInputSyncFeedbacks[ioSlot].LinkInputSig( + trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); + } + + if (InputNameFeedbacks[ioSlot] != null) + { + InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); + } + + trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s => + { + var inputCard = Dmps.SwitcherInputs[ioSlot] as DMInput; + + if (inputCard == null) + { + return; + } + + if (inputCard.NameFeedback == null || string.IsNullOrEmpty(inputCard.NameFeedback.StringValue) || + inputCard.NameFeedback.StringValue == s) + { + return; + } + + if (inputCard.Name != null) + { + inputCard.Name.StringValue = s; + } + }); + + + if (InputEndpointOnlineFeedbacks[ioSlot] != null) + { + InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( + trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]); + } + } + } + + /// /// Iterate the SwitcherOutputs collection to setup feedbacks and add routing ports /// void SetupOutputCards() { - foreach (var card in Dmps.SwitcherOutputs) - { + foreach (var card in Dmps.SwitcherOutputs) + { Debug.Console(1, this, "Output Card Type: {0}", card.CardInputOutputType); - var outputCard = card as DMOutput; - - if (outputCard == null) - { - Debug.Console(1, this, "Output card {0} is not a DMOutput", card.CardInputOutputType); - continue; - } - + var outputCard = card as DMOutput; + + if (outputCard == null) + { + Debug.Console(1, this, "Output card {0} is not a DMOutput", card.CardInputOutputType); + continue; + } + Debug.Console(1, this, "Adding Output Card Number {0} Type: {1}", outputCard.Number, outputCard.CardInputOutputType.ToString()); VideoOutputFeedbacks[outputCard.Number] = new IntFeedback(() => { - if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; } - return 0; + if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; } + return 0; ; }); AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() => { - if (outputCard.AudioOutFeedback != null) { return (ushort)outputCard.AudioOutFeedback.Number; } - return 0; - ; + try + { + if (outputCard.AudioOutFeedback != null) + { + return (ushort) outputCard.AudioOutFeedback.Number; + } + return 0; + } + catch (NotSupportedException) + { + return (ushort) outputCard.AudioOutSourceFeedback; + } }); - OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() => - { + OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() => + { if (outputCard.NameFeedback != null && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) { Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue); return outputCard.NameFeedback.StringValue; - } - return ""; + } + return ""; }); - OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => - { + OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => + { if (outputCard.VideoOutFeedback != null && outputCard.VideoOutFeedback.NameFeedback != null) { return outputCard.VideoOutFeedback.NameFeedback.StringValue; - } - return NoRouteText; + } + return NoRouteText; }); - OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => - { + OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => + { if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null) { return outputCard.AudioOutFeedback.NameFeedback.StringValue; - } - return NoRouteText; + } + return NoRouteText; }); OutputEndpointOnlineFeedbacks[outputCard.Number] = new BoolFeedback(() => outputCard.EndpointOnlineFeedback); - AddOutputCard(outputCard.Number, outputCard); + AddOutputCard(outputCard.Number, outputCard); } } @@ -513,26 +522,26 @@ namespace PepperDash.Essentials.DM AddInputPortWithDebug(number, string.Format("AirMediaIn{0}", number), eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Streaming); } - } - - - /// - /// Adds InputPort - /// - private 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) - { - FeedbackMatchObject = Dmps.SwitcherInputs[cardNum] - }; - ; - - InputPorts.Add(inputPort); - } - + } + + + /// + /// Adds InputPort + /// + private 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) + { + FeedbackMatchObject = Dmps.SwitcherInputs[cardNum] + }; + ; + + InputPorts.Add(inputPort); + } + /// /// Adds InputPort and sets Port as ICec object /// @@ -540,9 +549,9 @@ namespace PepperDash.Essentials.DM { 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) - { - FeedbackMatchObject = Dmps.SwitcherInputs[cardNum] + var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this) + { + FeedbackMatchObject = Dmps.SwitcherInputs[cardNum] }; ; @@ -550,7 +559,7 @@ namespace PepperDash.Essentials.DM inputPort.Port = cecPort; InputPorts.Add(inputPort); - } + } /// @@ -566,23 +575,23 @@ namespace PepperDash.Essentials.DM var cecPort = hdmiOutputCard.HdmiOutputPort; - AddHdmiOutputPort(number, cecPort); + AddHdmiOutputPort(number, cecPort); } - else if (outputCard is Card.Dmps3HdmiOutputBackend) - { - var hdmiOutputCard = outputCard as Card.Dmps3HdmiOutputBackend; - - var cecPort = hdmiOutputCard.HdmiOutputPort; - - AddHdmiOutputPort(number, cecPort); + else if (outputCard is Card.Dmps3HdmiOutputBackend) + { + var hdmiOutputCard = outputCard as Card.Dmps3HdmiOutputBackend; + + var cecPort = hdmiOutputCard.HdmiOutputPort; + + AddHdmiOutputPort(number, cecPort); } else if (outputCard is Card.Dmps3DmOutput) - { - AddDmOutputPort(number); + { + AddDmOutputPort(number); } - else if (outputCard is Card.Dmps3DmOutputBackend) - { - AddDmOutputPort(number); + else if (outputCard is Card.Dmps3DmOutputBackend) + { + AddDmOutputPort(number); } else if (outputCard is Card.Dmps3ProgramOutput) { @@ -590,51 +599,51 @@ namespace PepperDash.Essentials.DM var programOutput = new DmpsAudioOutputController(string.Format("processor-programAudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase); - DeviceManager.AddDevice(programOutput); + DeviceManager.AddDevice(programOutput); } - else if (outputCard is Card.Dmps3AuxOutput) - { - switch (outputCard.CardInputOutputType) - { - case eCardInputOutputType.Dmps3Aux1Output: + else if (outputCard is Card.Dmps3AuxOutput) + { + switch (outputCard.CardInputOutputType) + { + case eCardInputOutputType.Dmps3Aux1Output: { AddAudioOnlyOutputPort(number, "Aux1"); var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase); DeviceManager.AddDevice(aux1Output); - } - break; - case eCardInputOutputType.Dmps3Aux2Output: + } + break; + case eCardInputOutputType.Dmps3Aux2Output: { AddAudioOnlyOutputPort(number, "Aux2"); var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase); DeviceManager.AddDevice(aux2Output); - } - break; - } - } - else if (outputCard is Card.Dmps3CodecOutput) - { - switch (number) - { - case (uint)CrestronControlSystem.eDmps34K350COutputs.Codec1: - case (uint)CrestronControlSystem.eDmps34K250COutputs.Codec1: - case (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec1: - AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec1.ToString()); - break; - case (uint)CrestronControlSystem.eDmps34K350COutputs.Codec2: - case (uint)CrestronControlSystem.eDmps34K250COutputs.Codec2: - case (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec2: - AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec2.ToString()); - break; - } - } + } + break; + } + } + else if (outputCard is Card.Dmps3CodecOutput) + { + switch (number) + { + case (uint)CrestronControlSystem.eDmps34K350COutputs.Codec1: + case (uint)CrestronControlSystem.eDmps34K250COutputs.Codec1: + case (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec1: + AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec1.ToString()); + break; + case (uint)CrestronControlSystem.eDmps34K350COutputs.Codec2: + case (uint)CrestronControlSystem.eDmps34K250COutputs.Codec2: + case (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec2: + AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec2.ToString()); + break; + } + } else if (outputCard is Card.Dmps3DialerOutput) { - AddAudioOnlyOutputPort(number, "Dialer"); + AddAudioOnlyOutputPort(number, "Dialer"); } else if (outputCard is Card.Dmps3DigitalMixOutput) { @@ -645,11 +654,11 @@ namespace PepperDash.Essentials.DM if (number == (uint)CrestronControlSystem.eDmps34K250COutputs.Mix2 || number == (uint)CrestronControlSystem.eDmps34K300COutputs.Mix2 || number == (uint)CrestronControlSystem.eDmps34K350COutputs.Mix2) - AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString()); + AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString()); } else if (outputCard is Card.Dmps3AecOutput) { - AddAudioOnlyOutputPort(number, "Aec"); + AddAudioOnlyOutputPort(number, "Aec"); } else { @@ -692,9 +701,9 @@ namespace PepperDash.Essentials.DM { 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) - { - FeedbackMatchObject = Dmps.SwitcherOutputs[cardNum] + OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this) + { + FeedbackMatchObject = Dmps.SwitcherOutputs[cardNum] }); } @@ -705,9 +714,9 @@ namespace PepperDash.Essentials.DM { 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) - { - FeedbackMatchObject = Dmps.SwitcherOutputs[cardNum] + var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this) + { + FeedbackMatchObject = Dmps.SwitcherOutputs[cardNum] }; if (cecPort != null) @@ -768,74 +777,55 @@ namespace PepperDash.Essentials.DM { OutputEndpointOnlineFeedbacks[output].FireUpdate(); } - else if (args.EventId == DMOutputEventIds.VideoOutEventId) - { - if (outputCard == null) return; - - var outputFeedbackIndex = outputCard.VideoOutFeedback == null ? 0 : outputCard.VideoOutFeedback.Number; - - Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, - outputFeedbackIndex, output); - - if (VideoOutputFeedbacks.ContainsKey(output)) - { - var localInputPort = - InputPorts.FirstOrDefault(p => (DMInput) p.FeedbackMatchObject == outputCard.VideoOutFeedback); - var localOutputPort = OutputPorts.FirstOrDefault(p => (DMOutput) p.FeedbackMatchObject == outputCard); - - VideoOutputFeedbacks[output].FireUpdate(); - OnSwitchChange(new RoutingNumericEventArgs(output, VideoOutputFeedbacks[output].UShortValue, - localOutputPort, localInputPort, eRoutingSignalType.Video)); - } - if (OutputVideoRouteNameFeedbacks.ContainsKey(output)) - { - OutputVideoRouteNameFeedbacks[output].FireUpdate(); - } - } - else if (args.EventId == DMOutputEventIds.AudioOutEventId) - { - /* - if (outputCard == null || outputCard.AudioOutFeedback == null) return; - - Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, - outputCard.AudioOutFeedback.Number, output); - - if (AudioOutputFeedbacks.ContainsKey(output)) - { - AudioOutputFeedbacks[output].FireUpdate(); - OnSwitchChange(new RoutingNumericEventArgs(output, AudioOutputFeedbacks[output].UShortValue, eRoutingSignalType.Audio)); - } - */ - - if (outputCard == null) return; - - var outputFeedbackIndex = outputCard.AudioOutFeedback == null ? 0 : outputCard.VideoOutFeedback.Number; - - Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, - outputFeedbackIndex, output); - - if (AudioOutputFeedbacks.ContainsKey(output)) - { - var localInputPort = - InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == outputCard.AudioOutFeedback); - var localOutputPort = OutputPorts.FirstOrDefault(p => (DMOutput)p.FeedbackMatchObject == outputCard); - - AudioOutputFeedbacks[output].FireUpdate(); - OnSwitchChange(new RoutingNumericEventArgs(output, AudioOutputFeedbacks[output].UShortValue, - localOutputPort, localInputPort, eRoutingSignalType.Audio)); - } - if (OutputAudioRouteNameFeedbacks.ContainsKey(output)) - { - OutputAudioRouteNameFeedbacks[output].FireUpdate(); - } - } - else if (args.EventId == DMOutputEventIds.OutputNameEventId - && OutputNameFeedbacks.ContainsKey(output)) - { - Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output); - OutputNameFeedbacks[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) + { + try + { + 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(); + } + } + catch (NotSupportedException) + { + if (outputCard != null) + { + Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", Name, + outputCard.AudioOutSourceFeedback, output); + } + if (AudioOutputFeedbacks.ContainsKey(output)) + { + AudioOutputFeedbacks[output].FireUpdate(); + } + } + } + else if (args.EventId == DMOutputEventIds.OutputNameEventId + && OutputNameFeedbacks.ContainsKey(output)) + { + Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output); + OutputNameFeedbacks[output].FireUpdate(); + } + } /// @@ -861,7 +851,14 @@ namespace PepperDash.Essentials.DM var input = Convert.ToUInt32(inputSelector); // Cast can sometimes fail var output = Convert.ToUInt32(outputSelector); - if (input <= Dmps.NumberOfSwitcherInputs && output <= Dmps.NumberOfSwitcherOutputs) + var sigTypeIsUsbOrVideo = ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) || + ((sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput) || + ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput); + + if ((input <= Dmps.NumberOfSwitcherInputs && output <= Dmps.NumberOfSwitcherOutputs && + sigTypeIsUsbOrVideo) || + (input <= Dmps.NumberOfSwitcherInputs + 5 && output <= Dmps.NumberOfSwitcherOutputs && + (sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio)) { // Check to see if there's an off timer waiting on this and if so, cancel var key = new PortNumberType(output, sigType); @@ -879,37 +876,55 @@ namespace PepperDash.Essentials.DM } } - DMInput inCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput; - DMOutput outCard = output == 0 ? null : Dmps.SwitcherOutputs[output] as DMOutput; + + DMOutput dmOutputCard = output == 0 ? null : Dmps.SwitcherOutputs[output] as DMOutput; //if (inCard != null) //{ - // NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES - if ((sigType | eRoutingSignalType.Video) == eRoutingSignalType.Video) - { + // NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES + if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) + { + DMInput dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput; + //SystemControl.VideoEnter.BoolValue = true; + if (dmOutputCard != null) + dmOutputCard.VideoOut = dmInputCard; + } - //SystemControl.VideoEnter.BoolValue = true; - if (outCard != null) - outCard.VideoOut = inCard; + if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) + { + DMInput dmInputCard = null; + if (input <= Dmps.NumberOfSwitcherInputs) + { + dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput; } - if ((sigType | eRoutingSignalType.Audio) == eRoutingSignalType.Audio) - { - if (outCard != null) - outCard.AudioOut = inCard; - } + if (dmOutputCard != null) + try + { + dmOutputCard.AudioOut = dmInputCard; + } + catch (NotSupportedException) + { + Debug.Console(1, this, "Routing input {0} audio to output {1}", + (eDmps34KAudioOutSource) input, (CrestronControlSystem.eDmps34K350COutputs) output); - if ((sigType | eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput) - { - if (outCard != null) - outCard.USBRoutedTo = inCard; - } + dmOutputCard.AudioOutSource = (eDmps34KAudioOutSource) input; + } + } - if ((sigType | eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput) - { - if (inCard != null) - inCard.USBRoutedTo = outCard; - } + if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput) + { + DMInput dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput; + if (dmOutputCard != null) + dmOutputCard.USBRoutedTo = dmInputCard; + } + + if ((sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput) + { + DMInput dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput; + if (dmInputCard != null) + dmInputCard.USBRoutedTo = dmOutputCard; + } //} //else //{ @@ -919,7 +934,8 @@ namespace PepperDash.Essentials.DM } else { - Debug.Console(1, this, "Unable to execute route from input {0} to output {1}", inputSelector, outputSelector); + Debug.Console(1, this, "Unable to execute route from input {0} to output {1}", inputSelector, + outputSelector); } } catch (Exception e) @@ -928,15 +944,15 @@ namespace PepperDash.Essentials.DM } } - #endregion - - #region IRoutingNumeric Members - - public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType sigType) - { - ExecuteSwitch(inputSelector, outputSelector, sigType); - } - - #endregion + #endregion + + #region IRoutingNumeric Members + + public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType sigType) + { + ExecuteSwitch(inputSelector, outputSelector, sigType); + } + + #endregion } } \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj index 7d6b7bde..69045ea5 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -59,7 +59,7 @@ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - + False ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs index 89b6002a..c0a0442c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs @@ -92,8 +92,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// public interface IHasCameraPanControl : IHasCameraControls { - // void PanLeft(bool pressRelease); - // void PanRight(bool pressRelease); void PanLeft(); void PanRight(); void PanStop(); @@ -104,8 +102,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// public interface IHasCameraTiltControl : IHasCameraControls { - // void TiltDown(bool pressRelease); - // void TildUp(bool pressRelease); void TiltDown(); void TiltUp(); void TiltStop(); @@ -116,8 +112,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// public interface IHasCameraZoomControl : IHasCameraControls { - // void ZoomIn(bool pressRelease); - // void ZoomOut(bool pressRelease); void ZoomIn(); void ZoomOut(); void ZoomStop(); @@ -135,6 +129,13 @@ namespace PepperDash.Essentials.Devices.Common.Cameras void TriggerAutoFocus(); } + public interface IHasAutoFocusMode + { + void SetFocusModeAuto(); + void SetFocusModeManual(); + void ToggleFocusMode(); + } + public interface IHasCameraAutoMode : IHasCameraControls { void CameraAutoModeOn(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs index 2966bde4..fb8ae79c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs @@ -12,29 +12,86 @@ using PepperDash.Essentials.Devices.Common.Codec; using System.Text.RegularExpressions; using Crestron.SimplSharp.Reflection; +using Newtonsoft.Json; + namespace PepperDash.Essentials.Devices.Common.Cameras { - public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced + public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode { + CameraViscaPropertiesConfig PropertiesConfig; + public IBasicCommunication Communication { get; private set; } - public CommunicationGather PortGather { get; private set; } public StatusMonitorBase CommunicationMonitor { get; private set; } - public byte PanSpeed = 0x10; - public byte TiltSpeed = 0x10; + /// + /// Used to store the actions to parse inquiry responses as the inquiries are sent + /// + private CrestronQueue> InquiryResponseQueue; + + /// + /// Camera ID (Default 1) + /// + public byte ID = 0x01; + public byte ResponseID; + + + public byte PanSpeedSlow = 0x10; + public byte TiltSpeedSlow = 0x10; + + public byte PanSpeedFast = 0x13; + public byte TiltSpeedFast = 0x13; + private bool IsMoving; private bool IsZooming; - public bool PowerIsOn { get; private set; } + + bool _powerIsOn; + public bool PowerIsOn + { + get + { + return _powerIsOn; + } + private set + { + if (value != _powerIsOn) + { + _powerIsOn = value; + PowerIsOnFeedback.FireUpdate(); + CameraIsOffFeedback.FireUpdate(); + } + } + } + + const byte ZoomInCmd = 0x02; + const byte ZoomOutCmd = 0x03; + const byte ZoomStopCmd = 0x00; + + /// + /// Used to determine when to move the camera at a faster speed if a direction is held + /// + CTimer SpeedTimer; + // TODO: Implment speed timer for PTZ controls + + long FastSpeedHoldTimeMs = 2000; byte[] IncomingBuffer = new byte[] { }; public BoolFeedback PowerIsOnFeedback { get; private set; } - public CameraVisca(string key, string name, IBasicCommunication comm, CameraPropertiesConfig props) : + public CameraVisca(string key, string name, IBasicCommunication comm, CameraViscaPropertiesConfig props) : base(key, name) { + InquiryResponseQueue = new CrestronQueue>(15); + Presets = props.Presets; + PropertiesConfig = props; + + ID = (byte)(props.Id + 0x80); + ResponseID = (byte)((props.Id * 0x10) + 0x80); + + SetupCameraSpeeds(); + OutputPorts.Add(new RoutingOutputPort("videoOut", eRoutingSignalType.Video, eRoutingPortConnectionType.None, null, this, true)); // Default to all capabilties @@ -51,11 +108,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras { // This instance uses RS-232 control } - PortGather = new CommunicationGather(Communication, "\xFF"); - Communication.BytesReceived += new EventHandler(Communication_BytesReceived); PowerIsOnFeedback = new BoolFeedback(() => { return PowerIsOn; }); + CameraIsOffFeedback = new BoolFeedback(() => { return !PowerIsOn; }); if (props.CommunicationMonitorProperties != null) { @@ -66,9 +122,38 @@ namespace PepperDash.Essentials.Devices.Common.Cameras CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "\x81\x09\x04\x00\xFF"); } DeviceManager.AddDevice(CommunicationMonitor); - - } + + + /// + /// Sets up camera speed values based on config + /// + void SetupCameraSpeeds() + { + if (PropertiesConfig.FastSpeedHoldTimeMs > 0) + { + FastSpeedHoldTimeMs = PropertiesConfig.FastSpeedHoldTimeMs; + } + + if (PropertiesConfig.PanSpeedSlow > 0) + { + PanSpeedSlow = (byte)PropertiesConfig.PanSpeedSlow; + } + if (PropertiesConfig.PanSpeedFast > 0) + { + PanSpeedFast = (byte)PropertiesConfig.PanSpeedFast; + } + + if (PropertiesConfig.TiltSpeedSlow > 0) + { + TiltSpeedSlow = (byte)PropertiesConfig.TiltSpeedSlow; + } + if (PropertiesConfig.TiltSpeedFast > 0) + { + TiltSpeedFast = (byte)PropertiesConfig.TiltSpeedFast; + } + } + public override bool CustomActivate() { Communication.Connect(); @@ -110,40 +195,245 @@ namespace PepperDash.Essentials.Devices.Common.Cameras Communication.SendBytes(b); } + void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) { - // This is probably not thread-safe buffering - // Append the incoming bytes with whatever is in the buffer - var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length]; - IncomingBuffer.CopyTo(newBytes, 0); - e.Bytes.CopyTo(newBytes, IncomingBuffer.Length); - if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1 - Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes)); - } + var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length]; + try + { + // This is probably not thread-safe buffering + // Append the incoming bytes with whatever is in the buffer + IncomingBuffer.CopyTo(newBytes, 0); + e.Bytes.CopyTo(newBytes, IncomingBuffer.Length); + if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1 + Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes)); - private void SendPanTiltCommand (byte[] cmd) + byte[] message = new byte[] { }; + + // Search for the delimiter 0xFF character + for (int i = 0; i < newBytes.Length; i++) + { + if (newBytes[i] == 0xFF) + { + // i will be the index of the delmiter character + message = newBytes.Take(i).ToArray(); + // Skip over what we just took and save the rest for next time + newBytes = newBytes.Skip(i).ToArray(); + } + } + + if (message.Length > 0) + { + // Check for matching ID + if (message[0] != ResponseID) + { + return; + } + + switch (message[1]) + { + case 0x40: + { + // ACK received + Debug.Console(2, this, "ACK Received"); + break; + } + case 0x50: + { + + if (message[2] == 0xFF) + { + // Completion received + Debug.Console(2, this, "Completion Received"); + } + else + { + // Inquiry response received. Dequeue the next response handler and invoke it + if (InquiryResponseQueue.Count > 0) + { + var inquiryAction = InquiryResponseQueue.Dequeue(); + + inquiryAction.Invoke(message.Skip(2).ToArray()); + } + else + { + Debug.Console(2, this, "Response Queue is empty. Nothing to dequeue."); + } + } + + break; + } + case 0x60: + { + // Error message + + switch (message[2]) + { + case 0x01: + { + // Message Length Error + Debug.Console(2, this, "Error from device: Message Length Error"); + break; + } + case 0x02: + { + // Syntax Error + Debug.Console(2, this, "Error from device: Syntax Error"); + break; + } + case 0x03: + { + // Command Buffer Full + Debug.Console(2, this, "Error from device: Command Buffer Full"); + break; + } + case 0x04: + { + // Command Cancelled + Debug.Console(2, this, "Error from device: Command Cancelled"); + break; + } + case 0x05: + { + // No Socket + Debug.Console(2, this, "Error from device: No Socket"); + break; + } + case 0x41: + { + // Command not executable + Debug.Console(2, this, "Error from device: Command not executable"); + break; + } + } + break; + } + } + + if (message == new byte[] { ResponseID, 0x50, 0x02, 0xFF }) + { + PowerIsOn = true; + } + else if (message == new byte[] { ResponseID, 0x50, 0x03, 0xFF }) + { + PowerIsOn = false; + } + + } + + } + catch (Exception err) + { + Debug.Console(2, this, "Error parsing feedback: {0}", err); + } + finally + { + // Save whatever partial message is here + IncomingBuffer = newBytes; + } + } + + /// + /// Sends a pan/tilt command. If the command is not for fastSpeed then it starts a timer to initiate fast speed. + /// + /// + /// + private void SendPanTiltCommand (byte[] cmd, bool fastSpeedEnabled) { - var temp = new Byte[] { 0x81, 0x01, 0x06, 0x01, PanSpeed, TiltSpeed }; - int length = temp.Length + cmd.Length + 1; - - byte[] sum = new byte[length]; - temp.CopyTo(sum, 0); - cmd.CopyTo(sum, temp.Length); - sum[length - 1] = 0xFF; - SendBytes(sum); + SendBytes(GetPanTiltCommand(cmd, fastSpeedEnabled)); + + if (!fastSpeedEnabled) + { + if (SpeedTimer != null) + { + StopSpeedTimer(); + } + + // Start the timer to send fast speed if still moving after FastSpeedHoldTime elapses + SpeedTimer = new CTimer((o) => SendPanTiltCommand(GetPanTiltCommand(cmd, true), true), FastSpeedHoldTimeMs); + } + } + private void StopSpeedTimer() + { + if (SpeedTimer != null) + { + SpeedTimer.Stop(); + SpeedTimer.Dispose(); + SpeedTimer = null; + } + } + + /// + /// Generates the pan/tilt command with either slow or fast speed + /// + /// + /// + /// + private byte[] GetPanTiltCommand(byte[] cmd, bool fastSpeed) + { + byte panSpeed; + byte tiltSpeed; + + if (!fastSpeed) + { + panSpeed = PanSpeedSlow; + tiltSpeed = TiltSpeedSlow; + } + else + { + panSpeed = PanSpeedFast; + tiltSpeed = TiltSpeedFast; + } + + var temp = new byte[] { ID, 0x01, 0x06, 0x01, panSpeed, tiltSpeed }; + int length = temp.Length + cmd.Length + 1; + + byte[] sum = new byte[length]; + temp.CopyTo(sum, 0); + cmd.CopyTo(sum, temp.Length); + sum[length - 1] = 0xFF; + + return sum; + } + + + void SendPowerQuery() + { + SendBytes(new byte[] { ID, 0x09, 0x04, 0x00, 0xFF }); + InquiryResponseQueue.Enqueue(HandlePowerResponse); + } + public void PowerOn() { - - SendBytes(new Byte[] { 0x81, 0x01, 0x04, 0x00, 0x02, 0xFF }); + SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x02, 0xFF }); + SendPowerQuery(); } + void HandlePowerResponse(byte[] response) + { + switch (response[0]) + { + case 0x02: + { + PowerIsOn = true; + break; + } + case 0x03: + { + PowerIsOn = false; + break; + } + } + } + public void PowerOff() { - SendBytes(new Byte[] {0x81, 0x01, 0x04, 0x00, 0x03, 0xFF}); - } + SendBytes(new byte[] {ID, 0x01, 0x04, 0x00, 0x03, 0xFF}); + SendPowerQuery(); + } public void PowerToggle() { @@ -155,12 +445,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras public void PanLeft() { - SendPanTiltCommand(new byte[] {0x01, 0x03}); + SendPanTiltCommand(new byte[] {0x01, 0x03}, false); IsMoving = true; } public void PanRight() { - SendPanTiltCommand(new byte[] { 0x02, 0x03 }); + SendPanTiltCommand(new byte[] { 0x02, 0x03 }, false); IsMoving = true; } public void PanStop() @@ -169,12 +459,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } public void TiltDown() { - SendPanTiltCommand(new byte[] { 0x03, 0x02 }); + SendPanTiltCommand(new byte[] { 0x03, 0x02 }, false); IsMoving = true; } public void TiltUp() { - SendPanTiltCommand(new byte[] { 0x03, 0x01 }); + SendPanTiltCommand(new byte[] { 0x03, 0x01 }, false); IsMoving = true; } public void TiltStop() @@ -184,16 +474,18 @@ namespace PepperDash.Essentials.Devices.Common.Cameras private void SendZoomCommand (byte cmd) { - SendBytes(new byte[] {0x81, 0x01, 0x04, 0x07, cmd, 0xFF} ); + SendBytes(new byte[] {ID, 0x01, 0x04, 0x07, cmd, 0xFF} ); } + + public void ZoomIn() { - SendZoomCommand(0x02); + SendZoomCommand(ZoomInCmd); IsZooming = true; } public void ZoomOut() { - SendZoomCommand(0x03); + SendZoomCommand(ZoomOutCmd); IsZooming = true; } public void ZoomStop() @@ -205,26 +497,28 @@ namespace PepperDash.Essentials.Devices.Common.Cameras { if (IsZooming) { - SendZoomCommand(0x00); + SendZoomCommand(ZoomStopCmd); IsZooming = false; } else { - SendPanTiltCommand(new byte[] {0x03, 0x03}); + StopSpeedTimer(); + SendPanTiltCommand(new byte[] { 0x03, 0x03 }, false); IsMoving = false; } } public void PositionHome() { - throw new NotImplementedException(); + SendBytes(new byte[] { ID, 0x01, 0x06, 0x02, PanSpeedFast, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }); + SendBytes(new byte[] { ID, 0x01, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0xFF }); } public void RecallPreset(int presetNumber) { - SendBytes(new byte[] {0x81, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} ); + SendBytes(new byte[] {ID, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} ); } public void SavePreset(int presetNumber) { - SendBytes(new byte[] { 0x81, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF }); + SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF }); } #region IHasCameraPresets Members @@ -244,6 +538,90 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } #endregion + + #region IHasCameraFocusControl Members + + public void FocusNear() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x03, 0xFF }); + } + + public void FocusFar() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x02, 0xFF }); + } + + public void FocusStop() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x00, 0xFF }); + } + + public void TriggerAutoFocus() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x18, 0x01, 0xFF }); + SendAutoFocusQuery(); + } + + #endregion + + #region IHasAutoFocus Members + + public void SetFocusModeAuto() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x02, 0xFF }); + SendAutoFocusQuery(); + } + + public void SetFocusModeManual() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x03, 0xFF }); + SendAutoFocusQuery(); + } + + public void ToggleFocusMode() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x10, 0xFF }); + SendAutoFocusQuery(); + } + + #endregion + + void SendAutoFocusQuery() + { + SendBytes(new byte[] { ID, 0x09, 0x04, 0x38, 0xFF }); + InquiryResponseQueue.Enqueue(HandleAutoFocusResponse); + } + + void HandleAutoFocusResponse(byte[] response) + { + switch (response[0]) + { + case 0x02: + { + // Auto Mode + PowerIsOn = true; + break; + } + case 0x03: + { + // Manual Mode + PowerIsOn = false; + break; + } + } + } + + #region IHasCameraOff Members + + public BoolFeedback CameraIsOffFeedback { get; private set; } + + + public void CameraOff() + { + PowerOff(); + } + + #endregion } public class CameraViscaFactory : EssentialsDeviceFactory @@ -257,10 +635,51 @@ namespace PepperDash.Essentials.Devices.Common.Cameras { Debug.Console(1, "Factory Attempting to create new CameraVisca Device"); var comm = CommFactory.CreateCommForDevice(dc); - var props = Newtonsoft.Json.JsonConvert.DeserializeObject( + var props = Newtonsoft.Json.JsonConvert.DeserializeObject( dc.Properties.ToString()); return new Cameras.CameraVisca(dc.Key, dc.Name, comm, props); } } + + public class CameraViscaPropertiesConfig : CameraPropertiesConfig + { + /// + /// Control ID of the camera (1-7) + /// + [JsonProperty("id")] + public uint Id { get; set; } + + /// + /// Slow Pan speed (0-18) + /// + [JsonProperty("panSpeedSlow")] + public uint PanSpeedSlow { get; set; } + + /// + /// Fast Pan speed (0-18) + /// + [JsonProperty("panSpeedFast")] + public uint PanSpeedFast { get; set; } + + /// + /// Slow tilt speed (0-18) + /// + [JsonProperty("tiltSpeedSlow")] + public uint TiltSpeedSlow { get; set; } + + /// + /// Fast tilt speed (0-18) + /// + [JsonProperty("tiltSpeedFast")] + public uint TiltSpeedFast { get; set; } + + /// + /// Time a button must be held before fast speed is engaged (Milliseconds) + /// + [JsonProperty("fastSpeedHoldTimeMs")] + public uint FastSpeedHoldTimeMs { get; set; } + + } + } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index f115f401..54d37613 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -63,7 +63,7 @@ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Lighting.dll - + False ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index ce748699..429794bc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -1339,10 +1339,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public override void SendDtmf(string s) { - if (CallFavorites != null) - { - SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s)); - } + SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s)); } public void SelectPresentationSource(int source)