From 690499c86495e09eebc5455c1235c501c406346f Mon Sep 17 00:00:00 2001 From: Nick Genovese Date: Wed, 8 Nov 2023 15:10:16 -0500 Subject: [PATCH] feat: removed zoom room --- .../VideoCodec/Interfaces/IHasCodecLayouts.cs | 40 - .../IZoomWirelessShareInstructions.cs | 28 - .../VideoCodec/ZoomRoom/ResponseObjects.cs | 1822 -------- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 3943 ----------------- .../VideoCodec/ZoomRoom/ZoomRoomCamera.cs | 231 - .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 706 --- .../ZoomRoom/ZoomRoomPropertiesConfig.cs | 46 - 7 files changed, 6816 deletions(-) delete mode 100644 src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/IZoomWirelessShareInstructions.cs delete mode 100644 src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ResponseObjects.cs delete mode 100644 src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoom.cs delete mode 100644 src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs delete mode 100644 src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs delete mode 100644 src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecLayouts.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecLayouts.cs index d2393692..02280fdb 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecLayouts.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecLayouts.cs @@ -23,44 +23,4 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec void LocalLayoutToggleSingleProminent(); void MinMaxLayoutToggle(); } - - - /// - /// Defines the requirements for Zoom Room layout control - /// - public interface IHasZoomRoomLayouts : IHasCodecLayouts - { - event EventHandler LayoutInfoChanged; - - BoolFeedback LayoutViewIsOnFirstPageFeedback { get; } // TODO: #697 [*] Consider modifying to report button visibility in func - BoolFeedback LayoutViewIsOnLastPageFeedback { get; } // TODO: #697 [*] Consider modifying to report button visibility in func - BoolFeedback CanSwapContentWithThumbnailFeedback { get; } - BoolFeedback ContentSwappedWithThumbnailFeedback { get; } - - ZoomRoom.zConfiguration.eLayoutStyle LastSelectedLayout { get; } - ZoomRoom.zConfiguration.eLayoutStyle AvailableLayouts { get; } - - void GetAvailableLayouts(); // Mot sure this is necessary if we're already subscribed to zStatus Call Layout - void SetLayout(ZoomRoom.zConfiguration.eLayoutStyle layoutStyle); - void SwapContentWithThumbnail(); - - void LayoutTurnNextPage(); - void LayoutTurnPreviousPage(); - } - - public class LayoutInfoChangedEventArgs : EventArgs - { - [JsonProperty("availableLayouts", NullValueHandling = NullValueHandling.Ignore)] - public ZoomRoom.zConfiguration.eLayoutStyle AvailableLayouts { get; set; } - [JsonProperty("currentSelectedLayout", NullValueHandling = NullValueHandling.Ignore)] - public ZoomRoom.zConfiguration.eLayoutStyle CurrentSelectedLayout { get; set; } - [JsonProperty("canSwapContentWithThumbnail", NullValueHandling = NullValueHandling.Ignore)] - public bool CanSwapContentWithThumbnail { get; set; } - [JsonProperty("contentSwappedWithThumbnail", NullValueHandling = NullValueHandling.Ignore)] - public bool ContentSwappedWithThumbnail { get; set; } - [JsonProperty("layoutViewIsOnFirstPage", NullValueHandling = NullValueHandling.Ignore)] - public bool LayoutViewIsOnFirstPage { get; set; } - [JsonProperty("layoutViewIsOnLastPage", NullValueHandling = NullValueHandling.Ignore)] - public bool LayoutViewIsOnLastPage { get; set; } - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/IZoomWirelessShareInstructions.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/IZoomWirelessShareInstructions.cs deleted file mode 100644 index 465e2d2b..00000000 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/IZoomWirelessShareInstructions.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using PepperDash.Essentials.Core; - -using PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom; - -namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom -{ - public class ShareInfoEventArgs : EventArgs - { - public zStatus.Sharing SharingStatus { get; private set; } - - public ShareInfoEventArgs(zStatus.Sharing status) - { - SharingStatus = status; - } - } - - public interface IZoomWirelessShareInstructions - { - event EventHandler ShareInfoChanged; - - zStatus.Sharing SharingState { get; } - } -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ResponseObjects.cs deleted file mode 100644 index 0ba684a8..00000000 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ /dev/null @@ -1,1822 +0,0 @@ -extern alias Full; - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.ComponentModel; -using System.Runtime.CompilerServices; -using Crestron.SimplSharp; - -using PepperDash.Core; -using PepperDash.Essentials.Devices.Common.Codec; - -using Full.Newtonsoft.Json; -using Full.Newtonsoft.Json.Linq; -using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; - -namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom -{ - public enum eZoomRoomResponseType - { - zEvent, - zStatus, - zConfiguration, - zCommand - } - - public abstract class NotifiableObject : INotifyPropertyChanged - { - #region INotifyPropertyChanged Members - - public event PropertyChangedEventHandler PropertyChanged; - - protected void NotifyPropertyChanged(string propertyName) - { - var handler = PropertyChanged; - if (handler != null) - { - handler(this, new PropertyChangedEventArgs(propertyName)); - } - else - { - Debug.Console(2, "PropertyChanged event is NULL"); - } - } - - #endregion - } - - /// - /// Used to track the current status of a ZoomRoom - /// - public class ZoomRoomStatus - { - public zStatus.Login Login { get; set; } - public zStatus.SystemUnit SystemUnit { get; set; } - public zStatus.Phonebook Phonebook { get; set; } - public zStatus.Call Call { get; set; } - public zStatus.Capabilities Capabilities { get; set; } - public zStatus.Sharing Sharing { get; set; } - public zStatus.NumberOfScreens NumberOfScreens { get; set; } - public zStatus.Layout Layout { get; set; } - public zStatus.Video Video { get; set; } - public zStatus.CameraShare CameraShare { get; set; } - public List AudioInputs { get; set; } - public List AudioOuputs { get; set; } - public List Cameras { get; set; } - public zEvent.PhoneCallStatus PhoneCall { get; set; } - public zEvent.NeedWaitForHost NeedWaitForHost { get; set; } - - public ZoomRoomStatus() - { - Login = new zStatus.Login(); - SystemUnit = new zStatus.SystemUnit(); - Phonebook = new zStatus.Phonebook(); - Call = new zStatus.Call(); - Capabilities = new zStatus.Capabilities(); - Sharing = new zStatus.Sharing(); - NumberOfScreens = new zStatus.NumberOfScreens(); - Layout = new zStatus.Layout(); - Video = new zStatus.Video(); - CameraShare = new zStatus.CameraShare(); - AudioInputs = new List(); - AudioOuputs = new List(); - Cameras = new List(); - PhoneCall = new zEvent.PhoneCallStatus(); - NeedWaitForHost = new zEvent.NeedWaitForHost(); - } - } - - /// - /// Used to track the current configuration of a ZoomRoom - /// - public class ZoomRoomConfiguration - { - public zConfiguration.Call Call { get; set; } - public zConfiguration.Audio Audio { get; set; } - public zConfiguration.Video Video { get; set; } - public zConfiguration.Client Client { get; set; } - public zConfiguration.Camera Camera { get; set; } - - public ZoomRoomConfiguration() - { - Call = new zConfiguration.Call(); - Audio = new zConfiguration.Audio(); - Video = new zConfiguration.Video(); - Client = new zConfiguration.Client(); - Camera = new zConfiguration.Camera(); - } - } - - /// - /// Represents a response from a ZoomRoom system - /// - public class Response - { - public Status Status { get; set; } - public bool Sync { get; set; } - [JsonProperty("topKey")] - public string TopKey { get; set; } - [JsonProperty("type")] - public string Type { get; set; } - - public Response() - { - Status = new Status(); - } - } - - public class Status - { - [JsonProperty("message")] - public string Message { get; set; } - [JsonProperty("state")] - public string State { get; set; } - } - - - /// - /// zStatus class stucture - /// - public class zStatus - { - public class Login - { - [JsonProperty("ZAAPI Release")] - public string ZAAPIRelease { get; set; } - [JsonProperty("Zoom Room Release")] - public string ZoomRoomRelease { get; set; } - } - - public class SystemUnit - { - [JsonProperty("email")] - public string Email { get; set; } - [JsonProperty("login_type")] - public string LoginType { get; set; } - [JsonProperty("meeting_number")] - public string MeetingNumber { get; set; } - [JsonProperty("platform")] - public string Platform { get; set; } - [JsonProperty("room_info")] - public RoomInfo RoomInfo { get; set; } - [JsonProperty("room_version")] - public string RoomVersion { get; set; } - - public SystemUnit() - { - RoomInfo = new RoomInfo(); - } - } - - public class RoomInfo - { - [JsonProperty("account_email")] - public string AccountEmail { get; set; } - [JsonProperty("display_version")] - public string DisplayVersion { get; set; } - [JsonProperty("is_auto_answer_enabled")] - public bool AutoAnswerIsEnabled { get; set; } - [JsonProperty("is_auto_answer_selected")] - public bool AutoAnswerIsSelected { get; set; } - [JsonProperty("room_name")] - public string RoomName { get; set; } - } - - public class CloudPbxInfo - { - [JsonProperty("company_number")] - public string CompanyNumber { get; set; } - [JsonProperty("extension")] - public string Extension { get; set; } - [JsonProperty("isValid")] - public bool IsValid { get; set; } - } - - public enum ePresence - { - PRESENCE_OFFLINE, - PRESENCE_ONLINE, - PRESENCE_AWAY, - PRESENCE_BUSY, - PRESENCE_DND - } - - public class Contact - { - [JsonProperty("avatarURL")] - public string AvatarURL { get; set; } - [JsonProperty("cloud_pbx_info")] - public CloudPbxInfo CloudPbxInfo { get; set; } - [JsonProperty("email")] - public string Email { get; set; } - [JsonProperty("firstName")] - public string FirstName { get; set; } - [JsonProperty("index")] - public int Index { get; set; } - [JsonProperty("isLegacy")] - public bool IsLegacy { get; set; } - [JsonProperty("isZoomRoom")] - public bool IsZoomRoom { get; set; } - [JsonProperty("jid")] - public string Jid { get; set; } - [JsonProperty("lastName")] - public string LastName { get; set; } - [JsonProperty("onDesktop")] - public bool OnDesktop { get; set; } - [JsonProperty("onMobile")] - public bool OnMobile { get; set; } - [JsonProperty("phoneNumber")] - public string PhoneNumber { get; set; } - [JsonProperty("presence")] - public ePresence Presence { get; set; } - [JsonProperty("presence_status")] - public int PresenceStatus { get; set; } - [JsonProperty("screenName")] - public string ScreenName { get; set; } - [JsonProperty("sip_phone_number")] - public string SipPhoneNumber { get; set; } - - - public Contact() - { - CloudPbxInfo = new CloudPbxInfo(); - } - } - - public class Phonebook - { - [JsonProperty("Contacts")] - public List Contacts { get; set; } - - public Phonebook() - { - Contacts = new List(); - } - - /// - /// Converts from zStatus.Contact types to generic directory items - /// - /// - public static CodecDirectory ConvertZoomContactsToGeneric(List zoomContacts) - { - var directory = new CodecDirectory(); - - var folders = new List(); - - var roomFolder = new DirectoryFolder(); - - var contactFolder = new DirectoryFolder(); - - var contacts = new List(); - - // Check if there are any zoom rooms - var zoomRooms = zoomContacts.FindAll(c => c.IsZoomRoom); - - if (zoomRooms.Count > 0) - { - // If so, setup a rooms and contacts folder and add them. - - directory.ResultsFolderId = "root"; - - roomFolder.Name = "Rooms"; - roomFolder.ParentFolderId = "root"; - roomFolder.FolderId = "rooms"; - - contactFolder.Name = "Contacts"; - contactFolder.ParentFolderId = "root"; - contactFolder.FolderId = "contacts"; - - folders.Add(roomFolder); - folders.Add(contactFolder); - - directory.AddFoldersToDirectory(folders); - } - - try - { - if (zoomContacts.Count == 0) - { - return directory; - } - - foreach (Contact c in zoomContacts) - { - var contact = new InvitableDirectoryContact { Name = c.ScreenName, ContactId = c.Jid }; - - contact.ContactMethods.Add(new ContactMethod() - { - Number = c.Jid, - Device = eContactMethodDevice.Video, - CallType = eContactMethodCallType.Video, - ContactMethodId = c.Jid - }); - - if (folders.Count > 0) - { - contact.ParentFolderId = c.IsZoomRoom - ? roomFolder.FolderId // "rooms" - : contactFolder.FolderId; // "contacts" - } - - contacts.Add(contact); - } - - directory.AddContactsToDirectory(contacts); - } - catch (Exception e) - { - Debug.Console(1, "Error converting Zoom Phonebook results to generic: {0}", e); - } - - return directory; - } - } - - public enum eCallStatus - { - UNKNOWN, - NOT_IN_MEETING, - CONNECTING_MEETING, - IN_MEETING, - LOGGED_OUT - } - - public class ClosedCaption - { - public bool Available { get; set; } - } - - public class Call : NotifiableObject - { - private eCallStatus _status; - private List _participants; - - public bool IsInCall; - - public eCallStatus Status - { - get - { - return _status; - } - set - { - if (value != _status) - { - _status = value; - IsInCall = _status == eCallStatus.IN_MEETING || _status == eCallStatus.CONNECTING_MEETING; - NotifyPropertyChanged("Status"); - } - } - } - public ClosedCaption ClosedCaption { get; set; } - public List Participants - { - get - { - return _participants; - } - set - { - _participants = value; - NotifyPropertyChanged("Participants"); - } - } - public zEvent.SharingState Sharing { get; set; } - - public CallRecordInfo CallRecordInfo { get; set; } - - private zCommand.InfoResult _info; - - public zCommand.InfoResult Info - { - get - { - return _info; - } - set - { - _info = value; - NotifyPropertyChanged("Info"); - } - } - - public Call() - { - ClosedCaption = new ClosedCaption(); - Participants = new List(); - Sharing = new zEvent.SharingState(); - CallRecordInfo = new CallRecordInfo(); - Info = new zCommand.InfoResult(); - } - } - - public class Capabilities - { - public bool aec_Setting_Stored_In_ZR { get; set; } - public bool can_Dtmf_For_Invite_By_Phone { get; set; } - public bool can_Mute_On_Entry { get; set; } - public bool can_Ringing_In_Pstn_Call { get; set; } - public bool can_Switch_To_Specific_Camera { get; set; } - public bool is_Airhost_Disabled { get; set; } - public bool pstn_Call_In_Local_resentation { get; set; } - public bool support_Claim_Host { get; set; } - public bool support_Out_Room_Display { get; set; } - public bool support_Pin_And_Spotlight { get; set; } - public bool supports_Audio_Checkup { get; set; } - public bool supports_CheckIn { get; set; } - public bool supports_Cloud_PBX { get; set; } - public bool supports_Encrypted_Connection { get; set; } - public bool supports_Expel_User_Permanently { get; set; } - public bool supports_H323_DTMF { get; set; } - public bool supports_Hdmi_Cec_Control { get; set; } - public bool supports_Highly_Reverberant_Room { get; set; } - public bool supports_Loading_Contacts_Dynamically { get; set; } - public bool supports_Loading_Participants_Dynamically { get; set; } - public bool supports_Mic_Record_Test { get; set; } - public bool supports_Multi_Share { get; set; } - public bool supports_ShareCamera { get; set; } - public bool supports_Share_For_Floating_And_Content_Only { get; set; } - public bool supports_Sip_Call_out { get; set; } - public bool supports_Software_Audio_Processing { get; set; } - public bool supports_Web_Settings_Push { get; set; } - } - - public enum eDisplayState - { - None, - Laptop, - IOS, - } - - public class Sharing : NotifiableObject - { - private eDisplayState _dispState; - private string _password; - private bool _isAirHostClientConnected; - private bool _isSharingBlackMagic; - private bool _isDirectPresentationConnected; - private bool _isBlackMagicConnected; - - - public string directPresentationPairingCode { get; set; } - /// - /// Laptop client sharing key - /// - public string directPresentationSharingKey { get; set; } - public eDisplayState dispState - { - get - { - return _dispState; - } - set - { - if (value != _dispState) - { - _dispState = value; - NotifyPropertyChanged("dispState"); - } - } - } - - public bool isAirHostClientConnected - { - get { return _isAirHostClientConnected; } - set - { - if (value != _isAirHostClientConnected) - { - _isAirHostClientConnected = value; - NotifyPropertyChanged("isAirHostClientConnected"); - } - } - } - - public bool isBlackMagicConnected - { - get { return _isBlackMagicConnected; } - set - { - if (value != _isBlackMagicConnected) - { - _isBlackMagicConnected = value; - NotifyPropertyChanged("isBlackMagicConnected"); - } - } - } - public bool isBlackMagicDataAvailable { get; set; } - - public bool isDirectPresentationConnected - { - get { return _isDirectPresentationConnected; } - set - { - if (value != _isDirectPresentationConnected) - { - _isDirectPresentationConnected = value; - NotifyPropertyChanged("isDirectPresentationConnected"); - } - } - } - - public bool isSharingBlackMagic - { - get { return _isSharingBlackMagic; } - set - { - if (value != _isSharingBlackMagic) - { - _isSharingBlackMagic = value; - NotifyPropertyChanged("isSharingBlackMagic"); - } - } - } - - /// - /// IOS Airplay code - /// - public string password - { - get - { - return _password; - } - set - { - if (value != _password) - { - _password = value; - NotifyPropertyChanged("password"); - } - } - } - public string serverName { get; set; } - public string wifiName { get; set; } - } - - public class NumberOfScreens : NotifiableObject - { - private int _numOfScreens; - - [JsonProperty("NumberOfCECScreens")] - public int NumOfCECScreens { get; set; } - [JsonProperty("NumberOfScreens")] - public int NumOfScreens - { - get - { - return _numOfScreens; - } - set - { - if (value != _numOfScreens) - { - _numOfScreens = value; - NotifyPropertyChanged("NumberOfScreens"); - } - } - } - } - - /// - /// AudioInputLine/AudioOutputLine/VideoCameraLine list item - /// - public class AudioVideoInputOutputLineItem - { - public string Alias { get; set; } - public string Name { get; set; } - public bool Selected { get; set; } - public bool combinedDevice { get; set; } - public string id { get; set; } - public bool manuallySelected { get; set; } - public int numberOfCombinedDevices { get; set; } - public int ptzComId { get; set; } - } - - public class Video - { - public bool Optimizable { get; set; } - } - - public class CameraShare : NotifiableObject - { - private bool _canControlCamera; - private bool _isSharing; - - [JsonProperty("can_Control_Camera")] - public bool CanControlCamera - { - get - { - return _canControlCamera; - } - set - { - if (value != _canControlCamera) - { - _canControlCamera = value; - NotifyPropertyChanged("CanControlCamera"); - } - } - } - public string id { get; set; } - public bool is_Mirrored { get; set; } - [JsonProperty("is_Sharing")] - public bool IsSharing - { - get - { - return _isSharing; - } - set - { - if (value != _isSharing) - { - _isSharing = value; - NotifyPropertyChanged("IsSharing"); - } - } - } - public int pan_Tilt_Speed { get; set; } - - } - - public class Layout : NotifiableObject - { - // backer variables - private bool _can_Switch_Speaker_View; - private bool _can_Switch_Wall_View; - private bool _can_Switch_Strip_View; - private bool _can_Switch_Share_On_All_Screens; - private bool _can_Switch_Floating_Share_Content; - private bool _is_In_First_Page; - private bool _is_In_Last_Page; - private string _video_type; - - - public bool can_Adjust_Floating_Video { get; set; } - - - public bool can_Switch_Floating_Share_Content - { - get - { - return _can_Switch_Floating_Share_Content; - } - set - { - if (value != _can_Switch_Floating_Share_Content) - { - _can_Switch_Floating_Share_Content = value; - NotifyPropertyChanged("can_Switch_Floating_Share_Content"); - } - } - } - - - /// - /// [on/off] // Set to On if it is possible to invoke zConfiguration Call Layout Style: ShareAll, to switch to the ShareAll mode, where the content sharing is shown full screen on all monitors. - /// - [JsonProperty("can_Switch_Share_On_All_Screens")] - public bool can_Switch_Share_On_All_Screens - { - get - { - return _can_Switch_Share_On_All_Screens; - } - set - { - if (value != _can_Switch_Share_On_All_Screens) - { - _can_Switch_Share_On_All_Screens = value; - NotifyPropertyChanged("can_Switch_Share_On_All_Screens"); - } - } - } - - /// - /// [on/off] // Set to On if it is possible to switch to Speaker view by invoking zConfiguration Call Layout Style: Speaker. The active speaker is shown full screen, and other video streams, like self-view, are shown in thumbnails. - /// - [JsonProperty("can_Switch_Speaker_View")] - public bool can_Switch_Speaker_View - { - get - { - return _can_Switch_Speaker_View; - } - set - { - if (value != _can_Switch_Speaker_View) - { - _can_Switch_Speaker_View = value; - NotifyPropertyChanged("can_Switch_Speaker_View"); - } - } - } - - /// - /// [on/off] On if it is possible to invoke zConfiguration Call Layout Style: Gallery, to switch to the Gallery mode, showing video participants in tiled windows: The Zoom Room shows up to a 5x5 array of tiled windows per page. - /// - [JsonProperty("can_Switch_Wall_View")] - public bool can_Switch_Wall_View - { - get - { - return _can_Switch_Wall_View; - } - set - { - if (value != _can_Switch_Wall_View) - { - _can_Switch_Wall_View = value; - NotifyPropertyChanged("can_Switch_Wall_View"); - } - } - } - - [JsonProperty("can_Switch_Strip_View")] - public bool can_Switch_Strip_View - { - get - { - return _can_Switch_Strip_View; - } - set - { - if (value != _can_Switch_Strip_View) - { - _can_Switch_Strip_View = value; - NotifyPropertyChanged("can_Switch_Strip_View"); - } - } - } - - [JsonProperty("is_In_First_Page")] - public bool is_In_First_Page - { - get - { - return _is_In_First_Page; - } - set - { - if (value != _is_In_First_Page) - { - _is_In_First_Page = value; - NotifyPropertyChanged("is_In_First_Page"); - } - } - } - - [JsonProperty("is_In_Last_Page")] - public bool is_In_Last_Page - { - get - { - return _is_In_Last_Page; - } - set - { - if (value != _is_In_Last_Page) - { - _is_In_Last_Page = value; - NotifyPropertyChanged("is_In_Last_Page"); - } - } - } - - public bool is_supported { get; set; } - public int video_Count_In_Current_Page { get; set; } - - /// - /// [Gallery | Strip] Indicates which mode applies: Strip or Gallery. - /// - [JsonProperty("video_type")] - public string video_type - { - get - { - return _video_type; - } - set - { - if (value != _video_type) - { - _video_type = value; - NotifyPropertyChanged("video_type"); - } - } - } - } - - public class CallRecordInfo : NotifiableObject - { - private bool _meetingIsBeingRecorded; - private bool _canRecord; - private bool _emailRequired; - - public bool amIRecording { get; set; } - - public bool canRecord - { - get - { - return _canRecord; - } - set - { - if (value != _canRecord) - { - _canRecord = value; - NotifyPropertyChanged("canRecord"); - } - } - } - - public bool emailRequired - { - get - { - return _emailRequired; - } - set - { - if (value != _emailRequired) - { - _emailRequired = value; - NotifyPropertyChanged("emailRequired"); - } - } - } - - public bool meetingIsBeingRecorded - { - get - { - return _meetingIsBeingRecorded; - } - set - { - //Debug.Console(2, "************************************setting value of meetingIsBeingRecorded to: {0}", value); - if (value != _meetingIsBeingRecorded) - { - _meetingIsBeingRecorded = value; - //Debug.Console(2, "********************************set value of meetingIsBeingRecorded to: {0}", _meetingIsBeingRecorded); - NotifyPropertyChanged("meetingIsBeingRecorded"); - } - } - } - - /// - /// Indicates if recording is allowed (when meeting capable and and email is not required to be entered by the user) - /// - public bool AllowRecord - { - get - { - return canRecord && !emailRequired; - } - } - - public CallRecordInfo() - { - Debug.Console(2, Debug.ErrorLogLevel.Notice, "********************************************* CallRecordInfo() ******************************************"); - } - } - } - - /// - /// zEvent Class Structure - /// - public class zEvent - { - public class StartLocalPresentMeeting - { - public bool Success { get; set; } - } - public class NeedWaitForHost - { - public bool Wait { get; set; } - } - - public class IncomingCallIndication - { - public string callerJID { get; set; } - public string calleeJID { get; set; } - public string meetingID { get; set; } - public string password { get; set; } - public string meetingOption { get; set; } - public long MeetingNumber { get; set; } - public string callerName { get; set; } - public string avatarURL { get; set; } - public int lifeTime { get; set; } - public bool accepted { get; set; } - } - - public class CallConnectError - { - public int error_code { get; set; } - public string error_message { get; set; } - } - - public class CallDisconnect - { - public bool Successful - { - get - { - return success == "on"; - } - } - - public string success { get; set; } - } - - public class Layout - { - public bool Sharethumb { get; set; } - } - - public class Call - { - public Layout Layout { get; set; } - } - - public class Client - { - public Call Call { get; set; } - } - - public enum eSharingState - { - None, - Connecting, - Sending, - Receiving, - Send_Receiving - } - - public class SharingState : NotifiableObject - { - private bool _paused; - private eSharingState _state; - - public bool IsSharing { get; private set; } - - [JsonProperty("paused")] - public bool Paused - { - get - { - return _paused; - } - set - { - if (value != _paused) - { - _paused = value; - NotifyPropertyChanged("Paused"); - } - } - } - [JsonProperty("state")] - public eSharingState State - { - get - { - return _state; - } - set - { - if (value != _state) - { - _state = value; - IsSharing = _state == eSharingState.Sending; - NotifyPropertyChanged("State"); - } - } - } - } - - public class PinStatusOfScreenNotification - { - - - [JsonProperty("can_be_pinned")] - public bool CanBePinned { get; set; } - [JsonProperty("can_pin_share")] - public bool CanPinShare { get; set; } - [JsonProperty("pinned_share_source_id")] - public int PinnedShareSourceId { get; set; } - [JsonProperty("pinned_user_id")] - public int PinnedUserId { get; set; } - [JsonProperty("screen_index")] - public int ScreenIndex { get; set; } - [JsonProperty("screen_layout")] - public int ScreenLayout { get; set; } - [JsonProperty("share_source_type")] - public int ShareSourceType { get; set; } - [JsonProperty("why_cannot_pin_share")] - public string WhyCannotPinShare { get; set; } - } - - public class PhoneCallStatus : NotifiableObject - { - private bool _isIncomingCall; - private string _peerDisplayName; - private string _peerNumber; - - private bool _offHook; - - public string CallId { get; set; } - public bool IsIncomingCall - { - get { return _isIncomingCall; } - set - { - if (value == _isIncomingCall) return; - - _isIncomingCall = value; - NotifyPropertyChanged("IsIncomingCall"); - } - } - - public string PeerDisplayName - { - get { return _peerDisplayName; } - set - { - if (value == _peerDisplayName) return; - _peerDisplayName = value; - NotifyPropertyChanged("PeerDisplayName"); - } - } - - public string PeerNumber - { - get { return _peerNumber; } - set - { - if (value == _peerNumber) return; - - _peerNumber = value; - NotifyPropertyChanged("PeerNumber"); - } - } - - public string PeerUri { get; set; } - - private ePhoneCallStatus _status; - public ePhoneCallStatus Status - { - get { return _status; } - set - { - _status = value; - OffHook = _status == ePhoneCallStatus.PhoneCallStatus_Accepted || - _status == ePhoneCallStatus.PhoneCallStatus_InCall || - _status == ePhoneCallStatus.PhoneCallStatus_Init || - _status == ePhoneCallStatus.PhoneCallStatus_Ringing; - } - } - - public bool OffHook - { - get { return _offHook; } - set - { - if (value == _offHook) return; - - _offHook = value; - NotifyPropertyChanged("OffHook"); - } - } - } - - public enum ePhoneCallStatus - { - PhoneCallStatus_Ringing, - PhoneCallStatus_Terminated, - PhoneCallStatus_Accepted, - PhoneCallStatus_InCall, - PhoneCallStatus_Init, - } - - public class MeetingNeedsPassword - { - [JsonProperty("needsPassword")] - public bool NeedsPassword { get; set; } - - [JsonProperty("wrongAndRetry")] - public bool WrongAndRetry { get; set; } - } - } - - /// - /// zConfiguration class structure - /// - public class zConfiguration - { - public class Sharing - { - [JsonProperty("optimize_video_sharing")] - public bool OptimizeVideoSharing { get; set; } - } - - public class Camera : NotifiableObject - { - private bool _mute; - - public bool Mute - { - get { return _mute; } - set - { - Debug.Console(1, "Camera Mute response received: {0}", value); - - if (value == _mute) return; - - _mute = value; - NotifyPropertyChanged("Mute"); - } - } - } - - public class Microphone : NotifiableObject - { - private bool _mute; - - public bool Mute - { - get - { - return _mute; - } - set - { - if (value != _mute) - { - _mute = value; - NotifyPropertyChanged("Mute"); - } - } - } - } - - [Flags] - public enum eLayoutStyle - { - None = 0, - Gallery = 1, - Speaker = 2, - Strip = 4, - ShareAll = 8, - } - - public enum eLayoutSize - { - Off, - Size1, - Size2, - Size3, - Strip - } - - public enum eLayoutPosition - { - Center, - Up, - Right, - UpRight, - Down, - DownRight, - Left, - UpLeft, - DownLeft - } - - public class Layout : NotifiableObject - { - private bool _shareThumb; - private eLayoutStyle _style; - private eLayoutSize _size; - private eLayoutPosition _position; - - public bool ShareThumb - { - get { return _shareThumb; } - set - { - if (value != _shareThumb) - { - _shareThumb = value; - NotifyPropertyChanged("ShareThumb"); - } - } - } - - public eLayoutStyle Style - { - get { return _style; } - set - { - if (value != _style) - { - _style = value; - NotifyPropertyChanged("Style"); - } - } - } - - public eLayoutSize Size - { - get { return _size; } - set - { - if (value != _size) - { - _size = value; - NotifyPropertyChanged("Size"); - } - } - } - - public eLayoutPosition Position - { - get { return _position; } - set - { - if (value != _position) - { - _position = value; - NotifyPropertyChanged("Position"); - } - } - } - } - - public class Lock : NotifiableObject - { - private bool _enable; - - public bool Enable - { - get - { - return _enable; - } - set - { - if (value != _enable) - { - _enable = value; - NotifyPropertyChanged("Enable"); - } - } - } - } - - public class ClosedCaption - { - public bool Visible { get; set; } - public int FontSize { get; set; } - } - - public class MuteUserOnEntry - { - public bool Enable { get; set; } - } - - public class Call - { - public Sharing Sharing { get; set; } - public Camera Camera { get; set; } - public Microphone Microphone { get; set; } - public Layout Layout { get; set; } - public Lock Lock { get; set; } - public MuteUserOnEntry MuteUserOnEntry { get; set; } - public ClosedCaption ClosedCaption { get; set; } - - - public Call() - { - Sharing = new Sharing(); - Camera = new Camera(); - Microphone = new Microphone(); - Layout = new Layout(); - Lock = new Lock(); - MuteUserOnEntry = new MuteUserOnEntry(); - ClosedCaption = new ClosedCaption(); - } - } - - public class Audio - { - public Input Input { get; set; } - public Output Output { get; set; } - - public Audio() - { - Input = new Input(); - Output = new Output(); - } - } - - public class Input : Output - { - [JsonProperty("reduce_reverb")] - public bool ReduceReverb { get; set; } - } - - public class Output : NotifiableObject - { - private int _volume; - - [JsonProperty("volume")] - public int Volume - { - get - { - return _volume; - } - set - { - if (value != _volume) - { - _volume = value; - NotifyPropertyChanged("Volume"); - } - } - } - [JsonProperty("selectedId")] - public string SelectedId { get; set; } - [JsonProperty("is_sap_disabled")] - public bool IsSapDisabled { get; set; } - } - - public class Video : NotifiableObject - { - private bool _hideConfSelfVideo; - - [JsonProperty("hide_conf_self_video")] - public bool HideConfSelfVideo - { - get - { - return _hideConfSelfVideo; - } - set - { - //if (value != _hideConfSelfVideo) - //{ - _hideConfSelfVideo = value; - NotifyPropertyChanged("HideConfSelfVideo"); - //} - } - } - - public VideoCamera Camera { get; set; } - - public Video() - { - Camera = new VideoCamera(); - } - } - - public class VideoCamera : NotifiableObject - { - private string _selectedId; - - [JsonProperty("selectedId")] - public string SelectedId - { - get - { - return _selectedId; - } - set - { - if (value != _selectedId) - { - _selectedId = value; - NotifyPropertyChanged("SelectedId"); - } - } - - } - public bool Mirror { get; set; } - } - - public class Client - { - public string appVersion { get; set; } - public string deviceSystem { get; set; } - - // This doesn't belong here, but there's a bug in the object structure of Zoom Room 5.6.3 that puts it here - public zConfiguration.Call Call { get; set; } - - public Client() - { - Call = new zConfiguration.Call(); - } - } - - } - - /// - /// zCommand class structure - /// - public class zCommand - { - public class BookingsListResult - { - [JsonProperty("accessRole")] - public string AccessRole { get; set; } - [JsonProperty("calendarChangeKey")] - public string CalendarChangeKey { get; set; } - [JsonProperty("calendarID")] - public string CalendarId { get; set; } - [JsonProperty("checkIn")] - public bool CheckIn { get; set; } - [JsonProperty("creatorEmail")] - public string CreatorEmail { get; set; } - [JsonProperty("creatorName")] - public string CreatorName { get; set; } - [JsonProperty("endTime")] - public DateTime EndTime { get; set; } - [JsonProperty("hostName")] - public string HostName { get; set; } - [JsonProperty("isInstantMeeting")] - public bool IsInstantMeeting { get; set; } - [JsonProperty("isPrivate")] - public bool IsPrivate { get; set; } - [JsonProperty("location")] - public string Location { get; set; } - [JsonProperty("meetingName")] - public string MeetingName { get; set; } - [JsonProperty("meetingNumber")] - public string MeetingNumber { get; set; } - [JsonProperty("scheduledFrom")] - public string ScheduledFrom { get; set; } - [JsonProperty("startTime")] - public DateTime StartTime { get; set; } - [JsonProperty("third_party")] - public ThirdParty ThirdParty { get; set; } - } - - public static List GetGenericMeetingsFromBookingResult(List bookings, - int minutesBeforeMeetingStart) - { - var rv = GetGenericMeetingsFromBookingResult(bookings); - - foreach (var meeting in rv) - { - meeting.MinutesBeforeMeeting = minutesBeforeMeetingStart; - } - - return rv; - } - /// - /// Extracts the necessary meeting values from the Zoom bookings response and converts them to the generic class - /// - /// - /// - public static List GetGenericMeetingsFromBookingResult(List bookings) - { - var meetings = new List(); - - if (Debug.Level > 0) - { - Debug.Console(1, "Meetings List:\n"); - } - - foreach (var b in bookings) - { - var meeting = new Meeting(); - - if (b.MeetingNumber != null) - meeting.Id = b.MeetingNumber; - if (b.CreatorName != null) - meeting.Organizer = b.CreatorName; - if (b.MeetingName != null) - meeting.Title = b.MeetingName; - //if (b.Agenda != null) - // meeting.Agenda = b.Agenda.Value; - if (b.StartTime != null) - meeting.StartTime = b.StartTime; - if (b.EndTime != null) - meeting.EndTime = b.EndTime; - - meeting.Privacy = b.IsPrivate ? eMeetingPrivacy.Private : eMeetingPrivacy.Public; - - meeting.Dialable = meeting.Id != "0"; - - // No meeting.Calls data exists for Zoom Rooms. Leaving out for now. - var now = DateTime.Now; - if (meeting.StartTime < now && meeting.EndTime < now) - { - Debug.Console(1, "Skipping meeting {0}. Meeting is in the past.", meeting.Title); - continue; - } - - meetings.Add(meeting); - - if (Debug.Level > 0) - { - Debug.Console(1, "Title: {0}, ID: {1}, Organizer: {2}", meeting.Title, meeting.Id, meeting.Organizer); - Debug.Console(1, " Start Time: {0}, End Time: {1}, Duration: {2}", meeting.StartTime, meeting.EndTime, meeting.Duration); - Debug.Console(1, " Joinable: {0}\n", meeting.Joinable); - } - } - - meetings.OrderBy(m => m.StartTime); - - return meetings; - } - - public class HandStatus - { - // example return of the "hand_status" object - // !!!! Note the properties contain ': ' within the property name !!! - //"hand_status": { - // "is_raise_hand: ": false, - // "is_valid: ": "on", - // "time_stamp: ": "11825083" - //}, - [JsonProperty("is_raise_hand: ")] - public bool IsRaiseHand { get; set; } - [JsonProperty("is_valid: ")] - public string IsValid { get; set; } - [JsonProperty("time_stamp: ")] - public string TimeStamp { get; set; } - /// - /// Retuns a boolean value if the participant hand state is raised and is valid (both need to be true) - /// - public bool HandIsRaisedAndValid - { - get { return IsValid != null && IsValid == "on" && IsRaiseHand; } - } - } - public class ListParticipant - { - [JsonProperty("audio_status state")] - public string AudioStatusState { get; set; } - [JsonProperty("audio_status type")] - public string AudioStatusType { get; set; } - [JsonProperty("avatar_url")] - public string AvatarUrl { get; set; } - [JsonProperty("camera_status am_i_controlling")] - public bool CameraStatusAmIControlling { get; set; } - [JsonProperty("camera_status can_i_request_control")] - public bool CameraStatusCanIRequestConrol { get; set; } - [JsonProperty("camera_status can_move_camera")] - public bool CameraStatusCanMoveCamera { get; set; } - [JsonProperty("camera_status can_switch_camera")] - public bool CameraStatusCanSwitchCamera { get; set; } - [JsonProperty("camera_status can_zoom_camera")] - public bool CameraStatusCanZoomCamera { get; set; } - [JsonProperty("can_edit_closed_caption")] - public bool CanEditClosedCaption { get; set; } - [JsonProperty("can_record")] - public bool CanRecord { get; set; } - [JsonProperty("event")] - public string Event { get; set; } - [JsonProperty("hand_status")] - public HandStatus HandStatus { get; set; } - [JsonProperty("isCohost")] - public bool IsCohost { get; set; } - [JsonProperty("is_client_support_closed_caption")] - public bool IsClientSupportClosedCaption { get; set; } - [JsonProperty("is_client_support_coHost")] - public bool IsClientSupportCoHost { get; set; } - [JsonProperty("is_host")] - public bool IsHost { get; set; } - [JsonProperty("is_myself")] - public bool IsMyself { get; set; } - [JsonProperty("is_recording")] - public bool IsRecording { get; set; } - [JsonProperty("is_video_can_mute_byHost")] - public bool IsVideoCanMuteByHost { get; set; } - [JsonProperty("is_video_can_unmute_byHost")] - public bool IsVideoCanUnmuteByHost { get; set; } - [JsonProperty("local_recording_disabled")] - public bool LocalRecordingDisabled { get; set; } - [JsonProperty("user_id")] - public int UserId { get; set; } - [JsonProperty("user_name")] - public string UserName { get; set; } - [JsonProperty("user_type")] - public string UserType { get; set; } - [JsonProperty("video_status has_source")] - public bool VideoStatusHasSource { get; set; } - [JsonProperty("video_status is_receiving")] - public bool VideoStatusIsReceiving { get; set; } - [JsonProperty("video_status is_sending")] - public bool VideoStatusIsSending { get; set; } - - public ListParticipant() - { - HandStatus = new HandStatus(); - } - - /// - /// Converts ZoomRoom pariticpant list response to an Essentials participant list - /// - /// - /// - public static List GetGenericParticipantListFromParticipantsResult( - List participants) - { - if (participants.Count == 0) - { - return new List(); - } - //return participants.Select(p => new Participant - // { - // UserId = p.UserId, - // Name = p.UserName, - // IsHost = p.IsHost, - // CanMuteVideo = p.IsVideoCanMuteByHost, - // CanUnmuteVideo = p.IsVideoCanUnmuteByHost, - // AudioMuteFb = p.AudioStatusState == "AUDIO_MUTED", - // VideoMuteFb = p.VideoStatusIsSending, - // HandIsRaisedFb = p.HandStatus.HandIsRaisedAndValid, - // }).ToList(); - - var sortedParticipants = SortParticipantListByHandStatus(participants); - return sortedParticipants.Select(p => new Participant - { - UserId = p.UserId, - Name = p.UserName, - IsHost = p.IsHost, - IsMyself = p.IsMyself, - CanMuteVideo = p.IsVideoCanMuteByHost, - CanUnmuteVideo = p.IsVideoCanUnmuteByHost, - AudioMuteFb = p.AudioStatusState == "AUDIO_MUTED", - VideoMuteFb = !p.VideoStatusIsSending, - HandIsRaisedFb = p.HandStatus.HandIsRaisedAndValid, - }).ToList(); - } - - /// - /// Will sort by hand-raise status and then alphabetically - /// - /// Zoom Room response list of participants - /// List - public static List SortParticipantListByHandStatus(List participants) - { - if (participants == null) - { - //Debug.Console(1, "SortParticiapntListByHandStatu(participants == null)"); - return null; - } - - // debug testing - //foreach (ListParticipant participant in participants) - //{ - // Debug.Console(1, "{0} | IsValid: {1} | IsRaiseHand: {2} | HandIsRaisedAndValid: {3}", - // participant.UserName, participant.HandStatus.IsValid, participant.HandStatus.IsRaiseHand.ToString(), participant.HandStatus.HandIsRaisedAndValid.ToString()); - //} - - List handRaisedParticipantsList = participants.Where(p => p.HandStatus.HandIsRaisedAndValid).ToList(); - - if (handRaisedParticipantsList != null) - { - IOrderedEnumerable orderByDescending = handRaisedParticipantsList.OrderByDescending(p => p.HandStatus.TimeStamp); - - //foreach (var participant in handRaisedParticipantsList) - // Debug.Console(1, "handRaisedParticipantList: {0} | {1}", participant.UserName, participant.UserId); - } - - List allOtherParticipantsList = participants.Where(p => !p.HandStatus.HandIsRaisedAndValid).ToList(); - - if (allOtherParticipantsList != null) - { - allOtherParticipantsList.OrderBy(p => p.UserName); - - //foreach (var participant in allOtherParticipantsList) - // Debug.Console(1, "allOtherParticipantsList: {0} | {1}", participant.UserName, participant.UserId); - } - - // merge the lists - List sortedList = handRaisedParticipantsList.Union(allOtherParticipantsList).ToList(); - - // return the sorted list - return sortedList; - } - - } - - public class CallinCountryList - { - public int code { get; set; } - public string display_number { get; set; } - public string id { get; set; } - public string name { get; set; } - public string number { get; set; } - } - - public class CalloutCountryList - { - public int code { get; set; } - public string display_number { get; set; } - public string id { get; set; } - public string name { get; set; } - public string number { get; set; } - } - - public class TollFreeCallinList - { - public int code { get; set; } - public string display_number { get; set; } - public string id { get; set; } - public string name { get; set; } - public string number { get; set; } - } - - public class Info - { - public List callin_country_list { get; set; } - public List callout_country_list { get; set; } - public List toll_free_callin_list { get; set; } - } - - public class ThirdParty - { - public string h323_address { get; set; } - public string meeting_number { get; set; } - public string service_provider { get; set; } - public string sip_address { get; set; } - } - - public class MeetingListItem - { - public string accessRole { get; set; } - public string calendarChangeKey { get; set; } - public string calendarID { get; set; } - public bool checkIn { get; set; } - public string creatorEmail { get; set; } - public string creatorName { get; set; } - public string endTime { get; set; } - public string hostName { get; set; } - public bool isInstantMeeting { get; set; } - public bool isPrivate { get; set; } - public string location { get; set; } - public string meetingName { get; set; } - public string meetingNumber { get; set; } - public string scheduledFrom { get; set; } - public string startTime { get; set; } - public ThirdParty third_party { get; set; } - - public MeetingListItem() - { - third_party = new ThirdParty(); - } - } - - public class InfoResult - { - public Info Info { get; set; } - public bool am_i_original_host { get; set; } - public string default_callin_country { get; set; } - public string dialIn { get; set; } - public string international_url { get; set; } - public string invite_email_content { get; set; } - public string invite_email_subject { get; set; } - public bool is_callin_country_list_available { get; set; } - public bool is_calling_room_system_enabled { get; set; } - public bool is_toll_free_callin_list_available { get; set; } - public bool is_view_only { get; set; } - public bool is_waiting_room { get; set; } - public bool is_webinar { get; set; } - public string meeting_id { get; set; } - public MeetingListItem meeting_list_item { get; set; } - public string meeting_password { get; set; } - public string meeting_type { get; set; } - public int my_userid { get; set; } - public int participant_id { get; set; } - public string real_meeting_id { get; set; } - public string schedule_option { get; set; } - public string schedule_option2 { get; set; } - public string support_callout_type { get; set; } - public string toll_free_number { get; set; } - public string user_type { get; set; } - - public InfoResult() - { - Info = new Info(); - meeting_list_item = new MeetingListItem(); - } - } - - public class Phonebook - { - public List Contacts { get; set; } - public int Limit { get; set; } - public int Offset { get; set; } - } - } -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoom.cs deleted file mode 100644 index a9c6c0f2..00000000 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ /dev/null @@ -1,3943 +0,0 @@ -extern alias Full; - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro.CrestronThread; -using Crestron.SimplSharpPro.DeviceSupport; -using Full.Newtonsoft.Json; -using Full.Newtonsoft.Json.Linq; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Bridges; -using PepperDash.Essentials.Core.Config; -using PepperDash.Essentials.Core.DeviceTypeInterfaces; -using PepperDash.Essentials.Core.Routing; -using PepperDash.Essentials.Core.Queues; -using PepperDash.Essentials.Devices.Common.Cameras; -using PepperDash.Essentials.Devices.Common.Codec; -using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; -using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; - -namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom -{ - public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, - IRouting, - IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMuteWithUnmuteReqeust, IHasCameraAutoMode, - IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, - IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting, - IHasMeetingLock, IHasMeetingRecordingWithPrompt, IZoomWirelessShareInstructions - { - public event EventHandler VideoUnmuteRequested; - - private const long MeetingRefreshTimer = 60000; - public uint DefaultMeetingDurationMin { get; private set; } - - /// - /// CR LF CR LF Delimits an echoed response to a command - /// - private const string EchoDelimiter = "\x0D\x0A\x0D\x0A"; - - private const string SendDelimiter = "\x0D"; - - /// - /// CR LF } CR LF Delimits a JSON response - /// - private const string JsonDelimiter = "\x0D\x0A\x7D\x0D\x0A"; - - private string[] Delimiters = new string[] { EchoDelimiter, JsonDelimiter, "OK\x0D\x0A", "end\x0D\x0A" }; - private readonly GenericQueue _receiveQueue; - - private readonly ZoomRoomSyncState _syncState; - public bool CommDebuggingIsOn; - private CodecDirectory _currentDirectoryResult; - private uint _jsonCurlyBraceCounter; - private bool _jsonFeedbackMessageIsIncoming; - private StringBuilder _jsonMessage; - private int _previousVolumeLevel; - private CameraBase _selectedCamera; - private string _lastDialedMeetingNumber; - - private CTimer contactsDebounceTimer; - - - private readonly ZoomRoomPropertiesConfig _props; - - private bool _meetingPasswordRequired; - - private bool _waitingForUserToAcceptOrRejectIncomingCall; - - public void Poll(string pollString) - { - if(_meetingPasswordRequired || _waitingForUserToAcceptOrRejectIncomingCall) return; - - SendText(string.Format("{0}{1}", pollString, SendDelimiter)); - } - - public ZoomRoom(DeviceConfig config, IBasicCommunication comm) - : base(config) - { - DefaultMeetingDurationMin = 30; - - _props = JsonConvert.DeserializeObject(config.Properties.ToString()); - - _receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 2048); - - Communication = comm; - - if (_props.CommunicationMonitorProperties != null) - { - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, _props.CommunicationMonitorProperties.PollInterval, _props.CommunicationMonitorProperties.TimeToWarning, _props.CommunicationMonitorProperties.TimeToError, - () => Poll(_props.CommunicationMonitorProperties.PollString)); - } - else - { - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, () => Poll("zStatus SystemUnit")); - } - - DeviceManager.AddDevice(CommunicationMonitor); - - Status = new ZoomRoomStatus(); - - Configuration = new ZoomRoomConfiguration(); - - CodecInfo = new ZoomRoomInfo(Status, Configuration); - - _syncState = new ZoomRoomSyncState(Key + "--Sync", this); - - _syncState.InitialSyncCompleted += SyncState_InitialSyncCompleted; - - _syncState.FirstJsonResponseReceived += (o, a) => SetUpSyncQueries(); - - PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); - - PhonebookSyncState.InitialSyncCompleted += (o, a) => ResubscribeForAddedContacts(); - - PortGather = new CommunicationGather(Communication, Delimiters) {IncludeDelimiter = true}; - PortGather.LineReceived += Port_LineReceived; - - CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, - eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this); - - Output1 = new RoutingOutputPort(RoutingPortNames.HdmiOut1, - eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - - Output2 = new RoutingOutputPort(RoutingPortNames.HdmiOut2, - eRoutingSignalType.Video, - eRoutingPortConnectionType.DisplayPort, null, this); - - Output3 = new RoutingOutputPort(RoutingPortNames.HdmiOut3, - eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - - SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); - - CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc); - - CameraIsMutedFeedback = CameraIsOffFeedback; - - CameraAutoModeIsOnFeedback = new BoolFeedback(CameraAutoModeIsOnFeedbackFunc); - - CodecSchedule = new CodecScheduleAwareness(MeetingRefreshTimer); - - if (_props.MinutesBeforeMeetingStart > 0) - { - CodecSchedule.MeetingWarningMinutes = _props.MinutesBeforeMeetingStart; - } - - ReceivingContent = new BoolFeedback(FarEndIsSharingContentFeedbackFunc); - - SelfviewPipPositionFeedback = new StringFeedback(SelfviewPipPositionFeedbackFunc); - - // TODO: #714 [ ] SelfviewPipSizeFeedback - SelfviewPipSizeFeedback = new StringFeedback(SelfviewPipSizeFeedbackFunc); - - SetUpFeedbackActions(); - - Cameras = new List(); - - SetUpDirectory(); - - Participants = new CodecParticipants(); - - SupportsCameraOff = true; // Always allow turning off the camera for zoom calls? - SupportsCameraAutoMode = _props.SupportsCameraAutoMode; - - PhoneOffHookFeedback = new BoolFeedback(PhoneOffHookFeedbackFunc); - CallerIdNameFeedback = new StringFeedback(CallerIdNameFeedbackFunc); - CallerIdNumberFeedback = new StringFeedback(CallerIdNumberFeedbackFunc); - - LocalLayoutFeedback = new StringFeedback(LocalLayoutFeedbackFunc); - - LayoutViewIsOnFirstPageFeedback = new BoolFeedback(LayoutViewIsOnFirstPageFeedbackFunc); - LayoutViewIsOnLastPageFeedback = new BoolFeedback(LayoutViewIsOnLastPageFeedbackFunc); - CanSwapContentWithThumbnailFeedback = new BoolFeedback(CanSwapContentWithThumbnailFeedbackFunc); - ContentSwappedWithThumbnailFeedback = new BoolFeedback(ContentSwappedWithThumbnailFeedbackFunc); - - NumberOfScreensFeedback = new IntFeedback(NumberOfScreensFeedbackFunc); - - MeetingIsLockedFeedback = new BoolFeedback(() => Configuration.Call.Lock.Enable ); - - MeetingIsRecordingFeedback = new BoolFeedback(() => Status.Call.CallRecordInfo.meetingIsBeingRecorded ); - - RecordConsentPromptIsVisible = new BoolFeedback(() => _recordConsentPromptIsVisible); - - SetUpRouting(); - } - - public CommunicationGather PortGather { get; private set; } - - public ZoomRoomStatus Status { get; private set; } - - public ZoomRoomConfiguration Configuration { get; private set; } - - //CTimer LoginMessageReceivedTimer; - //CTimer RetryConnectionTimer; - - /// - /// Gets and returns the scaled volume of the codec - /// - protected override Func VolumeLevelFeedbackFunc - { - get - { - return () => - { - var scaledVol = CrestronEnvironment.ScaleWithLimits(Configuration.Audio.Output.Volume, 100, 0, 65535, 0); - - if (Configuration.Audio.Output.Volume != 0) - { - Debug.Console(2, this, "Storing previous volume level as: {0}, scaled: {1}", Configuration.Audio.Output.Volume, - scaledVol); - _previousVolumeLevel = scaledVol; // Store the previous level for recall - } - - return scaledVol; - }; - } - } - - protected override Func PrivacyModeIsOnFeedbackFunc - { - get - { - return () => - { - //Debug.Console(2, this, "PrivacyModeIsOnFeedbackFunc. IsInCall: {0} muteState: {1}", IsInCall, Configuration.Call.Microphone.Mute); - if (IsInCall) - { - //Debug.Console(2, this, "reporting muteState: ", Configuration.Call.Microphone.Mute); - return Configuration.Call.Microphone.Mute; - } - else - { - //Debug.Console(2, this, "muteState: true", IsInCall); - return false; - } - }; - } - } - - protected override Func StandbyIsOnFeedbackFunc - { - get { return () => false; } - } - - protected override Func SharingSourceFeedbackFunc - { - get - { - return () => - { - if (Status.Sharing.isAirHostClientConnected) - return "Airplay"; - else if (Status.Sharing.isDirectPresentationConnected || Status.Sharing.isBlackMagicConnected) - return "Laptop"; - else return "None"; - - }; - } - } - - protected override Func SharingContentIsOnFeedbackFunc - { - get { return () => Status.Sharing.isAirHostClientConnected || Status.Sharing.isDirectPresentationConnected || Status.Sharing.isSharingBlackMagic; } - } - - protected Func FarEndIsSharingContentFeedbackFunc - { - get { return () => Status.Call.Sharing.State == zEvent.eSharingState.Receiving; } - } - - protected override Func MuteFeedbackFunc - { - get { return () => Configuration.Audio.Output.Volume == 0; } - } - - //protected Func RoomIsOccupiedFeedbackFunc - //{ - // get - // { - // return () => false; - // } - //} - - //protected Func PeopleCountFeedbackFunc - //{ - // get - // { - // return () => 0; - // } - //} - - protected Func SelfViewIsOnFeedbackFunc - { - get { return () => !Configuration.Video.HideConfSelfVideo; } - } - - protected Func CameraIsOffFeedbackFunc - { - get { return () => Configuration.Call.Camera.Mute; } - } - - protected Func CameraAutoModeIsOnFeedbackFunc - { - get { return () => false; } - } - - protected Func SelfviewPipPositionFeedbackFunc - { - get - { - return - () => - _currentSelfviewPipPosition != null - ? _currentSelfviewPipPosition.Command ?? "Unknown" - : "Unknown"; - } - } - - // TODO: #714 [ ] SelfviewPipSizeFeedbackFunc - protected Func SelfviewPipSizeFeedbackFunc - { - get - { - return - () => - _currentSelfviewPipSize != null - ? _currentSelfviewPipSize.Command ?? "Unknown" - : "Unknown"; - } - } - - protected Func LocalLayoutIsProminentFeedbackFunc - { - get { return () => false; } - } - - - public RoutingInputPort CodecOsdIn { get; private set; } - public RoutingOutputPort Output1 { get; private set; } - public RoutingOutputPort Output2 { get; private set; } - public RoutingOutputPort Output3 { get; private set; } - - #region ICommunicationMonitor Members - - public StatusMonitorBase CommunicationMonitor { get; private set; } - - #endregion - - #region IHasCodecCameras Members - - public event EventHandler CameraSelected; - - public List Cameras { get; private set; } - - public CameraBase SelectedCamera - { - get { return _selectedCamera; } - private set - { - _selectedCamera = value; - SelectedCameraFeedback.FireUpdate(); - ControllingFarEndCameraFeedback.FireUpdate(); - - var handler = CameraSelected; - if (handler != null) - { - handler(this, new CameraSelectedEventArgs(_selectedCamera)); - } - } - } - - - public StringFeedback SelectedCameraFeedback { get; private set; } - - public void SelectCamera(string key) - { - if (CameraIsMutedFeedback.BoolValue) - { - CameraMuteOff(); - } - - SendText(string.Format("zConfiguration Video Camera selectedId: {0}", key)); - } - - public CameraBase FarEndCamera { get; private set; } - - public BoolFeedback ControllingFarEndCameraFeedback { get; private set; } - - #endregion - - #region IHasCodecSelfView Members - - public BoolFeedback SelfviewIsOnFeedback { get; private set; } - - public void GetSelfViewMode() - { - SendText("zConfiguration Video hide_conf_self_video"); - } - - public void SelfViewModeOn() - { - SendText("zConfiguration Video hide_conf_self_video: off"); - } - - public void SelfViewModeOff() - { - SendText("zConfiguration Video hide_conf_self_video: on"); - } - - public void SelfViewModeToggle() - { - if (SelfviewIsOnFeedback.BoolValue) - { - SelfViewModeOff(); - } - else - { - SelfViewModeOn(); - } - } - - #endregion - - #region IHasDirectoryHistoryStack Members - - public event EventHandler DirectoryResultReturned; - public CodecDirectory DirectoryRoot { get; private set; } - - public CodecDirectory CurrentDirectoryResult - { - get { return _currentDirectoryResult; } - private set - { - _currentDirectoryResult = value; - - Debug.Console(2, this, "CurrentDirectoryResult Updated. ResultsFolderId: {0} Contact Count: {1}", - _currentDirectoryResult.ResultsFolderId, _currentDirectoryResult.CurrentDirectoryResults.Count); - - OnDirectoryResultReturned(_currentDirectoryResult); - } - } - - public CodecPhonebookSyncState PhonebookSyncState { get; private set; } - - public void SearchDirectory(string searchString) - { - var directoryResults = new CodecDirectory(); - - directoryResults.AddContactsToDirectory( - DirectoryRoot.CurrentDirectoryResults.FindAll( - c => c.Name.IndexOf(searchString, 0, StringComparison.OrdinalIgnoreCase) > -1)); - - DirectoryBrowseHistoryStack.Clear(); - CurrentDirectoryResult = directoryResults; - } - - public void GetDirectoryFolderContents(string folderId) - { - var directoryResults = new CodecDirectory {ResultsFolderId = folderId}; - - directoryResults.AddContactsToDirectory( - DirectoryRoot.CurrentDirectoryResults.FindAll(c => c.ParentFolderId.Equals(folderId))); - - DirectoryBrowseHistoryStack.Push(_currentDirectoryResult); - - CurrentDirectoryResult = directoryResults; - } - - public void SetCurrentDirectoryToRoot() - { - DirectoryBrowseHistoryStack.Clear(); - - CurrentDirectoryResult = DirectoryRoot; - } - - public void GetDirectoryParentFolderContents() - { - if (DirectoryBrowseHistoryStack.Count == 0) - { - return; - } - - var currentDirectory = DirectoryBrowseHistoryStack.Pop(); - - CurrentDirectoryResult = currentDirectory; - } - - public BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; private set; } - - public List DirectoryBrowseHistory { get; private set; } - - public Stack DirectoryBrowseHistoryStack { get; private set; } - - #endregion - - #region IHasScheduleAwareness Members - - public CodecScheduleAwareness CodecSchedule { get; private set; } - - public void GetSchedule() - { - GetBookings(); - } - - #endregion - - #region IRouting Members - - public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) - { - ExecuteSwitch(inputSelector); - } - - #endregion - - private void SyncState_InitialSyncCompleted(object sender, EventArgs e) - { - SetIsReady(); - } - - /// - /// Handles subscriptions to Status.Call and sub objects. Needs to be called whenever Status.Call is constructed - /// - private void SetUpCallFeedbackActions() - { - Status.Sharing.PropertyChanged -= HandleSharingStateUpdate; - Status.Sharing.PropertyChanged += HandleSharingStateUpdate; - - Status.Call.Sharing.PropertyChanged -= HandleSharingStateUpdate; - Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate; - - Status.Call.PropertyChanged -= HandleCallStateUpdate; - Status.Call.PropertyChanged += HandleCallStateUpdate; - - Status.Call.CallRecordInfo.PropertyChanged -= HandleCallRecordInfoStateUpdate; - Status.Call.CallRecordInfo.PropertyChanged += HandleCallRecordInfoStateUpdate; - } - - private void HandleCallRecordInfoStateUpdate(object sender, PropertyChangedEventArgs a) - { - if (a.PropertyName == "meetingIsBeingRecorded" || a.PropertyName == "emailRequired" || a.PropertyName == "canRecord") - { - MeetingIsRecordingFeedback.FireUpdate(); - - var meetingInfo = new MeetingInfo(MeetingInfo.Id, - MeetingInfo.Name, - MeetingInfo.Host, - MeetingInfo.Password, - GetSharingStatus(), - GetIsHostMyself(), - MeetingInfo.IsSharingMeeting, - MeetingInfo.WaitingForHost, - MeetingIsLockedFeedback.BoolValue, - MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); - MeetingInfo = meetingInfo; - } - } - - private void HandleCallStateUpdate(object sender, PropertyChangedEventArgs a) - { - switch (a.PropertyName) - { - case "Info": - { - Debug.Console(1, this, "Updating Call Status"); - UpdateCallStatus(); - break; - } - - case "Status": - { - UpdateCallStatus(); - break; - } - } - } - - private void HandleSharingStateUpdate(object sender, PropertyChangedEventArgs a) - { - //if (a.PropertyName != "State") - //{ - // return; - //} - - SharingContentIsOnFeedback.FireUpdate(); - ReceivingContent.FireUpdate(); - try - { - - // Update the share status of the meeting info - if (MeetingInfo == null) - { - MeetingInfo = new MeetingInfo("", "", "", "", GetSharingStatus(), GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); - return; - } - - var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None", - MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); - MeetingInfo = meetingInfo; - } - catch (Exception e) - { - Debug.Console(1, this, "Error processing state property update. {0}", e.Message); - Debug.Console(2, this, e.StackTrace); - MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, false); - } - } - - /// - /// Subscribes to the PropertyChanged events on the state objects and fires the corresponding feedbacks. - /// - private void SetUpFeedbackActions() - { - // Set these up initially. - SetUpCallFeedbackActions(); - - Configuration.Audio.Output.PropertyChanged += (o, a) => - { - if (a.PropertyName == "Volume") - { - VolumeLevelFeedback.FireUpdate(); - MuteFeedback.FireUpdate(); - } - }; - - Configuration.Call.Microphone.PropertyChanged += (o, a) => - { - if (a.PropertyName == "Mute") - { - PrivacyModeIsOnFeedback.FireUpdate(); - } - }; - - Configuration.Video.PropertyChanged += (o, a) => - { - if (a.PropertyName == "HideConfSelfVideo") - { - SelfviewIsOnFeedback.FireUpdate(); - } - }; - Configuration.Video.Camera.PropertyChanged += (o, a) => - { - if (a.PropertyName == "SelectedId") - { - if (Cameras == null) - { - return; - } - - var camera = Cameras.FirstOrDefault(c => c.Key.IndexOf(Configuration.Video.Camera.SelectedId, StringComparison.OrdinalIgnoreCase) > -1); - if (camera != null) - { - Debug.Console(1, this, "Camera selected with key: '{0}'", camera.Key); - - SelectedCamera = camera; - - if (CameraIsMutedFeedback.BoolValue) - { - CameraMuteOff(); - } - } - else - { - Debug.Console(1, this, "No camera found with key: '{0}'", Configuration.Video.Camera.SelectedId); - } - } - }; - - Configuration.Call.Camera.PropertyChanged += (o, a) => - { - Debug.Console(1, this, "Configuration.Call.Camera.PropertyChanged: {0}", a.PropertyName); - - if (a.PropertyName != "Mute") return; - - CameraIsOffFeedback.FireUpdate(); - CameraAutoModeIsOnFeedback.FireUpdate(); - }; - - Configuration.Call.Layout.PropertyChanged += (o, a) => - { - switch (a.PropertyName) - { - case "Position": - { - ComputeSelfviewPipPositionStatus(); - - SelfviewPipPositionFeedback.FireUpdate(); - - break; - } - case "ShareThumb": - { - ContentSwappedWithThumbnailFeedback.FireUpdate(); - OnLayoutInfoChanged(); - break; - } - case "Style": - { - LocalLayoutFeedback.FireUpdate(); - OnLayoutInfoChanged(); - break; - } - case "Size": - { - // TODO: #714 [ ] SetupFeedbackActions >> Size - ComputeSelfviewPipSizeStatus(); - - SelfviewPipSizeFeedback.FireUpdate(); - - break; - } - } - }; - - Configuration.Call.Lock.PropertyChanged += (o, a) => - { - if (a.PropertyName == "Enable") - { - MeetingIsLockedFeedback.FireUpdate(); - MeetingInfo = new MeetingInfo - ( - MeetingInfo.Id, - MeetingInfo.Name, - MeetingInfo.Host, - MeetingInfo.Password, - GetSharingStatus(), - MeetingInfo.IsHost, - MeetingInfo.IsSharingMeeting, - MeetingInfo.WaitingForHost, - MeetingIsLockedFeedback.BoolValue, - MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord - ); - } - }; - - // This is to deal with incorrect object structure coming back from the Zoom Room on v 5.6.3 - Configuration.Client.Call.Layout.PropertyChanged += (o, a) => - { - switch (a.PropertyName) - { - case "Position": - { - ComputeSelfviewPipPositionStatus(); - - SelfviewPipPositionFeedback.FireUpdate(); - - break; - } - case "ShareThumb": - { - ContentSwappedWithThumbnailFeedback.FireUpdate(); - OnLayoutInfoChanged(); - break; - } - case "Style": - { - LocalLayoutFeedback.FireUpdate(); - OnLayoutInfoChanged(); - break; - } - } - }; - - - Status.Sharing.PropertyChanged += (o, a) => - { - OnShareInfoChanged(Status.Sharing); - SharingSourceFeedback.FireUpdate(); - switch (a.PropertyName) - { - case "password": - break; - case "isSharingBlackMagic": - { - Debug.Console(2, this, "Updating sharing status: {0}", a.PropertyName); - - SharingContentIsOnFeedback.FireUpdate(); - if (MeetingInfo == null) - { - //Ignoring for now, as the CallInfo return will create the appropriate value - return; - } - // Update the share status of the meeting info - var meetingInfo = new MeetingInfo(MeetingInfo.Id, - MeetingInfo.Name, - MeetingInfo.Host, - MeetingInfo.Password, - GetSharingStatus(), - GetIsHostMyself(), - MeetingInfo.IsSharingMeeting, - MeetingInfo.WaitingForHost, - MeetingIsLockedFeedback.BoolValue, - MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); - MeetingInfo = meetingInfo; - break; - } - } - }; - - Status.PhoneCall.PropertyChanged += (o, a) => - { - switch (a.PropertyName) - { - case "IsIncomingCall": - Debug.Console(1, this, "Incoming Phone Call: {0}", Status.PhoneCall.IsIncomingCall); - break; - case "PeerDisplayName": - Debug.Console(1, this, "Peer Display Name: {0}", Status.PhoneCall.PeerDisplayName); - CallerIdNameFeedback.FireUpdate(); - break; - case "PeerNumber": - Debug.Console(1, this, "Peer Number: {0}", Status.PhoneCall.PeerNumber); - CallerIdNumberFeedback.FireUpdate(); - break; - case "OffHook": - Debug.Console(1, this, "Phone is OffHook: {0}", Status.PhoneCall.OffHook); - PhoneOffHookFeedback.FireUpdate(); - break; - } - }; - - Status.Layout.PropertyChanged += (o, a) => - { - Debug.Console(1, this, "Status.Layout.PropertyChanged a.PropertyName: {0}", a.PropertyName); - switch (a.PropertyName.ToLower()) - { - case "can_Switch_speaker_view": - case "can_switch_wall_view": - case "can_switch_strip_view": - case "video_type": - case "can_switch_share_on_all_screens": - { - ComputeAvailableLayouts(); - break; - } - case "is_in_first_page": - { - LayoutViewIsOnFirstPageFeedback.FireUpdate(); - break; - } - case "is_in_last_page": - { - LayoutViewIsOnLastPageFeedback.FireUpdate(); - break; - } - case "can_switch_floating_share_content": - { - CanSwapContentWithThumbnailFeedback.FireUpdate(); - break; - } - } - OnLayoutInfoChanged(); - }; - - Status.NumberOfScreens.PropertyChanged += (o, a) => - { - switch (a.PropertyName) - { - case "NumberOfScreens": - { - NumberOfScreensFeedback.FireUpdate(); - break; - } - } - }; - } - - private void SetUpDirectory() - { - DirectoryRoot = new CodecDirectory() {ResultsFolderId = "root"}; - - CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => CurrentDirectoryResult.ResultsFolderId != "root"); - - CurrentDirectoryResult = DirectoryRoot; - - DirectoryBrowseHistory = new List(); - DirectoryBrowseHistoryStack = new Stack(); - } - - private void SetUpRouting() - { - // Set up input ports - CreateOsdSource(); - InputPorts.Add(CodecOsdIn); - - // Set up output ports - OutputPorts.Add(Output1); - OutputPorts.Add(Output2); - } - - /// - /// Creates the fake OSD source, and connects it's AudioVideo output to the CodecOsdIn input - /// to enable routing - /// - private void CreateOsdSource() - { - OsdSource = new DummyRoutingInputsDevice(Key + "[osd]"); - DeviceManager.AddDevice(OsdSource); - var tl = new TieLine(OsdSource.AudioVideoOutputPort, CodecOsdIn); - TieLineCollection.Default.Add(tl); - - //foreach(var input in Status.Video. - } - - /// - /// Starts the HTTP feedback server and syncronizes state of codec - /// - /// - public override bool CustomActivate() - { - CrestronConsole.AddNewConsoleCommand(SetCommDebug, "SetCodecCommDebug", "0 for Off, 1 for on", - ConsoleAccessLevelEnum.AccessOperator); - if (!_props.DisablePhonebookAutoDownload) - { - CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 10000"), - "GetZoomRoomContacts", "Triggers a refresh of the codec phonebook", - ConsoleAccessLevelEnum.AccessOperator); - } - - CrestronConsole.AddNewConsoleCommand(s => GetBookings(), "GetZoomRoomBookings", - "Triggers a refresh of the booking data for today", ConsoleAccessLevelEnum.AccessOperator); - - - - return base.CustomActivate(); - } - - #region Overrides of Device - - public override void Initialize() - { - var socket = Communication as ISocketStatus; - if (socket != null) - { - socket.ConnectionChange += socket_ConnectionChange; - } - - CommDebuggingIsOn = false; - - Communication.Connect(); - - CommunicationMonitor.Start(); - } - - #endregion - - public void SetCommDebug(string s) - { - if (s == "1") - { - CommDebuggingIsOn = true; - Debug.Console(1, this, "Comm Debug Enabled."); - } - else - { - CommDebuggingIsOn = false; - Debug.Console(1, this, "Comm Debug Disabled."); - } - } - - private void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) - { - Debug.Console(1, this, "Socket status change {0}", e.Client.ClientStatus); - if (e.Client.IsConnected) - { - } - else - { - _syncState.CodecDisconnected(); - PhonebookSyncState.CodecDisconnected(); - } - } - - public void SendText(string command) - { - if (_meetingPasswordRequired) - { - Debug.Console(2, this, "Blocking commands to ZoomRoom while waiting for user to enter meeting password"); - return; - } - - if (_waitingForUserToAcceptOrRejectIncomingCall) - { - Debug.Console(2, this, "Blocking commands to ZoomRoom while waiting for user to accept or reject incoming call"); - return; - } - - if (CommDebuggingIsOn) - { - Debug.Console(1, this, "Sending: '{0}'", command); - } - - Communication.SendText(command + SendDelimiter); - } - - /// - /// Gathers responses and enqueues them. - /// - /// - /// - private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args) - { - //Debug.Console(0, this, "Port_LineReceived"); - - if (args.Delimiter != JsonDelimiter) - { -// Debug.Console(0, this, -//@"Non JSON response: -//Delimiter: {0} -//{1}", ComTextHelper.GetDebugText(args.Delimiter), args.Text); - ProcessNonJsonResponse(args.Text); - return; - } - else - { -// Debug.Console(0, this, -//@"JSON response: -//Delimiter: {0} -//{1}", ComTextHelper.GetDebugText(args.Delimiter), args.Text); - _receiveQueue.Enqueue(new ProcessStringMessage(args.Text, DeserializeResponse)); - //_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage)); - } - } - - /// - /// Queues the initial queries to be sent upon connection - /// - private void SetUpSyncQueries() - { - // zStatus - _syncState.AddQueryToQueue("zStatus Call Status"); - _syncState.AddQueryToQueue("zStatus Audio Input Line"); - _syncState.AddQueryToQueue("zStatus Audio Output Line"); - _syncState.AddQueryToQueue("zStatus Video Camera Line"); - _syncState.AddQueryToQueue("zStatus Video Optimizable"); - _syncState.AddQueryToQueue("zStatus Capabilities"); - _syncState.AddQueryToQueue("zStatus Sharing"); - _syncState.AddQueryToQueue("zStatus CameraShare"); - _syncState.AddQueryToQueue("zStatus Call Layout"); - _syncState.AddQueryToQueue("zStatus Call ClosedCaption Available"); - _syncState.AddQueryToQueue("zStatus NumberOfScreens"); - - // zConfiguration - - _syncState.AddQueryToQueue("zConfiguration Call Sharing optimize_video_sharing"); - _syncState.AddQueryToQueue("zConfiguration Call Microphone Mute"); - _syncState.AddQueryToQueue("zConfiguration Call Camera Mute"); - _syncState.AddQueryToQueue("zConfiguration Audio Input SelectedId"); - _syncState.AddQueryToQueue("zConfiguration Audio Input is_sap_disabled"); - _syncState.AddQueryToQueue("zConfiguration Audio Input reduce_reverb"); - _syncState.AddQueryToQueue("zConfiguration Audio Input volume"); - _syncState.AddQueryToQueue("zConfiguration Audio Output selectedId"); - _syncState.AddQueryToQueue("zConfiguration Audio Output volume"); - _syncState.AddQueryToQueue("zConfiguration Video hide_conf_self_video"); - _syncState.AddQueryToQueue("zConfiguration Video Camera selectedId"); - _syncState.AddQueryToQueue("zConfiguration Video Camera Mirror"); - _syncState.AddQueryToQueue("zConfiguration Client appVersion"); - _syncState.AddQueryToQueue("zConfiguration Client deviceSystem"); - _syncState.AddQueryToQueue("zConfiguration Call Layout ShareThumb"); - _syncState.AddQueryToQueue("zConfiguration Call Layout Style"); - _syncState.AddQueryToQueue("zConfiguration Call Layout Size"); - _syncState.AddQueryToQueue("zConfiguration Call Layout Position"); - _syncState.AddQueryToQueue("zConfiguration Call Lock Enable"); - _syncState.AddQueryToQueue("zConfiguration Call MuteUserOnEntry Enable"); - _syncState.AddQueryToQueue("zConfiguration Call ClosedCaption FontSize "); - _syncState.AddQueryToQueue("zConfiguration Call ClosedCaption Visible"); - - // zCommand - - if (!_props.DisablePhonebookAutoDownload) - { - _syncState.AddQueryToQueue("zCommand Phonebook List Offset: 0 Limit: 10000"); - } - - _syncState.AddQueryToQueue("zCommand Bookings List"); - _syncState.AddQueryToQueue("zCommand Call ListParticipants"); - _syncState.AddQueryToQueue("zCommand Call Info"); - - - _syncState.StartSync(); - } - - private void SetupSession() - { - // disable echo of commands - SendText("echo off"); - // switch to json format - // set feedback exclusions - // Currently the feedback exclusions don't work when using the API in JSON response mode - // But leave these here in case the API gets updated in the future - // These may work as of 5.9.4 - - // In 5.9.4 we're getting sent an AddedContact message for every contact in the phonebook on connect, which is redunant and way too much data - // We want to exclude these messages right away until after we've retrieved the entire phonebook and then we can re-enable them - SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); - - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list"); - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list"); - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist"); - - SendText("zStatus SystemUnit"); - } - - /// - /// Removes the feedback exclusion for added contacts - /// - private void ResubscribeForAddedContacts() - { - SendText("zFeedback Register Op: in Path: /Event/Phonebook/AddedContact"); - } - - /// - /// Processes non-JSON responses as their are received - /// - /// - private void ProcessNonJsonResponse(string response) - { - if (response.Contains("client_loop: send disconnect: Broken pipe")) - { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, - "Zoom Room Controller or App connected. Essentials will NOT control the Zoom Room until it is disconnected."); - - return; - } - - if (!_syncState.InitialSyncComplete) - { - if(response.ToLower().Contains("*r login successful")) - { - _syncState.LoginResponseReceived(); - - SendText("format json"); - - SetupSession(); - } - - //switch (response.Trim().ToLower()) // remove the whitespace - //{ - // case "*r login successful": - // { - // _syncState.LoginMessageReceived(); - - // //// Fire up a thread to send the intial commands. - // //CrestronInvoke.BeginInvoke(o => - // //{ - // // disable echo of commands - // SendText("echo off"); - // // switch to json format - // SendText("format json"); - // // set feedback exclusions - // // Currently the feedback exclusions don't work when using the API in JSON response mode - // // But leave these here in case the API gets updated in the future - // // These may work as of 5.9.4 - // if (_props.DisablePhonebookAutoDownload) - // { - // SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); - // } - // SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list"); - // SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list"); - // SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist"); - - // //}); - - // break; - // } - //} - } - } - - /// - /// Processes messages as they are dequeued - /// - /// - private void ProcessMessage(string message) - { - // Counts the curly braces - if (message.Contains("client_loop: send disconnect: Broken pipe")) - { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, - "Zoom Room Controller or App connected. Essentials will NOT control the Zoom Room until it is disconnected."); - - return; - } - - if (message.Contains('{')) - { - _jsonCurlyBraceCounter++; - } - - if (message.Contains('}')) - { - _jsonCurlyBraceCounter--; - } - - //Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter); - - if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + EchoDelimiter) - // Check for the beginning of a new JSON message - { - _jsonFeedbackMessageIsIncoming = true; - _jsonCurlyBraceCounter = 1; // reset the counter for each new message - - _jsonMessage = new StringBuilder(); - - _jsonMessage.Append(message); - - if (CommDebuggingIsOn) - { - Debug.Console(2, this, "Incoming JSON message..."); - } - - return; - } - if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + EchoDelimiter) - // Check for the end of a JSON message - { - _jsonMessage.Append(message); - - if (_jsonCurlyBraceCounter == 0) - { - _jsonFeedbackMessageIsIncoming = false; - - if (CommDebuggingIsOn) - { - Debug.Console(2, this, "Complete JSON Received:\n{0}", _jsonMessage.ToString()); - } - - // Forward the complete message to be deserialized - DeserializeResponse(_jsonMessage.ToString()); - } - - //JsonMessage = new StringBuilder(); - return; - } - - // NOTE: This must happen after the above conditions have been checked - // Append subsequent partial JSON fragments to the string builder - if (_jsonFeedbackMessageIsIncoming) - { - _jsonMessage.Append(message); - - //Debug.Console(1, this, "Building JSON:\n{0}", JsonMessage.ToString()); - return; - } - - if (CommDebuggingIsOn) - { - Debug.Console(1, this, "Non-JSON response: '{0}'", message); - } - - _jsonCurlyBraceCounter = 0; // reset on non-JSON response - - if (!_syncState.InitialSyncComplete) - { - switch (message.Trim().ToLower()) // remove the whitespace - { - case "*r login successful": - { - _syncState.LoginResponseReceived(); - - - // Fire up a thread to send the intial commands. - CrestronInvoke.BeginInvoke(o => - { - // Currently the feedback exclusions don't work when using the API in JSON response mode - // But leave these here in case the API gets updated in the future - - - Thread.Sleep(100); - // disable echo of commands - SendText("echo off"); - Thread.Sleep(100); - // set feedback exclusions - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list"); - Thread.Sleep(100); - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list"); - Thread.Sleep(100); - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist"); - Thread.Sleep(100); - - if (_props.DisablePhonebookAutoDownload) - { - SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); - } - // switch to json format - SendText("format json"); - }); - - break; - } - } - } - } - - /// - /// Deserializes a JSON formatted response - /// - /// - private void DeserializeResponse(string response) - { - try - { - var trimmedResponse = response.Trim(); - - if (trimmedResponse.Length <= 0) - { - return; - } - - var message = JObject.Parse(trimmedResponse); - - if (!_syncState.FirstJsonResponseWasReceived) - { - _syncState.ReceivedFirstJsonResponse(); - } - - var eType = - (eZoomRoomResponseType) - Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value(), true); - - var topKey = message["topKey"].Value(); - - var responseObj = message[topKey]; - - Debug.Console(1, this, "{0} Response Received. topKey: '{1}'\n{2}", eType, topKey, responseObj.ToString().Replace("\n", CrestronEnvironment.NewLine)); - - switch (eType) - { - case eZoomRoomResponseType.zConfiguration: - { - switch (topKey.ToLower()) - { - case "call": - { - JsonConvert.PopulateObject(responseObj.ToString(), Configuration.Call); - - break; - } - case "audio": - { - JsonConvert.PopulateObject(responseObj.ToString(), Configuration.Audio); - - break; - } - case "video": - { - JsonConvert.PopulateObject(responseObj.ToString(), Configuration.Video); - - break; - } - case "client": - { - JsonConvert.PopulateObject(responseObj.ToString(), Configuration.Client); - - break; - } - default: - { - break; - } - } - break; - } - case eZoomRoomResponseType.zCommand: - { - switch (topKey.ToLower()) - { - case "inforesult": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Info); - break; - } - case "phonebooklistresult": - { - // This result will always be the complete contents of the directory and never - // A subset of the results via a search - - // Clear out any existing data - Status.Phonebook = new zStatus.Phonebook(); - - JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); - - UpdateDirectory(); - - break; - } - case "listparticipantsresult": - { - Debug.Console(1, this, "JTokenType: {0}", responseObj.Type); - - switch (responseObj.Type) - { - case JTokenType.Array: - Status.Call.Participants = - JsonConvert.DeserializeObject>( - responseObj.ToString()); - break; - case JTokenType.Object: - { - // this is a single participant event notification - - var participant = - JsonConvert.DeserializeObject( - responseObj.ToString()); - - if (participant != null) - { - Debug.Console(1, this, - "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} **********************************", - participant.Event); - Debug.Console(1, this, - "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} - UserId: {1} Name: {2} IsHost: {3}", - participant.Event, participant.UserId, participant.UserName, participant.IsHost); - - switch (participant.Event) - { - case "ZRCUserChangedEventUserInfoUpdated": - case "ZRCUserChangedEventLeftMeeting": - { - var existingParticipant = - Status.Call.Participants.FirstOrDefault( - p => p.UserId.Equals(participant.UserId)); - - if (existingParticipant != null) - { - switch (participant.Event) - { - case "ZRCUserChangedEventLeftMeeting": - Status.Call.Participants.Remove(existingParticipant); - break; - case "ZRCUserChangedEventUserInfoUpdated": - JsonConvert.PopulateObject(responseObj.ToString(), - existingParticipant); - break; - } - } - } - break; - case "ZRCUserChangedEventJoinedMeeting": - { - var existingParticipant = - Status.Call.Participants.FirstOrDefault(p => p.UserId.Equals(participant.UserId)); - - if (existingParticipant != null) - { - Debug.Console(1, this, - "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...updating matching UserId participant with UserId: {1} UserName: {2}", - participant.Event, participant.UserId, participant.UserName); - - JsonConvert.PopulateObject(responseObj.ToString(), existingParticipant); - } - else - { - Debug.Console(1, this, - "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...adding participant with UserId: {1} UserName: {2}", - participant.Event, participant.UserId, participant.UserName); - - Status.Call.Participants.Add(participant); - } - - break; - } - } - - Debug.Console(1, this, - "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ***********************************", - participant.Event); - } - } - break; - } - - var participants = - zCommand.ListParticipant.GetGenericParticipantListFromParticipantsResult( - Status.Call.Participants); - - Participants.CurrentParticipants = participants; - - // Update the share status of the meeting info - var meetingInfo = new MeetingInfo( - MeetingInfo.Id, - MeetingInfo.Name, - Participants.Host.Name, - MeetingInfo.Password, - GetSharingStatus(), - GetIsHostMyself(), - MeetingInfo.IsSharingMeeting, - MeetingInfo.WaitingForHost, - MeetingIsLockedFeedback.BoolValue, - MeetingIsRecordingFeedback.BoolValue, - Status.Call.CallRecordInfo.AllowRecord - ); - MeetingInfo = meetingInfo; - - PrintCurrentCallParticipants(); - - break; - } - default: - { - break; - } - } - break; - } - case eZoomRoomResponseType.zEvent: - { - switch (topKey.ToLower()) - { - case "phonebook": - { - zStatus.Contact contact = new zStatus.Contact(); - - if (responseObj["Updated Contact"] != null) - { - contact = responseObj["Updated Contact"].ToObject(); - } - else if (responseObj["Added Contact"] != null) - { - contact = responseObj["Added Contact"].ToObject(); - } - - var existingContactIndex = Status.Phonebook.Contacts.FindIndex(c => c.Jid.Equals(contact.Jid)); - - if (existingContactIndex > 0) - { - Status.Phonebook.Contacts[existingContactIndex] = contact; - } - else - { - Status.Phonebook.Contacts.Add(contact); - } - - if(contactsDebounceTimer == null) - { - contactsDebounceTimer = new CTimer(o => UpdateDirectory(), 2000); - } - else - { - contactsDebounceTimer.Reset(); - } - - break; - } - case "bookingslistresult": - { - if (!_syncState.InitialSyncComplete) - { - _syncState.LastQueryResponseReceived(); - } - - var codecBookings = JsonConvert.DeserializeObject>( - responseObj.ToString()); - - if (codecBookings != null && codecBookings.Count > 0) - { - CodecSchedule.Meetings = zCommand.GetGenericMeetingsFromBookingResult( - codecBookings, CodecSchedule.MeetingWarningMinutes); - } - else - { - //need to clear the list if it's empty - CodecSchedule.Meetings = new List(); - } - - break; - } - case "bookings updated": - { - GetBookings(); - - break; - } - case "sharingstate": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing); - - SetDefaultLayout(); - - break; - } - case "incomingcallindication": - { - var incomingCall = - JsonConvert.DeserializeObject(responseObj.ToString()); - - if (incomingCall != null) - { - var newCall = new CodecActiveCallItem - { - Direction = eCodecCallDirection.Incoming, - Status = eCodecCallStatus.Ringing, - Type = eCodecCallType.Video, - Name = incomingCall.callerName, - Id = incomingCall.callerJID - }; - - _waitingForUserToAcceptOrRejectIncomingCall = true; - - ActiveCalls.Add(newCall); - - OnCallStatusChange(newCall); - } - - break; - } - case "treatedincomingcallindication": - { - var incomingCall = - JsonConvert.DeserializeObject(responseObj.ToString()); - - if (incomingCall != null) - { - var existingCall = - ActiveCalls.FirstOrDefault(c => c.Id.Equals(incomingCall.callerJID)); - - if (existingCall != null) - { - existingCall.Status = !incomingCall.accepted - ? eCodecCallStatus.Disconnected - : eCodecCallStatus.Connecting; - - OnCallStatusChange(existingCall); - } - - _waitingForUserToAcceptOrRejectIncomingCall = false; - - UpdateCallStatus(); - } - - break; - } - case "calldisconnect": - { - var disconnectEvent = - JsonConvert.DeserializeObject(responseObj.ToString()); - - Debug.Console(1, this, - "[DeserializeResponse] zEvent.calldisconnect ********************************************"); - Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect - disconnectEvent.Successful: {0}", - disconnectEvent.Successful); - - if (disconnectEvent.Successful) - { - if (ActiveCalls.Count > 0) - { - var activeCall = ActiveCalls.FirstOrDefault(c => c.IsActiveCall); - - if (activeCall != null) - { - Debug.Console(1, this, - "[DeserializeResponse] zEvent.calldisconnect - ActiveCalls.Count: {0} activeCall.Id: {1}, activeCall.Number: {2} activeCall.Name: {3}, activeCall.IsActive: {4}", - ActiveCalls.Count, activeCall.Id, activeCall.Number, activeCall.Name, activeCall.IsActiveCall); - activeCall.Status = eCodecCallStatus.Disconnected; - - OnCallStatusChange(activeCall); - } - } - } - - Debug.Console(1, this, - "[DeserializeResponse] zEvent.calldisconnect ********************************************"); - - UpdateCallStatus(); - break; - } - case "callconnecterror": - { - UpdateCallStatus(); - break; - } - case "videounmuterequest": - { - var handler = VideoUnmuteRequested; - - if (handler != null) - { - handler(this, null); - } - - break; - } - case "meetingneedspassword": - { - var meetingNeedsPassword = - responseObj.ToObject(); - - if (meetingNeedsPassword.NeedsPassword) - { - var prompt = "Password required to join this meeting. Please enter the meeting password."; - - OnPasswordRequired(meetingNeedsPassword.WrongAndRetry, false, false, prompt); - } - else - { - OnPasswordRequired(false, false, true, ""); - } - - break; - } - case "needwaitforhost": - { - Status.NeedWaitForHost = JsonConvert.DeserializeObject(responseObj.ToString()); - - Debug.Console(1, this, "WaitingForHost: {0}", Status.NeedWaitForHost.Wait); - - if (Status.NeedWaitForHost.Wait) - { - if (MeetingInfo == null) - { - MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", - GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); - - UpdateCallStatus(); - break; - } - - MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", - GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); - - UpdateCallStatus(); - - break; - } - - if (MeetingInfo == null) - { - MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", - GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); - break; - } - - MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, - GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); - - break; - } - case "openvideofailforhoststop": - { - // TODO: notify user that host has disabled unmuting video - break; - } - case "updatecallrecordinfo": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.CallRecordInfo); - - break; - } - case "recordingconsent": - { - _recordConsentPromptIsVisible = responseObj["isShow"].Value(); - RecordConsentPromptIsVisible.FireUpdate(); - break; - } - case "phonecallstatus": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall); - break; - } - case "pinstatusofscreennotification": - { - var status = responseObj.ToObject(); - - Debug.Console(1, this, "Pin Status notification for UserId: {0}, ScreenIndex: {1}", status.PinnedUserId, - status.ScreenIndex); - - Participant alreadyPinnedParticipant = null; - - // Check for a participant already pinned to the same screen index. - if (status.PinnedUserId > 0) - { - alreadyPinnedParticipant = - Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); - - // Make sure that the already pinned participant isn't the same ID as for this message. If true, clear the pinned fb. - if (alreadyPinnedParticipant != null && alreadyPinnedParticipant.UserId != status.PinnedUserId) - { - Debug.Console(1, this, "Participant: {0} with id: {1} already pinned to screenIndex {2}. Clearing pinned fb.", - alreadyPinnedParticipant.Name, alreadyPinnedParticipant.UserId, - alreadyPinnedParticipant.ScreenIndexIsPinnedToFb); - alreadyPinnedParticipant.IsPinnedFb = false; - alreadyPinnedParticipant.ScreenIndexIsPinnedToFb = -1; - } - } - - var participant = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(status.PinnedUserId)); - - if (participant != null) - { - participant.IsPinnedFb = true; - participant.ScreenIndexIsPinnedToFb = status.ScreenIndex; - } - else - { - participant = - Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); - - if (participant == null && alreadyPinnedParticipant == null) - { - Debug.Console(1, this, "no matching participant found by pinned_user_id: {0} or screen_index: {1}", - status.PinnedUserId, status.ScreenIndex); - return; - } - else if (participant != null) - { - Debug.Console(2, this, "Unpinning {0} with id: {1} from screen index: {2}", participant.Name, - participant.UserId, status.ScreenIndex); - participant.IsPinnedFb = false; - participant.ScreenIndexIsPinnedToFb = -1; - } - } - - // fire the event as we've modified the participants list - Participants.OnParticipantsChanged(); - - break; - } - case "startlocalpresentmeeting": - { - var result = JsonConvert.DeserializeObject(responseObj.ToString()); - - if (result.Success) - { - MeetingInfo = new MeetingInfo("", "", "", "", GetSharingStatus(), true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); - break; - } - - break; - } - default: - { - break; - } - } - break; - } - case eZoomRoomResponseType.zStatus: - { - switch (topKey.ToLower()) - { - case "login": - { - _syncState.LoginResponseReceived(); - - SetupSession(); - - JsonConvert.PopulateObject(responseObj.ToString(), Status.Login); - - break; - } - case "systemunit": - { - - JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit); - - break; - } - case "call": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call); - - Debug.Console(1, this, - "[DeserializeResponse] zStatus.call - Status.Call.Info.meeting_id: {0} Status.Call.Info.meeting_list_item.meetingName: {1}", - Status.Call.Info.meeting_id, Status.Call.Info.meeting_list_item.meetingName); - foreach (var participant in Status.Call.Participants) - { - Debug.Console(1, this, - "[DeserializeResponse] zStatus.call - Status.Call.Participants participant.UserId: {0} participant.UserName: {1}", - participant.UserId, participant.UserName); - } - - UpdateCallStatus(); - - break; - } - case "capabilities": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Capabilities); - break; - } - case "sharing": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Sharing); - - break; - } - case "numberofscreens": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.NumberOfScreens); - break; - } - case "video": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Video); - break; - } - case "camerashare": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.CameraShare); - break; - } - case "layout": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Layout); - break; - } - case "audio input line": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.AudioInputs); - break; - } - case "audio output line": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.AudioOuputs); - break; - } - case "video camera line": - { - Status.Cameras.Clear(); - - JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras); - - if (!_syncState.CamerasHaveBeenSetUp) - { - SetUpCameras(); - } - - break; - } - default: - { - break; - } - } - - break; - } - default: - { - Debug.Console(1, "Unknown Response Type:"); - break; - } - } - } - catch (Exception ex) - { - Debug.Console(1, this, "Error Deserializing feedback: {0}", ex.Message); - Debug.Console(2, this, "{0}", ex); - - if (ex.InnerException != null) - { - Debug.Console(1, this,"Error Deserializing feedback inner exception: {0}", ex.InnerException.Message); - Debug.Console(2, this, "{0}", ex.InnerException.StackTrace); - } - } - } - - private void SetDefaultLayout() - { - if (!_props.AutoDefaultLayouts) return; - - if ( - (Status.Call.Sharing.State == zEvent.eSharingState.Receiving || - Status.Call.Sharing.State == zEvent.eSharingState.Sending)) - { - SendText(String.Format("zconfiguration call layout style: {0}", - _props.DefaultSharingLayout)); - } - else - { - if (_props.DefaultCallLayout == (_props.DefaultCallLayout & AvailableLayouts)) - { - SendText(String.Format("zconfiguration call layout style: {0}", - _props.DefaultCallLayout)); - } - else - Debug.Console(0, this, "Unable to set default Layout. {0} not currently an available layout based on meeting state", _props.DefaultCallLayout); - } - } - - /// - /// Retrieves the current call participants list - /// - public void GetCurrentCallParticipants() - { - SendText("zCommand Call ListParticipants"); - } - - /// - /// Prints the current call particiapnts list - /// - public void PrintCurrentCallParticipants() - { - if (Debug.Level <= 0) return; - - Debug.Console(1, this, "*************************** Call Participants **************************"); - foreach (var participant in Participants.CurrentParticipants) - { - Debug.Console(1, this, "UserId: {3} Name: {0} Audio: {1} IsHost: {2}", - participant.Name, participant.AudioMuteFb, participant.IsHost, participant.UserId); - } - Debug.Console(1, this, "************************************************************************"); - } - - /// - /// Retrieves bookings list - /// - private void GetBookings() - { - if (_meetingPasswordRequired || _waitingForUserToAcceptOrRejectIncomingCall) return; - - SendText("zCommand Bookings List"); - } - - - /// - /// Updates the current call status - /// - private void UpdateCallStatus() - { - Debug.Console(1, this, - "[UpdateCallStatus] Current Call Status: {0} Active Call Count: {1} Need Wait For Host: {2}", - Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count, Status.NeedWaitForHost.Wait); - - if (Status.Call != null) - { - var callStatus = Status.Call.Status; - - // If not crrently in a meeting, intialize the call object - if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING) - { - Status.Call = new zStatus.Call {Status = callStatus}; - // Resubscribe to all property change events after Status.Call is reconstructed - SetUpCallFeedbackActions(); - - OnCallStatusChange(new CodecActiveCallItem() {Status = eCodecCallStatus.Disconnected}); - } - - if (ActiveCalls.Count == 0) - { - if (callStatus == zStatus.eCallStatus.CONNECTING_MEETING || - callStatus == zStatus.eCallStatus.IN_MEETING) - { - var newStatus = eCodecCallStatus.Unknown; - - switch (callStatus) - { - case zStatus.eCallStatus.CONNECTING_MEETING: - newStatus = eCodecCallStatus.Connecting; - break; - case zStatus.eCallStatus.IN_MEETING: - newStatus = eCodecCallStatus.Connected; - break; - } - - if (!string.IsNullOrEmpty(Status.Call.Info.meeting_id)) - { - var newCall = new CodecActiveCallItem - { - Name = Status.Call.Info.meeting_list_item.meetingName, - Number = Status.Call.Info.meeting_list_item.meetingNumber, - Id = Status.Call.Info.meeting_id, - Status = newStatus, - Type = eCodecCallType.Video, - }; - - if (!String.IsNullOrEmpty(_lastDialedMeetingNumber)) - { - _lastDialedMeetingNumber = String.Empty; - } - ActiveCalls.Add(newCall); - - OnCallStatusChange(newCall); - } else if (String.IsNullOrEmpty(Status.Call.Info.meeting_id) && Status.NeedWaitForHost.Wait) - { - var newCall = new CodecActiveCallItem - { - Name = "Waiting For Host", - Number = "Waiting For Host", - Id = "Waiting For Host", - Status = newStatus, - Type = eCodecCallType.Video, - }; - - if (!String.IsNullOrEmpty(_lastDialedMeetingNumber)) - { - _lastDialedMeetingNumber = String.Empty; - } - - ActiveCalls.Add(newCall); - - OnCallStatusChange(newCall); - } - } - } - else - { - var existingCall = ActiveCalls.FirstOrDefault(c => !c.Status.Equals(eCodecCallStatus.Ringing)); - - switch (callStatus) - { - case zStatus.eCallStatus.IN_MEETING: - if (Status.NeedWaitForHost.Wait) - { - Status.NeedWaitForHost.Wait = false; - } - existingCall.Status = eCodecCallStatus.Connected; - break; - case zStatus.eCallStatus.NOT_IN_MEETING: - if (Status.NeedWaitForHost.Wait) - { - Status.NeedWaitForHost.Wait = false; - } - existingCall.Status = eCodecCallStatus.Disconnected; - break; - } - - Debug.Console(1, this, "[UpdateCallStatus] ELSE ActiveCalls.Count == {1} - Current Call Status: {0}", - Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); - - - OnCallStatusChange(existingCall); - } - } - - Debug.Console(1, this, "[UpdateCallStatus] Active Calls ------------------------------"); - - // Clean up any disconnected calls left in the list - for (int i = 0; i < ActiveCalls.Count; i++) - { - var call = ActiveCalls[i]; - - Debug.Console(1, this, - @"ID: {1} - Number: {5} - Name: {0} - IsActive: {2} - Status: {3} - Direction: {4} - IsActiveCall: {6}", call.Name, call.Id, call.IsActiveCall, call.Status, call.Direction, call.Number, - call.IsActiveCall); - - if (!call.IsActiveCall) - { - Debug.Console(1, this, "[UpdateCallStatus] Removing Inactive call.Id: {1} call.Name: {0}", call.Name, call.Id); - ActiveCalls.Remove(call); - } - } - Debug.Console(1, this, "[UpdateCallStatus] Active Calls ------------------------------"); - - //clear participants list after call cleanup - var emptyList = new List(); - Participants.CurrentParticipants = emptyList; - if (ActiveCalls.Count > 0) GetCurrentCallParticipants(); - } - - protected override void OnCallStatusChange(CodecActiveCallItem item) - { - if (item.Status == eCodecCallStatus.Connected) - { - - var host = ""; - - if (Participants.Host != null) - host = Participants.Host.Name; - - MeetingInfo = new MeetingInfo( - Status.Call.Info.meeting_id, - Status.Call.Info.meeting_list_item.meetingName, - host, - Status.Call.Info.meeting_password, - GetSharingStatus(), - GetIsHostMyself(), - !String.Equals(Status.Call.Info.meeting_type,"NORMAL"), - false, - MeetingIsLockedFeedback.BoolValue, - MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord - ); - - SetDefaultLayout(); - } - - else if (item.Status == eCodecCallStatus.Disconnected) - { - MeetingInfo = new MeetingInfo( - string.Empty, - string.Empty, - string.Empty, - string.Empty, - string.Empty, - false, - false, - false, - false, - false, Status.Call.CallRecordInfo.AllowRecord - ); - } - - _meetingPasswordRequired = false; - base.OnCallStatusChange(item); - - Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}", - Status.Call != null ? Status.Call.Status.ToString() : "no call"); - } - - private string GetSharingStatus() - { - string sharingState = "None"; - - try - { - if (Status.Call.Sharing.State == zEvent.eSharingState.Receiving) - { - sharingState = "Receiving Content"; - } - if (Status.Sharing.isAirHostClientConnected) - { - sharingState = "Sharing AirPlay"; - } - if (Status.Sharing.isDirectPresentationConnected) - { - sharingState = "Sharing Laptop"; - } - if (Status.Sharing.isSharingBlackMagic) - { - sharingState = "Sharing HDMI Source"; - } - - return sharingState; - } - catch (Exception e) - { - Debug.Console(1, this, "Exception getting sharing status: {0}", e.Message); - Debug.Console(2, this, "{0}", e.StackTrace); - return sharingState; - } - } - - private void UpdateDirectory() - { - Debug.Console(2, this, "Updating directory"); - var directoryResults = zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); - - if (!PhonebookSyncState.InitialSyncComplete) - { - PhonebookSyncState.InitialPhonebookFoldersReceived(); - PhonebookSyncState.PhonebookRootEntriesReceived(); - PhonebookSyncState.SetPhonebookHasFolders(true); - PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); - } - - directoryResults.ResultsFolderId = "root"; - - DirectoryRoot = directoryResults; - - CurrentDirectoryResult = directoryResults; - - // - if (contactsDebounceTimer != null) - { - ClearContactDebounceTimer(); - } - } - - private void ClearContactDebounceTimer() - { - Debug.Console(2, this, "Clearing Timer"); - if (!contactsDebounceTimer.Disposed && contactsDebounceTimer != null) - { - contactsDebounceTimer.Dispose(); - contactsDebounceTimer = null; - } - } - - /// - /// Will return true if the host is myself (this zoom room) - /// - /// - private bool GetIsHostMyself() - { - try - { - if (Participants.CurrentParticipants.Count == 0) - { - Debug.Console(2, this, "No current participants"); - return false; - } - - var host = Participants.Host; - - if(host == null) - { - Debug.Console(2, this, "Host is currently null"); - return false; - } - Debug.Console(2, this, "Host is: '{0}' IsMyself?: {1}", host.Name, host.IsMyself); - return host.IsMyself; - } - catch (Exception e) - { - Debug.Console(1, "Exception getting isHost: {0}", e.Message); - Debug.Console(2, "{0}", e.StackTrace); - return false; - } - } - - /// - /// Starts sharing HDMI source - /// - public override void StartSharing() - { - SendText("zCommand Call Sharing HDMI Start"); - } - - /// - /// Stops sharing the current presentation - /// - public override void StopSharing() - { - if (Status.Sharing.isSharingBlackMagic) - { - SendText("zCommand Call Sharing HDMI Stop"); - } - else - { - SendText("zCommand Call Sharing Disconnect"); - } - } - - public override void PrivacyModeOn() - { - SendText("zConfiguration Call Microphone Mute: on"); - } - - public override void PrivacyModeOff() - { - SendText("zConfiguration Call Microphone Mute: off"); - } - - public override void PrivacyModeToggle() - { - if (PrivacyModeIsOnFeedback.BoolValue) - { - PrivacyModeOff(); - } - else - { - PrivacyModeOn(); - } - } - - public override void MuteOff() - { - Debug.Console(2, this, "Unmuting to previous level: {0}", _previousVolumeLevel); - SetVolume((ushort) _previousVolumeLevel); - } - - public override void MuteOn() - { - SetVolume(0); - } - - public override void MuteToggle() - { - if (MuteFeedback.BoolValue) - { - MuteOff(); - } - else - { - MuteOn(); - } - } - - - /// - /// Increments the voluem - /// - /// - public override void VolumeUp(bool pressRelease) - { - // TODO: Implment volume decrement that calls SetVolume() - } - - /// - /// Decrements the volume - /// - /// - public override void VolumeDown(bool pressRelease) - { - // TODO: Implment volume decrement that calls SetVolume() - } - - /// - /// Scales the level and sets the codec to the specified level within its range - /// - /// level from slider (0-65535 range) - public override void SetVolume(ushort level) - { - var scaledLevel = CrestronEnvironment.ScaleWithLimits(level, 65535, 0, 100, 0); - SendText(string.Format("zConfiguration Audio Output volume: {0}", scaledLevel)); - } - - /// - /// Recalls the default volume on the codec - /// - public void VolumeSetToDefault() - { - } - - /// - /// - /// - public override void StandbyActivate() - { - // No corresponding function on device - } - - /// - /// - /// - public override void StandbyDeactivate() - { - // No corresponding function on device - } - - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new ZoomRoomJoinMap(joinStart); - - var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); - - if (customJoins != null) - { - joinMap.SetCustomJoinData(customJoins); - } - - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - - LinkVideoCodecToApi(this, trilist, joinMap); - - LinkZoomRoomToApi(trilist, joinMap); - } - - /// - /// Links all the specific Zoom functionality to the API bridge - /// - /// - /// - public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap) - { - var meetingInfoCodec = this as IHasMeetingInfo; - if (meetingInfoCodec != null) - { - if (meetingInfoCodec.MeetingInfo != null) - { - trilist.SetBool(joinMap.MeetingCanRecord.JoinNumber, meetingInfoCodec.MeetingInfo.CanRecord); - } - - meetingInfoCodec.MeetingInfoChanged += (o, a) => - { - trilist.SetBool(joinMap.MeetingCanRecord.JoinNumber, a.Info.CanRecord); - }; - } - - var recordingCodec = this as IHasMeetingRecordingWithPrompt; - if (recordingCodec != null) - { - trilist.SetSigFalseAction(joinMap.StartRecording.JoinNumber, () => recordingCodec.StartRecording()); - trilist.SetSigFalseAction(joinMap.StopRecording.JoinNumber, () => recordingCodec.StopRecording()); - - recordingCodec.MeetingIsRecordingFeedback.LinkInputSig(trilist.BooleanInput[joinMap.StartRecording.JoinNumber]); - recordingCodec.MeetingIsRecordingFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.StopRecording.JoinNumber]); - - trilist.SetSigFalseAction(joinMap.RecordingPromptAgree.JoinNumber, () => recordingCodec.RecordingPromptAcknowledgement(true)); - trilist.SetSigFalseAction(joinMap.RecordingPromptDisagree.JoinNumber, () => recordingCodec.RecordingPromptAcknowledgement(false)); - - recordingCodec.RecordConsentPromptIsVisible.LinkInputSig(trilist.BooleanInput[joinMap.RecordConsentPromptIsVisible.JoinNumber]); - } - - var layoutsCodec = this as IHasZoomRoomLayouts; - if (layoutsCodec != null) - { - layoutsCodec.LayoutInfoChanged += (o, a) => - { - trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber, - zConfiguration.eLayoutStyle.Gallery == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Gallery)); - - trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber, - zConfiguration.eLayoutStyle.Speaker == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Speaker)); - - - - trilist.SetBool(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip - == - (a.AvailableLayouts & zConfiguration.eLayoutStyle.Strip)); - trilist.SetBool(joinMap.LayoutShareAllIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.ShareAll - == - (a.AvailableLayouts & - zConfiguration.eLayoutStyle.ShareAll)); - - // pass the names used to set the layout through the bridge - trilist.SetString(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery.ToString()); - trilist.SetString(joinMap.LayoutSpeakerIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Speaker.ToString()); - trilist.SetString(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip.ToString()); - trilist.SetString(joinMap.LayoutShareAllIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.ShareAll.ToString()); - }; - - trilist.SetSigFalseAction(joinMap.SwapContentWithThumbnail.JoinNumber, () => layoutsCodec.SwapContentWithThumbnail()); - - layoutsCodec.CanSwapContentWithThumbnailFeedback.LinkInputSig( - trilist.BooleanInput[joinMap.CanSwapContentWithThumbnail.JoinNumber]); - layoutsCodec.ContentSwappedWithThumbnailFeedback.LinkInputSig( - trilist.BooleanInput[joinMap.SwapContentWithThumbnail.JoinNumber]); - - layoutsCodec.LayoutViewIsOnFirstPageFeedback.LinkInputSig( - trilist.BooleanInput[joinMap.LayoutIsOnFirstPage.JoinNumber]); - layoutsCodec.LayoutViewIsOnLastPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnLastPage.JoinNumber]); - trilist.SetSigFalseAction(joinMap.LayoutTurnToNextPage.JoinNumber, () => layoutsCodec.LayoutTurnNextPage()); - trilist.SetSigFalseAction(joinMap.LayoutTurnToPreviousPage.JoinNumber, () => layoutsCodec.LayoutTurnPreviousPage()); - trilist.SetSigFalseAction(joinMap.GetAvailableLayouts.JoinNumber, () => layoutsCodec.GetAvailableLayouts()); - - trilist.SetStringSigAction(joinMap.GetSetCurrentLayout.JoinNumber, (s) => - { - try - { - var style = (zConfiguration.eLayoutStyle) Enum.Parse(typeof (zConfiguration.eLayoutStyle), s, true); - SetLayout(style); - } - catch (Exception e) - { - Debug.Console(1, this, "Unable to parse '{0}' to zConfiguration.eLayoutStyle: {1}", s, e); - } - }); - - layoutsCodec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); - } - - var pinCodec = this as IHasParticipantPinUnpin; - if (pinCodec != null) - { - pinCodec.NumberOfScreensFeedback.LinkInputSig(trilist.UShortInput[joinMap.NumberOfScreens.JoinNumber]); - - // Set the value of the local property to be used when pinning a participant - trilist.SetUShortSigAction(joinMap.ScreenIndexToPinUserTo.JoinNumber, (u) => ScreenIndexToPinUserTo = u); - } - - var layoutSizeCodec = this as IHasSelfviewSize; - if (layoutSizeCodec != null) - { - trilist.SetSigFalseAction(joinMap.GetSetSelfviewPipSize.JoinNumber, layoutSizeCodec.SelfviewPipSizeToggle); - trilist.SetStringSigAction(joinMap.GetSetSelfviewPipSize.JoinNumber, (s) => - { - try - { - var size = (zConfiguration.eLayoutSize) Enum.Parse(typeof (zConfiguration.eLayoutSize), s, true); - var cmd = SelfviewPipSizes.FirstOrDefault(c => c.Command.Equals(size.ToString())); - SelfviewPipSizeSet(cmd); - } - catch (Exception e) - { - Debug.Console(1, this, "Unable to parse '{0}' to zConfiguration.eLayoutSize: {1}", s, e); - } - }); - - layoutSizeCodec.SelfviewPipSizeFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetSelfviewPipSize.JoinNumber]); - } - - MeetingInfoChanged += (device, args) => - { - trilist.SetString(joinMap.MeetingInfoId.JoinNumber, args.Info.Id); - trilist.SetString(joinMap.MeetingInfoHost.JoinNumber, args.Info.Host); - trilist.SetString(joinMap.MeetingInfoPassword.JoinNumber, args.Info.Password); - trilist.SetBool(joinMap.IsHost.JoinNumber, args.Info.IsHost); - trilist.SetBool(joinMap.ShareOnlyMeeting.JoinNumber, args.Info.IsSharingMeeting); - trilist.SetBool(joinMap.WaitingForHost.JoinNumber, args.Info.WaitingForHost); - //trilist.SetString(joinMap.CurrentSource.JoinNumber, args.Info.ShareStatus); - }; - - trilist.SetSigFalseAction(joinMap.StartMeetingNow.JoinNumber, () => StartMeeting(0)); - trilist.SetSigFalseAction(joinMap.ShareOnlyMeeting.JoinNumber, StartSharingOnlyMeeting); - trilist.SetSigFalseAction(joinMap.StartNormalMeetingFromSharingOnlyMeeting.JoinNumber, StartNormalMeetingFromSharingOnlyMeeting); - - trilist.SetStringSigAction(joinMap.SubmitPassword.JoinNumber, SubmitPassword); - - // Subscribe to call status to clear ShowPasswordPrompt when in meeting - this.CallStatusChange += (o, a) => - { - if (a.CallItem.Status == eCodecCallStatus.Connected || a.CallItem.Status == eCodecCallStatus.Disconnected) - { - trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false); - } - - }; - - trilist.SetSigFalseAction(joinMap.CancelJoinAttempt.JoinNumber, () => { - trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false); - EndAllCalls(); - }); - - PasswordRequired += (devices, args) => - { - Debug.Console(2, this, "***********************************PaswordRequired. Message: {0} Cancelled: {1} Last Incorrect: {2} Failed: {3}", args.Message, args.LoginAttemptCancelled, args.LastAttemptWasIncorrect, args.LoginAttemptFailed); - - if (args.LoginAttemptCancelled) - { - trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false); - return; - } - - if (!string.IsNullOrEmpty(args.Message)) - { - trilist.SetString(joinMap.PasswordPromptMessage.JoinNumber, args.Message); - } - - if (args.LoginAttemptFailed) - { - // login attempt failed - return; - } - - trilist.SetBool(joinMap.PasswordIncorrect.JoinNumber, args.LastAttemptWasIncorrect); - trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, true); - }; - - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; - - ComputeAvailableLayouts(); - layoutsCodec.LocalLayoutFeedback.FireUpdate(); - layoutsCodec.CanSwapContentWithThumbnailFeedback.FireUpdate(); - layoutsCodec.ContentSwappedWithThumbnailFeedback.FireUpdate(); - layoutsCodec.LayoutViewIsOnFirstPageFeedback.FireUpdate(); - layoutsCodec.LayoutViewIsOnLastPageFeedback.FireUpdate(); - pinCodec.NumberOfScreensFeedback.FireUpdate(); - layoutSizeCodec.SelfviewPipSizeFeedback.FireUpdate(); - }; - - var wirelessInfoCodec = this as IZoomWirelessShareInstructions; - if (wirelessInfoCodec != null) - { - if (Status != null && Status.Sharing != null) - { - SetSharingStateJoins(Status.Sharing, trilist, joinMap); - } - - wirelessInfoCodec.ShareInfoChanged += (o, a) => - { - SetSharingStateJoins(a.SharingStatus, trilist, joinMap); - }; - } - } - - void SetSharingStateJoins(zStatus.Sharing state, BasicTriList trilist, ZoomRoomJoinMap joinMap) - { - trilist.SetBool(joinMap.IsSharingAirplay.JoinNumber, state.isAirHostClientConnected); - trilist.SetBool(joinMap.IsSharingHdmi.JoinNumber, state.isBlackMagicConnected || state.isDirectPresentationConnected); - - trilist.SetString(joinMap.DisplayState.JoinNumber, state.dispState.ToString()); - trilist.SetString(joinMap.AirplayShareCode.JoinNumber, state.password); - trilist.SetString(joinMap.LaptopShareKey.JoinNumber, state.directPresentationSharingKey); - trilist.SetString(joinMap.WifiName.JoinNumber, state.wifiName); - trilist.SetString(joinMap.ServerName.JoinNumber, state.serverName); - } - - public override void ExecuteSwitch(object selector) - { - var action = selector as Action; - if (action == null) - { - return; - } - - action(); - } - - public void AcceptCall() - { - _waitingForUserToAcceptOrRejectIncomingCall = false; - - var incomingCall = - ActiveCalls.FirstOrDefault( - c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); - - AcceptCall(incomingCall); - } - - public override void AcceptCall(CodecActiveCallItem call) - { - _waitingForUserToAcceptOrRejectIncomingCall = false; - - SendText(string.Format("zCommand Call Accept callerJID: {0}", call.Id)); - - call.Status = eCodecCallStatus.Connected; - - OnCallStatusChange(call); - - UpdateCallStatus(); - } - - public void RejectCall() - { - _waitingForUserToAcceptOrRejectIncomingCall = false; - - var incomingCall = - ActiveCalls.FirstOrDefault( - c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); - - RejectCall(incomingCall); - } - - public override void RejectCall(CodecActiveCallItem call) - { - _waitingForUserToAcceptOrRejectIncomingCall = false; - - SendText(string.Format("zCommand Call Reject callerJID: {0}", call.Id)); - - call.Status = eCodecCallStatus.Disconnected; - - OnCallStatusChange(call); - - UpdateCallStatus(); - } - - public override void Dial(Meeting meeting) - { - Debug.Console(1, this, "Dialing meeting.Id: {0} Title: {1}", meeting.Id, meeting.Title); - _lastDialedMeetingNumber = meeting.Id; - SendText(string.Format("zCommand Dial Start meetingNumber: {0}", meeting.Id)); - } - - public override void Dial(string number) - { - Debug.Console(2, this, "Dialing number: {0}", number); - _lastDialedMeetingNumber = number; - SendText(string.Format("zCommand Dial Join meetingNumber: {0}", number)); - } - - /// - /// Dials a meeting with a password - /// - /// - /// - public void Dial(string number, string password) - { - Debug.Console(2, this, "Dialing meeting number: {0} with password: {1}", number, password); - SendText(string.Format("zCommand Dial Join meetingNumber: {0} password: {1}", number, password)); - } - - /// - /// Invites a contact to either a new meeting (if not already in a meeting) or the current meeting. - /// Currently only invites a single user - /// - /// - public override void Dial(IInvitableContact contact) - { - var ic = contact as InvitableDirectoryContact; - - if (ic != null) - { - Debug.Console(1, this, "Attempting to Dial (Invite): {0}", ic.Name); - - if (!IsInCall) - { - SendText(string.Format("zCommand Invite Duration: {0} user: {1}", DefaultMeetingDurationMin, - ic.ContactId)); - } - else - { - SendText(string.Format("zCommand Call invite user: {0}", ic.ContactId)); - } - } - } - - /// - /// Invites contacts to a new meeting for a specified duration - /// - /// - /// - public void InviteContactsToNewMeeting(List contacts, uint duration) - { - if(duration == 0) - { - duration = DefaultMeetingDurationMin; - } - - StringBuilder message = new StringBuilder(); - - // Add the prefix - message.Append(string.Format("zCommand Invite Duration: {0}", duration)); - - // Add each invitee - foreach (var contact in contacts) - { - var invitee = string.Format(" user: {0}", contact.ContactId); - - message.Append(invitee); - } - - SendText(message.ToString()); - } - - /// - /// Invites contacts to an existing meeting - /// - /// - public void InviteContactsToExistingMeeting(List contacts) - { - StringBuilder message = new StringBuilder(); - - // Add the prefix - message.Append(string.Format("zCommand Call Invite")); - - // Add each invitee - foreach (var contact in contacts) - { - var invitee = string.Format(" user: {0}", contact.ContactId); - - message.Append(invitee); - } - - SendText(message.ToString()); - } - - - /// - /// Starts a PMI Meeting for the specified duration (or default meeting duration if 0 is specified) - /// - /// duration of meeting - public void StartMeeting(uint duration) - { - uint dur = DefaultMeetingDurationMin; - - if (duration > 0) - dur = duration; - - SendText(string.Format("zCommand Dial StartPmi Duration: {0}", dur)); - } - - public void LeaveMeeting() - { - _meetingPasswordRequired = false; - _waitingForUserToAcceptOrRejectIncomingCall = false; - - SendText("zCommand Call Leave"); - } - - public override void EndCall(CodecActiveCallItem call) - { - _meetingPasswordRequired = false; - _waitingForUserToAcceptOrRejectIncomingCall = false; - - SendText("zCommand Call Disconnect"); - } - - public override void EndAllCalls() - { - _meetingPasswordRequired = false; - _waitingForUserToAcceptOrRejectIncomingCall = false; - - SendText("zCommand Call Disconnect"); - } - - public override void SendDtmf(string s) - { - SendDtmfToPhone(s); - } - - /// - /// Call when directory results are updated - /// - /// - private void OnDirectoryResultReturned(CodecDirectory result) - { - try - { - Debug.Console(2, this, "OnDirectoryResultReturned. Result has {0} contacts", result.Contacts.Count); - - CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); - - var directoryResult = result; - var directoryIsRoot = CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false; - - // If result is Root, create a copy and filter out contacts whose parent folder is not root - //if (!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue) - //{ - // Debug.Console(2, this, "Filtering DirectoryRoot to remove contacts for display"); - - // directoryResult.ResultsFolderId = result.ResultsFolderId; - // directoryResult.AddFoldersToDirectory(result.Folders); - // directoryResult.AddContactsToDirectory( - // result.Contacts.Where((c) => c.ParentFolderId == result.ResultsFolderId).ToList()); - //} - //else - //{ - // directoryResult = result; - //} - - Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0} Contact Count: {1}", - directoryIsRoot, directoryResult.Contacts.Count); - - // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology - var handler = DirectoryResultReturned; - if (handler != null) - { - handler(this, new DirectoryEventArgs - { - Directory = directoryResult, - DirectoryIsOnRoot = directoryIsRoot - }); - } - - - } - catch (Exception e) - { - Debug.Console(2, this, "Error: {0}", e); - } - - //PrintDirectory(result); - } - - /// - /// Builds the cameras List by using the Zoom Room zStatus.Cameras data. Could later be modified to build from config data - /// - private void SetUpCameras() - { - SelectedCameraFeedback = new StringFeedback(() => Configuration.Video.Camera.SelectedId); - - ControllingFarEndCameraFeedback = new BoolFeedback(() => SelectedCamera is IAmFarEndCamera); - - foreach (var cam in Status.Cameras) - { - // Known Issue: - // Crestron UC engine systems seem to report an item in the cameras list that represnts the USB bridge device. - // If we know the name and it's reliably consistent, we could ignore it here... - - if (cam.Name.IndexOf("HD-CONV-USB") > -1) - { - // Skip this as it's the Crestron USB box, not a real camera - continue; - } - - var existingCam = Cameras.FirstOrDefault((c) => c.Key.Equals(cam.id)); - - if (existingCam == null) - { - var camera = new ZoomRoomCamera(cam.id, cam.Name, this); - - Cameras.Add(camera); - - if (cam.Selected) - { - SelectedCamera = camera; - } - } - } - - if (IsInCall) - { - UpdateFarEndCameras(); - } - - _syncState.CamerasSetUp(); - } - - /// - /// Dynamically creates far end cameras for call participants who have far end control enabled. - /// - private void UpdateFarEndCameras() - { - // TODO: set up far end cameras for the current call - } - - #region Implementation of IHasParticipants - - public CodecParticipants Participants { get; private set; } - - public void RemoveParticipant(int userId) - { - SendText(string.Format("zCommand Call Expel Id: {0}", userId)); - } - - public void SetParticipantAsHost(int userId) - { - SendText(string.Format("zCommand Call HostChange Id: {0}", userId)); - } - - public void AdmitParticipantFromWaitingRoom(int userId) - { - SendText(string.Format("zCommand Call Admit Participant Id: {0}", userId)); - } - - #endregion - - #region IHasParticipantAudioMute Members - - public void MuteAudioForAllParticipants() - { - SendText(string.Format("zCommand Call MuteAll Mute: on")); - } - - public void MuteAudioForParticipant(int userId) - { - SendText(string.Format("zCommand Call MuteParticipant Mute: on Id: {0}", userId)); - } - - public void UnmuteAudioForParticipant(int userId) - { - SendText(string.Format("zCommand Call MuteParticipant Mute: off Id: {0}", userId)); - } - - public void ToggleAudioForParticipant(int userId) - { - var user = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(userId)); - - if (user == null) - { - Debug.Console(2, this, "Unable to find user with id: {0}", userId); - return; - } - - if (user.AudioMuteFb) - { - UnmuteAudioForParticipant(userId); - } - else - { - MuteAudioForParticipant(userId); - } - } - - #endregion - - #region IHasParticipantVideoMute Members - - public void MuteVideoForParticipant(int userId) - { - SendText(string.Format("zCommand Call MuteParticipantVideo Mute: on Id: {0}", userId)); - } - - public void UnmuteVideoForParticipant(int userId) - { - SendText(string.Format("zCommand Call MuteParticipantVideo Mute: off Id: {0}", userId)); - } - - public void ToggleVideoForParticipant(int userId) - { - var user = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(userId)); - - if (user == null) - { - Debug.Console(2, this, "Unable to find user with id: {0}", userId); - return; - } - - if (user.VideoMuteFb) - { - UnmuteVideoForParticipant(userId); - } - else - { - MuteVideoForParticipant(userId); - } - } - - #endregion - - #region IHasParticipantPinUnpin Members - - private Func NumberOfScreensFeedbackFunc - { - get { return () => Status.NumberOfScreens.NumOfScreens; } - } - - public IntFeedback NumberOfScreensFeedback { get; private set; } - - public int ScreenIndexToPinUserTo { get; private set; } - - public void PinParticipant(int userId, int screenIndex) - { - SendText(string.Format("zCommand Call Pin Id: {0} Enable: on Screen: {1}", userId, screenIndex)); - } - - public void UnPinParticipant(int userId) - { - SendText(string.Format("zCommand Call Pin Id: {0} Enable: off", userId)); - } - - public void ToggleParticipantPinState(int userId, int screenIndex) - { - var user = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(userId)); - - if (user == null) - { - Debug.Console(2, this, "Unable to find user with id: {0}", userId); - return; - } - - if (user.IsPinnedFb) - { - UnPinParticipant(userId); - } - else - { - PinParticipant(userId, screenIndex); - } - } - - #endregion - - #region Implementation of IHasCameraOff - - public BoolFeedback CameraIsOffFeedback { get; private set; } - - public void CameraOff() - { - CameraMuteOn(); - } - - #endregion - - public BoolFeedback CameraIsMutedFeedback { get; private set; } - - public void CameraMuteOn() - { - SendText("zConfiguration Call Camera Mute: On"); - } - - public void CameraMuteOff() - { - SendText("zConfiguration Call Camera Mute: Off"); - } - - public void CameraMuteToggle() - { - if (CameraIsMutedFeedback.BoolValue) - CameraMuteOff(); - else - CameraMuteOn(); - } - - #region Implementation of IHasCameraAutoMode - - //Zoom doesn't support camera auto modes. Setting this to just unmute video - public void CameraAutoModeOn() - { - CameraMuteOff(); - throw new NotImplementedException("Zoom Room Doesn't support camera auto mode"); - } - - //Zoom doesn't support camera auto modes. Setting this to just unmute video - public void CameraAutoModeOff() - { - SendText("zConfiguration Call Camera Mute: Off"); - } - - public void CameraAutoModeToggle() - { - throw new NotImplementedException("Zoom Room doesn't support camera auto mode"); - } - - public BoolFeedback CameraAutoModeIsOnFeedback { get; private set; } - - #endregion - - #region Implementation of IHasFarEndContentStatus - - public BoolFeedback ReceivingContent { get; private set; } - - #endregion - - #region Implementation of IHasSelfviewPosition - - private CodecCommandWithLabel _currentSelfviewPipPosition; - - public StringFeedback SelfviewPipPositionFeedback { get; private set; } - - public void SelfviewPipPositionSet(CodecCommandWithLabel position) - { - SendText(String.Format("zConfiguration Call Layout Position: {0}", position.Command)); - } - - public void SelfviewPipPositionToggle() - { - if (_currentSelfviewPipPosition != null) - { - var nextPipPositionIndex = SelfviewPipPositions.IndexOf(_currentSelfviewPipPosition) + 1; - - if (nextPipPositionIndex >= SelfviewPipPositions.Count) - // Check if we need to loop back to the first item in the list - nextPipPositionIndex = 0; - - SelfviewPipPositionSet(SelfviewPipPositions[nextPipPositionIndex]); - } - } - - public List SelfviewPipPositions = new List() - { - new CodecCommandWithLabel("UpLeft", "Center Left"), - new CodecCommandWithLabel("UpRight", "Center Right"), - new CodecCommandWithLabel("DownRight", "Lower Right"), - new CodecCommandWithLabel("DownLeft", "Lower Left") - }; - - private void ComputeSelfviewPipPositionStatus() - { - _currentSelfviewPipPosition = - SelfviewPipPositions.FirstOrDefault( - p => p.Command.ToLower().Equals(Configuration.Call.Layout.Position.ToString().ToLower())); - } - - #endregion - - // TODO: #714 [ ] Implementation of IHasSelfviewPipSize - - #region Implementation of IHasSelfviewPipSize - - private CodecCommandWithLabel _currentSelfviewPipSize; - - public StringFeedback SelfviewPipSizeFeedback { get; private set; } - - public void SelfviewPipSizeSet(CodecCommandWithLabel size) - { - SendText(String.Format("zConfiguration Call Layout Size: {0}", size.Command)); - } - - public void SelfviewPipSizeToggle() - { - if (_currentSelfviewPipSize != null) - { - var nextPipSizeIndex = SelfviewPipSizes.IndexOf(_currentSelfviewPipSize) + 1; - - if (nextPipSizeIndex >= SelfviewPipSizes.Count) - // Check if we need to loop back to the first item in the list - nextPipSizeIndex = 0; - - SelfviewPipSizeSet(SelfviewPipSizes[nextPipSizeIndex]); - } - } - - public List SelfviewPipSizes = new List() - { - new CodecCommandWithLabel("Off", "Off"), - new CodecCommandWithLabel("Size1", "Size 1"), - new CodecCommandWithLabel("Size2", "Size 2"), - new CodecCommandWithLabel("Size3", "Size 3"), - new CodecCommandWithLabel("Strip", "Strip") - }; - - private void ComputeSelfviewPipSizeStatus() - { - _currentSelfviewPipSize = - SelfviewPipSizes.FirstOrDefault( - p => p.Command.ToLower().Equals(Configuration.Call.Layout.Size.ToString().ToLower())); - } - - #endregion - - #region Implementation of IHasPhoneDialing - - private Func PhoneOffHookFeedbackFunc - { - get { return () => Status.PhoneCall.OffHook; } - } - - private Func CallerIdNameFeedbackFunc - { - get { return () => Status.PhoneCall.PeerDisplayName; } - } - - private Func CallerIdNumberFeedbackFunc - { - get { return () => Status.PhoneCall.PeerNumber; } - } - - public BoolFeedback PhoneOffHookFeedback { get; private set; } - public StringFeedback CallerIdNameFeedback { get; private set; } - public StringFeedback CallerIdNumberFeedback { get; private set; } - - public void DialPhoneCall(string number) - { - SendText(String.Format("zCommand Dial PhoneCallOut Number: {0}", number)); - } - - public void EndPhoneCall() - { - SendText(String.Format("zCommand Dial PhoneHangUp CallId: {0}", Status.PhoneCall.CallId)); - } - - public void SendDtmfToPhone(string digit) - { - SendText(String.Format("zCommand SendSipDTMF CallId: {0} Key: {1}", Status.PhoneCall.CallId, digit)); - } - - #endregion - - #region IHasZoomRoomLayouts Members - - public event EventHandler LayoutInfoChanged; - - private Func LayoutViewIsOnFirstPageFeedbackFunc - { - get { return () => Status.Layout.is_In_First_Page; } - } - - private Func LayoutViewIsOnLastPageFeedbackFunc - { - get { return () => Status.Layout.is_In_Last_Page; } - } - - private Func CanSwapContentWithThumbnailFeedbackFunc - { - get { return () => Status.Layout.can_Switch_Floating_Share_Content; } - } - - private Func ContentSwappedWithThumbnailFeedbackFunc - { - get { return () => Configuration.Call.Layout.ShareThumb; } - } - - public BoolFeedback LayoutViewIsOnFirstPageFeedback { get; private set; } - - public BoolFeedback LayoutViewIsOnLastPageFeedback { get; private set; } - - public BoolFeedback CanSwapContentWithThumbnailFeedback { get; private set; } - - public BoolFeedback ContentSwappedWithThumbnailFeedback { get; private set; } - - - public zConfiguration.eLayoutStyle LastSelectedLayout { get; private set; } - - public zConfiguration.eLayoutStyle AvailableLayouts { get; private set; } - - /// - /// Reads individual properties to determine if which layouts are avalailable - /// - private void ComputeAvailableLayouts() - { - Debug.Console(1, this, "Computing available layouts..."); - zConfiguration.eLayoutStyle availableLayouts = zConfiguration.eLayoutStyle.None; - if (Status.Layout.can_Switch_Wall_View) - { - availableLayouts |= zConfiguration.eLayoutStyle.Gallery; - } - - if (Status.Layout.can_Switch_Speaker_View) - { - availableLayouts |= zConfiguration.eLayoutStyle.Speaker; - } - - if (Status.Layout.can_Switch_Share_On_All_Screens) - { - availableLayouts |= zConfiguration.eLayoutStyle.ShareAll; - } - - // There is no property that directly reports if strip mode is valid, but API stipulates - // that strip mode is available if the number of screens is 1 - if (Status.NumberOfScreens.NumOfScreens == 1 || Status.Layout.can_Switch_Strip_View || Status.Layout.video_type.ToLower() == "strip") - { - availableLayouts |= zConfiguration.eLayoutStyle.Strip; - } - - Debug.Console(1, this, "availablelayouts: {0}", availableLayouts); - - AvailableLayouts = availableLayouts; - } - - private void OnLayoutInfoChanged() - { - var handler = LayoutInfoChanged; - if (handler != null) - { - - var currentLayout = zConfiguration.eLayoutStyle.None; - - currentLayout = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle), string.IsNullOrEmpty(LocalLayoutFeedback.StringValue) ? "None" : LocalLayoutFeedback.StringValue, true); - - handler(this, new LayoutInfoChangedEventArgs() - { - AvailableLayouts = AvailableLayouts, - CurrentSelectedLayout = currentLayout, - LayoutViewIsOnFirstPage = LayoutViewIsOnFirstPageFeedback.BoolValue, - LayoutViewIsOnLastPage = LayoutViewIsOnLastPageFeedback.BoolValue, - CanSwapContentWithThumbnail = CanSwapContentWithThumbnailFeedback.BoolValue, - ContentSwappedWithThumbnail = ContentSwappedWithThumbnailFeedback.BoolValue, - }); - } - } - - public void GetAvailableLayouts() - { - SendText("zStatus Call Layout"); - } - - public void SetLayout(zConfiguration.eLayoutStyle layoutStyle) - { - LastSelectedLayout = layoutStyle; - SendText(String.Format("zConfiguration Call Layout Style: {0}", layoutStyle.ToString())); - } - - public void SwapContentWithThumbnail() - { - if (CanSwapContentWithThumbnailFeedback.BoolValue) - { - var oppositeValue = ContentSwappedWithThumbnailFeedback.BoolValue ? "on" : "off"; - // Get the value based on the opposite of the current state - // TODO: #697 [*] Need to verify the ternary above and make sure that the correct on/off value is being send based on the true/false value of the feedback - // to toggle the state - SendText(String.Format("zConfiguration Call Layout ShareThumb: {0}", oppositeValue)); - } - } - - public void LayoutTurnNextPage() - { - SendText("zCommand Call Layout TurnPage Forward: On"); - } - - public void LayoutTurnPreviousPage() - { - SendText("zCommand Call Layout TurnPage Forward: Off"); - } - - #endregion - - #region IHasCodecLayouts Members - - private Func LocalLayoutFeedbackFunc - { - get - { - return () => - { - if (Configuration.Call.Layout.Style != zConfiguration.eLayoutStyle.None) - return Configuration.Call.Layout.Style.ToString(); - else - return Configuration.Client.Call.Layout.Style.ToString(); - }; - } - } - - public StringFeedback LocalLayoutFeedback { get; private set; } - - public void LocalLayoutToggle() - { - var currentLayout = LocalLayoutFeedback.StringValue; - - var eCurrentLayout = (int) Enum.Parse(typeof (zConfiguration.eLayoutStyle), currentLayout, true); - - var nextLayout = GetNextLayout(eCurrentLayout); - - if (nextLayout != zConfiguration.eLayoutStyle.None) - { - SetLayout(nextLayout); - } - } - - /// - /// Tries to get the next available layout - /// - /// - /// - private zConfiguration.eLayoutStyle GetNextLayout(int currentLayout) - { - if (AvailableLayouts == zConfiguration.eLayoutStyle.None) - { - return zConfiguration.eLayoutStyle.None; - } - - zConfiguration.eLayoutStyle nextLayout; - - if (((zConfiguration.eLayoutStyle) currentLayout & zConfiguration.eLayoutStyle.ShareAll) == - zConfiguration.eLayoutStyle.ShareAll) - { - nextLayout = zConfiguration.eLayoutStyle.Gallery; - } - else - { - nextLayout = (zConfiguration.eLayoutStyle) (currentLayout << 1); - } - - if ((AvailableLayouts & nextLayout) == nextLayout) - { - return nextLayout; - } - else - { - return GetNextLayout((int) nextLayout); - } - } - - public void LocalLayoutToggleSingleProminent() - { - throw new NotImplementedException(); - } - - public void MinMaxLayoutToggle() - { - throw new NotImplementedException(); - } - - #endregion - - #region IPasswordPrompt Members - - public event EventHandler PasswordRequired; - - public void SubmitPassword(string password) - { - _meetingPasswordRequired = false; - Debug.Console(2, this, "Password Submitted: {0}", password); - Dial(_lastDialedMeetingNumber, password); - } - - void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) - { - _meetingPasswordRequired = !loginFailed || !loginCancelled; - - var handler = PasswordRequired; - if (handler != null) - { - Debug.Console(2, this, "Meeting Password Required: {0}", _meetingPasswordRequired); - - handler(this, new PasswordPromptEventArgs(lastAttemptIncorrect, loginFailed, loginCancelled, message)); - } - } - - #endregion - - #region IHasMeetingInfo Members - - public event EventHandler MeetingInfoChanged; - - private MeetingInfo _meetingInfo; - - public MeetingInfo MeetingInfo - { - get { return _meetingInfo; } - private set - { - if (value != _meetingInfo) - { - _meetingInfo = value; - - var handler = MeetingInfoChanged; - if (handler != null) - { - handler(this, new MeetingInfoEventArgs(_meetingInfo)); - } - } - } - } - - #endregion - - #region Implementation of IHasPresentationOnlyMeeting - - public void StartSharingOnlyMeeting() - { - StartSharingOnlyMeeting(eSharingMeetingMode.None, 30, String.Empty); - } - - public void StartSharingOnlyMeeting(eSharingMeetingMode displayMode) - { - StartSharingOnlyMeeting(displayMode, DefaultMeetingDurationMin, String.Empty); - } - - public void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration) - { - StartSharingOnlyMeeting(displayMode, duration, String.Empty); - } - - public void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration, string password) - { - SendText(String.Format("zCommand Dial Sharing Duration: {0} DisplayState: {1} Password: {2}", duration, displayMode, password)); - } - - public void StartNormalMeetingFromSharingOnlyMeeting() - { - Debug.Console(2, this, "Converting Sharing Meeting to Normal Meeting"); - SendText("zCommand call sharing ToNormal"); - } - - #endregion - - #region IHasMeetingLock Members - - public BoolFeedback MeetingIsLockedFeedback { get; private set; } - - public void LockMeeting() - { - SendText(string.Format("zConfiguration Call Lock Enable: on")); - } - - public void UnLockMeeting() - { - SendText(string.Format("zConfiguration Call Lock Enable: off")); - } - - public void ToggleMeetingLock() - { - if (MeetingIsLockedFeedback.BoolValue) - { - UnLockMeeting(); - } - else - { - LockMeeting(); - } - } - - #endregion - - #region IHasMeetingRecordingWithPrompt Members - - public BoolFeedback MeetingIsRecordingFeedback { get; private set; } - - bool _recordConsentPromptIsVisible; - - public BoolFeedback RecordConsentPromptIsVisible { get; private set; } - - public void RecordingPromptAcknowledgement(bool agree) - { - var command = string.Format("zCommand Agree Recording: {0}", agree ? "on" : "off"); - //Debug.Console(2, this, "Sending agree: {0} {1}", agree, command); - SendText(command); - } - - public void StartRecording() - { - SendText(string.Format("zCommand Call Record Enable: on")); - } - - public void StopRecording() - { - SendText(string.Format("zCommand Call Record Enable: off")); - } - - public void ToggleRecording() - { - if (MeetingIsRecordingFeedback.BoolValue) - { - StopRecording(); - } - else - { - StartRecording(); - } - } - - #endregion - - #region IZoomWirelessShareInstructions Members - - public event EventHandler ShareInfoChanged; - - public zStatus.Sharing SharingState - { - get - { - return Status.Sharing; - } - } - - void OnShareInfoChanged(zStatus.Sharing status) - { - Debug.Console(2, this, -@"ShareInfoChanged: -isSharingHDMI: {0} -isSharingAirplay: {1} -AirplayPassword: {2} -OSD Display State: {3} -", -status.isSharingBlackMagic, -status.isAirHostClientConnected, -status.password, -status.dispState); - - var handler = ShareInfoChanged; - if (handler != null) - { - handler(this, new ShareInfoEventArgs(status)); - } - } - - #endregion - } - - /// - /// Zoom Room specific info object - /// - public class ZoomRoomInfo : VideoCodecInfo - { - public ZoomRoomInfo(ZoomRoomStatus status, ZoomRoomConfiguration configuration) - { - Status = status; - Configuration = configuration; - } - - [JsonIgnore] - public ZoomRoomStatus Status { get; private set; } - [JsonIgnore] - public ZoomRoomConfiguration Configuration { get; private set; } - - public override bool AutoAnswerEnabled - { - get { return Status.SystemUnit.RoomInfo.AutoAnswerIsEnabled; } - } - - public override string E164Alias - { - get - { - if (!string.IsNullOrEmpty(Status.SystemUnit.MeetingNumber)) - { - return Status.SystemUnit.MeetingNumber; - } - return string.Empty; - } - } - - public override string H323Id - { - get - { - if (!string.IsNullOrEmpty(Status.Call.Info.meeting_list_item.third_party.h323_address)) - { - return Status.Call.Info.meeting_list_item.third_party.h323_address; - } - return string.Empty; - } - } - - public override string IpAddress - { - get - { - if (!string.IsNullOrEmpty(Status.SystemUnit.RoomInfo.AccountEmail)) - { - return Status.SystemUnit.RoomInfo.AccountEmail; - } - return string.Empty; - } - } - - public override bool MultiSiteOptionIsEnabled - { - get { return true; } - } - - public override string SipPhoneNumber - { - get - { - if (!string.IsNullOrEmpty(Status.Call.Info.dialIn)) - { - return Status.Call.Info.dialIn; - } - return string.Empty; - } - } - - public override string SipUri - { - get - { - if (!string.IsNullOrEmpty(Status.Call.Info.meeting_list_item.third_party.sip_address)) - { - return Status.Call.Info.meeting_list_item.third_party.sip_address; - } - return string.Empty; - } - } - } - - /// - /// Tracks the initial sycnronization state when establishing a new connection - /// - public class ZoomRoomSyncState : IKeyed - { - private readonly ZoomRoom _parent; - private readonly CrestronQueue _syncQueries; - private bool _initialSyncComplete; - - public ZoomRoomSyncState(string key, ZoomRoom parent) - { - _parent = parent; - Key = key; - _syncQueries = new CrestronQueue(50); - CodecDisconnected(); - } - - public bool InitialSyncComplete - { - get { return _initialSyncComplete; } - private set - { - if (value) - { - var handler = InitialSyncCompleted; - if (handler != null) - { - handler(this, new EventArgs()); - } - } - _initialSyncComplete = value; - } - } - - public bool LoginResponseWasReceived { get; private set; } - - public bool FirstJsonResponseWasReceived { get; private set; } - - public bool InitialQueryMessagesWereSent { get; private set; } - - public bool LastQueryResponseWasReceived { get; private set; } - - public bool CamerasHaveBeenSetUp { get; private set; } - - #region IKeyed Members - - public string Key { get; private set; } - - #endregion - - public event EventHandler InitialSyncCompleted; - - public event EventHandler FirstJsonResponseReceived; - - public void StartSync() - { - DequeueQueries(); - } - - private void DequeueQueries() - { - while (!_syncQueries.IsEmpty) - { - var query = _syncQueries.Dequeue(); - - _parent.SendText(query); - } - - InitialQueryMessagesSent(); - } - - public void AddQueryToQueue(string query) - { - _syncQueries.Enqueue(query); - } - - public void LoginResponseReceived() - { - LoginResponseWasReceived = true; - Debug.Console(1, this, "Login Rsponse Received."); - CheckSyncStatus(); - } - - public void ReceivedFirstJsonResponse() - { - FirstJsonResponseWasReceived = true; - Debug.Console(1, this, "First JSON Response Received."); - - var handler = FirstJsonResponseReceived; - if (handler != null) - { - handler(this, null); - } - CheckSyncStatus(); - } - - public void InitialQueryMessagesSent() - { - InitialQueryMessagesWereSent = true; - Debug.Console(1, this, "Query Messages Sent."); - CheckSyncStatus(); - } - - public void LastQueryResponseReceived() - { - LastQueryResponseWasReceived = true; - Debug.Console(1, this, "Last Query Response Received."); - CheckSyncStatus(); - } - - public void CamerasSetUp() - { - CamerasHaveBeenSetUp = true; - Debug.Console(1, this, "Cameras Set Up."); - CheckSyncStatus(); - } - - public void CodecDisconnected() - { - _syncQueries.Clear(); - LoginResponseWasReceived = false; - FirstJsonResponseWasReceived = false; - InitialQueryMessagesWereSent = false; - LastQueryResponseWasReceived = false; - CamerasHaveBeenSetUp = false; - InitialSyncComplete = false; - } - - private void CheckSyncStatus() - { - if (LoginResponseWasReceived && FirstJsonResponseWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived && - CamerasHaveBeenSetUp) - { - InitialSyncComplete = true; - Debug.Console(1, this, "Initial Codec Sync Complete!"); - } - else - { - InitialSyncComplete = false; - } - } - } - - public class ZoomRoomFactory : EssentialsDeviceFactory - { - public ZoomRoomFactory() - { - TypeNames = new List {"zoomroom"}; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.Console(1, "Factory Attempting to create new ZoomRoom Device"); - var comm = CommFactory.CreateCommForDevice(dc); - return new ZoomRoom(dc, comm); - } - } -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs deleted file mode 100644 index bb0abeea..00000000 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs +++ /dev/null @@ -1,231 +0,0 @@ -extern alias Full; - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro.DeviceSupport; -using PepperDash.Essentials.Core.Bridges; -using PepperDash.Essentials.Devices.Common.Cameras; - -using Full.Newtonsoft.Json; - -namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom -{ - public enum eZoomRoomCameraState - { - Start, - Continue, - Stop, - RequestRemote, - GiveupRemote, - RequestedByFarEnd - } - - public enum eZoomRoomCameraAction - { - Left, - Right, - Up, - Down, - In, - Out - } - - - public class ZoomRoomCamera : CameraBase, IHasCameraPtzControl, IBridgeAdvanced - { - protected ZoomRoom ParentCodec { get; private set; } - - [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] - public int? Id = 0; // ID of near end selected camara is always 0 - - private int ContinueTime = 10; // number of milliseconds between issuing continue commands - - private CTimer ContinueTimer; - - eZoomRoomCameraAction LastAction; - - private bool isPanning; - - private bool isTilting; - - private bool isZooming; - - //private bool isFocusing; - - private bool isMoving - { - get - { - return isPanning || isTilting || isZooming; - - } - } - - public ZoomRoomCamera(string key, string name, ZoomRoom codec) - : base(key, name) - { - ParentCodec = codec; - - Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom; - } - - /// - /// Builds the command and triggers the parent ZoomRoom to send it - /// - /// - /// - void SendCommand(eZoomRoomCameraState state, eZoomRoomCameraAction action) - { - LastAction = action; - ParentCodec.SendText(string.Format("zCommand Call CameraControl Id: {0} State: {1} Action: {2}", Id, state, action)); - } - - void StartContinueTimer() - { - if (ContinueTimer == null) - ContinueTimer = new CTimer((o) => SendContinueAction(LastAction), null, ContinueTime, ContinueTime); - } - - void SendContinueAction(eZoomRoomCameraAction action) - { - SendCommand(eZoomRoomCameraState.Continue, action); - } - - void StopContinueTimer() - { - if (ContinueTimer == null) - { - return; - } - - ContinueTimer.Stop(); - ContinueTimer.Dispose(); - ContinueTimer = null; - } - - #region IHasCameraPtzControl Members - - public void PositionHome() - { - throw new NotImplementedException(); - } - - #endregion - - #region IHasCameraPanControl Members - - public void PanLeft() - { - if (isMoving) - { - return; - } - - SendCommand(eZoomRoomCameraState.Start, eZoomRoomCameraAction.Left); - StartContinueTimer(); - isPanning = true; - } - - public void PanRight() - { - if (isMoving) - { - return; - } - - SendCommand(eZoomRoomCameraState.Start, eZoomRoomCameraAction.Right); - StartContinueTimer(); - isPanning = true; - } - - public void PanStop() - { - StopContinueTimer(); - SendCommand(eZoomRoomCameraState.Stop, LastAction); - isPanning = false; - } - - #endregion - - #region IHasCameraTiltControl Members - - public void TiltDown() - { - if (!isMoving) - { - SendCommand(eZoomRoomCameraState.Start, eZoomRoomCameraAction.Down); - StartContinueTimer(); - isTilting = true; - } - } - - public void TiltUp() - { - if (!isMoving) - { - SendCommand(eZoomRoomCameraState.Start, eZoomRoomCameraAction.Up); - StartContinueTimer(); - isTilting = true; - } - } - - public void TiltStop() - { - StopContinueTimer(); - SendCommand(eZoomRoomCameraState.Stop, LastAction); - isTilting = false; - } - - #endregion - - #region IHasCameraZoomControl Members - - public void ZoomIn() - { - if (!isMoving) - { - SendCommand(eZoomRoomCameraState.Start, eZoomRoomCameraAction.In); - StartContinueTimer(); - isZooming = true; - } - } - - public void ZoomOut() - { - if (!isMoving) - { - SendCommand(eZoomRoomCameraState.Start, eZoomRoomCameraAction.Out); - StartContinueTimer(); - isZooming = true; - } - } - - public void ZoomStop() - { - StopContinueTimer(); - SendCommand(eZoomRoomCameraState.Stop, LastAction); - isZooming = false; - } - - #endregion - - public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge); - } - } - - public class ZoomRoomFarEndCamera : ZoomRoomCamera, IAmFarEndCamera - { - - public ZoomRoomFarEndCamera(string key, string name, ZoomRoom codec, int id) - : base(key, name, codec) - { - Id = id; - } - - } -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs deleted file mode 100644 index bb6bf90f..00000000 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs +++ /dev/null @@ -1,706 +0,0 @@ -using System; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Bridges.JoinMaps; - -namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom -{ - public class ZoomRoomJoinMap : VideoCodecControllerJoinMap - { - #region Digital - - [JoinName("CancelJoinAttempt")] - public JoinDataComplete CancelJoinAttempt = new JoinDataComplete( - new JoinData - { - JoinNumber = 5, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to hide the password prompt", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MeetingPasswordRequired")] - public JoinDataComplete MeetingPasswordRequired = new JoinDataComplete( - new JoinData - { - JoinNumber = 6, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "FB Indicates to show the password prompt", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("PasswordIncorrect")] - public JoinDataComplete PasswordIncorrect = new JoinDataComplete( - new JoinData - { - JoinNumber = 7, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "FB Indicates the password entered is incorrect", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("PasswordLoginFailed")] - public JoinDataComplete PasswordLoginFailed = new JoinDataComplete( - new JoinData - { - JoinNumber = 8, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "FB Indicates the password entered is incorrect", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("WaitingForHost")] - public JoinDataComplete WaitingForHost = new JoinDataComplete( - new JoinData - { - JoinNumber = 9, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "FB Indicates system is waiting for host", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IsHost")] - public JoinDataComplete IsHost = new JoinDataComplete( - new JoinData - { - JoinNumber = 10, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "FB Indicates system is the host", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("StartMeetingNow")] - public JoinDataComplete StartMeetingNow = new JoinDataComplete( - new JoinData - { - JoinNumber = 25, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to start an ad-hoc meeting with the default duration", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ShareOnlyMeeting")] - public JoinDataComplete ShareOnlyMeeting = new JoinDataComplete( - new JoinData - { - JoinNumber = 26, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Triggers a share only meeting, feedback indicates the current meeting is share only", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("StartNormalMeetingFromSharingOnlyMeeting")] - public JoinDataComplete StartNormalMeetingFromSharingOnlyMeeting = new JoinDataComplete( - new JoinData - { - JoinNumber = 27, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Starts a normal meeting from a share only meeting", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CanSwapContentWithThumbnail")] - public JoinDataComplete CanSwapContentWithThumbnail = new JoinDataComplete( - new JoinData - { - JoinNumber = 206, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "FB Indicates if content can be swapped with thumbnail", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SwapContentWithThumbnail")] - public JoinDataComplete SwapContentWithThumbnail = new JoinDataComplete( - new JoinData - { - JoinNumber = 206, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to swap content with thumbnail. FB reports current state", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("GetAvailableLayouts")] - public JoinDataComplete GetAvailableLayouts = new JoinDataComplete( - new JoinData - { - JoinNumber = 215, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Gets the available layouts. Will update the LayoutXXXXXIsAvailbale signals.", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("LayoutIsOnFirstPage")] - public JoinDataComplete LayoutIsOnFirstPage = new JoinDataComplete( - new JoinData - { - JoinNumber = 216, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Indicates if layout is on first page", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("LayoutIsOnLastPage")] - public JoinDataComplete LayoutIsOnLastPage = new JoinDataComplete( - new JoinData - { - JoinNumber = 217, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Indicates if layout is on first page", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("LayoutTurnToNextPage")] - public JoinDataComplete LayoutTurnToNextPage = new JoinDataComplete( - new JoinData - { - JoinNumber = 216, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Turns layout view to next page", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("LayoutTurnToPreviousPage")] - public JoinDataComplete LayoutTurnToPreviousPage = new JoinDataComplete( - new JoinData - { - JoinNumber = 217, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Turns layout view to previous page", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("LayoutGalleryIsAvailable")] - public JoinDataComplete LayoutGalleryIsAvailable = new JoinDataComplete( - new JoinData - { - JoinNumber = 221, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "FB Indicates if layout 'Gallery' is available", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.DigitalSerial - }); - - [JoinName("LayoutSpeakerIsAvailable")] - public JoinDataComplete LayoutSpeakerIsAvailable = new JoinDataComplete( - new JoinData - { - JoinNumber = 222, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "FB Indicates if layout 'Speaker' is available", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.DigitalSerial - }); - - [JoinName("LayoutStripIsAvailable")] - public JoinDataComplete LayoutStripIsAvailable = new JoinDataComplete( - new JoinData - { - JoinNumber = 223, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "FB Indicates if layout 'Strip' is available", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.DigitalSerial - }); - - [JoinName("LayoutShareAllIsAvailable")] - public JoinDataComplete LayoutShareAllIsAvailable = new JoinDataComplete( - new JoinData - { - JoinNumber = 224, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "FB Indicates if layout 'ShareAll' is available", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.DigitalSerial - }); - - // TODO: #714 [ ] JoinMap >> SelfivewPipSizeToggle - [JoinName("SelfviewPipSizeToggle")] - public JoinDataComplete SelfviewPipSizeToggle = new JoinDataComplete( - new JoinData - { - JoinNumber = 231, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Toggles the selfview pip size, (aka layout size)", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("StartRecording")] - public JoinDataComplete StartRecording = new JoinDataComplete( - new JoinData - { - JoinNumber = 241, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to start the Meeting Recording. FB high if meeting is currently recording", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("StopRecording")] - public JoinDataComplete StopRecording = new JoinDataComplete( - new JoinData - { - JoinNumber = 242, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to stop the Meeting Recording. FB high if meeting is currently NOT recording", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("RecordConsentPromptIsVisible")] - public JoinDataComplete RecordConsentPromptIsVisible = new JoinDataComplete( - new JoinData - { - JoinNumber = 243, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "When high, indicates that the recording consent prompt is visible on the ZoomRoom UI", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("RecordingPromptAgree")] - public JoinDataComplete RecordingPromptAgree = new JoinDataComplete( - new JoinData - { - JoinNumber = 244, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to agree to consent for meeting recording", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("RecordingPromptDisagree")] - public JoinDataComplete RecordingPromptDisagree = new JoinDataComplete( - new JoinData - { - JoinNumber = 245, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to disagree to consent for meeting recording", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MeetingCanRecord")] - public JoinDataComplete MeetingCanRecord = new JoinDataComplete( - new JoinData - { - JoinNumber = 246, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "When high, indicated that the current meeting can be recorded", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - - #region Sharing Status - - [JoinName("IsSharingAirplay")] - public JoinDataComplete IsSharingAirplay = new JoinDataComplete( - new JoinData - { - JoinNumber = 250, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Indicates an Airplay source is sharing", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IsSharingHdmi")] - public JoinDataComplete IsSharingHdmi = new JoinDataComplete( - new JoinData - { - JoinNumber = 251, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Indicates an HDMI source is sharing", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - - - #endregion - //[JoinName("ParticipantAudioMuteToggleStart")] - //public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( - // new JoinData - // { - // JoinNumber = 500, - // JoinSpan = 100 - // }, - // new JoinMetadata - // { - // Description = "Toggles the participant's audio mute status", - // JoinCapabilities = eJoinCapabilities.ToSIMPL, - // JoinType = eJoinType.Digital - // }); - - //[JoinName("ParticipantVideoMuteToggleStart")] - //public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( - // new JoinData - // { - // JoinNumber = 800, - // JoinSpan = 100 - // }, - // new JoinMetadata - // { - // Description = "Toggles the participant's video mute status", - // JoinCapabilities = eJoinCapabilities.ToSIMPL, - // JoinType = eJoinType.Digital - // }); - - //[JoinName("ParticipantPinToggleStart")] - //public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( - // new JoinData - // { - // JoinNumber = 1100, - // JoinSpan = 100 - // }, - // new JoinMetadata - // { - // Description = "Toggles the participant's pin status", - // JoinCapabilities = eJoinCapabilities.ToSIMPL, - // JoinType = eJoinType.Digital - // }); - - #endregion - - - #region Analog - - [JoinName("NumberOfScreens")] - public JoinDataComplete NumberOfScreens = new JoinDataComplete( - new JoinData - { - JoinNumber = 11, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reports the number of screens connected", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("ScreenIndexToPinUserTo")] - public JoinDataComplete ScreenIndexToPinUserTo = new JoinDataComplete( - new JoinData - { - JoinNumber = 11, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Specifies the screen index a participant should be pinned to", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - #endregion - - - #region Serials - - // TODO [ ] Issue #868 - [JoinName("SubmitPassword")] - public JoinDataComplete SubmitPassword = new JoinDataComplete( - new JoinData - { - JoinNumber = 6, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Submit password text", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - // TODO [ ] Issue #868 - [JoinName("PasswordPromptMessage")] - public JoinDataComplete PasswordPromptMessage = new JoinDataComplete( - new JoinData - { - JoinNumber = 6, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Password prompt message", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - // TODO [ ] Issue #868 - [JoinName("MeetingInfoId")] - public JoinDataComplete MeetingInfoId = new JoinDataComplete( - new JoinData - { - JoinNumber = 11, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Meeting info ID text feedback", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - // TODO [ ] Issue #868 - [JoinName("MeetingInfoHostt")] - public JoinDataComplete MeetingInfoHost = new JoinDataComplete( - new JoinData - { - JoinNumber = 12, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Meeting info Host text feedback", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - // TODO [ ] Issue #868 - [JoinName("MeetingInfoPassword")] - public JoinDataComplete MeetingInfoPassword = new JoinDataComplete( - new JoinData - { - JoinNumber = 13, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Meeting info Password text feedback", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("GetSetCurrentLayout")] - public JoinDataComplete GetSetCurrentLayout = new JoinDataComplete( - new JoinData - { - JoinNumber = 215, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Sets and reports the current layout. Use the LayoutXXXXIsAvailable signals to determine valid layouts", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - - // TODO: #714 [ ] JoinMap >> GetSetSelfviewPipSize - [JoinName("GetSetSelfviewPipSize")] - public JoinDataComplete GetSetSelfviewPipSize = new JoinDataComplete( - new JoinData - { - JoinNumber = 230, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Sets and reports the selfview pip size, (aka layout size).", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.DigitalSerial - }); - - [JoinName("DisplayState")] - public JoinDataComplete DisplayState = new JoinDataComplete( - new JoinData - { - JoinNumber = 250, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reports the instructions the ZoomRoom is displaying on the monitor. ", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("AirplayShareCode")] - public JoinDataComplete AirplayShareCode = new JoinDataComplete( - new JoinData - { - JoinNumber = 251, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reports the current code for Airplay Sharing.", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("LaptopShareKey")] - public JoinDataComplete LaptopShareKey = new JoinDataComplete( - new JoinData - { - JoinNumber = 252, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "The alpha-only sharing key that users type into a laptop client to share with the Zoom Room.", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("LaptopSharePairingCode")] - public JoinDataComplete LaptopSharePairingCode = new JoinDataComplete( - new JoinData - { - JoinNumber = 253, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "This is the paring code that is broadcast via an ultrasonic signal from the ZRC. It is different than the user-supplied paring code. The ZRC uses a Zoom-proprietary method of advertizing the ultrasonic pairing code, so it\'s not possible to advertize it using commonly available libraries.", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("WifiName")] - public JoinDataComplete WifiName = new JoinDataComplete( - new JoinData - { - JoinNumber = 254, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reports the Wifi SSID used by the ZoomRoom.", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("ServerName")] - public JoinDataComplete ServerName = new JoinDataComplete( - new JoinData - { - JoinNumber = 255, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reports the namne of the the ZoomRoom.", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - - - #endregion - - public ZoomRoomJoinMap(uint joinStart) - : base(joinStart, typeof(ZoomRoomJoinMap)) - { - } - - public ZoomRoomJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } - } -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs deleted file mode 100644 index e0d10f75..00000000 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs +++ /dev/null @@ -1,46 +0,0 @@ -extern alias Full; - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Full.Newtonsoft.Json; -using Full.Newtonsoft.Json.Converters; -using PepperDash.Core; -using PepperDash.Essentials.Core; - -namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom -{ - public class ZoomRoomPropertiesConfig - { - [JsonProperty("communicationMonitorProperties")] - public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; } - - [JsonProperty("disablePhonebookAutoDownload")] - public bool DisablePhonebookAutoDownload { get; set; } - - [JsonProperty("supportsCameraAutoMode")] - public bool SupportsCameraAutoMode { get; set; } - - [JsonProperty("supportsCameraOff")] - public bool SupportsCameraOff { get; set; } - - //if true, the layouts will be set automatically when sharing starts/ends or a call is joined - [JsonProperty("autoDefaultLayouts")] - public bool AutoDefaultLayouts { get; set; } - - /* This layout will be selected when Sharing starts (either from Far end or locally)*/ - [JsonProperty("defaultSharingLayout")] - [JsonConverter(typeof(StringEnumConverter))] - public zConfiguration.eLayoutStyle DefaultSharingLayout { get; set; } - - //This layout will be selected when a call is connected and no content is being shared - [JsonProperty("defaultCallLayout")] - [JsonConverter(typeof(StringEnumConverter))] - public zConfiguration.eLayoutStyle DefaultCallLayout { get; set; } - - [JsonProperty("minutesBeforeMeetingStart")] - public int MinutesBeforeMeetingStart { get; set; } - } -} \ No newline at end of file