diff --git a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs index d307d088..3897afa5 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs @@ -120,14 +120,22 @@ namespace PepperDash.Essentials /// 1206 /// public const uint VCRecentsVisible = 1206; - /// - /// 1207 - /// - public const uint VCCameraVisible = 1207; + /// /// 1208 /// - public const uint VCSelfViewLayoutVisible = 1208; + public const uint VCCameraAutoVisible = 1208; + + /// + /// 1209 + /// + public const uint VCCameraManualVisible = 1209; + + /// + /// 1210 + /// + public const uint VCCameraOffVisible = 1210; + /// /// 1211 - 1215 /// @@ -225,6 +233,45 @@ namespace PepperDash.Essentials /// public const uint VCMinMaxEnable = 1256; + /// + /// 1260 + /// + public const uint VCCameraModeBarVisible = 1260; + + /// + /// 1261 + /// + public const uint VCCameraSelectBarWithoutModeVisible = 1261; + + + /// + /// 1271 + /// + public const uint VCCameraZoomIn = 1271; + /// + /// 1272 + /// + public const uint VCCameraZoomOut = 1272; + + + /// + /// 1280 + /// + public const uint VCCameraPresetSavedLabelVisible = 1280; + /// + /// 1281 + /// + public const uint VCCameraPreset1 = 1281; + /// + /// 1282 + /// + public const uint VCCameraPreset2 = 1282; + /// + /// 1283 + /// + public const uint VCCameraPreset3 = 1283; + + // Letter joins start at 2921; //****************************************************** diff --git a/PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs b/PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs index 8da0b355..b48d78c9 100644 --- a/PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs @@ -33,6 +33,21 @@ /// public const uint VCLayoutsList = 1205; + /// + /// 1206 VC Camera Mode horizontal list + /// + public const uint VCCameraMode = 1206; + + /// + /// 1207 VC Camera Mode Dpad + /// + public const uint VCCameraDpad = 1207; + + /// + /// 1208 VC Camera Select + /// + public const uint VCCameraSelect = 1208; + //****************************************************** // General diff --git a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs index ea60526b..9b2b8a95 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs @@ -41,6 +41,21 @@ namespace PepperDash.Essentials public const uint VCRecentListTimeTextStart = 1231; // RANGE IN USE public const uint VCRecentListTimeTextEnd = 1260; + + + /// + /// 1281 + /// + public const uint VCCameraPresetLabel1 = 1281; + /// + /// 1282 + /// + public const uint VCCameraPresetLabel2 = 1282; + /// + /// 1283 + /// + public const uint VCCameraPresetLabel3 = 1283; + /// /// 1291 - the current layout mode /// diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index 55811d44..0c219426 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; using Crestron.SimplSharp; +using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; @@ -13,6 +14,7 @@ using PepperDash.Essentials.Core.SmartObjects; using PepperDash.Essentials.Core.Touchpanels.Keyboards; using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.VideoCodec; +using PepperDash.Essentials.Devices.Common.Cameras; namespace PepperDash.Essentials.UIDrivers.VC { @@ -41,6 +43,11 @@ namespace PepperDash.Essentials.UIDrivers.VC /// JoinedSigInterlock VCControlsInterlock; + /// + /// For the camera control mode (auto/manual/off) + /// + JoinedSigInterlock VCCameraControlModeInterlock; + /// /// For the different staging bars: Active, inactive /// @@ -58,6 +65,12 @@ namespace PepperDash.Essentials.UIDrivers.VC SmartObjectDynamicList RecentCallsList; SmartObjectDynamicList DirectoryList; + + SmartObjectDPad CameraPtzPad; + + SmartObjectDynamicList CameraModeList; + + SmartObjectDynamicList CameraSelectList; BoolFeedback DirectoryBackButtonVisibleFeedback; @@ -76,6 +89,8 @@ namespace PepperDash.Essentials.UIDrivers.VC bool CodecHasFavorites; + bool ShowCameraModeControls; + CTimer BackspaceTimer; @@ -118,6 +133,9 @@ namespace PepperDash.Essentials.UIDrivers.VC LocalPrivacyIsMuted = new BoolFeedback(() => false); VCControlsInterlock = new JoinedSigInterlock(triList); + VCCameraControlModeInterlock = new JoinedSigInterlock(triList); + + if (CodecHasFavorites) VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadWithFavoritesVisible); else @@ -161,6 +179,7 @@ namespace PepperDash.Essentials.UIDrivers.VC SetupDirectoryList(); + SearchStringBackspaceVisibleFeedback = new BoolFeedback(() => SearchStringBuilder.Length > 0); SearchStringBackspaceVisibleFeedback.LinkInputSig(triList.BooleanInput[UIBoolJoin.VCDirectoryBackspaceVisible]); @@ -196,6 +215,8 @@ namespace PepperDash.Essentials.UIDrivers.VC if(HeaderDriver.HeaderButtonsAreSetUp) HeaderDriver.ComputeHeaderCallStatus(Codec); + + SetupCameraControls(); } void SetupAddresses() @@ -450,6 +471,7 @@ namespace PepperDash.Essentials.UIDrivers.VC TriList.SetSigFalseAction(UIBoolJoin.VCStagingDirectoryPress, ShowDirectory); TriList.SetSigFalseAction(UIBoolJoin.VCStagingKeypadPress, ShowKeypad); TriList.SetSigFalseAction(UIBoolJoin.VCStagingRecentsPress, ShowRecents); + TriList.SetSigFalseAction(UIBoolJoin.VCStagingCameraPress, ShowCameraControls); TriList.SetSigFalseAction(UIBoolJoin.VCStagingConnectPress, ConnectPress); TriList.SetSigFalseAction(UIBoolJoin.CallEndPress, () => { @@ -467,6 +489,365 @@ namespace PepperDash.Essentials.UIDrivers.VC }); } + void SetupCameraControls() + { + CameraPtzPad = new SmartObjectDPad(TriList.SmartObjects[UISmartObjectJoin.VCCameraDpad], true); + + // If the codec supports camera auto or off, we need to show the mode selector subpage + ShowCameraModeControls = Codec is IHasCameraAutoMode || Codec is IHasCameraOff; + + if (ShowCameraModeControls) + { + CameraModeList = new SmartObjectDynamicList(TriList.SmartObjects[UISmartObjectJoin.VCCameraMode], true, 0); + + VCControlsInterlock.StatusChanged += new EventHandler(VCControlsInterlock_StatusChanged); + + + var codecOffCameras = Codec as IHasCameraOff; + + var codecAutoCameras = Codec as IHasCameraAutoMode; + + if (codecAutoCameras != null) + { + CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn()); + TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true; + codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 1 Selected"]); + //TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 1 Pressed"].SetSigFalseAction( + //() => codecAutoCameras.CameraAutoModeOn()); + + + codecAutoCameras.CameraAutoModeIsOnFeedback.OutputChange += (o, a) => + { + if (a.BoolValue) + { + SetCameraManualModeButtonFeedback(false); + + if (VCControlsInterlock.CurrentJoin == UIBoolJoin.VCCameraModeBarVisible) + { + VCCameraControlModeInterlock.ShowInterlocked(UIBoolJoin.VCCameraAutoVisible); + } + else + { + VCCameraControlModeInterlock.SetButDontShow(UIBoolJoin.VCCameraAutoVisible); + } + } + else + { + ShowCameraManualMode(); + } + + }; + } + + // Manual button always visible + CameraModeList.SetItemButtonAction(2, (b) => ShowCameraManualMode()); + + TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 2 Visible"].BoolValue = true; + //TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 2 Pressed"].SetSigFalseAction( + // () => ShowCameraManualMode()); + + if (codecOffCameras != null) + { + TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 3 Visible"].BoolValue = true; + codecOffCameras.CameraIsOffFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 3 Selected"]); + CameraModeList.SetItemButtonAction(3, (b) => codecOffCameras.CameraOff()); + //TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 3 Pressed"].SetSigFalseAction( + // () => codecOffCameras.CameraOff()); + + codecOffCameras.CameraIsOffFeedback.OutputChange += (o, a) => + { + if (a.BoolValue) + { + SetCameraManualModeButtonFeedback(false); + + if (VCControlsInterlock.CurrentJoin == UIBoolJoin.VCCameraModeBarVisible) + { + VCCameraControlModeInterlock.ShowInterlocked(UIBoolJoin.VCCameraOffVisible); + } + else + { + VCCameraControlModeInterlock.SetButDontShow(UIBoolJoin.VCCameraOffVisible); + } + } + else + { + ShowCameraManualMode(); + } + + }; + } + } + + var camerasCodec = Codec as IHasCameras; + + if(camerasCodec != null) + { + //CameraSelectList = new SmartObjectDynamicList(TriList.SmartObjects[UISmartObjectJoin.VCCameraSelect], true, 0); + + var so = TriList.SmartObjects[UISmartObjectJoin.VCCameraSelect]; + + so.SigChange += SmartObject_SigChange; + + for (uint i = 1; i <= camerasCodec.Cameras.Count; i++) + { + var cameraKey = camerasCodec.Cameras[(int)i - 1].Key; + Debug.Console(1, "Setting up action for Camera {0} with Key: {1} for button Item {0} Pressed", i, cameraKey); + + //TODO: Fix camera selection action. For some reson this action doesn't execute when the buttons are pressed + + var sig = so.BooleanOutput[String.Format("Item {0} Pressed", i)]; + + so.BooleanOutput[string.Format("Item {0} Pressed", i)].SetSigFalseAction( + () => camerasCodec.SelectCamera(cameraKey)); + } + + so.UShortInput["Set Number of Items"].UShortValue = (ushort)camerasCodec.Cameras.Count; + //TriList.SmartObjects[UISmartObjectJoin.VCCameraSelect].UShortOutput["Item Clicked"].SetUShortSigAction( + // (u) => + // { + // var cameraKey = camerasCodec.Cameras[u - 1].Key; + // Debug.Console(1, "Selecting Camera {0} with Key: {1}", u, cameraKey); + // camerasCodec.SelectCamera(cameraKey); + // }); + + + // Set the names for the cameras + for (int i = 1; i <= camerasCodec.Cameras.Count; i++) + { + so.StringInput[string.Format("Set Item {0} Text", i)].StringValue = camerasCodec.Cameras[i - 1].Name; + } + + SetCameraSelectedFeedback(); + camerasCodec.CameraSelected += camerasCodec_CameraSelected; + MapCameraActions(); + } + + SetupPresets(); + + } + + void SmartObject_SigChange(GenericBase currentDevice, SmartObjectEventArgs args) + { + var uo = args.Sig.UserObject; + if (uo is Action) + (uo as Action)(args.Sig.BoolValue); + else if (uo is Action) + (uo as Action)(args.Sig.UShortValue); + else if (uo is Action) + (uo as Action)(args.Sig.StringValue); + } + + void VCControlsInterlock_StatusChanged(object sender, StatusChangedEventArgs e) + { + // Need to hide the camera mode interlock if the mode bar gets hidden + if (e.PreviousJoin == UIBoolJoin.VCCameraModeBarVisible) + VCCameraControlModeInterlock.Hide(); + + // These deal with hiding/showing the camera select bar if no mode controls are visible (tied to manual controls being visible) + if(!ShowCameraModeControls) + { + if(e.PreviousJoin == UIBoolJoin.VCCameraManualVisible) + TriList.SetBool(UIBoolJoin.VCCameraSelectBarWithoutModeVisible, false); + + if (e.NewJoin == UIBoolJoin.VCCameraManualVisible) + TriList.SetBool(UIBoolJoin.VCCameraSelectBarWithoutModeVisible, true); + } + + + } + + + /// + /// Shows the preset saved label for 2 seconds + /// + void ShowPresetStoreFeedback() + { + TriList.BooleanInput[UIBoolJoin.VCCameraPresetSavedLabelVisible].BoolValue = true; + + var timer = new CTimer((o) => TriList.BooleanInput[UIBoolJoin.VCCameraPresetSavedLabelVisible].BoolValue = false, 2000); + } + + void presetsCodec_CodecRoomPresetsListHasChanged(object sender, EventArgs e) + { + SetupPresets(); + } + + + void camerasCodec_CameraSelected(object sender, CameraSelectedEventArgs e) + { + MapCameraActions(); + + SetCameraSelectedFeedback(); + } + + /// + /// Set the feedback for the button of the selected camera + /// + void SetCameraSelectedFeedback() + { + var camerasCodec = Codec as IHasCameras; + + for (int i = 1; i <= camerasCodec.Cameras.Count; i++) + { + var cameraSelected = camerasCodec.SelectedCameraFeedback.StringValue; + var state = false; + if (cameraSelected == camerasCodec.Cameras[i - 1].Key) + { + state = true; + } + + TriList.SmartObjects[UISmartObjectJoin.VCCameraSelect].BooleanInput[string.Format("Item {0} Selected", i)].BoolValue = state; + } + + } + + void SetupPresets() + { + var presetsCodec = Codec as IHasCodecRoomPresets; + if (presetsCodec != null) + { + uint holdTime = 5000; + presetsCodec.CodecRoomPresetsListHasChanged += new EventHandler(presetsCodec_CodecRoomPresetsListHasChanged); + + TriList.BooleanOutput[UIBoolJoin.VCCameraPreset1].SetSigHeldAction( + holdTime, () => presetsCodec.CodecRoomPresetStore(1, presetsCodec.NearEndPresets[0].Description), ShowPresetStoreFeedback, () => presetsCodec.CodecRoomPresetSelect(1)); + TriList.BooleanOutput[UIBoolJoin.VCCameraPreset2].SetSigHeldAction( + holdTime, () => presetsCodec.CodecRoomPresetStore(2, presetsCodec.NearEndPresets[1].Description), ShowPresetStoreFeedback, () => presetsCodec.CodecRoomPresetSelect(2)); + TriList.BooleanOutput[UIBoolJoin.VCCameraPreset3].SetSigHeldAction( + holdTime, () => presetsCodec.CodecRoomPresetStore(3, presetsCodec.NearEndPresets[2].Description), ShowPresetStoreFeedback, () => presetsCodec.CodecRoomPresetSelect(3)); + + TriList.StringInput[UIStringJoin.VCCameraPresetLabel1].StringValue = presetsCodec.NearEndPresets[0].Description; + TriList.StringInput[UIStringJoin.VCCameraPresetLabel2].StringValue = presetsCodec.NearEndPresets[1].Description; + TriList.StringInput[UIStringJoin.VCCameraPresetLabel3].StringValue = presetsCodec.NearEndPresets[2].Description; + + } + } + + /// + /// Maps button actions to the selected camera + /// + void MapCameraActions() + { + // Now we setup the button actions for the manual controls + var camerasCodec = Codec as IHasCameras; + + if (camerasCodec != null && camerasCodec.SelectedCamera != null) + { + + var dpad = CameraPtzPad; + + var camera = camerasCodec.SelectedCamera as IHasCameraPtzControl; + if (camera != null) + { + if (camerasCodec.SelectedCamera.CanTilt) + { + dpad.SigUp.SetBoolSigAction((b) => + { + if (b) + camera.TiltUp(); + else + camera.TiltStop(); + }); + dpad.SigDown.SetBoolSigAction((b) => + { + if (b) + camera.TiltDown(); + else + camera.TiltStop(); + }); + } + + if (camerasCodec.SelectedCamera.CanPan) + { + dpad.SigLeft.SetBoolSigAction((b) => + { + if (b) + camera.PanLeft(); + else + camera.PanStop(); + }); + dpad.SigRight.SetBoolSigAction((b) => + { + if (b) + camera.PanRight(); + else + camera.PanStop(); + }); + } + + + //dpad.SigCenter.SetSigFalseAction(() => camera.PositionHome()); + + //var homeButton = dpad.BooleanOutput["Home"]; + //if (homeButton != null) + //{ + // homeButton.SetSigFalseAction(() => camera.PositionHome()); + //} + + if (camerasCodec.SelectedCamera.CanZoom) + { + TriList.BooleanOutput[UIBoolJoin.VCCameraZoomIn].SetBoolSigAction((b) => + { + if (b) + camera.ZoomIn(); + else + camera.ZoomStop(); + }); + TriList.BooleanOutput[UIBoolJoin.VCCameraZoomOut].SetBoolSigAction((b) => + { + if (b) + camera.ZoomOut(); + else + camera.ZoomStop(); + }); + } + + } + } + } + + // Determines if codec is in manual camera control mode and shows feedback + void ShowCameraManualMode() + { + var inManualMode = true; + + var codecOffCameras = Codec as IHasCameraOff; + + var codecAutoCameras = Codec as IHasCameraAutoMode; + + if (codecOffCameras != null && codecOffCameras.CameraIsOffFeedback.BoolValue) + { + inManualMode = false; + } + + // Clear auto mode + if (codecAutoCameras != null ) + { + if (codecAutoCameras.CameraAutoModeIsOnFeedback.BoolValue) + { + codecAutoCameras.CameraAutoModeOff(); + inManualMode = true; + } + } + + if (inManualMode) + { + VCCameraControlModeInterlock.SetButDontShow(UIBoolJoin.VCCameraManualVisible); + + if (VCControlsInterlock.CurrentJoin == UIBoolJoin.VCCameraModeBarVisible) + VCCameraControlModeInterlock.Show(); + } + + SetCameraManualModeButtonFeedback(inManualMode); + + } + + void SetCameraManualModeButtonFeedback(bool state) + { + // Set button feedback for manual mode + TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 2 Selected"].BoolValue = state; + } + /// /// /// @@ -927,7 +1308,32 @@ namespace PepperDash.Essentials.UIDrivers.VC /// void ShowCameraControls() { - VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCCameraVisible); + if (ShowCameraModeControls) + { + VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCCameraModeBarVisible); + + if (VCCameraControlModeInterlock.CurrentJoin != 0) + { + VCCameraControlModeInterlock.Show(); + } + else + { + var codecAutoCamera = Codec as IHasCameraAutoMode; + if (codecAutoCamera != null) + { + ShowCameraManualMode(); + VCCameraControlModeInterlock.Show(); + } + } + } + else + { + // Just show the manual camera control page + VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCCameraManualVisible); + } + + + StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingCameraPress); } @@ -960,7 +1366,7 @@ namespace PepperDash.Essentials.UIDrivers.VC /// void ShowSelfViewLayout() { - VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCSelfViewLayoutVisible); + VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCCameraAutoVisible); StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingSelfViewLayoutPress); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Remotes/Hrxx0WirelessRemoteController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Remotes/Hrxx0WirelessRemoteController.cs index e2dfadbc..161cba45 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Remotes/Hrxx0WirelessRemoteController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Remotes/Hrxx0WirelessRemoteController.cs @@ -18,32 +18,29 @@ using PepperDash.Essentials.Core.Bridges; namespace PepperDash.Essentials.Core { - [Description("Wrapper class for all HR-Series remotes")] - public class Hrxx0WirelessRemoteController : EssentialsBridgeableDevice, IHasFeedback + [Description("Wrapper class for all HR-Series remotes")] + public class Hrxx0WirelessRemoteController : EssentialsBridgeableDevice, IHasFeedback, IHR52Button { private CenRfgwController _gateway; private GatewayBase _gatewayBase; - - private Hr1x0WirelessRemoteBase _remote; - + private Hr1x0WirelessRemoteBase _remote; + public FeedbackCollection Feedbacks { get; set; } public CrestronCollection