using System; using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PepperDash.Core; using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials.AppServer.Messengers { /// /// Provides a messaging bridge for a VideoCodecBase device /// public class VideoCodecBaseMessenger : MessengerBase { /// /// /// public VideoCodecBase Codec { get; private set; } /// /// /// /// public VideoCodecBaseMessenger(string key, VideoCodecBase codec, string messagePath) : base(key, messagePath) { if (codec == null) throw new ArgumentNullException("codec"); Codec = codec; codec.CallStatusChange += new EventHandler(codec_CallStatusChange); codec.IsReadyChange += new EventHandler(codec_IsReadyChange); var dirCodec = codec as IHasDirectory; if (dirCodec != null) { dirCodec.DirectoryResultReturned += new EventHandler(dirCodec_DirectoryResultReturned); } var recCodec = codec as IHasCallHistory; if (recCodec != null) { recCodec.CallHistory.RecentCallsListHasChanged += new EventHandler(CallHistory_RecentCallsListHasChanged); } } /// /// /// /// /// void CallHistory_RecentCallsListHasChanged(object sender, EventArgs e) { var recents = (sender as CodecCallHistory).RecentCalls; if (recents != null) { PostStatusMessage(new { recentCalls = recents }); } } /// /// /// /// /// void dirCodec_DirectoryResultReturned(object sender, DirectoryEventArgs e) { SendDirectory((Codec as IHasDirectory).CurrentDirectoryResult, e.DirectoryIsOnRoot); } /// /// Posts the current directory /// void SendDirectory(CodecDirectory directory, bool isRoot) { var dirCodec = Codec as IHasDirectory; if (dirCodec != null) { var prefixedDirectoryResults = PrefixDirectoryFolderItems(directory); var directoryMessage = new { currentDirectory = new { directoryResults = prefixedDirectoryResults, isRootDirectory = isRoot } }; PostStatusMessage(directoryMessage); } } /// /// Iterates a directory object and prefixes any folder items with "[+] " /// /// /// List PrefixDirectoryFolderItems (CodecDirectory directory) { var tempDirectoryList = new List(); if (directory.CurrentDirectoryResults.Count > 0) { foreach (var item in directory.CurrentDirectoryResults) { if (item is DirectoryFolder) { var newFolder = new DirectoryFolder(); newFolder = (DirectoryFolder)item.Clone(); string prefixName = "[+] " + newFolder.Name; newFolder.Name = prefixName; tempDirectoryList.Add(newFolder); } else { tempDirectoryList.Add(item); } } } //else //{ // DirectoryItem noResults = new DirectoryItem() { Name = "No Results Found" }; // tempDirectoryList.Add(noResults); //} return tempDirectoryList; } /// /// /// /// /// void codec_IsReadyChange(object sender, EventArgs e) { PostStatusMessage(new { isReady = true }); } /// /// Called from base's RegisterWithAppServer method /// /// protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController) { appServerController.AddAction("/device/videoCodec/isReady", new Action(SendIsReady)); appServerController.AddAction("/device/videoCodec/fullStatus", new Action(SendVtcFullMessageObject)); appServerController.AddAction("/device/videoCodec/dial", new Action(s => Codec.Dial(s))); appServerController.AddAction("/device/videoCodec/endCallById", new Action(s => { var call = GetCallWithId(s); if (call != null) Codec.EndCall(call); })); appServerController.AddAction(MessagePath + "/endAllCalls", new Action(Codec.EndAllCalls)); appServerController.AddAction(MessagePath + "/dtmf", new Action(s => Codec.SendDtmf(s))); appServerController.AddAction(MessagePath + "/rejectById", new Action(s => { var call = GetCallWithId(s); if (call != null) Codec.RejectCall(call); })); appServerController.AddAction(MessagePath + "/acceptById", new Action(s => { var call = GetCallWithId(s); if (call != null) Codec.AcceptCall(call); })); // Directory actions var dirCodec = Codec as IHasDirectory; if (dirCodec != null) { appServerController.AddAction(MessagePath + "/getDirectory", new Action(GetDirectoryRoot)); appServerController.AddAction(MessagePath + "/directoryById", new Action(s => GetDirectory(s))); appServerController.AddAction(MessagePath + "/directorySearch", new Action(s => DirectorySearch(s))); appServerController.AddAction(MessagePath + "/directoryBack", new Action(GetPreviousDirectory)); } // History actions var recCodec = Codec as IHasCallHistory; if (recCodec != null) { appServerController.AddAction(MessagePath + "/getCallHistory", new Action(GetCallHistory)); } var cameraCodec = Codec as IHasCodecCameras; if (cameraCodec != null) { Debug.Console(2, this, "Adding IHasCodecCameras Actions"); cameraCodec.CameraSelected += new EventHandler(cameraCodec_CameraSelected); appServerController.AddAction(MessagePath + "/cameraSelect", new Action(s => cameraCodec.SelectCamera(s))); MapCameraActions(); var presetsCodec = Codec as IHasCodecRoomPresets; if (presetsCodec != null) { Debug.Console(2, this, "Adding IHasCodecRoomPresets Actions"); presetsCodec.CodecRoomPresetsListHasChanged += new EventHandler(presetsCodec_CameraPresetsListHasChanged); appServerController.AddAction(MessagePath + "/cameraPreset", new Action(u => presetsCodec.CodecRoomPresetSelect(u))); appServerController.AddAction(MessagePath + "/cameraPresetStore", new Action(p => presetsCodec.CodecRoomPresetStore(p.ID, p.Description))); } var speakerTrackCodec = Codec as IHasCameraAutoMode; if (speakerTrackCodec != null) { Debug.Console(2, this, "Adding IHasCameraAutoMode Actions"); speakerTrackCodec.CameraAutoModeIsOnFeedback.OutputChange += new EventHandler(CameraAutoModeIsOnFeedback_OutputChange); appServerController.AddAction(MessagePath + "/cameraAuto", new Action(speakerTrackCodec.CameraAutoModeOn)); appServerController.AddAction(MessagePath + "/cameraManual", new Action(speakerTrackCodec.CameraAutoModeOff)); } } var selfViewCodec = Codec as IHasCodecSelfView; if (selfViewCodec != null) { Debug.Console(2, this, "Adding IHasCodecSelfView Actions"); appServerController.AddAction(MessagePath + "/cameraSelfView", new Action(selfViewCodec.SelfViewModeToggle)); } var layoutsCodec = Codec as IHasCodecLayouts; if (layoutsCodec != null) { Debug.Console(2, this, "Adding IHasCodecLayouts Actions"); appServerController.AddAction(MessagePath + "/cameraRemoteView", new Action(layoutsCodec.LocalLayoutToggle)); } Debug.Console(2, this, "Adding Privacy & Standby Actions"); appServerController.AddAction(MessagePath + "/privacyModeOn", new Action(Codec.PrivacyModeOn)); appServerController.AddAction(MessagePath + "/privacyModeOff", new Action(Codec.PrivacyModeOff)); appServerController.AddAction(MessagePath + "/privacyModeToggle", new Action(Codec.PrivacyModeToggle)); appServerController.AddAction(MessagePath + "/sharingStart", new Action(Codec.StartSharing)); appServerController.AddAction(MessagePath + "/sharingStop", new Action(Codec.StopSharing)); appServerController.AddAction(MessagePath + "/standbyOn", new Action(Codec.StandbyActivate)); appServerController.AddAction(MessagePath + "/standbyOff", new Action(Codec.StandbyDeactivate)); } void presetsCodec_CameraPresetsListHasChanged(object sender, EventArgs e) { PostCameraPresets(); } void CameraAutoModeIsOnFeedback_OutputChange(object sender, PepperDash.Essentials.Core.FeedbackEventArgs e) { PostCameraMode(); } void cameraCodec_CameraSelected(object sender, CameraSelectedEventArgs e) { MapCameraActions(); PostSelectedCamera(); } /// /// Maps the camera control actions to the current selected camera on the codec /// void MapCameraActions() { var cameraCodec = Codec as IHasCameras; if (cameraCodec != null && cameraCodec.SelectedCamera != null) { AppServerController.RemoveAction(MessagePath + "/cameraUp"); AppServerController.RemoveAction(MessagePath + "/cameraDown"); AppServerController.RemoveAction(MessagePath + "/cameraLeft"); AppServerController.RemoveAction(MessagePath + "/cameraRight"); AppServerController.RemoveAction(MessagePath + "/cameraZoomIn"); AppServerController.RemoveAction(MessagePath + "/cameraZoomOut"); AppServerController.RemoveAction(MessagePath + "/cameraHome"); var camera = cameraCodec.SelectedCamera as IHasCameraPtzControl; if (camera != null) { AppServerController.AddAction(MessagePath + "/cameraUp", new PressAndHoldAction(new Action(b => { if (b)camera.TiltUp(); else camera.TiltStop(); }))); AppServerController.AddAction(MessagePath + "/cameraDown", new PressAndHoldAction(new Action(b => { if (b)camera.TiltDown(); else camera.TiltStop(); }))); AppServerController.AddAction(MessagePath + "/cameraLeft", new PressAndHoldAction(new Action(b => { if (b)camera.PanLeft(); else camera.PanStop(); }))); AppServerController.AddAction(MessagePath + "/cameraRight", new PressAndHoldAction(new Action(b => { if (b)camera.PanRight(); else camera.PanStop(); }))); AppServerController.AddAction(MessagePath + "/cameraZoomIn", new PressAndHoldAction(new Action(b => { if (b)camera.ZoomIn(); else camera.ZoomStop(); }))); AppServerController.AddAction(MessagePath + "/cameraZoomOut", new PressAndHoldAction(new Action(b => { if (b)camera.ZoomOut(); else camera.ZoomStop(); }))); AppServerController.AddAction(MessagePath + "/cameraHome", new Action(camera.PositionHome)); var focusCamera = cameraCodec as IHasCameraFocusControl; AppServerController.RemoveAction(MessagePath + "/cameraAutoFocus"); AppServerController.RemoveAction(MessagePath + "/cameraFocusNear"); AppServerController.RemoveAction(MessagePath + "/cameraFocusFar"); if (focusCamera != null) { AppServerController.AddAction(MessagePath + "/cameraAutoFocus", new Action(focusCamera.TriggerAutoFocus)); AppServerController.AddAction(MessagePath + "/cameraFocusNear", new PressAndHoldAction(new Action(b => { if (b)focusCamera.FocusNear(); else focusCamera.FocusStop(); }))); AppServerController.AddAction(MessagePath + "/cameraFocusFar", new PressAndHoldAction(new Action(b => { if (b)focusCamera.FocusFar(); else focusCamera.FocusStop(); }))); } } } } string GetCameraMode() { string m = ""; var speakerTrackCodec = Codec as IHasCameraAutoMode; if (speakerTrackCodec != null) { if (speakerTrackCodec.CameraAutoModeIsOnFeedback.BoolValue) m = eCameraControlMode.Auto.ToString(); else m = eCameraControlMode.Manual.ToString(); } var cameraOffCodec = Codec as IHasCameraOff; if (cameraOffCodec != null) { if (cameraOffCodec.CameraIsOffFeedback.BoolValue) m = eCameraControlMode.Off.ToString(); } return m; } void GetCallHistory() { var codec = (Codec as IHasCallHistory); if (codec != null) { var recents = codec.CallHistory.RecentCalls; if (recents != null) { PostStatusMessage(new { recentCalls = recents }); } } } public void GetFullStatusMessage() { } /// /// Helper to grab a call with string ID /// /// /// CodecActiveCallItem GetCallWithId(string id) { return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id); } /// /// /// /// void DirectorySearch(string s) { var dirCodec = Codec as IHasDirectory; if (dirCodec != null) { dirCodec.SearchDirectory(s); } } /// /// /// /// void GetDirectory(string id) { var dirCodec = Codec as IHasDirectory; if(dirCodec == null) { return; } dirCodec.GetDirectoryFolderContents(id); } /// /// /// void GetDirectoryRoot() { var dirCodec = Codec as IHasDirectory; if (dirCodec == null) { // do something else? return; } if (!dirCodec.PhonebookSyncState.InitialSyncComplete) { PostStatusMessage(new { initialSyncComplete = false }); return; } dirCodec.SetCurrentDirectoryToRoot(); //PostStatusMessage(new //{ // currentDirectory = dirCodec.DirectoryRoot //}); } /// /// Requests the parent folder contents /// void GetPreviousDirectory() { var dirCodec = Codec as IHasDirectory; if (dirCodec == null) { return; } dirCodec.GetDirectoryParentFolderContents(); } /// /// Handler for codec changes /// void codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) { SendVtcFullMessageObject(); } /// /// /// void SendIsReady() { PostStatusMessage(new { isReady = Codec.IsReady }); } /// /// Helper method to build call status for vtc /// /// void SendVtcFullMessageObject() { if (!Codec.IsReady) { return; } object cameraInfo = null; var camerasCodec = Codec as IHasCodecCameras; if (camerasCodec != null) { cameraInfo = new { cameraManualSupported = true, // For now, we assume manual mode is supported and selectively hide controls based on camera selection cameraAutoSupported = Codec is IHasCameraAutoMode, cameraOffSupported = Codec is IHasCameraOff, cameraMode = GetCameraMode(), cameraList = camerasCodec.Cameras, selectedCamera = GetSelectedCamera(camerasCodec) }; } var info = Codec.CodecInfo; PostStatusMessage(new { isInCall = Codec.IsInCall, privacyModeIsOn = Codec.PrivacyModeIsOnFeedback.BoolValue, sharingContentIsOn = Codec.SharingContentIsOnFeedback.BoolValue, sharingSource = Codec.SharingSourceFeedback.StringValue, standbyIsOn = Codec.StandbyIsOnFeedback.StringValue, calls = Codec.ActiveCalls, info = new { autoAnswerEnabled = info.AutoAnswerEnabled, e164Alias = info.E164Alias, h323Id = info.H323Id, ipAddress = info.IpAddress, sipPhoneNumber = info.SipPhoneNumber, sipURI = info.SipUri }, showSelfViewByDefault = Codec.ShowSelfViewByDefault, hasDirectory = Codec is IHasDirectory, hasDirectorySearch = true, hasRecents = Codec is IHasCallHistory, hasCameras = Codec is IHasCameras, cameras = cameraInfo, presets = GetCurrentPresets() }); } /// /// /// void PostCameraMode() { PostStatusMessage(new { cameras = new { cameraMode = GetCameraMode() } }); } void PostSelectedCamera() { var camerasCodec = Codec as IHasCodecCameras; PostStatusMessage(new { cameras = new { selectedCamera = GetSelectedCamera(camerasCodec) }, presets = GetCurrentPresets() }); } void PostCameraPresets() { PostStatusMessage(new { presets = GetCurrentPresets() }); } object GetSelectedCamera(IHasCodecCameras camerasCodec) { return new { key = camerasCodec.SelectedCameraFeedback.StringValue, isFarEnd = camerasCodec.ControllingFarEndCameraFeedback.BoolValue, capabilites = new { canPan = camerasCodec.SelectedCamera.CanPan, canTilt = camerasCodec.SelectedCamera.CanTilt, canZoom = camerasCodec.SelectedCamera.CanZoom, canFocus = camerasCodec.SelectedCamera.CanFocus } }; } List GetCurrentPresets() { var presetsCodec = Codec as IHasCodecRoomPresets; List currentPresets = null; if (presetsCodec != null && Codec is IHasFarEndCameraControl && (Codec as IHasFarEndCameraControl).ControllingFarEndCameraFeedback.BoolValue) currentPresets = presetsCodec.FarEndRoomPresets; else currentPresets = presetsCodec.NearEndPresets; return currentPresets; } } }