From f583b849518c88cb3cee35be397cfe7ad9b7ad04 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 16 Sep 2020 16:32:03 -0600 Subject: [PATCH 01/42] Add VideoCodecControllerJoinMap --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs new file mode 100644 index 00000000..80d7016f --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -0,0 +1,136 @@ +using System; +using PepperDash.Essentials.Core; + +namespace PepperDash_Essentials_Core.Bridges.JoinMaps +{ + public class VideoCodecControllerJoinMap:JoinMapBaseAdvanced + { + #region Status + + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData {JoinNumber = 1, JoinSpan = 1}, + new JoinMetadata + { + Description = "Device is Online", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + #endregion + + + #region NearEndCameraControls + + public JoinDataComplete NearEndCameraUp = new JoinDataComplete(new JoinData {JoinNumber = 11, JoinSpan = 1}, + new JoinMetadata + { + Description = "Near Camera Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + public JoinDataComplete NearEndCameraDown = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Near Camera Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + public JoinDataComplete NearEndCameraLeft = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Near Camera Left", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + public JoinDataComplete NearEndCameraRight = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Near Camera Right", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + public JoinDataComplete NearEndCameraZoomIn = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Near Camera Zoom In", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + public JoinDataComplete NearEndCameraZoomOut = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Near Camera Zoom Out", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + public JoinDataComplete NearEndCameraFocusNear = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Near Camera Focus Near", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + public JoinDataComplete NearEndCameraFocusFar = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Near Camera Right", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + public JoinDataComplete NearEndCameraSelectSerial = new JoinDataComplete( + new JoinData {JoinNumber = 11, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Select & Feedback by name", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + public JoinDataComplete NearEndCameraSelectAnalog = new JoinDataComplete( + new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Select & Feedback by index", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + + + #endregion + #region Camera Tracking Controls + + public JoinDataComplete CameraTrackingOn = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Tracking On", + JoinType = eJoinType.Digital, + JoinCapabilities = eJoinCapabilities.ToFromSIMPL}); + + public JoinDataComplete CameraTrackingOff = new JoinDataComplete(new JoinData {JoinNumber = 12, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Tracking Off", + JoinType = eJoinType.Digital, + JoinCapabilities = eJoinCapabilities.ToFromSIMPL + }); + + public JoinDataComplete CameraTrackingToggle = new JoinDataComplete( + new JoinData {JoinNumber = 13, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Tracking Toggle", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + #endregion + + public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart) + { + } + + public VideoCodecControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) + { + } + } +} \ No newline at end of file From a203eef9a6e73c7cfa8aaac625ee9e8b0ca86021 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 16 Sep 2020 16:33:16 -0600 Subject: [PATCH 02/42] clean up and organize --- .../PepperDash_Essentials_Core.csproj | 7 +- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 1504 +++++++++-------- 2 files changed, 790 insertions(+), 721 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index ae420105..83916856 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -98,12 +98,12 @@ False - ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll False False - ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll False @@ -113,7 +113,7 @@ False - ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe False @@ -158,6 +158,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 2f834c36..179b4001 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -4,45 +4,102 @@ using System.Linq; using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharpPro.CrestronThread; - using Newtonsoft.Json; using Newtonsoft.Json.Linq; - using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; -using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { - public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectory, ICommunicationMonitor, IRouting, IHasScheduleAwareness, IHasCodecCameras + public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectory, ICommunicationMonitor, IRouting, + IHasScheduleAwareness, IHasCodecCameras { + private readonly CrestronQueue ReceiveQueue; + + private readonly Thread ReceiveThread; + + private readonly ZoomRoomSyncState SyncState; + public bool CommDebuggingIsOn; + private uint DefaultMeetingDurationMin = 30; + private string Delimiter = "\x0D\x0A"; + private uint JsonCurlyBraceCounter = 0; + private bool JsonFeedbackMessageIsIncoming; + private StringBuilder JsonMessage; + private int PreviousVolumeLevel = 0; + private CameraBase _selectedCamera; + + public ZoomRoom(DeviceConfig config, IBasicCommunication comm) + : base(config) + { + var props = JsonConvert.DeserializeObject(config.Properties.ToString()); + + // The queue that will collect the repsonses in the order they are received + ReceiveQueue = new CrestronQueue(25); + + // The thread responsible for dequeuing and processing the messages + ReceiveThread = new Thread((o) => ProcessQueue(), null); + ReceiveThread.Priority = Thread.eThreadPriority.MediumPriority; + + Communication = comm; + + if (props.CommunicationMonitorProperties != null) + { + CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, + props.CommunicationMonitorProperties); + } + else + { + CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, + "zStatus SystemUnit\r"); + } + + DeviceManager.AddDevice(CommunicationMonitor); + + Status = new ZoomRoomStatus(); + + Configuration = new ZoomRoomConfiguration(); + + CodecInfo = new ZoomRoomInfo(Status, Configuration); + + SyncState = new ZoomRoomSyncState(Key + "--Sync", this); + + SyncState.InitialSyncCompleted += new EventHandler(SyncState_InitialSyncCompleted); + + PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); + + PortGather = new CommunicationGather(Communication, "\x0A"); + PortGather.IncludeDelimiter = true; + PortGather.LineReceived += this.Port_LineReceived; + + CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, + eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this); + + Output1 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, + eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, null, this); + + SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); + + CodecSchedule = new CodecScheduleAwareness(); + + SetUpFeedbackActions(); + + Cameras = new List(); + + SetUpDirectory(); + } + public CommunicationGather PortGather { get; private set; } - public StatusMonitorBase CommunicationMonitor { get; private set; } - - private CrestronQueue ReceiveQueue; - - private Thread ReceiveThread; - - string Delimiter = "\x0D\x0A"; - - private ZoomRoomSyncState SyncState; - public ZoomRoomStatus Status { get; private set; } public ZoomRoomConfiguration Configuration { get; private set; } - private StringBuilder JsonMessage; - - private bool JsonFeedbackMessageIsIncoming; - private uint JsonCurlyBraceCounter = 0; - - public bool CommDebuggingIsOn; - //CTimer LoginMessageReceivedTimer; //CTimer RetryConnectionTimer; @@ -59,50 +116,32 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom protected override Func PrivacyModeIsOnFeedbackFunc { - get - { - return () => Configuration.Call.Microphone.Mute; - } + get { return () => Configuration.Call.Microphone.Mute; } } protected override Func StandbyIsOnFeedbackFunc { - get - { - return () => false; - } + get { return () => false; } } protected override Func SharingSourceFeedbackFunc { - get - { - return () => Status.Sharing.dispState; - } + get { return () => Status.Sharing.dispState; } } protected override Func SharingContentIsOnFeedbackFunc { - get - { - return () => Status.Call.Sharing.IsSharing; - } + get { return () => Status.Call.Sharing.IsSharing; } } protected Func FarEndIsSharingContentFeedbackFunc { - get - { - return () => false; - } + get { return () => false; } } protected override Func MuteFeedbackFunc { - get - { - return () => Configuration.Audio.Output.Volume == 0; - } + get { return () => Configuration.Audio.Output.Volume == 0; } } //protected Func RoomIsOccupiedFeedbackFunc @@ -123,103 +162,214 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom protected Func SelfViewIsOnFeedbackFunc { - get - { - return () => !Configuration.Video.HideConfSelfVideo; - } + get { return () => !Configuration.Video.HideConfSelfVideo; } } protected Func SelfviewPipPositionFeedbackFunc { - get - { - return () => ""; - } + get { return () => ""; } } protected Func LocalLayoutFeedbackFunc { - get - { - return () => ""; - } + get { return () => ""; } } protected Func LocalLayoutIsProminentFeedbackFunc { - get - { - return () => false; - } + get { return () => false; } } public RoutingInputPort CodecOsdIn { get; private set; } public RoutingOutputPort Output1 { get; private set; } - uint DefaultMeetingDurationMin = 30; + #region ICommunicationMonitor Members - int PreviousVolumeLevel = 0; + public StatusMonitorBase CommunicationMonitor { get; private set; } - public ZoomRoom(DeviceConfig config, IBasicCommunication comm) - : base(config) + #endregion + + #region IHasCodecCameras Members + + public event EventHandler CameraSelected; + + public List Cameras { get; private set; } + + public CameraBase SelectedCamera { - var props = JsonConvert.DeserializeObject(config.Properties.ToString()); - - // The queue that will collect the repsonses in the order they are received - ReceiveQueue = new CrestronQueue(25); - - // The thread responsible for dequeuing and processing the messages - ReceiveThread = new Thread((o) => ProcessQueue(), null); - ReceiveThread.Priority = Thread.eThreadPriority.MediumPriority; - - Communication = comm; - - if (props.CommunicationMonitorProperties != null) + get { return _selectedCamera; } + private set { - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties); + _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 (Cameras != null) + { + var camera = Cameras.FirstOrDefault(c => c.Key.IndexOf(key, StringComparison.OrdinalIgnoreCase) > -1); + if (camera != null) + { + Debug.Console(1, this, "Selected Camera with key: '{0}'", camera.Key); + SelectedCamera = camera; + } + else + { + Debug.Console(1, this, "Unable to select camera with key: '{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 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 { - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, "zStatus SystemUnit\r"); + SelfViewModeOn(); } - - DeviceManager.AddDevice(CommunicationMonitor); - - Status = new ZoomRoomStatus(); - - Configuration = new ZoomRoomConfiguration(); - - CodecInfo = new ZoomRoomInfo(Status, Configuration); - - SyncState = new ZoomRoomSyncState(Key + "--Sync", this); - - SyncState.InitialSyncCompleted += new EventHandler(SyncState_InitialSyncCompleted); - - PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); - - PortGather = new CommunicationGather(Communication, "\x0A"); - PortGather.IncludeDelimiter = true; - PortGather.LineReceived += this.Port_LineReceived; - - CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this); - - Output1 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - - SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); - - CodecSchedule = new CodecScheduleAwareness(); - - SetUpFeedbackActions(); - - Cameras = new List(); - - SetUpDirectory(); } - void SyncState_InitialSyncCompleted(object sender, EventArgs e) + #endregion + + #region IHasDirectory Members + + public event EventHandler DirectoryResultReturned; + public CodecDirectory DirectoryRoot { get; private set; } + + public CodecDirectory CurrentDirectoryResult + { + get + { + if (DirectoryBrowseHistory.Count > 0) + { + return DirectoryBrowseHistory[DirectoryBrowseHistory.Count - 1]; + } + else + { + return DirectoryRoot; + } + } + } + + 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)); + + DirectoryBrowseHistory.Add(directoryResults); + + OnDirectoryResultReturned(directoryResults); + } + + public void GetDirectoryFolderContents(string folderId) + { + var directoryResults = new CodecDirectory(); + + directoryResults.ResultsFolderId = folderId; + directoryResults.AddContactsToDirectory( + DirectoryRoot.CurrentDirectoryResults.FindAll(c => c.FolderId.Equals(folderId))); + + DirectoryBrowseHistory.Add(directoryResults); + + OnDirectoryResultReturned(directoryResults); + } + + public void SetCurrentDirectoryToRoot() + { + DirectoryBrowseHistory.Clear(); + + OnDirectoryResultReturned(DirectoryRoot); + } + + public void GetDirectoryParentFolderContents() + { + var currentDirectory = new CodecDirectory(); + + if (DirectoryBrowseHistory.Count > 0) + { + var lastItemIndex = DirectoryBrowseHistory.Count - 1; + var parentDirectoryContents = DirectoryBrowseHistory[lastItemIndex]; + + DirectoryBrowseHistory.Remove(DirectoryBrowseHistory[lastItemIndex]); + + currentDirectory = parentDirectoryContents; + } + else + { + currentDirectory = DirectoryRoot; + } + + OnDirectoryResultReturned(currentDirectory); + } + + public BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; private set; } + + public List DirectoryBrowseHistory { 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) { SetUpRouting(); @@ -230,7 +380,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// /// Subscribes to the PropertyChanged events on the state objects and fires the corresponding feedbacks. /// - void SetUpFeedbackActions() + private void SetUpFeedbackActions() { Configuration.Audio.Output.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler( (o, a) => @@ -264,7 +414,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { if (a.PropertyName == "SelectedId") { - SelectCamera(Configuration.Video.Camera.SelectedId); // this will in turn fire the affected feedbacks + SelectCamera(Configuration.Video.Camera.SelectedId); + // this will in turn fire the affected feedbacks } }); @@ -291,7 +442,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom }); } - void SetUpDirectory() + private void SetUpDirectory() { DirectoryRoot = new CodecDirectory(); @@ -302,7 +453,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); } - void SetUpRouting() + private void SetUpRouting() { // Set up input ports CreateOsdSource(); @@ -316,7 +467,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// Creates the fake OSD source, and connects it's AudioVideo output to the CodecOsdIn input /// to enable routing /// - void CreateOsdSource() + private void CreateOsdSource() { OsdSource = new DummyRoutingInputsDevice(Key + "[osd]"); DeviceManager.AddDevice(OsdSource); @@ -332,9 +483,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// public override bool CustomActivate() { - CrestronConsole.AddNewConsoleCommand(SetCommDebug, "SetCodecCommDebug", "0 for Off, 1 for on", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand((s) => SendText("zCommand Phonebook List Offset: 0 Limit: 512"), "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); + CrestronConsole.AddNewConsoleCommand(SetCommDebug, "SetCodecCommDebug", "0 for Off, 1 for on", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand((s) => SendText("zCommand Phonebook List Offset: 0 Limit: 512"), + "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); var socket = Communication as ISocketStatus; if (socket != null) @@ -366,12 +521,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } - void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) + private void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) { Debug.Console(1, this, "Socket status change {0}", e.Client.ClientStatus); if (e.Client.IsConnected) { - } else { @@ -383,7 +537,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void SendText(string command) { if (CommDebuggingIsOn) + { Debug.Console(1, this, "Sending: '{0}'", command); + } Communication.SendText(command + Delimiter); } @@ -393,7 +549,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// /// /// - void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args) + private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args) { //if (CommDebuggingIsOn) // Debug.Console(1, this, "Gathered: '{0}'", args.Text); @@ -412,7 +568,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// Runs in it's own thread to dequeue messages in the order they were received to be processed /// /// - object ProcessQueue() + private object ProcessQueue() { try { @@ -435,7 +591,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// /// Queues the initial queries to be sent upon connection /// - void SetUpSyncQueries() + private void SetUpSyncQueries() { // zStatus SyncState.AddQueryToQueue("zStatus Call Status"); @@ -488,41 +644,51 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// Processes messages as they are dequeued /// /// - void ProcessMessage(string message) - { + private void ProcessMessage(string message) + { // Counts the curly braces - if(message.Contains('{')) + if (message.Contains('{')) + { JsonCurlyBraceCounter++; + } if (message.Contains('}')) + { JsonCurlyBraceCounter--; + } Debug.Console(2, this, "JSON Curly Brace Count: {0}", JsonCurlyBraceCounter); - if (!JsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter) // Check for the beginning of a new JSON message + if (!JsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter) + // Check for the beginning of a new JSON message { JsonFeedbackMessageIsIncoming = true; - JsonCurlyBraceCounter = 1; // reset the counter for each new message + 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; } - else if (JsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + Delimiter) // Check for the end of a JSON message + else if (JsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + Delimiter) + // Check for the end of a JSON message { JsonMessage.Append(message); - if(JsonCurlyBraceCounter == 0) + 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()); @@ -543,36 +709,38 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } if (CommDebuggingIsOn) + { Debug.Console(1, this, "Non-JSON response: '{0}'", message); + } - JsonCurlyBraceCounter = 0; // reset on non-JSON response + JsonCurlyBraceCounter = 0; // reset on non-JSON response if (!SyncState.InitialSyncComplete) { switch (message.Trim().ToLower()) // remove the whitespace { case "*r login successful": + { + SyncState.LoginMessageReceived(); + + // Fire up a thread to send the intial commands. + CrestronInvoke.BeginInvoke((o) => { - SyncState.LoginMessageReceived(); + 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); + // switch to json format + SendText("format json"); + }); - // Fire up a thread to send the intial commands. - CrestronInvoke.BeginInvoke((o) => - { - 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); - // switch to json format - SendText("format json"); - }); - - break; - } + break; + } } } } @@ -581,18 +749,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// Deserializes a JSON formatted response /// /// - void DeserializeResponse(string response) + private void DeserializeResponse(string response) { try { var trimmedResponse = response.Trim(); if (trimmedResponse.Length <= 0) + { return; + } var message = JObject.Parse(trimmedResponse); - eZoomRoomResponseType eType = (eZoomRoomResponseType)Enum.Parse(typeof(eZoomRoomResponseType), message["type"].Value(), true); + eZoomRoomResponseType eType = + (eZoomRoomResponseType) + Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value(), true); var topKey = message["topKey"].Value(); @@ -603,385 +775,413 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom switch (eType) { case eZoomRoomResponseType.zConfiguration: + { + switch (topKey.ToLower()) { - switch (topKey.ToLower()) + case "call": { - case "call": - { - JsonConvert.PopulateObject(responseObj.ToString(), Configuration.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 "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; } + break; + } case eZoomRoomResponseType.zCommand: + { + switch (topKey.ToLower()) { - switch (topKey.ToLower()) + case "phonebooklistresult": { - case "phonebooklistresult": + JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); + + if (!PhonebookSyncState.InitialSyncComplete) + { + PhonebookSyncState.InitialPhonebookFoldersReceived(); + PhonebookSyncState.PhonebookRootEntriesReceived(); + PhonebookSyncState.SetPhonebookHasFolders(false); + PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); + } + + var directoryResults = new CodecDirectory(); + + directoryResults = + zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); + + DirectoryRoot = directoryResults; + + OnDirectoryResultReturned(directoryResults); + + break; + } + case "listparticipantsresult": + { + Debug.Console(1, this, "JTokenType: {0}", responseObj.Type); + + if (responseObj.Type == JTokenType.Array) + { + // if the type is array this must be the complete list + Status.Call.Participants = + JsonConvert.DeserializeObject>( + responseObj.ToString()); + } + else if (responseObj.Type == JTokenType.Object) + { + // this is a single participant event notification + + var participant = + JsonConvert.DeserializeObject(responseObj.ToString()); + + if (participant != null) { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); - - if(!PhonebookSyncState.InitialSyncComplete) + if (participant.Event == "ZRCUserChangedEventLeftMeeting" || + participant.Event == "ZRCUserChangedEventUserInfoUpdated") { - PhonebookSyncState.InitialPhonebookFoldersReceived(); - PhonebookSyncState.PhonebookRootEntriesReceived(); - PhonebookSyncState.SetPhonebookHasFolders(false); - PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); - } + var existingParticipant = + Status.Call.Participants.FirstOrDefault( + p => p.UserId.Equals(participant.UserId)); - var directoryResults = new CodecDirectory(); - - directoryResults = zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); - - DirectoryRoot = directoryResults; - - OnDirectoryResultReturned(directoryResults); - - break; - } - case "listparticipantsresult": - { - Debug.Console(1, this, "JTokenType: {0}", responseObj.Type); - - if (responseObj.Type == JTokenType.Array) - { - // if the type is array this must be the complete list - Status.Call.Participants = JsonConvert.DeserializeObject>(responseObj.ToString()); - } - else if (responseObj.Type == JTokenType.Object) - { - // this is a single participant event notification - - var participant = JsonConvert.DeserializeObject(responseObj.ToString()); - - if (participant != null) + if (existingParticipant != null) { - if (participant.Event == "ZRCUserChangedEventLeftMeeting" || participant.Event == "ZRCUserChangedEventUserInfoUpdated") + if (participant.Event == "ZRCUserChangedEventLeftMeeting") { - var existingParticipant = Status.Call.Participants.FirstOrDefault(p => p.UserId.Equals(participant.UserId)); - - if (existingParticipant != null) - { - if (participant.Event == "ZRCUserChangedEventLeftMeeting") - { - // Remove participant - Status.Call.Participants.Remove(existingParticipant); - } - else if (participant.Event == "ZRCUserChangedEventUserInfoUpdated") - { - // Update participant - JsonConvert.PopulateObject(responseObj.ToString(), existingParticipant); - } - } + // Remove participant + Status.Call.Participants.Remove(existingParticipant); } - else if(participant.Event == "ZRCUserChangedEventJoinedMeeting") + else if (participant.Event == "ZRCUserChangedEventUserInfoUpdated") { - Status.Call.Participants.Add(participant); + // Update participant + JsonConvert.PopulateObject(responseObj.ToString(), + existingParticipant); } } } - - PrintCurrentCallParticipants(); - - break; - } - default: - { - break; + else if (participant.Event == "ZRCUserChangedEventJoinedMeeting") + { + Status.Call.Participants.Add(participant); + } } + } + + PrintCurrentCallParticipants(); + + break; + } + default: + { + break; } - break; } + break; + } case eZoomRoomResponseType.zEvent: + { + switch (topKey.ToLower()) { - switch (topKey.ToLower()) + case "phonebook": { - case "phonebook": + if (responseObj["Updated Contact"] != null) + { + var updatedContact = + JsonConvert.DeserializeObject( + responseObj["Updated Contact"].ToString()); + + var existingContact = + Status.Phonebook.Contacts.FirstOrDefault(c => c.Jid.Equals(updatedContact.Jid)); + + if (existingContact != null) { - if (responseObj["Updated Contact"] != null) - { - var updatedContact = JsonConvert.DeserializeObject(responseObj["Updated Contact"].ToString()); - - var existingContact = Status.Phonebook.Contacts.FirstOrDefault(c => c.Jid.Equals(updatedContact.Jid)); - - if (existingContact != null) - { - // Update existing contact - JsonConvert.PopulateObject(responseObj["Updated Contact"].ToString(), existingContact); - } - } - else if (responseObj["Added Contact"] != null) - { - var newContact = JsonConvert.DeserializeObject(responseObj["Updated Contact"].ToString()); - - // Add a new contact - Status.Phonebook.Contacts.Add(newContact); - } - - break; + // Update existing contact + JsonConvert.PopulateObject(responseObj["Updated Contact"].ToString(), + existingContact); } - case "bookingslistresult": - { - if (!SyncState.InitialSyncComplete) - SyncState.LastQueryResponseReceived(); + } + else if (responseObj["Added Contact"] != null) + { + var newContact = + JsonConvert.DeserializeObject( + responseObj["Updated Contact"].ToString()); - var codecBookings = new List(); + // Add a new contact + Status.Phonebook.Contacts.Add(newContact); + } - codecBookings = JsonConvert.DeserializeObject < List>(responseObj.ToString()); - - if (codecBookings != null && codecBookings.Count > 0) - { - CodecSchedule.Meetings = zCommand.GetGenericMeetingsFromBookingResult(codecBookings); - } - - break; - } - case "bookings": - { - // Bookings have been updated, trigger a query to retreive the new bookings - if (responseObj["Updated"] != null) - GetBookings(); - - break; - } - case "sharingstate": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing); - - break; - } - case "incomingcallindication": - { - var incomingCall = JsonConvert.DeserializeObject(responseObj.ToString()); - - if (incomingCall != null) - { - var newCall = new CodecActiveCallItem(); - - newCall.Direction = eCodecCallDirection.Incoming; - newCall.Status = eCodecCallStatus.Ringing; - newCall.Type = eCodecCallType.Unknown; - newCall.Name = incomingCall.callerName; - newCall.Id = incomingCall.callerJID; - - 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) - { - if (!incomingCall.accepted) - { - existingCall.Status = eCodecCallStatus.Disconnected; - } - else - { - existingCall.Status = eCodecCallStatus.Connecting; - } - - OnCallStatusChange(existingCall); - } - - UpdateCallStatus(); - } - - break; - } - case "calldisconnect": - { - var disconnectEvent = JsonConvert.DeserializeObject(responseObj.ToString()); - - if (disconnectEvent.Successful) - { - if (ActiveCalls.Count > 0) - { - var activeCall = ActiveCalls.FirstOrDefault(c => c.IsActiveCall); - - if (activeCall != null) - { - activeCall.Status = eCodecCallStatus.Disconnected; - - OnCallStatusChange(activeCall); - } - } - } - - UpdateCallStatus(); - break; - } - case "callconnecterror": - { - UpdateCallStatus(); - break; - } - case "videounmuterequest": - { - // TODO: notify room of a request to unmute video - break; - } - case "meetingneedspassword": - { - // TODO: notify user to enter a password - break; - } - case "needwaitforhost": - { - var needWait = JsonConvert.DeserializeObject(responseObj.ToString()); - - if (needWait.Wait) - { - // TODO: notify user to wait for host - } - - break; - } - case "openvideofailforhoststop": - { - // TODO: notify user that host has disabled unmuting video - break; - } - case "updatedcallrecordinfo": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.CallRecordInfo); - - break; - } - default: - { - break; - } + break; + } + case "bookingslistresult": + { + if (!SyncState.InitialSyncComplete) + { + SyncState.LastQueryResponseReceived(); + } + + var codecBookings = new List(); + + codecBookings = + JsonConvert.DeserializeObject>( + responseObj.ToString()); + + if (codecBookings != null && codecBookings.Count > 0) + { + CodecSchedule.Meetings = zCommand.GetGenericMeetingsFromBookingResult(codecBookings); + } + + break; + } + case "bookings": + { + // Bookings have been updated, trigger a query to retreive the new bookings + if (responseObj["Updated"] != null) + { + GetBookings(); + } + + break; + } + case "sharingstate": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing); + + break; + } + case "incomingcallindication": + { + var incomingCall = + JsonConvert.DeserializeObject(responseObj.ToString()); + + if (incomingCall != null) + { + var newCall = new CodecActiveCallItem(); + + newCall.Direction = eCodecCallDirection.Incoming; + newCall.Status = eCodecCallStatus.Ringing; + newCall.Type = eCodecCallType.Unknown; + newCall.Name = incomingCall.callerName; + newCall.Id = incomingCall.callerJID; + + 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) + { + if (!incomingCall.accepted) + { + existingCall.Status = eCodecCallStatus.Disconnected; + } + else + { + existingCall.Status = eCodecCallStatus.Connecting; + } + + OnCallStatusChange(existingCall); + } + + UpdateCallStatus(); + } + + break; + } + case "calldisconnect": + { + var disconnectEvent = + JsonConvert.DeserializeObject(responseObj.ToString()); + + if (disconnectEvent.Successful) + { + if (ActiveCalls.Count > 0) + { + var activeCall = ActiveCalls.FirstOrDefault(c => c.IsActiveCall); + + if (activeCall != null) + { + activeCall.Status = eCodecCallStatus.Disconnected; + + OnCallStatusChange(activeCall); + } + } + } + + UpdateCallStatus(); + break; + } + case "callconnecterror": + { + UpdateCallStatus(); + break; + } + case "videounmuterequest": + { + // TODO: notify room of a request to unmute video + break; + } + case "meetingneedspassword": + { + // TODO: notify user to enter a password + break; + } + case "needwaitforhost": + { + var needWait = + JsonConvert.DeserializeObject(responseObj.ToString()); + + if (needWait.Wait) + { + // TODO: notify user to wait for host + } + + break; + } + case "openvideofailforhoststop": + { + // TODO: notify user that host has disabled unmuting video + break; + } + case "updatedcallrecordinfo": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.CallRecordInfo); + + break; + } + default: + { + break; } - break; } + break; + } case eZoomRoomResponseType.zStatus: + { + switch (topKey.ToLower()) { - switch (topKey.ToLower()) + case "login": { - case "login": - { - SyncState.LoginMessageReceived(); + SyncState.LoginMessageReceived(); - if (!SyncState.InitialQueryMessagesWereSent) - SetUpSyncQueries(); + if (!SyncState.InitialQueryMessagesWereSent) + { + SetUpSyncQueries(); + } - JsonConvert.PopulateObject(responseObj.ToString(), Status.Login); + JsonConvert.PopulateObject(responseObj.ToString(), Status.Login); - break; - } - case "systemunit": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit); - - break; - } - case "call": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call); - - 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": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras); - - if(!SyncState.CamerasHaveBeenSetUp) - SetUpCameras(); - - break; - } - default: - { - break; - } + break; } + case "systemunit": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit); - break; + break; + } + case "call": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Call); + + 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": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras); + + if (!SyncState.CamerasHaveBeenSetUp) + { + SetUpCameras(); + } + + break; + } + default: + { + break; + } } + + break; + } default: - { - Debug.Console(1, "Unknown Response Type:"); - break; - } + { + Debug.Console(1, "Unknown Response Type:"); + break; + } } - } catch (Exception ex) { @@ -996,7 +1196,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(1, this, "****************************Call Participants***************************"); foreach (var participant in Status.Call.Participants) { - Debug.Console(1, this, "Name: {0} Audio: {1} IsHost: {2}", participant.UserName, participant.AudioStatusState, participant.IsHost); + Debug.Console(1, this, "Name: {0} Audio: {1} IsHost: {2}", participant.UserName, + participant.AudioStatusState, participant.IsHost); } Debug.Console(1, this, "************************************************************************"); } @@ -1005,7 +1206,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// /// Retrieves bookings list /// - void GetBookings() + private void GetBookings() { SendText("zCommand Bookings List"); } @@ -1014,7 +1215,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// /// Updates the current call status /// - void UpdateCallStatus() + private void UpdateCallStatus() { zStatus.eCallStatus callStatus; @@ -1031,7 +1232,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (ActiveCalls.Count == 0) { - if(callStatus == zStatus.eCallStatus.CONNECTING_MEETING) + if (callStatus == zStatus.eCallStatus.CONNECTING_MEETING) { var newCall = new CodecActiveCallItem(); @@ -1057,7 +1258,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom OnCallStatusChange(existingCall); } - } Debug.Console(1, this, "****************************Active Calls*********************************"); @@ -1067,7 +1267,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { var call = ActiveCalls[i]; - Debug.Console(1, this, + Debug.Console(1, this, @"Name: {0} ID: {1} IsActive: {2} @@ -1082,7 +1282,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } Debug.Console(1, this, "**************************************************************************"); - } public override void StartSharing() @@ -1111,19 +1310,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void PrivacyModeToggle() { if (PrivacyModeIsOnFeedback.BoolValue) + { PrivacyModeOff(); + } else + { PrivacyModeOn(); + } } public override void MuteOff() { - SetVolume((ushort)PreviousVolumeLevel); + SetVolume((ushort) PreviousVolumeLevel); } public override void MuteOn() { - PreviousVolumeLevel = Configuration.Audio.Output.Volume; // Store the previous level for recall + PreviousVolumeLevel = Configuration.Audio.Output.Volume; // Store the previous level for recall SetVolume(0); } @@ -1131,9 +1334,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void MuteToggle() { if (MuteFeedback.BoolValue) + { MuteOff(); + } else + { MuteOn(); + } } /// @@ -1169,7 +1376,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// public void VolumeSetToDefault() { - } /// @@ -1193,20 +1399,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom (selector as Action)(); } - public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) - { - ExecuteSwitch(inputSelector); - } - public override void AcceptCall(CodecActiveCallItem call) { - var incomingCall = ActiveCalls.FirstOrDefault(c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); + var incomingCall = + ActiveCalls.FirstOrDefault( + c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); SendText(string.Format("zCommand Call Accept callerJID: {0}", incomingCall.Id)); } public override void RejectCall(CodecActiveCallItem call) { - var incomingCall = ActiveCalls.FirstOrDefault(c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); + var incomingCall = + ActiveCalls.FirstOrDefault( + c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); SendText(string.Format("zCommand Call Reject callerJID: {0}", incomingCall.Id)); } @@ -1234,9 +1439,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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)); + { + SendText(string.Format("zCommand Invite Duration: {0} user: {1}", DefaultMeetingDurationMin, + ic.ContactId)); + } else + { SendText(string.Format("zCommand Call invite user: {0}", ic.ContactId)); + } } } @@ -1255,39 +1465,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom throw new NotImplementedException(); } - - #region IHasCodecSelfView Members - - public BoolFeedback SelfviewIsOnFeedback { get; private set; } - - 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 IHasDirectory Members - - public event EventHandler DirectoryResultReturned; - /// Call when directory results are updated /// /// - void OnDirectoryResultReturned(CodecDirectory result) + private void OnDirectoryResultReturned(CodecDirectory result) { CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); @@ -1305,94 +1486,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom //PrintDirectory(result); } - public CodecDirectory DirectoryRoot { get; private set; } - - public CodecDirectory CurrentDirectoryResult - { - get - { - if (DirectoryBrowseHistory.Count > 0) - return DirectoryBrowseHistory[DirectoryBrowseHistory.Count - 1]; - else - return DirectoryRoot; - } - } - - 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)); - - DirectoryBrowseHistory.Add(directoryResults); - - OnDirectoryResultReturned(directoryResults); - } - - public void GetDirectoryFolderContents(string folderId) - { - var directoryResults = new CodecDirectory(); - - directoryResults.ResultsFolderId = folderId; - directoryResults.AddContactsToDirectory(DirectoryRoot.CurrentDirectoryResults.FindAll(c => c.FolderId.Equals(folderId))); - - DirectoryBrowseHistory.Add(directoryResults); - - OnDirectoryResultReturned(directoryResults); - } - - public void SetCurrentDirectoryToRoot() - { - DirectoryBrowseHistory.Clear(); - - OnDirectoryResultReturned(DirectoryRoot); - } - - public void GetDirectoryParentFolderContents() - { - var currentDirectory = new CodecDirectory(); - - if (DirectoryBrowseHistory.Count > 0) - { - var lastItemIndex = DirectoryBrowseHistory.Count - 1; - var parentDirectoryContents = DirectoryBrowseHistory[lastItemIndex]; - - DirectoryBrowseHistory.Remove(DirectoryBrowseHistory[lastItemIndex]); - - currentDirectory = parentDirectoryContents; - - } - else - { - currentDirectory = DirectoryRoot; - } - - OnDirectoryResultReturned(currentDirectory); - } - - public BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; private set; } - - public List DirectoryBrowseHistory { get; private set; } - - #endregion - - #region IHasScheduleAwareness Members - - public CodecScheduleAwareness CodecSchedule { get; private set; } - - public void GetSchedule() - { - GetBookings(); - } - - #endregion - /// /// Builds the cameras List by using the Zoom Room zStatus.Cameras data. Could later be modified to build from config data /// - void SetUpCameras() + private void SetUpCameras() { SelectedCameraFeedback = new StringFeedback(() => Configuration.Video.Camera.SelectedId); @@ -1405,11 +1502,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Cameras.Add(camera); if (cam.Selected) - SelectedCamera = camera; + { + SelectedCamera = camera; + } } if (IsInCall) + { UpdateFarEndCameras(); + } SyncState.CamerasSetUp(); } @@ -1417,66 +1518,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// /// Dynamically creates far end cameras for call participants who have far end control enabled. /// - void UpdateFarEndCameras() + private void UpdateFarEndCameras() { // TODO: set up far end cameras for the current call } - - #region IHasCameras Members - - public event EventHandler CameraSelected; - - public List Cameras { get; private set; } - - private CameraBase _selectedCamera; - - 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(Cameras != null) - { - var camera = Cameras.FirstOrDefault(c => c.Key.IndexOf(key, StringComparison.OrdinalIgnoreCase) > -1); - if (camera != null) - { - Debug.Console(1, this, "Selected Camera with key: '{0}'", camera.Key); - SelectedCamera = camera; - } - else - Debug.Console(1, this, "Unable to select camera with key: '{0}'", key); - } - } - - #endregion - - #region IHasFarEndCameraControl Members - - public CameraBase FarEndCamera { get; private set; } - - public BoolFeedback ControllingFarEndCameraFeedback { get; private set; } - - #endregion } /// @@ -1484,15 +1529,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// public class ZoomRoomInfo : VideoCodecInfo { + public ZoomRoomInfo(ZoomRoomStatus status, ZoomRoomConfiguration configuration) + { + Status = status; + Configuration = configuration; + } + public ZoomRoomStatus Status { get; private set; } public ZoomRoomConfiguration Configuration { get; private set; } public override bool AutoAnswerEnabled { - get - { - return Status.SystemUnit.RoomInfo.AutoAnswerIsEnabled; - } + get { return Status.SystemUnit.RoomInfo.AutoAnswerIsEnabled; } } public override string E164Alias @@ -1500,9 +1548,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom get { if (!string.IsNullOrEmpty(Status.SystemUnit.MeetingNumber)) + { return Status.SystemUnit.MeetingNumber; + } else + { return string.Empty; + } } } @@ -1511,9 +1563,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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; + } else + { return string.Empty; + } } } @@ -1522,9 +1578,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom get { if (!string.IsNullOrEmpty(Status.SystemUnit.RoomInfo.AccountEmail)) + { return Status.SystemUnit.RoomInfo.AccountEmail; + } else + { return string.Empty; + } } } @@ -1538,9 +1598,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom get { if (!string.IsNullOrEmpty(Status.Call.Info.dialIn)) + { return Status.Call.Info.dialIn; + } else + { return string.Empty; + } } } @@ -1549,17 +1613,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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; + } else + { return string.Empty; + } } } - - public ZoomRoomInfo(ZoomRoomStatus status, ZoomRoomConfiguration configuration) - { - Status = status; - Configuration = configuration; - } } /// @@ -1567,15 +1629,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// public class ZoomRoomSyncState : IKeyed { - bool _InitialSyncComplete; + private readonly ZoomRoom Parent; + private readonly CrestronQueue SyncQueries; + private bool _InitialSyncComplete; - public event EventHandler InitialSyncCompleted; - - private CrestronQueue SyncQueries; - - private ZoomRoom Parent; - - public string Key { get; private set; } + public ZoomRoomSyncState(string key, ZoomRoom parent) + { + Parent = parent; + Key = key; + SyncQueries = new CrestronQueue(50); + CodecDisconnected(); + } public bool InitialSyncComplete { @@ -1586,7 +1650,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { var handler = InitialSyncCompleted; if (handler != null) + { handler(this, new EventArgs()); + } } _InitialSyncComplete = value; } @@ -1598,28 +1664,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public bool LastQueryResponseWasReceived { get; private set; } - public bool CamerasHaveBeenSetUp { get; private set;} + public bool CamerasHaveBeenSetUp { get; private set; } - public ZoomRoomSyncState(string key, ZoomRoom parent) - { - Parent = parent; - Key = key; - SyncQueries = new CrestronQueue(50); - CodecDisconnected(); - } + #region IKeyed Members + + public string Key { get; private set; } + + #endregion + + public event EventHandler InitialSyncCompleted; public void StartSync() { DequeueQueries(); } - void DequeueQueries() + private void DequeueQueries() { while (!SyncQueries.IsEmpty) { var query = SyncQueries.Dequeue(); - Parent.SendText(query); + Parent.SendText(query); } InitialQueryMessagesSent(); @@ -1668,15 +1734,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom InitialSyncComplete = false; } - void CheckSyncStatus() + private void CheckSyncStatus() { - if (LoginMessageWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived && CamerasHaveBeenSetUp) + if (LoginMessageWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived && + CamerasHaveBeenSetUp) { InitialSyncComplete = true; Debug.Console(1, this, "Initial Codec Sync Complete!"); } else + { InitialSyncComplete = false; + } } } @@ -1684,15 +1753,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { public ZoomRoomFactory() { - TypeNames = new List() { "zoomroom" }; + 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 VideoCodec.ZoomRoom.ZoomRoom(dc, comm); + return new ZoomRoom(dc, comm); } } - } \ No newline at end of file From 1bd9eca806b6f9478006c8c405f1c2610d09d690 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 17 Sep 2020 11:02:36 -0600 Subject: [PATCH 03/42] Update to PepperDash Core 1.0.42 --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index 11087174..296413b6 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From 6972b544ec8ebed9d5a1174208ec03c202b5e6aa Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 17 Sep 2020 11:03:04 -0600 Subject: [PATCH 04/42] Add IBridgeAdvanced to VideoCodecBase --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 8 +- .../VideoCodec/MockVC/MockVC.cs | 8 +- .../VideoCodec/VideoCodecBase.cs | 315 ++++++++++-------- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 53 ++- 4 files changed, 231 insertions(+), 153 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 9759cfdd..9e5ce331 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -5,12 +5,13 @@ using System.Text; using System.Text.RegularExpressions; using Crestron.SimplSharp; using Crestron.SimplSharpPro.CrestronThread; - +using Crestron.SimplSharpPro.DeviceSupport; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PepperDash.Core; using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Common.Cameras; @@ -1388,6 +1389,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco SendText("xCommand Standby Deactivate"); } + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + throw new NotImplementedException(); + } + /// /// Reboots the codec /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs index dc32ecd8..c4bfa298 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs @@ -3,9 +3,10 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; - +using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Common.Codec; @@ -226,6 +227,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec _StandbyIsOn = false; } + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + throw new NotImplementedException(); + } + /// /// Called by routing to make it happen /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 1f8938f6..fe18e7ca 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -2,83 +2,22 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using Crestron.SimplSharp; - +using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Devices; using PepperDash.Essentials.Core.Routing; -using PepperDash.Essentials.Devices.Common; using PepperDash.Essentials.Devices.Common.Codec; +using Feedback = PepperDash.Essentials.Core.Feedback; namespace PepperDash.Essentials.Devices.Common.VideoCodec { public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutputs, - IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo + IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced { - /// - /// Fires when the status of any active, dialing, or incoming call changes or is new - /// - public event EventHandler CallStatusChange; - - public event EventHandler IsReadyChange; - - public IBasicCommunication Communication { get; protected set; } - - #region IUsageTracking Members - - /// - /// This object can be added by outside users of this class to provide usage tracking - /// for various services - /// - public UsageTracking UsageTracker { get; set; } - - #endregion - - /// - /// An internal pseudo-source that is routable and connected to the osd input - /// - public DummyRoutingInputsDevice OsdSource { get; protected set; } - - public RoutingPortCollection InputPorts { get; private set; } - - public RoutingPortCollection OutputPorts { get; private set; } - - /// - /// Returns true when any call is not in state Unknown, Disconnecting, Disconnected - /// - public bool IsInCall - { - get - { - bool value; - - if (ActiveCalls != null) - value = ActiveCalls.Any(c => c.IsActiveCall); - else - value = false; - return value; - } - } - - public BoolFeedback StandbyIsOnFeedback { get; private set; } - - abstract protected Func PrivacyModeIsOnFeedbackFunc { get; } - abstract protected Func VolumeLevelFeedbackFunc { get; } - abstract protected Func MuteFeedbackFunc { get; } - abstract protected Func StandbyIsOnFeedbackFunc { get; } - - public List ActiveCalls { get; set; } - - public VideoCodecInfo CodecInfo { get; protected set; } - - public bool ShowSelfViewByDefault { get; protected set; } - - - public bool IsReady { get; protected set; } - - public VideoCodecBase(DeviceConfig config) + protected VideoCodecBase(DeviceConfig config) : base(config) { StandbyIsOnFeedback = new BoolFeedback(StandbyIsOnFeedbackFunc); @@ -90,85 +29,45 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec InputPorts = new RoutingPortCollection(); OutputPorts = new RoutingPortCollection(); - + ActiveCalls = new List(); } - #region IHasDialer Members + public IBasicCommunication Communication { get; protected set; } - public abstract void Dial(string number); - public abstract void Dial(Meeting meeting); - public virtual void Dial(IInvitableContact contact) - { + /// + /// An internal pseudo-source that is routable and connected to the osd input + /// + public DummyRoutingInputsDevice OsdSource { get; protected set; } - } - public abstract void EndCall(CodecActiveCallItem call); - public abstract void EndAllCalls(); - public abstract void AcceptCall(CodecActiveCallItem call); - public abstract void RejectCall(CodecActiveCallItem call); - public abstract void SendDtmf(string s); + public BoolFeedback StandbyIsOnFeedback { get; private set; } - #endregion + protected abstract Func PrivacyModeIsOnFeedbackFunc { get; } + protected abstract Func VolumeLevelFeedbackFunc { get; } + protected abstract Func MuteFeedbackFunc { get; } + protected abstract Func StandbyIsOnFeedbackFunc { get; } + + public List ActiveCalls { get; set; } + + public bool ShowSelfViewByDefault { get; protected set; } + + + public bool IsReady { get; protected set; } public virtual List Feedbacks { get { return new List - { + { PrivacyModeIsOnFeedback, SharingSourceFeedback - }; + }; } } - public abstract void ExecuteSwitch(object selector); - - /// - /// Helper method to fire CallStatusChange event with old and new status - /// - protected void SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus newStatus, CodecActiveCallItem call) - { - call.Status = newStatus; - - OnCallStatusChange(call); - - } - - /// - /// - /// - /// - /// - /// - protected void OnCallStatusChange(CodecActiveCallItem item) - { - var handler = CallStatusChange; - if (handler != null) - handler(this, new CodecCallStatusItemChangeEventArgs(item)); - - if (AutoShareContentWhileInCall) - StartSharing(); - - if (UsageTracker != null) - { - if (IsInCall && !UsageTracker.UsageTrackingStarted) - UsageTracker.StartDeviceUsage(); - else if (UsageTracker.UsageTrackingStarted && !IsInCall) - UsageTracker.EndDeviceUsage(); - } - } - - /// - /// Sets IsReady property and fires the event. Used for dependent classes to sync up their data. - /// - protected void SetIsReady() - { - IsReady = true; - var h = IsReadyChange; - if(h != null) - h(this, new EventArgs()); - } + protected abstract Func SharingSourceFeedbackFunc { get; } + protected abstract Func SharingContentIsOnFeedbackFunc { get; } #region ICodecAudio Members @@ -197,7 +96,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec #endregion - #region IHasSharing Members + #region IHasContentSharing Members public abstract void StartSharing(); public abstract void StopSharing(); @@ -207,12 +106,133 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public StringFeedback SharingSourceFeedback { get; private set; } public BoolFeedback SharingContentIsOnFeedback { get; private set; } - abstract protected Func SharingSourceFeedbackFunc { get; } - abstract protected Func SharingContentIsOnFeedbackFunc { get; } + #endregion + #region IHasDialer Members + + /// + /// Fires when the status of any active, dialing, or incoming call changes or is new + /// + public event EventHandler CallStatusChange; + + /// + /// Returns true when any call is not in state Unknown, Disconnecting, Disconnected + /// + public bool IsInCall + { + get + { + bool value; + + if (ActiveCalls != null) + { + value = ActiveCalls.Any(c => c.IsActiveCall); + } + else + { + value = false; + } + return value; + } + } + + public abstract void Dial(string number); + public abstract void EndCall(CodecActiveCallItem call); + public abstract void EndAllCalls(); + public abstract void AcceptCall(CodecActiveCallItem call); + public abstract void RejectCall(CodecActiveCallItem call); + public abstract void SendDtmf(string s); #endregion + #region IRoutingInputsOutputs Members + + public RoutingPortCollection InputPorts { get; private set; } + + public RoutingPortCollection OutputPorts { get; private set; } + + #endregion + + #region IUsageTracking Members + + /// + /// This object can be added by outside users of this class to provide usage tracking + /// for various services + /// + public UsageTracking UsageTracker { get; set; } + + #endregion + + #region iVideoCodecInfo Members + + public VideoCodecInfo CodecInfo { get; protected set; } + + #endregion + + public event EventHandler IsReadyChange; + public abstract void Dial(Meeting meeting); + + public virtual void Dial(IInvitableContact contact) + { + } + + public abstract void ExecuteSwitch(object selector); + + /// + /// Helper method to fire CallStatusChange event with old and new status + /// + protected void SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus newStatus, CodecActiveCallItem call) + { + call.Status = newStatus; + + OnCallStatusChange(call); + } + + /// + /// + /// + /// + /// + /// + protected void OnCallStatusChange(CodecActiveCallItem item) + { + var handler = CallStatusChange; + if (handler != null) + { + handler(this, new CodecCallStatusItemChangeEventArgs(item)); + } + + if (AutoShareContentWhileInCall) + { + StartSharing(); + } + + if (UsageTracker != null) + { + if (IsInCall && !UsageTracker.UsageTrackingStarted) + { + UsageTracker.StartDeviceUsage(); + } + else if (UsageTracker.UsageTrackingStarted && !IsInCall) + { + UsageTracker.EndDeviceUsage(); + } + } + } + + /// + /// Sets IsReady property and fires the event. Used for dependent classes to sync up their data. + /// + protected void SetIsReady() + { + IsReady = true; + var h = IsReadyChange; + if (h != null) + { + h(this, new EventArgs()); + } + } + // **** DEBUGGING THINGS **** /// /// @@ -221,7 +241,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { var sb = new StringBuilder(); foreach (var c in ActiveCalls) + { sb.AppendFormat("{0} {1} -- {2} {3}\n", c.Id, c.Number, c.Name, c.Status); + } Debug.Console(1, this, "\n{0}\n", sb.ToString()); } @@ -229,6 +251,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public abstract void StandbyDeactivate(); + #region Implementation of IBridgeAdvanced + + public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); + + #endregion } @@ -237,11 +264,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public class CodecPhonebookSyncState : IKeyed { - bool _InitialSyncComplete; + private bool _InitialSyncComplete; - public event EventHandler InitialSyncCompleted; + public CodecPhonebookSyncState(string key) + { + Key = key; - public string Key { get; private set; } + CodecDisconnected(); + } public bool InitialSyncComplete { @@ -252,7 +282,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { var handler = InitialSyncCompleted; if (handler != null) + { handler(this, new EventArgs()); + } } _InitialSyncComplete = value; } @@ -268,12 +300,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public int NumberOfContacts { get; private set; } - public CodecPhonebookSyncState(string key) - { - Key = key; + #region IKeyed Members - CodecDisconnected(); - } + public string Key { get; private set; } + + #endregion + + public event EventHandler InitialSyncCompleted; public void InitialPhonebookFoldersReceived() { @@ -314,7 +347,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec NumberOfContactsWasReceived = false; } - void CheckSyncStatus() + private void CheckSyncStatus() { if (InitialPhonebookFoldersWasReceived && NumberOfContactsWasReceived && PhonebookRootEntriesWasRecieved) { @@ -322,7 +355,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec Debug.Console(1, this, "Initial Phonebook Sync Complete!"); } else + { InitialSyncComplete = false; + } } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 179b4001..d25abb22 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -4,14 +4,17 @@ using System.Linq; using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharpPro.CrestronThread; +using Crestron.SimplSharpPro.DeviceSupport; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PepperDash.Core; using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; +using PepperDash_Essentials_Core.Bridges.JoinMaps; namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { @@ -218,18 +221,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void SelectCamera(string key) { - if (Cameras != null) + if (Cameras == null) { - var camera = Cameras.FirstOrDefault(c => c.Key.IndexOf(key, StringComparison.OrdinalIgnoreCase) > -1); - if (camera != null) - { - Debug.Console(1, this, "Selected Camera with key: '{0}'", camera.Key); - SelectedCamera = camera; - } - else - { - Debug.Console(1, this, "Unable to select camera with key: '{0}'", key); - } + return; + } + + var camera = Cameras.FirstOrDefault(c => c.Key.IndexOf(key, StringComparison.OrdinalIgnoreCase) > -1); + if (camera != null) + { + Debug.Console(1, this, "Selected Camera with key: '{0}'", camera.Key); + SelectedCamera = camera; + } + else + { + Debug.Console(1, this, "Unable to select camera with key: '{0}'", key); } } @@ -1394,6 +1399,32 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // No corresponding function on device } + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new VideoCodecControllerJoinMap(joinStart); + + var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); + + if (customJoins != null) + { + joinMap.SetCustomJoinData(customJoins); + } + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + + Debug.Console(1, this, "Linking to Trilist {0}", trilist.ID.ToString("X")); + + LinkCameraActions(trilist, joinMap); + } + + private void LinkCameraActions(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + + } + public override void ExecuteSwitch(object selector) { (selector as Action)(); From 41b39a5d3b9e942770066fd752b329cec8db08ba Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 17 Sep 2020 11:03:14 -0600 Subject: [PATCH 05/42] remove duplicate using statement --- .../Essentials Devices Common/Factory/DeviceFactory.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs index dd99fe34..a18d3b65 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs @@ -17,7 +17,6 @@ using PepperDash.Essentials.Core.CrestronIO; using PepperDash.Essentials.Devices.Common; using PepperDash.Essentials.Devices.Common.DSP; using PepperDash.Essentials.Devices.Common.VideoCodec; -using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.Environment; namespace PepperDash.Essentials.Devices.Common From 477d7957e3aa5f2d5f5cb136deff8ae240ebba11 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 17 Sep 2020 11:03:29 -0600 Subject: [PATCH 06/42] Working through join map stuff --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 134 ++++++++++++++++-- 1 file changed, 124 insertions(+), 10 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 80d7016f..e8f820b0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -7,6 +7,7 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps { #region Status + [JoinName("IsOnline")] public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData {JoinNumber = 1, JoinSpan = 1}, new JoinMetadata { @@ -20,6 +21,7 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps #region NearEndCameraControls + [JoinName("NearCamUp")] public JoinDataComplete NearEndCameraUp = new JoinDataComplete(new JoinData {JoinNumber = 11, JoinSpan = 1}, new JoinMetadata { @@ -27,6 +29,7 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("NearCamDown")] public JoinDataComplete NearEndCameraDown = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, new JoinMetadata { @@ -34,6 +37,7 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("NearCamLeft")] public JoinDataComplete NearEndCameraLeft = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, new JoinMetadata { @@ -41,6 +45,7 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("NearCamRight")] public JoinDataComplete NearEndCameraRight = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, new JoinMetadata { @@ -48,6 +53,7 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("NearCamZoomIn")] public JoinDataComplete NearEndCameraZoomIn = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, new JoinMetadata { @@ -55,6 +61,7 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("NearCamZoomOut")] public JoinDataComplete NearEndCameraZoomOut = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, new JoinMetadata { @@ -62,6 +69,7 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("NearCamFocusNear")] public JoinDataComplete NearEndCameraFocusNear = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, new JoinMetadata { @@ -69,45 +77,150 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("NearCamFocusFar")] public JoinDataComplete NearEndCameraFocusFar = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, new JoinMetadata { - Description = "Near Camera Right", + Description = "Near Camera Focus Far", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("NearCamSelectSerial")] public JoinDataComplete NearEndCameraSelectSerial = new JoinDataComplete( - new JoinData {JoinNumber = 11, JoinSpan = 1}, + new JoinData {JoinNumber = 21, JoinSpan = 1}, new JoinMetadata { Description = "Camera Select & Feedback by name", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Serial }); - + [JoinName("NearCamSelectAnalog")] public JoinDataComplete NearEndCameraSelectAnalog = new JoinDataComplete( - new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinData { JoinNumber = 21, JoinSpan = 1 }, new JoinMetadata { Description = "Camera Select & Feedback by index", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial + JoinType = eJoinType.Analog }); + [JoinName("NearCamPresetSelect")] + public JoinDataComplete NearEndCameraPresetSelect = + new JoinDataComplete(new JoinData {JoinNumber = 31, JoinSpan = 1}, + new JoinMetadata + { + Description = "Recall Preset", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + [JoinName("NearCamPresetSave")] + public JoinDataComplete NearEndCameraPresetSave = + new JoinDataComplete(new JoinData {JoinNumber = 21, JoinSpan = 1}, + new JoinMetadata + { + Description = "Save Current Preset", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("NearCamPresetNames")] + public JoinDataComplete NearEndCameraNames = new JoinDataComplete(new JoinData {JoinNumber = 11, JoinSpan = 1}, + new JoinMetadata + { + Description = "XSig - Camera Names", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + #endregion + #region Far End Camera Controls + [JoinName("FarCamUp")] + public JoinDataComplete FarEndCameraUp = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Far Camera Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("FarCamDown")] + public JoinDataComplete FarEndCameraDown = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Far Camera Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("FarCamLeft")] + public JoinDataComplete FarEndCameraLeft = new JoinDataComplete(new JoinData { JoinNumber = 33, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Far Camera Left", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("FarCamRight")] + public JoinDataComplete FarEndCameraRight = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Far Camera Right", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("FarCamZoomIn")] + public JoinDataComplete FarEndCameraZoomIn = new JoinDataComplete(new JoinData { JoinNumber = 35, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Far Camera Zoom In", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("FarCamZoomOut")] + public JoinDataComplete FarEndCameraZoomOut = new JoinDataComplete(new JoinData { JoinNumber = 36, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Far Camera Zoom Out", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("FarCamFocusNear")] + public JoinDataComplete FarEndCameraFocusNear = new JoinDataComplete(new JoinData { JoinNumber = 37, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Far Camera Focus Near", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("FarCamFocusFar")] + public JoinDataComplete FarEndCameraFocusFar = new JoinDataComplete(new JoinData { JoinNumber = 38, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Far Camera Focus Far", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("FarCamPresetSelect")] + public JoinDataComplete FarEndCameraPresetSelect = + new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Recall Preset", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); #endregion #region Camera Tracking Controls - public JoinDataComplete CameraTrackingOn = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + [JoinName("CameraTrackingOn")] + public JoinDataComplete CameraTrackingOn = new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, new JoinMetadata { Description = "Camera Tracking On", JoinType = eJoinType.Digital, JoinCapabilities = eJoinCapabilities.ToFromSIMPL}); - - public JoinDataComplete CameraTrackingOff = new JoinDataComplete(new JoinData {JoinNumber = 12, JoinSpan = 1}, + [JoinName("CameraTrackingOff")] + public JoinDataComplete CameraTrackingOff = new JoinDataComplete(new JoinData {JoinNumber = 52, JoinSpan = 1}, new JoinMetadata { Description = "Camera Tracking Off", @@ -115,8 +228,9 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinCapabilities = eJoinCapabilities.ToFromSIMPL }); + [JoinName("CameraTrackingToggle")] public JoinDataComplete CameraTrackingToggle = new JoinDataComplete( - new JoinData {JoinNumber = 13, JoinSpan = 1}, + new JoinData {JoinNumber = 53, JoinSpan = 1}, new JoinMetadata { Description = "Camera Tracking Toggle", @@ -125,7 +239,7 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); #endregion - public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart) + public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof(VideoCodecControllerJoinMap)) { } From 5d5652907bd29dc9757a6d5c09bb7def7888a712 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 18 Sep 2020 16:28:04 -0600 Subject: [PATCH 07/42] Started linking classes to the API --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 1091 ++++++++++++++--- .../VideoCodec/VideoCodecBase.cs | 298 +++++ .../VideoCodec/ZoomRoom/ZoomRoom.cs | 55 +- 3 files changed, 1217 insertions(+), 227 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index e8f820b0..617262f4 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -3,120 +3,69 @@ using PepperDash.Essentials.Core; namespace PepperDash_Essentials_Core.Bridges.JoinMaps { - public class VideoCodecControllerJoinMap:JoinMapBaseAdvanced + public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced { #region Status - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData {JoinNumber = 1, JoinSpan = 1}, - new JoinMetadata - { - Description = "Device is Online", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("IsOnline")] public JoinDataComplete IsOnline = + new JoinDataComplete(new JoinData {JoinNumber = 1, JoinSpan = 1}, + new JoinMetadata + { + Description = "Device is Online", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); #endregion - - #region NearEndCameraControls + /*#region NearEndCameraControls - [JoinName("NearCamUp")] - public JoinDataComplete NearEndCameraUp = new JoinDataComplete(new JoinData {JoinNumber = 11, JoinSpan = 1}, - new JoinMetadata - { - Description = "Near Camera Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("NearCamDown")] - public JoinDataComplete NearEndCameraDown = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Near Camera Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("NearCamLeft")] - public JoinDataComplete NearEndCameraLeft = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Near Camera Left", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("NearCamRight")] - public JoinDataComplete NearEndCameraRight = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Near Camera Right", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("NearCamZoomIn")] - public JoinDataComplete NearEndCameraZoomIn = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Near Camera Zoom In", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("NearCamZoomOut")] - public JoinDataComplete NearEndCameraZoomOut = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Near Camera Zoom Out", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("NearCamFocusNear")] - public JoinDataComplete NearEndCameraFocusNear = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Near Camera Focus Near", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("NearCamFocusFar")] - public JoinDataComplete NearEndCameraFocusFar = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Near Camera Focus Far", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("NearCamSelectSerial")] - public JoinDataComplete NearEndCameraSelectSerial = new JoinDataComplete( - new JoinData {JoinNumber = 21, JoinSpan = 1}, - new JoinMetadata - { - Description = "Camera Select & Feedback by name", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - [JoinName("NearCamSelectAnalog")] - public JoinDataComplete NearEndCameraSelectAnalog = new JoinDataComplete( - new JoinData { JoinNumber = 21, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Select & Feedback by index", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("NearCamPresetSelect")] - public JoinDataComplete NearEndCameraPresetSelect = - new JoinDataComplete(new JoinData {JoinNumber = 31, JoinSpan = 1}, + [JoinName("NearCamDown")] public JoinDataComplete NearEndCameraDown = + new JoinDataComplete(new JoinData {JoinNumber = 12, JoinSpan = 1}, new JoinMetadata { - Description = "Recall Preset", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog + Description = "Near Camera Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital }); - [JoinName("NearCamPresetSave")] - public JoinDataComplete NearEndCameraPresetSave = + [JoinName("NearCamFocusFar")] public JoinDataComplete NearEndCameraFocusFar = + new JoinDataComplete(new JoinData {JoinNumber = 18, JoinSpan = 1}, + new JoinMetadata + { + Description = "Near Camera Focus Far", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("NearCamFocusNear")] public JoinDataComplete NearEndCameraFocusNear = + new JoinDataComplete(new JoinData {JoinNumber = 17, JoinSpan = 1}, + new JoinMetadata + { + Description = "Near Camera Focus Near", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("NearCamLeft")] public JoinDataComplete NearEndCameraLeft = + new JoinDataComplete(new JoinData {JoinNumber = 13, JoinSpan = 1}, + new JoinMetadata + { + Description = "Near Camera Left", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("NearCamPresetNames")] public JoinDataComplete NearEndCameraNames = + new JoinDataComplete(new JoinData {JoinNumber = 11, JoinSpan = 1}, + new JoinMetadata + { + Description = "XSig - Camera Names", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("NearCamPresetSave")] public JoinDataComplete NearEndCameraPresetSave = new JoinDataComplete(new JoinData {JoinNumber = 21, JoinSpan = 1}, new JoinMetadata { @@ -125,111 +74,177 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("NearCamPresetNames")] - public JoinDataComplete NearEndCameraNames = new JoinDataComplete(new JoinData {JoinNumber = 11, JoinSpan = 1}, - new JoinMetadata - { - Description = "XSig - Camera Names", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - #endregion - #region Far End Camera Controls - [JoinName("FarCamUp")] - public JoinDataComplete FarEndCameraUp = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Far Camera Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("FarCamDown")] - public JoinDataComplete FarEndCameraDown = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Far Camera Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("FarCamLeft")] - public JoinDataComplete FarEndCameraLeft = new JoinDataComplete(new JoinData { JoinNumber = 33, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Far Camera Left", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("FarCamRight")] - public JoinDataComplete FarEndCameraRight = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Far Camera Right", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("FarCamZoomIn")] - public JoinDataComplete FarEndCameraZoomIn = new JoinDataComplete(new JoinData { JoinNumber = 35, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Far Camera Zoom In", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("FarCamZoomOut")] - public JoinDataComplete FarEndCameraZoomOut = new JoinDataComplete(new JoinData { JoinNumber = 36, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Far Camera Zoom Out", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("FarCamFocusNear")] - public JoinDataComplete FarEndCameraFocusNear = new JoinDataComplete(new JoinData { JoinNumber = 37, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Far Camera Focus Near", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("FarCamFocusFar")] - public JoinDataComplete FarEndCameraFocusFar = new JoinDataComplete(new JoinData { JoinNumber = 38, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Far Camera Focus Far", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("FarCamPresetSelect")] - public JoinDataComplete FarEndCameraPresetSelect = - new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, + [JoinName("NearCamPresetSelect")] public JoinDataComplete NearEndCameraPresetSelect = + new JoinDataComplete(new JoinData {JoinNumber = 31, JoinSpan = 1}, new JoinMetadata { Description = "Recall Preset", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - #endregion - #region Camera Tracking Controls - [JoinName("CameraTrackingOn")] - public JoinDataComplete CameraTrackingOn = new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, + [JoinName("NearCamRight")] public JoinDataComplete NearEndCameraRight = + new JoinDataComplete(new JoinData {JoinNumber = 14, JoinSpan = 1}, + new JoinMetadata + { + Description = "Near Camera Right", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("NearCamSelectAnalog")] public JoinDataComplete NearEndCameraSelectAnalog = new JoinDataComplete( + new JoinData {JoinNumber = 12, JoinSpan = 1}, new JoinMetadata { - Description = "Camera Tracking On", - JoinType = eJoinType.Digital, - JoinCapabilities = eJoinCapabilities.ToFromSIMPL}); - [JoinName("CameraTrackingOff")] - public JoinDataComplete CameraTrackingOff = new JoinDataComplete(new JoinData {JoinNumber = 52, JoinSpan = 1}, - new JoinMetadata - { - Description = "Camera Tracking Off", - JoinType = eJoinType.Digital, - JoinCapabilities = eJoinCapabilities.ToFromSIMPL + Description = "Camera Select & Feedback by index", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog }); - [JoinName("CameraTrackingToggle")] - public JoinDataComplete CameraTrackingToggle = new JoinDataComplete( + [JoinName("NearCamSelectSerial")] public JoinDataComplete NearEndCameraSelectSerial = new JoinDataComplete( + new JoinData {JoinNumber = 12, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Select & Feedback by name", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("NearCamUp")] public JoinDataComplete NearEndCameraUp = + new JoinDataComplete(new JoinData {JoinNumber = 11, JoinSpan = 1}, + new JoinMetadata + { + Description = "Near Camera Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("NearCamZoomIn")] public JoinDataComplete NearEndCameraZoomIn = + new JoinDataComplete(new JoinData {JoinNumber = 15, JoinSpan = 1}, + new JoinMetadata + { + Description = "Near Camera Zoom In", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("NearCamZoomOut")] public JoinDataComplete NearEndCameraZoomOut = + new JoinDataComplete(new JoinData {JoinNumber = 16, JoinSpan = 1}, + new JoinMetadata + { + Description = "Near Camera Zoom Out", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + #endregion + + #region Far End Camera Controls + + [JoinName("FarCamDown")] public JoinDataComplete FarEndCameraDown = + new JoinDataComplete(new JoinData {JoinNumber = 32, JoinSpan = 1}, + new JoinMetadata + { + Description = "Far Camera Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("FarCamFocusFar")] public JoinDataComplete FarEndCameraFocusFar = + new JoinDataComplete(new JoinData {JoinNumber = 38, JoinSpan = 1}, + new JoinMetadata + { + Description = "Far Camera Focus Far", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("FarCamFocusNear")] public JoinDataComplete FarEndCameraFocusNear = + new JoinDataComplete(new JoinData {JoinNumber = 37, JoinSpan = 1}, + new JoinMetadata + { + Description = "Far Camera Focus Near", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("FarCamLeft")] public JoinDataComplete FarEndCameraLeft = + new JoinDataComplete(new JoinData {JoinNumber = 33, JoinSpan = 1}, + new JoinMetadata + { + Description = "Far Camera Left", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("FarCamPresetSelect")] public JoinDataComplete FarEndCameraPresetSelect = + new JoinDataComplete(new JoinData {JoinNumber = 41, JoinSpan = 1}, + new JoinMetadata + { + Description = "Recall Preset", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("FarCamRight")] public JoinDataComplete FarEndCameraRight = + new JoinDataComplete(new JoinData {JoinNumber = 34, JoinSpan = 1}, + new JoinMetadata + { + Description = "Far Camera Right", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("FarCamUp")] public JoinDataComplete FarEndCameraUp = + new JoinDataComplete(new JoinData {JoinNumber = 31, JoinSpan = 1}, + new JoinMetadata + { + Description = "Far Camera Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("FarCamZoomIn")] public JoinDataComplete FarEndCameraZoomIn = + new JoinDataComplete(new JoinData {JoinNumber = 35, JoinSpan = 1}, + new JoinMetadata + { + Description = "Far Camera Zoom In", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("FarCamZoomOut")] public JoinDataComplete FarEndCameraZoomOut = + new JoinDataComplete(new JoinData {JoinNumber = 36, JoinSpan = 1}, + new JoinMetadata + { + Description = "Far Camera Zoom Out", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + #endregion + + #region Camera Tracking Controls + + [JoinName("CameraTrackingOff")] public JoinDataComplete CameraTrackingOff = + new JoinDataComplete(new JoinData {JoinNumber = 52, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Tracking Off", + JoinType = eJoinType.Digital, + JoinCapabilities = eJoinCapabilities.ToFromSIMPL + }); + + [JoinName("CameraTrackingOn")] public JoinDataComplete CameraTrackingOn = + new JoinDataComplete(new JoinData {JoinNumber = 51, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Tracking On", + JoinType = eJoinType.Digital, + JoinCapabilities = eJoinCapabilities.ToFromSIMPL + }); + + [JoinName("CameraTrackingToggle")] public JoinDataComplete CameraTrackingToggle = new JoinDataComplete( new JoinData {JoinNumber = 53, JoinSpan = 1}, new JoinMetadata { @@ -237,9 +252,689 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + #endregion - public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof(VideoCodecControllerJoinMap)) + #region Incoming Call + + [JoinName("IncomingCallAnswer")] public JoinDataComplete IncomingCallAnswer = + new JoinDataComplete(new JoinData {JoinNumber = 61, JoinSpan = 1}, + new JoinMetadata + { + Description = "Answer Incoming Call & Incoming Call FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingCallId")] public JoinDataComplete IncomingCallId = + new JoinDataComplete(new JoinData {JoinNumber = 64, JoinSpan = 1}, + new JoinMetadata + { + Description = "Incoming Call ID", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallName")] public JoinDataComplete IncomingCallName = + new JoinDataComplete(new JoinData {JoinNumber = 61, JoinSpan = 1}, + new JoinMetadata + { + Description = "Incoming Call Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallNumber")] public JoinDataComplete IncomingCallNumber = + new JoinDataComplete(new JoinData {JoinNumber = 62, JoinSpan = 1}, + new JoinMetadata + { + Description = "Incoming Call Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallReject")] public JoinDataComplete IncomingCallReject = + new JoinDataComplete(new JoinData {JoinNumber = 62, JoinSpan = 1}, + new JoinMetadata + { + Description = "Reject Incoming Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingCallType")] public JoinDataComplete IncomingCallType = + new JoinDataComplete(new JoinData {JoinNumber = 63, JoinSpan = 1}, + new JoinMetadata + { + Description = "Incoming Call Type", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + #endregion + + #region Manual Dial + [JoinName("ManualDial")] + public JoinDataComplete ManualDial = new JoinDataComplete(new JoinData {JoinNumber = 71, JoinSpan = 1}, + new JoinMetadata + { + Description = "Dial Entered String", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("HangUpAllCalls")] + public JoinDataComplete HangUpAllCalls = new JoinDataComplete(new JoinData {JoinNumber = 72, JoinSpan = 1}, + new JoinMetadata + { + Description = "Hang up All calls", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("ManualDialString")] + public JoinDataComplete ManualDialString = new JoinDataComplete(new JoinData {JoinNumber = 71, JoinSpan = 1}, + new JoinMetadata + { + Description = "Manual String to dial", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + #endregion + + #region Connected Calls + + [JoinName("ConnectedCallCount")] + public JoinDataComplete ConnectedCallCount = new JoinDataComplete(new JoinData {JoinNumber = 81, JoinSpan = 1}, + new JoinMetadata + { + Description = "Connected Call Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("ConnectedCallHangup")] + public JoinDataComplete ConnectedCallHangupStart = + new JoinDataComplete(new JoinData {JoinNumber = 81, JoinSpan = 8}, + new JoinMetadata + { + Description = "Hang up selected call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ConnectedCallData")] public JoinDataComplete ConnectedCallData = + new JoinDataComplete(new JoinData {JoinNumber = 81, JoinSpan = 1}, + new JoinMetadata + { + Description = + "XSig - Connected Call info\r\nDigital 1: Connecting\r\nDigital 2: Connected\r\nSerial 1: Name\r\nSerial 2: Number\r\nSerial 3: Status\r\nSerial 4: Type\r\nSerial 5: ID", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + #endregion + #region NearEnd Source Select + + [JoinName("NearEndSourceSelect")] public JoinDataComplete NearEndSourceSelect = + new JoinDataComplete(new JoinData {JoinNumber = 5, JoinSpan = 1}, + new JoinMetadata + { + Description = "Near End Source Select", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog, + ValidValues = new[] {"1", "2", "3", "4"} + }); + #endregion + + #region Sharing + //Putting share start/stop only in this base join map. The map can be extended for features of other codecs + + public JoinDataComplete SharingStart = new JoinDataComplete(new JoinData {JoinNumber = 101, JoinSpan = 1}, + new JoinMetadata + { + Description = "Start sharing & feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + public JoinDataComplete SharingStop = new JoinDataComplete(new JoinData {JoinNumber = 102, JoinSpan = 1}, + new JoinMetadata + { + Description = "Stop Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + #endregion + + #region Phonebook + + #endregion*/ + + [JoinName("CallDirection")] public JoinDataComplete CallDirection = + new JoinDataComplete(new JoinData {JoinNumber = 22, JoinSpan = 1}, + new JoinMetadata + { + Description = "Current Call Direction", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraLayout")] public JoinDataComplete CameraLayout = + new JoinDataComplete(new JoinData {JoinNumber = 142, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Layout Toggle", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeAuto")] public JoinDataComplete CameraModeAuto = + new JoinDataComplete(new JoinData {JoinNumber = 131, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Mode Auto", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeManual")] public JoinDataComplete CameraModeManual = + new JoinDataComplete(new JoinData {JoinNumber = 132, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Mode Manual", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeOff")] public JoinDataComplete CameraModeOff = + new JoinDataComplete(new JoinData {JoinNumber = 133, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Mode Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraNumberSelect")] public JoinDataComplete CameraNumberSelect = + new JoinDataComplete(new JoinData {JoinNumber = 60, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Number Select/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraPanLeft")] public JoinDataComplete CameraPanLeft = + new JoinDataComplete(new JoinData {JoinNumber = 113, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Pan Left", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPanRight")] public JoinDataComplete CameraPanRight = + new JoinDataComplete(new JoinData {JoinNumber = 114, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Pan Right", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPresetSelect")] public JoinDataComplete CameraPresetSelect = + new JoinDataComplete(new JoinData {JoinNumber = 121, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Preset Select", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraPresetNames")] public JoinDataComplete CameraPresetNames = + new JoinDataComplete(new JoinData {JoinNumber = 121, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Preset Names - XSIG, max of 15", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraSelfView")] public JoinDataComplete CameraSelfView = + new JoinDataComplete(new JoinData {JoinNumber = 141, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Self View Toggle/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsAutoMode")] public JoinDataComplete CameraSupportsAutoMode = + new JoinDataComplete(new JoinData {JoinNumber = 143, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Supports Auto Mode FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsOffMode")] public JoinDataComplete CameraSupportsOffMode = + new JoinDataComplete(new JoinData {JoinNumber = 144, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Supports Off Mode FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraTiltDown")] public JoinDataComplete CameraTiltDown = + new JoinDataComplete(new JoinData {JoinNumber = 112, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Tilt Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraTiltUp")] public JoinDataComplete CameraTiltUp = + new JoinDataComplete(new JoinData {JoinNumber = 111, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Tilt Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomIn")] public JoinDataComplete CameraZoomIn = + new JoinDataComplete(new JoinData {JoinNumber = 115, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Zoom In", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomOut")] public JoinDataComplete CameraZoomOut = + new JoinDataComplete(new JoinData {JoinNumber = 116, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Zoom Out", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CurrentCallName")] public JoinDataComplete CurrentCallData = + new JoinDataComplete(new JoinData {JoinNumber = 2, JoinSpan = 1}, + new JoinMetadata + { + Description = "Current Call Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + /* + [JoinName("CurrentCallNumber")] public JoinDataComplete CurrentCallNumber = + new JoinDataComplete(new JoinData {JoinNumber = 3, JoinSpan = 1}, + new JoinMetadata + { + Description = "Current Call Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + });*/ + + [JoinName("CurrentDialString")] public JoinDataComplete CurrentDialString = + new JoinDataComplete(new JoinData {JoinNumber = 1, JoinSpan = 1}, + new JoinMetadata + { + Description = "Current Dial String", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryHasChanged")] public JoinDataComplete DirectoryHasChanged = + new JoinDataComplete(new JoinData {JoinNumber = 103, JoinSpan = 1}, + new JoinMetadata + { + Description = "Directory has changed FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryDialSelectedLine")] public JoinDataComplete DirectoryDialSelectedLine = + new JoinDataComplete(new JoinData {JoinNumber = 106, JoinSpan = 1}, + new JoinMetadata + { + Description = "Dial selected directory line", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryEntries")] public JoinDataComplete DirectoryEntries = + new JoinDataComplete(new JoinData {JoinNumber = 101, JoinSpan = 1}, + new JoinMetadata + { + Description = "Directory Entries - XSig, 255 entries", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntryIsContact")] public JoinDataComplete DirectoryEntryIsContact = + new JoinDataComplete(new JoinData {JoinNumber = 101, JoinSpan = 1}, + new JoinMetadata + { + Description = "Directory Selected Entry Is Contact FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryEntrySelectedName")] public JoinDataComplete DirectoryEntrySelectedName = + new JoinDataComplete(new JoinData {JoinNumber = 356, JoinSpan = 1}, + new JoinMetadata + { + Description = "Selected Directory Entry Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntrySelectedNumber")] public JoinDataComplete DirectoryEntrySelectedNumber = + new JoinDataComplete(new JoinData {JoinNumber = 357, JoinSpan = 1}, + new JoinMetadata + { + Description = "Selected Directory Entry Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryFolderBack")] public JoinDataComplete DirectoryFolderBack = + new JoinDataComplete(new JoinData {JoinNumber = 105, JoinSpan = 1}, + new JoinMetadata + { + Description = "Go back one directory level", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryIsRoot")] public JoinDataComplete DirectoryIsRoot = + new JoinDataComplete(new JoinData {JoinNumber = 102, JoinSpan = 1}, + new JoinMetadata + { + Description = "Directory is on Root FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryLineSelected")] public JoinDataComplete DirectoryLineSelected = + new JoinDataComplete(new JoinData {JoinNumber = 101, JoinSpan = 1}, + new JoinMetadata + { + Description = "Directory Line Selected FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryRoot")] public JoinDataComplete DirectoryRoot = + new JoinDataComplete(new JoinData {JoinNumber = 104, JoinSpan = 1}, + new JoinMetadata + { + Description = "Go to Directory Root", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryRowCount")] public JoinDataComplete DirectoryRowCount = + new JoinDataComplete(new JoinData {JoinNumber = 101, JoinSpan = 1}, + new JoinMetadata + { + Description = "Directory Row Count FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectorySearchBusy")] public JoinDataComplete DirectorySearchBusy = + new JoinDataComplete(new JoinData {JoinNumber = 100, JoinSpan = 1}, + new JoinMetadata + { + Description = "Directory Search Busy FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectorySearchString")] public JoinDataComplete DirectorySearchString = + new JoinDataComplete(new JoinData {JoinNumber = 100, JoinSpan = 1}, + new JoinMetadata + { + Description = "Directory Search String", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectorySelectRow")] public JoinDataComplete DirectorySelectRow = + new JoinDataComplete(new JoinData {JoinNumber = 101, JoinSpan = 1}, + new JoinMetadata + { + Description = "Directory Select Row", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectorySelectedFolderName")] public JoinDataComplete DirectorySelectedFolderName = + new JoinDataComplete(new JoinData {JoinNumber = 358, JoinSpan = 1}, + new JoinMetadata + { + Description = "Selected Directory Folder Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("0")] public JoinDataComplete Dtmf0 = + new JoinDataComplete(new JoinData {JoinNumber = 20, JoinSpan = 1}, + new JoinMetadata + { + Description = "DTMF 0", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("1")] public JoinDataComplete Dtmf1 = + new JoinDataComplete(new JoinData {JoinNumber = 11, JoinSpan = 1}, + new JoinMetadata + { + Description = "DTMF 1", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("2")] public JoinDataComplete Dtmf2 = + new JoinDataComplete(new JoinData {JoinNumber = 12, JoinSpan = 1}, + new JoinMetadata + { + Description = "DTMF 2", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("3")] public JoinDataComplete Dtmf3 = + new JoinDataComplete(new JoinData {JoinNumber = 13, JoinSpan = 1}, + new JoinMetadata + { + Description = "DTMF 3", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("4")] public JoinDataComplete Dtmf4 = + new JoinDataComplete(new JoinData {JoinNumber = 14, JoinSpan = 1}, + new JoinMetadata + { + Description = "DTMF 4", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("5")] public JoinDataComplete Dtmf5 = + new JoinDataComplete(new JoinData {JoinNumber = 15, JoinSpan = 1}, + new JoinMetadata + { + Description = "DTMF 5", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("6")] public JoinDataComplete Dtmf6 = + new JoinDataComplete(new JoinData {JoinNumber = 16, JoinSpan = 1}, + new JoinMetadata + { + Description = "DTMF 6", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("7")] public JoinDataComplete Dtmf7 = + new JoinDataComplete(new JoinData {JoinNumber = 17, JoinSpan = 1}, + new JoinMetadata + { + Description = "DTMF 7", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("8")] public JoinDataComplete Dtmf8 = + new JoinDataComplete(new JoinData {JoinNumber = 18, JoinSpan = 1}, + new JoinMetadata + { + Description = "DTMF 8", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("9")] public JoinDataComplete Dtmf9 = + new JoinDataComplete(new JoinData {JoinNumber = 19, JoinSpan = 1}, + new JoinMetadata + { + Description = "DTMF 9", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("#")] public JoinDataComplete DtmfPound = + new JoinDataComplete(new JoinData {JoinNumber = 22, JoinSpan = 1}, + new JoinMetadata + { + Description = "DTMF #", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("*")] public JoinDataComplete DtmfStar = + new JoinDataComplete(new JoinData {JoinNumber = 21, JoinSpan = 1}, + new JoinMetadata + { + Description = "DTMF *", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("EndCall")] public JoinDataComplete EndCall = + new JoinDataComplete(new JoinData {JoinNumber = 24, JoinSpan = 1}, + new JoinMetadata + { + Description = "Hang Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("HookState")] public JoinDataComplete HookState = + new JoinDataComplete(new JoinData {JoinNumber = 31, JoinSpan = 1}, + new JoinMetadata + { + Description = "Current Hook State", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingAnswer")] public JoinDataComplete IncomingAnswer = + new JoinDataComplete(new JoinData {JoinNumber = 51, JoinSpan = 1}, + new JoinMetadata + { + Description = "Answer Incoming Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingCall")] public JoinDataComplete IncomingCall = + new JoinDataComplete(new JoinData {JoinNumber = 50, JoinSpan = 1}, + new JoinMetadata + { + Description = "Incoming Call", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingCallName")] public JoinDataComplete IncomingCallName = + new JoinDataComplete(new JoinData {JoinNumber = 51, JoinSpan = 1}, + new JoinMetadata + { + Description = "Incoming Call Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallNumber")] public JoinDataComplete IncomingCallNumber = + new JoinDataComplete(new JoinData {JoinNumber = 52, JoinSpan = 1}, + new JoinMetadata + { + Description = "Incoming Call Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingReject")] public JoinDataComplete IncomingReject = + new JoinDataComplete(new JoinData {JoinNumber = 52, JoinSpan = 1}, + new JoinMetadata + { + Description = "Reject Incoming Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SpeedDialStart")] public JoinDataComplete SpeedDialStart = + new JoinDataComplete(new JoinData {JoinNumber = 41, JoinSpan = 4}, + new JoinMetadata + { + Description = "Speed Dial", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Schedule")] public JoinDataComplete Schedule = + new JoinDataComplete(new JoinData {JoinNumber = 102, JoinSpan = 1}, + new JoinMetadata + { + Description = "Schedule Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraLayoutStringFb")] + public JoinDataComplete CameraLayoutStringFb = + new JoinDataComplete(new JoinData { JoinNumber = 141, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Current Layout Fb", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("ManualDial")] public JoinDataComplete ManualDial = + new JoinDataComplete(new JoinData {JoinNumber = 71, JoinSpan = 1}, + new JoinMetadata + { + Description = "Dial manual string", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof (VideoCodecControllerJoinMap)) { } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index fe18e7ca..55969a71 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -2,14 +2,21 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharp.Ssh; using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; +using PepperDash.Core.Intersystem; +using PepperDash.Core.Intersystem.Tokens; +using PepperDash.Core.WebApi.Presets; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Devices; using PepperDash.Essentials.Core.Routing; +using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; +using PepperDash_Essentials_Core.Bridges.JoinMaps; using Feedback = PepperDash.Essentials.Core.Feedback; namespace PepperDash.Essentials.Devices.Common.VideoCodec @@ -17,9 +24,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutputs, IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced { + private const int XSigEncoding = 28591; protected VideoCodecBase(DeviceConfig config) : base(config) { + StandbyIsOnFeedback = new BoolFeedback(StandbyIsOnFeedbackFunc); PrivacyModeIsOnFeedback = new BoolFeedback(PrivacyModeIsOnFeedbackFunc); VolumeLevelFeedback = new IntFeedback(VolumeLevelFeedbackFunc); @@ -255,6 +264,295 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); + protected void LinkVideoCodecToApi(VideoCodecBase codec, BasicTriList trilist, uint joinStart, string joinMapKey, + EiscApiAdvanced bridge) + { + var joinMap = new VideoCodecControllerJoinMap(joinStart); + + var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); + + if (customJoins != null) + { + joinMap.SetCustomJoinData(customJoins); + } + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + + Debug.Console(1, this, "Linking to Trilist {0}", trilist.ID.ToString("X")); + + LinkVideoCodecDtmfToApi(trilist, joinMap); + + LinkVideoCodecCallControlsToApi(trilist, joinMap); + + if (codec is IHasCodecCameras) + { + LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap); + } + + if (codec is IHasCodecSelfView) + { + LinkVideoCodecSelfviewToApi(codec as IHasCodecSelfView, trilist, joinMap); + } + + if (codec is IHasCameraAutoMode) + { + trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true); + LinkVideoCodecCameraModeToApi(codec as IHasCameraAutoMode, trilist, joinMap); + } + + if (codec is IHasCodecLayouts) + { + LinkVideoCodecCameraLayoutsToApi(codec as IHasCodecLayouts, trilist, joinMap); + } + + + } + + private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + trilist.SetSigFalseAction(joinMap.ManualDial.JoinNumber, + () => Dial(trilist.StringOutput[joinMap.CurrentDialString.JoinNumber].StringValue)); + + //End All calls for now + trilist.SetSigFalseAction(joinMap.EndCall.JoinNumber, EndAllCalls); + + + + CallStatusChange += (sender, args) => + { + trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); + + trilist.SetBool(joinMap.IncomingCall.JoinNumber, args.CallItem.Direction == eCodecCallDirection.Incoming); + + if (args.CallItem.Direction == eCodecCallDirection.Incoming) + { + trilist.SetSigFalseAction(joinMap.IncomingAnswer.JoinNumber, () => AcceptCall(args.CallItem)); + trilist.SetSigFalseAction(joinMap.IncomingReject.JoinNumber, () => RejectCall(args.CallItem)); + } + + var callStatusXsig = UpdateCallStatusXSig(); + + trilist.SetString(joinMap.CurrentCallData.JoinNumber, callStatusXsig); + }; + } + + private string UpdateCallStatusXSig() + { + const int offset = 6; + var callIndex = 1; + + + var tokenArray = new XSigToken[ActiveCalls.Count*offset]; //set array size for number of calls * pieces of info + + foreach (var call in ActiveCalls) + { + //digitals + tokenArray[callIndex] = new XSigDigitalToken((callIndex/offset) + 1, call.IsActiveCall); + + //serials + tokenArray[callIndex + 1] = new XSigSerialToken(callIndex, call.Name); + tokenArray[callIndex + 2] = new XSigSerialToken(callIndex + 1, call.Number); + tokenArray[callIndex + 3] = new XSigSerialToken(callIndex + 2, call.Direction.ToString()); + tokenArray[callIndex + 4] = new XSigSerialToken(callIndex + 3, call.Type.ToString()); + tokenArray[callIndex + 5] = new XSigSerialToken(callIndex + 4, call.Status.ToString()); + + callIndex += offset; + } + + return GetXSigString(tokenArray); + } + + private void LinkVideoCodecDtmfToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + trilist.SetSigFalseAction(joinMap.Dtmf0.JoinNumber, () => SendDtmf("0")); + trilist.SetSigFalseAction(joinMap.Dtmf1.JoinNumber, () => SendDtmf("1")); + trilist.SetSigFalseAction(joinMap.Dtmf2.JoinNumber, () => SendDtmf("2")); + trilist.SetSigFalseAction(joinMap.Dtmf3.JoinNumber, () => SendDtmf("3")); + trilist.SetSigFalseAction(joinMap.Dtmf4.JoinNumber, () => SendDtmf("4")); + trilist.SetSigFalseAction(joinMap.Dtmf5.JoinNumber, () => SendDtmf("5")); + trilist.SetSigFalseAction(joinMap.Dtmf6.JoinNumber, () => SendDtmf("6")); + trilist.SetSigFalseAction(joinMap.Dtmf7.JoinNumber, () => SendDtmf("7")); + trilist.SetSigFalseAction(joinMap.Dtmf8.JoinNumber, () => SendDtmf("8")); + trilist.SetSigFalseAction(joinMap.Dtmf9.JoinNumber, () => SendDtmf("9")); + trilist.SetSigFalseAction(joinMap.DtmfStar.JoinNumber, () => SendDtmf("*")); + trilist.SetSigFalseAction(joinMap.DtmfPound.JoinNumber, () => SendDtmf("#")); + } + + private void LinkVideoCodecCameraLayoutsToApi(IHasCodecLayouts codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + trilist.SetSigFalseAction(joinMap.CameraLayout.JoinNumber, codec.LocalLayoutToggle); + + codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.CameraLayoutStringFb.JoinNumber]); + } + + private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + trilist.SetSigFalseAction(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeOn); + trilist.SetSigFalseAction(joinMap.CameraModeManual.JoinNumber, codec.CameraAutoModeOff); + + codec.CameraAutoModeIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.CameraModeAuto.JoinNumber]); + codec.CameraAutoModeIsOnFeedback.LinkComplementInputSig( + trilist.BooleanInput[joinMap.CameraModeManual.JoinNumber]); + } + + private void LinkVideoCodecSelfviewToApi(IHasCodecSelfView codec, BasicTriList trilist, + VideoCodecControllerJoinMap joinMap) + { + trilist.SetSigFalseAction(joinMap.CameraSelfView.JoinNumber, codec.SelfViewModeToggle); + + codec.SelfviewIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.CameraSelfView.JoinNumber]); + } + + private void LinkVideoCodecCameraToApi(IHasCodecCameras codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + //Camera PTZ + trilist.SetBoolSigAction(joinMap.CameraTiltUp.JoinNumber, (b) => + { + if (codec.SelectedCamera == null) return; + var camera = codec.SelectedCamera as IHasCameraPtzControl; + + if (camera == null) return; + + if (b) camera.TiltUp(); + else camera.TiltStop(); + }); + + trilist.SetBoolSigAction(joinMap.CameraTiltDown.JoinNumber, (b) => + { + if (codec.SelectedCamera == null) return; + var camera = codec.SelectedCamera as IHasCameraPtzControl; + + if (camera == null) return; + + if (b) camera.TiltDown(); + else camera.TiltStop(); + }); + trilist.SetBoolSigAction(joinMap.CameraPanLeft.JoinNumber, (b) => + { + if (codec.SelectedCamera == null) return; + var camera = codec.SelectedCamera as IHasCameraPtzControl; + + if (camera == null) return; + + if (b) camera.PanLeft(); + else camera.PanStop(); + }); + trilist.SetBoolSigAction(joinMap.CameraPanRight.JoinNumber, (b) => + { + if (codec.SelectedCamera == null) return; + var camera = codec.SelectedCamera as IHasCameraPtzControl; + + if (camera == null) return; + + if (b) camera.PanRight(); + else camera.PanStop(); + }); + + trilist.SetBoolSigAction(joinMap.CameraZoomIn.JoinNumber, (b) => + { + if (codec.SelectedCamera == null) return; + var camera = codec.SelectedCamera as IHasCameraPtzControl; + + if (camera == null) return; + + if (b) camera.ZoomIn(); + else camera.ZoomStop(); + }); + + trilist.SetBoolSigAction(joinMap.CameraZoomOut.JoinNumber, (b) => + { + if (codec.SelectedCamera == null) return; + var camera = codec.SelectedCamera as IHasCameraPtzControl; + + if (camera == null) return; + + if (b) camera.ZoomOut(); + else camera.ZoomStop(); + }); + + //Camera Select + trilist.SetUShortSigAction(joinMap.CameraNumberSelect.JoinNumber, (i) => + { + if (codec.SelectedCamera == null) return; + + codec.SelectCamera(codec.Cameras[i].Key); + }); + + codec.CameraSelected += (sender, args) => + { + var i = (ushort) codec.Cameras.FindIndex((c) => c.Key == args.SelectedCamera.Key); + + trilist.SetUshort(joinMap.CameraPresetSelect.JoinNumber, i); + + if (codec is IHasCodecRoomPresets) + { + return; + } + + if (!(args.SelectedCamera is IHasCameraPresets)) + { + return; + } + + var cam = args.SelectedCamera as IHasCameraPresets; + SetCameraPresetNames(cam.Presets); + + (args.SelectedCamera as IHasCameraPresets).PresetsListHasChanged += (o, eventArgs) => SetCameraPresetNames(cam.Presets); + }; + + //Camera Presets + trilist.SetUShortSigAction(joinMap.CameraPresetSelect.JoinNumber, (i) => + { + if (codec.SelectedCamera == null) return; + + var cam = codec.SelectedCamera as IHasCameraPresets; + + if (cam == null) return; + + cam.PresetSelect(i); + + trilist.SetUshort(joinMap.CameraPresetSelect.JoinNumber, i); + }); + } + + private string SetCameraPresetNames(List presets) + { + var i = 1; //start index for xsig; + + var tokenArray = new XSigToken[presets.Count]; + + string returnString; + + foreach (var token in presets.Select(cameraPreset => new XSigSerialToken(i, cameraPreset.Description))) + { + tokenArray[i - 1] = token; + i++; + } + + return GetXSigString(tokenArray); + } + + private string GetXSigString(XSigToken[] tokenArray) + { + string returnString; + using (var s = new MemoryStream()) + { + using (var tw = new XSigTokenStreamWriter(s, true)) + { + tw.WriteXSigData(tokenArray); + } + + var xSig = s.ToArray(); + + returnString = Encoding.GetEncoding(XSigEncoding).GetString(xSig, 0, xSig.Length); + } + + return returnString; + } + #endregion } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index d25abb22..ba5dc3e4 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -1401,49 +1401,46 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - var joinMap = new VideoCodecControllerJoinMap(joinStart); - - var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); - - if (customJoins != null) - { - joinMap.SetCustomJoinData(customJoins); - } - - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - - Debug.Console(1, this, "Linking to Trilist {0}", trilist.ID.ToString("X")); - - LinkCameraActions(trilist, joinMap); - } - - private void LinkCameraActions(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) - { - + LinkVideoCodecToApi(this, trilist, joinStart, joinMapKey, bridge); } public override void ExecuteSwitch(object selector) { - (selector as Action)(); + var action = selector as Action; + if (action == null) + { + return; + } + + action(); + } + + public void AcceptCall() + { + var incomingCall = + ActiveCalls.FirstOrDefault( + c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); + + AcceptCall(incomingCall); } public override void AcceptCall(CodecActiveCallItem call) { - var incomingCall = - ActiveCalls.FirstOrDefault( - c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); - SendText(string.Format("zCommand Call Accept callerJID: {0}", incomingCall.Id)); + SendText(string.Format("zCommand Call Accept callerJID: {0}", call.Id)); } - public override void RejectCall(CodecActiveCallItem call) + public void RejectCall() { var incomingCall = ActiveCalls.FirstOrDefault( c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); - SendText(string.Format("zCommand Call Reject callerJID: {0}", incomingCall.Id)); + + RejectCall(incomingCall); + } + + public override void RejectCall(CodecActiveCallItem call) + { + SendText(string.Format("zCommand Call Reject callerJID: {0}", call.Id)); } public override void Dial(Meeting meeting) From 832060e8ad6ddc4d4f375b8084d282be23e84540 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 21 Sep 2020 18:59:17 -0600 Subject: [PATCH 08/42] Lots of changes * Copied join map from Mobile Control * Started implementing for JoinMapBase * Made some changes and improvements to ZoomRoom for handling Directory stuff --- .../PepperDash_Essentials_Core.csproj | 36 ++---- .../PepperDash_Essentials_DM.csproj | 15 +-- .../Codec/iHasDirectory.cs | 13 ++- .../Essentials Devices Common.csproj | 18 +-- .../VideoCodec/VideoCodecBase.cs | 107 ++++++++++++++++-- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 24 ++-- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 55 ++++----- 7 files changed, 165 insertions(+), 103 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 83916856..8c7bc10c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -48,48 +48,39 @@ False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DM.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DM.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.EthernetCommunications.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.EthernetCommunications.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Fusion.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Fusion.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.GeneralIO.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.GeneralIO.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Remotes.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Remotes.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.ThreeSeriesCards.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.ThreeSeriesCards.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll @@ -108,8 +99,7 @@ False - ..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll False @@ -118,13 +108,11 @@ False - ..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SimplSharpTimerEventInterface.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpTimerEventInterface.dll diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj index 7c8b163a..7d6b7bde 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -48,18 +48,15 @@ False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DM.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DM.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll @@ -78,8 +75,7 @@ False - ..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll False @@ -88,8 +84,7 @@ False - ..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs index 3a984ab2..3a59b62d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs @@ -40,9 +40,15 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// /// Tracks the directory browse history when browsing beyond the root directory /// + [Obsolete("Please use the Stack-based history instead")] List DirectoryBrowseHistory { get; } } + public interface IHasDirectoryHistoryStack : IHasDirectory + { + Stack DirectoryBrowseHistoryStack { get; } + } + /// /// /// @@ -147,6 +153,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec [JsonProperty("name")] public string Name { get; set; } + + [JsonProperty("parentFolderId")] + public string ParentFolderId { get; set; } } /// @@ -157,8 +166,6 @@ namespace PepperDash.Essentials.Devices.Common.Codec [JsonProperty("contacts")] public List Contacts { get; set; } - [JsonProperty("parentFolderId")] - public string ParentFolderId { get; set; } public DirectoryFolder() { @@ -177,6 +184,8 @@ namespace PepperDash.Essentials.Devices.Common.Codec [JsonProperty("title")] public string Title { get; set; } + + [JsonProperty("contactMethods")] public List ContactMethods { get; set; } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index d18cb6ce..d3d468fc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -48,23 +48,19 @@ False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.GeneralIO.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.GeneralIO.dll False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Lighting.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Lighting.dll @@ -83,8 +79,7 @@ False - ..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll False @@ -93,8 +88,7 @@ False - ..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll - True + ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 55969a71..7c5c784b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -308,9 +308,95 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecCameraLayoutsToApi(codec as IHasCodecLayouts, trilist, joinMap); } + if (codec is IHasDirectory) + { + LinkVideoCodecDirectoryToApi(codec as IHasDirectory, trilist, joinMap); + } } + private void LinkVideoCodecDirectoryToApi(IHasDirectory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + codec.CurrentDirectoryResultIsNotDirectoryRoot.LinkComplementInputSig( + trilist.BooleanInput[joinMap.DirectoryIsRoot.JoinNumber]); + + trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot); + + trilist.SetStringSigAction(joinMap.DirectorySearchString.JoinNumber, codec.SearchDirectory); + + trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i)); + + trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot); + + trilist.SetSigFalseAction(joinMap.DirectoryFolderBack.JoinNumber, codec.GetDirectoryParentFolderContents); + + codec.DirectoryResultReturned += (sender, args) => + { + trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort) args.Directory.CurrentDirectoryResults.Count); + + var clearBytes = XSigHelpers.ClearOutputs(); + + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var directoryXSig = UpdateDirectoryXSig(args.Directory, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); + + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); + }; + } + + private void SelectDirectoryEntry(IHasDirectory codec, ushort i) + { + var entry = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1]; + + if (entry is DirectoryFolder) + { + codec.GetDirectoryFolderContents(entry.FolderId); + return; + } + + var dialableEntry = entry as IInvitableContact; + + if (dialableEntry != null) + { + Dial(dialableEntry); + return; + } + + var entryToDial = entry as DirectoryContact; + + if (entryToDial == null) return; + + Dial(entryToDial.ContactMethods[0].Number); + } + + private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) + { + var contactIndex = 1; + var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count]; + + foreach(var entry in directory.CurrentDirectoryResults) + { + var arrayIndex = contactIndex - 1; + + if (entry is DirectoryFolder && entry.ParentFolderId == "root") + { + tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, String.Format("[+] {0}", entry.Name)); + + contactIndex++; + + continue; + } + + if(isRoot && String.IsNullOrEmpty(entry.FolderId)) continue; + + tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, entry.Name); + + contactIndex++; + } + + return GetXSigString(tokenArray); + } + private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { trilist.SetSigFalseAction(joinMap.ManualDial.JoinNumber, @@ -319,8 +405,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //End All calls for now trilist.SetSigFalseAction(joinMap.EndCall.JoinNumber, EndAllCalls); - - CallStatusChange += (sender, args) => { trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); @@ -341,25 +425,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec private string UpdateCallStatusXSig() { + const int maxCalls = 8; + const int maxStrings = 5; const int offset = 6; - var callIndex = 1; + var callIndex = 0; + var digitalIndex = maxStrings*maxCalls; var tokenArray = new XSigToken[ActiveCalls.Count*offset]; //set array size for number of calls * pieces of info foreach (var call in ActiveCalls) { + var arrayIndex = callIndex; //digitals - tokenArray[callIndex] = new XSigDigitalToken((callIndex/offset) + 1, call.IsActiveCall); + tokenArray[arrayIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall); //serials - tokenArray[callIndex + 1] = new XSigSerialToken(callIndex, call.Name); - tokenArray[callIndex + 2] = new XSigSerialToken(callIndex + 1, call.Number); - tokenArray[callIndex + 3] = new XSigSerialToken(callIndex + 2, call.Direction.ToString()); - tokenArray[callIndex + 4] = new XSigSerialToken(callIndex + 3, call.Type.ToString()); - tokenArray[callIndex + 5] = new XSigSerialToken(callIndex + 4, call.Status.ToString()); + tokenArray[arrayIndex + 1] = new XSigSerialToken(callIndex + 1, call.Name ?? String.Empty); + tokenArray[arrayIndex + 2] = new XSigSerialToken(callIndex + 2, call.Number ?? String.Empty); + tokenArray[arrayIndex + 3] = new XSigSerialToken(callIndex + 3, call.Direction.ToString()); + tokenArray[arrayIndex + 4] = new XSigSerialToken(callIndex + 4, call.Type.ToString()); + tokenArray[arrayIndex + 5] = new XSigSerialToken(callIndex + 5, call.Status.ToString()); callIndex += offset; + digitalIndex++; } return GetXSigString(tokenArray); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index c603ca08..780b7d29 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -255,9 +255,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// public static CodecDirectory ConvertZoomContactsToGeneric(List zoomContacts) { - var directory = new Codec.CodecDirectory(); + var directory = new CodecDirectory(); - var folders = new List(); + var folders = new List(); var roomFolder = new DirectoryFolder(); @@ -272,9 +272,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { // If so, setup a rooms and contacts folder and add them. roomFolder.Name = "Rooms"; + roomFolder.ParentFolderId = "root"; roomFolder.FolderId = "rooms"; contactFolder.Name = "Contacts"; + contactFolder.ParentFolderId = "root"; contactFolder.FolderId = "contacts"; folders.Add(roomFolder); @@ -285,21 +287,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom try { - if (zoomContacts.Count > 0) + if (zoomContacts.Count == 0) return directory; { foreach (Contact c in zoomContacts) { - var contact = new ZoomDirectoryContact(); - - contact.Name = c.ScreenName; - contact.ContactId = c.Jid; + var contact = new ZoomDirectoryContact {Name = c.ScreenName, ContactId = c.Jid}; if (folders.Count > 0) { - if (c.IsZoomRoom) - contact.FolderId = roomFolder.FolderId; - else - contact.FolderId = contactFolder.FolderId; + contact.ParentFolderId = c.IsZoomRoom ? "rooms" : "contacts"; } contacts.Add(contact); @@ -577,7 +573,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public string meetingID { get; set; } public string password { get; set; } public string meetingOption { get; set; } - public int MeetingNumber { get; set; } + public long MeetingNumber { get; set; } public string callerName { get; set; } public string avatarURL { get; set; } public int lifeTime { get; set; } @@ -831,13 +827,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { get { - return this._volume; + return _volume; } set { if (value != _volume) { - this._volume = value; + _volume = value; NotifyPropertyChanged("Volume"); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index ba5dc3e4..5fec376c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -18,7 +18,7 @@ using PepperDash_Essentials_Core.Bridges.JoinMaps; namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { - public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectory, ICommunicationMonitor, IRouting, + public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, IRouting, IHasScheduleAwareness, IHasCodecCameras { private readonly CrestronQueue ReceiveQueue; @@ -277,19 +277,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public event EventHandler DirectoryResultReturned; public CodecDirectory DirectoryRoot { get; private set; } + private CodecDirectory _currentDirectoryResult; public CodecDirectory CurrentDirectoryResult { - get - { - if (DirectoryBrowseHistory.Count > 0) - { - return DirectoryBrowseHistory[DirectoryBrowseHistory.Count - 1]; - } - else - { - return DirectoryRoot; - } - } + get { return _currentDirectoryResult; } } public CodecPhonebookSyncState PhonebookSyncState { get; private set; } @@ -302,48 +293,42 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom DirectoryRoot.CurrentDirectoryResults.FindAll( c => c.Name.IndexOf(searchString, 0, StringComparison.OrdinalIgnoreCase) > -1)); - DirectoryBrowseHistory.Add(directoryResults); + DirectoryBrowseHistoryStack.Push(_currentDirectoryResult); + _currentDirectoryResult = directoryResults; OnDirectoryResultReturned(directoryResults); } public void GetDirectoryFolderContents(string folderId) { - var directoryResults = new CodecDirectory(); + var directoryResults = new CodecDirectory {ResultsFolderId = folderId}; - directoryResults.ResultsFolderId = folderId; directoryResults.AddContactsToDirectory( - DirectoryRoot.CurrentDirectoryResults.FindAll(c => c.FolderId.Equals(folderId))); + DirectoryRoot.CurrentDirectoryResults.FindAll(c => c.ParentFolderId.Equals(folderId))); - DirectoryBrowseHistory.Add(directoryResults); + DirectoryBrowseHistoryStack.Push(_currentDirectoryResult); + + _currentDirectoryResult = directoryResults; OnDirectoryResultReturned(directoryResults); } public void SetCurrentDirectoryToRoot() { - DirectoryBrowseHistory.Clear(); + DirectoryBrowseHistoryStack.Clear(); + + _currentDirectoryResult = DirectoryRoot; OnDirectoryResultReturned(DirectoryRoot); } public void GetDirectoryParentFolderContents() { - var currentDirectory = new CodecDirectory(); + if (DirectoryBrowseHistoryStack.Count == 0) return; - if (DirectoryBrowseHistory.Count > 0) - { - var lastItemIndex = DirectoryBrowseHistory.Count - 1; - var parentDirectoryContents = DirectoryBrowseHistory[lastItemIndex]; + var currentDirectory = DirectoryBrowseHistoryStack.Pop(); - DirectoryBrowseHistory.Remove(DirectoryBrowseHistory[lastItemIndex]); - - currentDirectory = parentDirectoryContents; - } - else - { - currentDirectory = DirectoryRoot; - } + _currentDirectoryResult = currentDirectory; OnDirectoryResultReturned(currentDirectory); } @@ -352,6 +337,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public List DirectoryBrowseHistory { get; private set; } + public Stack DirectoryBrowseHistoryStack { get; private set; } + #endregion #region IHasScheduleAwareness Members @@ -452,8 +439,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom DirectoryRoot = new CodecDirectory(); DirectoryBrowseHistory = new List(); + DirectoryBrowseHistoryStack = new Stack(); - CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => DirectoryBrowseHistory.Count > 0); + CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => DirectoryBrowseHistoryStack.Count > 0); CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); } @@ -828,6 +816,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom PhonebookSyncState.PhonebookRootEntriesReceived(); PhonebookSyncState.SetPhonebookHasFolders(false); PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); + } var directoryResults = new CodecDirectory(); @@ -837,6 +826,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom DirectoryRoot = directoryResults; + _currentDirectoryResult = DirectoryRoot; + OnDirectoryResultReturned(directoryResults); break; From 9d15704b78a6338e614124c9685132580bde950d Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 23 Sep 2020 08:51:44 -0600 Subject: [PATCH 09/42] cleaning some things up and getting more pieces working --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 432 ++---------------- .../VideoCodec/VideoCodecBase.cs | 91 +++- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 6 + .../VideoCodec/ZoomRoom/ZoomRoom.cs | 407 ++++++++--------- 4 files changed, 311 insertions(+), 625 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 617262f4..b1c46717 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -18,399 +18,6 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps #endregion - /*#region NearEndCameraControls - - [JoinName("NearCamDown")] public JoinDataComplete NearEndCameraDown = - new JoinDataComplete(new JoinData {JoinNumber = 12, JoinSpan = 1}, - new JoinMetadata - { - Description = "Near Camera Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("NearCamFocusFar")] public JoinDataComplete NearEndCameraFocusFar = - new JoinDataComplete(new JoinData {JoinNumber = 18, JoinSpan = 1}, - new JoinMetadata - { - Description = "Near Camera Focus Far", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("NearCamFocusNear")] public JoinDataComplete NearEndCameraFocusNear = - new JoinDataComplete(new JoinData {JoinNumber = 17, JoinSpan = 1}, - new JoinMetadata - { - Description = "Near Camera Focus Near", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("NearCamLeft")] public JoinDataComplete NearEndCameraLeft = - new JoinDataComplete(new JoinData {JoinNumber = 13, JoinSpan = 1}, - new JoinMetadata - { - Description = "Near Camera Left", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("NearCamPresetNames")] public JoinDataComplete NearEndCameraNames = - new JoinDataComplete(new JoinData {JoinNumber = 11, JoinSpan = 1}, - new JoinMetadata - { - Description = "XSig - Camera Names", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("NearCamPresetSave")] public JoinDataComplete NearEndCameraPresetSave = - new JoinDataComplete(new JoinData {JoinNumber = 21, JoinSpan = 1}, - new JoinMetadata - { - Description = "Save Current Preset", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("NearCamPresetSelect")] public JoinDataComplete NearEndCameraPresetSelect = - new JoinDataComplete(new JoinData {JoinNumber = 31, JoinSpan = 1}, - new JoinMetadata - { - Description = "Recall Preset", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("NearCamRight")] public JoinDataComplete NearEndCameraRight = - new JoinDataComplete(new JoinData {JoinNumber = 14, JoinSpan = 1}, - new JoinMetadata - { - Description = "Near Camera Right", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("NearCamSelectAnalog")] public JoinDataComplete NearEndCameraSelectAnalog = new JoinDataComplete( - new JoinData {JoinNumber = 12, JoinSpan = 1}, - new JoinMetadata - { - Description = "Camera Select & Feedback by index", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("NearCamSelectSerial")] public JoinDataComplete NearEndCameraSelectSerial = new JoinDataComplete( - new JoinData {JoinNumber = 12, JoinSpan = 1}, - new JoinMetadata - { - Description = "Camera Select & Feedback by name", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("NearCamUp")] public JoinDataComplete NearEndCameraUp = - new JoinDataComplete(new JoinData {JoinNumber = 11, JoinSpan = 1}, - new JoinMetadata - { - Description = "Near Camera Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("NearCamZoomIn")] public JoinDataComplete NearEndCameraZoomIn = - new JoinDataComplete(new JoinData {JoinNumber = 15, JoinSpan = 1}, - new JoinMetadata - { - Description = "Near Camera Zoom In", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("NearCamZoomOut")] public JoinDataComplete NearEndCameraZoomOut = - new JoinDataComplete(new JoinData {JoinNumber = 16, JoinSpan = 1}, - new JoinMetadata - { - Description = "Near Camera Zoom Out", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - #endregion - - #region Far End Camera Controls - - [JoinName("FarCamDown")] public JoinDataComplete FarEndCameraDown = - new JoinDataComplete(new JoinData {JoinNumber = 32, JoinSpan = 1}, - new JoinMetadata - { - Description = "Far Camera Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("FarCamFocusFar")] public JoinDataComplete FarEndCameraFocusFar = - new JoinDataComplete(new JoinData {JoinNumber = 38, JoinSpan = 1}, - new JoinMetadata - { - Description = "Far Camera Focus Far", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("FarCamFocusNear")] public JoinDataComplete FarEndCameraFocusNear = - new JoinDataComplete(new JoinData {JoinNumber = 37, JoinSpan = 1}, - new JoinMetadata - { - Description = "Far Camera Focus Near", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("FarCamLeft")] public JoinDataComplete FarEndCameraLeft = - new JoinDataComplete(new JoinData {JoinNumber = 33, JoinSpan = 1}, - new JoinMetadata - { - Description = "Far Camera Left", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("FarCamPresetSelect")] public JoinDataComplete FarEndCameraPresetSelect = - new JoinDataComplete(new JoinData {JoinNumber = 41, JoinSpan = 1}, - new JoinMetadata - { - Description = "Recall Preset", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("FarCamRight")] public JoinDataComplete FarEndCameraRight = - new JoinDataComplete(new JoinData {JoinNumber = 34, JoinSpan = 1}, - new JoinMetadata - { - Description = "Far Camera Right", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("FarCamUp")] public JoinDataComplete FarEndCameraUp = - new JoinDataComplete(new JoinData {JoinNumber = 31, JoinSpan = 1}, - new JoinMetadata - { - Description = "Far Camera Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("FarCamZoomIn")] public JoinDataComplete FarEndCameraZoomIn = - new JoinDataComplete(new JoinData {JoinNumber = 35, JoinSpan = 1}, - new JoinMetadata - { - Description = "Far Camera Zoom In", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("FarCamZoomOut")] public JoinDataComplete FarEndCameraZoomOut = - new JoinDataComplete(new JoinData {JoinNumber = 36, JoinSpan = 1}, - new JoinMetadata - { - Description = "Far Camera Zoom Out", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - #endregion - - #region Camera Tracking Controls - - [JoinName("CameraTrackingOff")] public JoinDataComplete CameraTrackingOff = - new JoinDataComplete(new JoinData {JoinNumber = 52, JoinSpan = 1}, - new JoinMetadata - { - Description = "Camera Tracking Off", - JoinType = eJoinType.Digital, - JoinCapabilities = eJoinCapabilities.ToFromSIMPL - }); - - [JoinName("CameraTrackingOn")] public JoinDataComplete CameraTrackingOn = - new JoinDataComplete(new JoinData {JoinNumber = 51, JoinSpan = 1}, - new JoinMetadata - { - Description = "Camera Tracking On", - JoinType = eJoinType.Digital, - JoinCapabilities = eJoinCapabilities.ToFromSIMPL - }); - - [JoinName("CameraTrackingToggle")] public JoinDataComplete CameraTrackingToggle = new JoinDataComplete( - new JoinData {JoinNumber = 53, JoinSpan = 1}, - new JoinMetadata - { - Description = "Camera Tracking Toggle", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - #endregion - - #region Incoming Call - - [JoinName("IncomingCallAnswer")] public JoinDataComplete IncomingCallAnswer = - new JoinDataComplete(new JoinData {JoinNumber = 61, JoinSpan = 1}, - new JoinMetadata - { - Description = "Answer Incoming Call & Incoming Call FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingCallId")] public JoinDataComplete IncomingCallId = - new JoinDataComplete(new JoinData {JoinNumber = 64, JoinSpan = 1}, - new JoinMetadata - { - Description = "Incoming Call ID", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallName")] public JoinDataComplete IncomingCallName = - new JoinDataComplete(new JoinData {JoinNumber = 61, JoinSpan = 1}, - new JoinMetadata - { - Description = "Incoming Call Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallNumber")] public JoinDataComplete IncomingCallNumber = - new JoinDataComplete(new JoinData {JoinNumber = 62, JoinSpan = 1}, - new JoinMetadata - { - Description = "Incoming Call Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallReject")] public JoinDataComplete IncomingCallReject = - new JoinDataComplete(new JoinData {JoinNumber = 62, JoinSpan = 1}, - new JoinMetadata - { - Description = "Reject Incoming Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingCallType")] public JoinDataComplete IncomingCallType = - new JoinDataComplete(new JoinData {JoinNumber = 63, JoinSpan = 1}, - new JoinMetadata - { - Description = "Incoming Call Type", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - #endregion - - #region Manual Dial - [JoinName("ManualDial")] - public JoinDataComplete ManualDial = new JoinDataComplete(new JoinData {JoinNumber = 71, JoinSpan = 1}, - new JoinMetadata - { - Description = "Dial Entered String", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("HangUpAllCalls")] - public JoinDataComplete HangUpAllCalls = new JoinDataComplete(new JoinData {JoinNumber = 72, JoinSpan = 1}, - new JoinMetadata - { - Description = "Hang up All calls", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("ManualDialString")] - public JoinDataComplete ManualDialString = new JoinDataComplete(new JoinData {JoinNumber = 71, JoinSpan = 1}, - new JoinMetadata - { - Description = "Manual String to dial", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - #endregion - - #region Connected Calls - - [JoinName("ConnectedCallCount")] - public JoinDataComplete ConnectedCallCount = new JoinDataComplete(new JoinData {JoinNumber = 81, JoinSpan = 1}, - new JoinMetadata - { - Description = "Connected Call Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("ConnectedCallHangup")] - public JoinDataComplete ConnectedCallHangupStart = - new JoinDataComplete(new JoinData {JoinNumber = 81, JoinSpan = 8}, - new JoinMetadata - { - Description = "Hang up selected call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ConnectedCallData")] public JoinDataComplete ConnectedCallData = - new JoinDataComplete(new JoinData {JoinNumber = 81, JoinSpan = 1}, - new JoinMetadata - { - Description = - "XSig - Connected Call info\r\nDigital 1: Connecting\r\nDigital 2: Connected\r\nSerial 1: Name\r\nSerial 2: Number\r\nSerial 3: Status\r\nSerial 4: Type\r\nSerial 5: ID", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - #endregion - #region NearEnd Source Select - - [JoinName("NearEndSourceSelect")] public JoinDataComplete NearEndSourceSelect = - new JoinDataComplete(new JoinData {JoinNumber = 5, JoinSpan = 1}, - new JoinMetadata - { - Description = "Near End Source Select", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog, - ValidValues = new[] {"1", "2", "3", "4"} - }); - #endregion - - #region Sharing - //Putting share start/stop only in this base join map. The map can be extended for features of other codecs - - public JoinDataComplete SharingStart = new JoinDataComplete(new JoinData {JoinNumber = 101, JoinSpan = 1}, - new JoinMetadata - { - Description = "Start sharing & feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - public JoinDataComplete SharingStop = new JoinDataComplete(new JoinData {JoinNumber = 102, JoinSpan = 1}, - new JoinMetadata - { - Description = "Stop Sharing & Feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - #endregion - - #region Phonebook - - #endregion*/ - [JoinName("CallDirection")] public JoinDataComplete CallDirection = new JoinDataComplete(new JoinData {JoinNumber = 22, JoinSpan = 1}, new JoinMetadata @@ -572,15 +179,6 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - /* - [JoinName("CurrentCallNumber")] public JoinDataComplete CurrentCallNumber = - new JoinDataComplete(new JoinData {JoinNumber = 3, JoinSpan = 1}, - new JoinMetadata - { - Description = "Current Call Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - });*/ [JoinName("CurrentDialString")] public JoinDataComplete CurrentDialString = new JoinDataComplete(new JoinData {JoinNumber = 1, JoinSpan = 1}, @@ -915,6 +513,33 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + [JoinName("DialMeeting")] public JoinDataComplete DialMeeting = new JoinDataComplete(new JoinData{JoinNumber=161, JoinSpan = 1}, + new JoinMetadata + { + Description = "Join first joinable meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("UpdateMeetings")] public JoinDataComplete UpdateMeetings = + new JoinDataComplete(new JoinData {JoinNumber = 162, JoinSpan = 1}, + new JoinMetadata + { + Description = "Update Meetings", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Meeting Count Fb")] public JoinDataComplete MeetingCount = + new JoinDataComplete(new JoinData {JoinNumber = 161, JoinSpan = 1}, + new JoinMetadata + { + Description = "Meeting Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraLayoutStringFb")] public JoinDataComplete CameraLayoutStringFb = new JoinDataComplete(new JoinData { JoinNumber = 141, JoinSpan = 1 }, @@ -925,6 +550,9 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Analog }); + + + [JoinName("ManualDial")] public JoinDataComplete ManualDial = new JoinDataComplete(new JoinData {JoinNumber = 71, JoinSpan = 1}, new JoinMetadata diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 7c5c784b..fb330049 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -313,6 +313,90 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecDirectoryToApi(codec as IHasDirectory, trilist, joinMap); } + if (codec is IHasScheduleAwareness) + { + LinkVideoCodecScheduleToApi(codec as IHasScheduleAwareness, trilist, joinMap); + } + } + + private void LinkVideoCodecScheduleToApi(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + trilist.SetSigFalseAction(joinMap.UpdateMeetings.JoinNumber, codec.GetSchedule); + + codec.CodecSchedule.MeetingsListHasChanged += (sender, args) => + { + var clearBytes = XSigHelpers.ClearOutputs(); + + trilist.SetString(joinMap.Schedule.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + + var meetingsData = UpdateMeetingsListXSig(codec.CodecSchedule.Meetings); + + trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData); + + trilist.SetSigFalseAction(joinMap.DialMeeting.JoinNumber, () => + { + if (codec.CodecSchedule.Meetings[0].Joinable) + { + Dial(codec.CodecSchedule.Meetings[0]); + } + }); + }; + } + + private string UpdateMeetingsListXSig(List meetings) + { + /*const int maxCalls = 8; + const int maxStrings = 5; + const int offset = 6; + var callIndex = 0; + var digitalIndex = maxStrings*maxCalls; + */ + + const int maxMeetings = 3; + const int maxDigitals = 1; + const int maxStrings = 4; + const int offset = maxDigitals + maxStrings; + var digitalIndex = maxStrings*maxMeetings; //15 + var stringIndex = 0; + var meetingIndex = 0; + + var tokenArray = new XSigToken[maxMeetings*offset]; + /* + * Digitals + * IsJoinable - 1 + * + * Serials + * Organizer - 1 + * Title - 2 + * Agenda - 3 + * Start Time - 4 + * End Time - 5 + */ + + foreach(var meeting in meetings) + { + var currentTime = DateTime.Now; + + if(meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue; + + if (meetingIndex > maxMeetings*offset) break; + + //digitals + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, meeting.Joinable); + + //serials + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, meeting.Title); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString("MM/dd/yyyy h:mm")); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.EndTime.ToString("MM/dd/yyyy h:mm")); + + digitalIndex += maxDigitals; + meetingIndex += offset; + stringIndex += maxStrings; + } + + return GetXSigString(tokenArray); } private void LinkVideoCodecDirectoryToApi(IHasDirectory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) @@ -613,11 +697,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec var tokenArray = new XSigToken[presets.Count]; - string returnString; - - foreach (var token in presets.Select(cameraPreset => new XSigSerialToken(i, cameraPreset.Description))) + foreach (var preset in presets) { - tokenArray[i - 1] = token; + var cameraPreset = new XSigSerialToken(i, preset.Description); + tokenArray[i - 1] = cameraPreset; i++; } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index 780b7d29..c81a47cb 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -979,6 +979,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom meeting.Privacy = b.IsPrivate ? eMeetingPrivacy.Private : eMeetingPrivacy.Public; // 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); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 5fec376c..045d6482 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -14,25 +14,26 @@ using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; -using PepperDash_Essentials_Core.Bridges.JoinMaps; namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { - public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, IRouting, + public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, + IRouting, IHasScheduleAwareness, IHasCodecCameras { - private readonly CrestronQueue ReceiveQueue; + private const uint DefaultMeetingDurationMin = 30; + private const string Delimiter = "\x0D\x0A"; + private readonly CrestronQueue _receiveQueue; - private readonly Thread ReceiveThread; + private readonly Thread _receiveThread; - private readonly ZoomRoomSyncState SyncState; + private readonly ZoomRoomSyncState _syncState; public bool CommDebuggingIsOn; - private uint DefaultMeetingDurationMin = 30; - private string Delimiter = "\x0D\x0A"; - private uint JsonCurlyBraceCounter = 0; - private bool JsonFeedbackMessageIsIncoming; - private StringBuilder JsonMessage; - private int PreviousVolumeLevel = 0; + private CodecDirectory _currentDirectoryResult; + private uint _jsonCurlyBraceCounter; + private bool _jsonFeedbackMessageIsIncoming; + private StringBuilder _jsonMessage; + private int _previousVolumeLevel; private CameraBase _selectedCamera; public ZoomRoom(DeviceConfig config, IBasicCommunication comm) @@ -41,11 +42,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var props = JsonConvert.DeserializeObject(config.Properties.ToString()); // The queue that will collect the repsonses in the order they are received - ReceiveQueue = new CrestronQueue(25); + _receiveQueue = new CrestronQueue(25); // The thread responsible for dequeuing and processing the messages - ReceiveThread = new Thread((o) => ProcessQueue(), null); - ReceiveThread.Priority = Thread.eThreadPriority.MediumPriority; + _receiveThread = new Thread(o => ProcessQueue(), null) {Priority = Thread.eThreadPriority.MediumPriority}; Communication = comm; @@ -68,15 +68,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom CodecInfo = new ZoomRoomInfo(Status, Configuration); - SyncState = new ZoomRoomSyncState(Key + "--Sync", this); + _syncState = new ZoomRoomSyncState(Key + "--Sync", this); - SyncState.InitialSyncCompleted += new EventHandler(SyncState_InitialSyncCompleted); + _syncState.InitialSyncCompleted += SyncState_InitialSyncCompleted; PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); - PortGather = new CommunicationGather(Communication, "\x0A"); - PortGather.IncludeDelimiter = true; - PortGather.LineReceived += this.Port_LineReceived; + PortGather = new CommunicationGather(Communication, "\x0A") {IncludeDelimiter = true}; + PortGather.LineReceived += Port_LineReceived; CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, eRoutingSignalType.Audio | eRoutingSignalType.Video, @@ -272,12 +271,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom #endregion - #region IHasDirectory Members + #region IHasDirectoryHistoryStack Members public event EventHandler DirectoryResultReturned; public CodecDirectory DirectoryRoot { get; private set; } - private CodecDirectory _currentDirectoryResult; public CodecDirectory CurrentDirectoryResult { get { return _currentDirectoryResult; } @@ -293,7 +291,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom DirectoryRoot.CurrentDirectoryResults.FindAll( c => c.Name.IndexOf(searchString, 0, StringComparison.OrdinalIgnoreCase) > -1)); - DirectoryBrowseHistoryStack.Push(_currentDirectoryResult); + DirectoryBrowseHistoryStack.Clear(); _currentDirectoryResult = directoryResults; OnDirectoryResultReturned(directoryResults); @@ -324,7 +322,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void GetDirectoryParentFolderContents() { - if (DirectoryBrowseHistoryStack.Count == 0) return; + if (DirectoryBrowseHistoryStack.Count == 0) + { + return; + } var currentDirectory = DirectoryBrowseHistoryStack.Pop(); @@ -337,7 +338,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public List DirectoryBrowseHistory { get; private set; } - public Stack DirectoryBrowseHistoryStack { get; private set; } + public Stack DirectoryBrowseHistoryStack { get; private set; } #endregion @@ -374,64 +375,58 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// private void SetUpFeedbackActions() { - Configuration.Audio.Output.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler( - (o, a) => + Configuration.Audio.Output.PropertyChanged += (o, a) => + { + if (a.PropertyName == "Volume") { - if (a.PropertyName == "Volume") - { - VolumeLevelFeedback.FireUpdate(); - MuteFeedback.FireUpdate(); - } - }); + VolumeLevelFeedback.FireUpdate(); + MuteFeedback.FireUpdate(); + } + }; - Configuration.Call.Microphone.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler( - (o, a) => + Configuration.Call.Microphone.PropertyChanged += (o, a) => + { + if (a.PropertyName == "Mute") { - if (a.PropertyName == "Mute") - { - PrivacyModeIsOnFeedback.FireUpdate(); - } - }); + PrivacyModeIsOnFeedback.FireUpdate(); + } + }; - Configuration.Video.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler( - (o, a) => + Configuration.Video.PropertyChanged += (o, a) => + { + if (a.PropertyName == "HideConfSelfVideo") { - if (a.PropertyName == "HideConfSelfVideo") - { - SelfviewIsOnFeedback.FireUpdate(); - } - }); - Configuration.Video.Camera.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler( - (o, a) => + SelfviewIsOnFeedback.FireUpdate(); + } + }; + Configuration.Video.Camera.PropertyChanged += (o, a) => + { + if (a.PropertyName == "SelectedId") { - if (a.PropertyName == "SelectedId") - { - SelectCamera(Configuration.Video.Camera.SelectedId); - // this will in turn fire the affected feedbacks - } - }); + SelectCamera(Configuration.Video.Camera.SelectedId); + // this will in turn fire the affected feedbacks + } + }; - Status.Call.Sharing.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler( - (o, a) => + Status.Call.Sharing.PropertyChanged += (o, a) => + { + if (a.PropertyName == "State") { - if (a.PropertyName == "State") - { - SharingContentIsOnFeedback.FireUpdate(); - } - }); + SharingContentIsOnFeedback.FireUpdate(); + } + }; - Status.Sharing.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler( - (o, a) => + Status.Sharing.PropertyChanged += (o, a) => + { + switch (a.PropertyName) { - if (a.PropertyName == "dispState") - { + case "dispState": SharingSourceFeedback.FireUpdate(); - } - else if (a.PropertyName == "password") - { - //TODO: Fire Sharing Password Update - } - }); + break; + case "password": + break; + } + }; } private void SetUpDirectory() @@ -441,7 +436,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom DirectoryBrowseHistory = new List(); DirectoryBrowseHistoryStack = new Stack(); - CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => DirectoryBrowseHistoryStack.Count > 0); + CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => _currentDirectoryResult != DirectoryRoot); CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); } @@ -478,20 +473,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { CrestronConsole.AddNewConsoleCommand(SetCommDebug, "SetCodecCommDebug", "0 for Off, 1 for on", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand((s) => SendText("zCommand Phonebook List Offset: 0 Limit: 512"), + CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 512"), "GetZoomRoomContacts", "Triggers a refresh of the codec phonebook", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand((s) => GetBookings(), "GetZoomRoomBookings", + CrestronConsole.AddNewConsoleCommand(s => GetBookings(), "GetZoomRoomBookings", "Triggers a refresh of the booking data for today", ConsoleAccessLevelEnum.AccessOperator); var socket = Communication as ISocketStatus; if (socket != null) { - socket.ConnectionChange += new EventHandler(socket_ConnectionChange); + socket.ConnectionChange += socket_ConnectionChange; } - // TODO: Turn this off when done initial development - CommDebuggingIsOn = true; + CommDebuggingIsOn = false; Communication.Connect(); @@ -522,7 +516,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } else { - SyncState.CodecDisconnected(); + _syncState.CodecDisconnected(); PhonebookSyncState.CodecDisconnected(); } } @@ -547,12 +541,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom //if (CommDebuggingIsOn) // Debug.Console(1, this, "Gathered: '{0}'", args.Text); - ReceiveQueue.Enqueue(args.Text); + _receiveQueue.Enqueue(args.Text); // If the receive thread has for some reason stopped, this will restart it - if (ReceiveThread.ThreadState != Thread.eThreadStates.ThreadRunning) + if (_receiveThread.ThreadState != Thread.eThreadStates.ThreadRunning) { - ReceiveThread.Start(); + _receiveThread.Start(); } } @@ -567,7 +561,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { while (true) { - var message = ReceiveQueue.Dequeue(); + var message = _receiveQueue.Dequeue(); ProcessMessage(message); } @@ -587,50 +581,50 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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"); + _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"); + _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 - SyncState.AddQueryToQueue("zCommand Phonebook List Offset: 0 Limit: 512"); - SyncState.AddQueryToQueue("zCommand Bookings List"); + _syncState.AddQueryToQueue("zCommand Phonebook List Offset: 0 Limit: 512"); + _syncState.AddQueryToQueue("zCommand Bookings List"); - SyncState.StartSync(); + _syncState.StartSync(); } /// @@ -642,25 +636,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // Counts the curly braces if (message.Contains('{')) { - JsonCurlyBraceCounter++; + _jsonCurlyBraceCounter++; } if (message.Contains('}')) { - JsonCurlyBraceCounter--; + _jsonCurlyBraceCounter--; } - Debug.Console(2, this, "JSON Curly Brace Count: {0}", JsonCurlyBraceCounter); + Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter); - if (!JsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter) + if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter) // Check for the beginning of a new JSON message { - JsonFeedbackMessageIsIncoming = true; - JsonCurlyBraceCounter = 1; // reset the counter for each new message + _jsonFeedbackMessageIsIncoming = true; + _jsonCurlyBraceCounter = 1; // reset the counter for each new message - JsonMessage = new StringBuilder(); + _jsonMessage = new StringBuilder(); - JsonMessage.Append(message); + _jsonMessage.Append(message); if (CommDebuggingIsOn) { @@ -669,22 +663,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom return; } - else if (JsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + Delimiter) + if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + Delimiter) // Check for the end of a JSON message { - JsonMessage.Append(message); + _jsonMessage.Append(message); - if (JsonCurlyBraceCounter == 0) + if (_jsonCurlyBraceCounter == 0) { - JsonFeedbackMessageIsIncoming = false; + _jsonFeedbackMessageIsIncoming = false; if (CommDebuggingIsOn) { - Debug.Console(2, this, "Complete JSON Received:\n{0}", JsonMessage.ToString()); + Debug.Console(2, this, "Complete JSON Received:\n{0}", _jsonMessage.ToString()); } // Forward the complete message to be deserialized - DeserializeResponse(JsonMessage.ToString()); + DeserializeResponse(_jsonMessage.ToString()); } //JsonMessage = new StringBuilder(); @@ -693,9 +687,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // NOTE: This must happen after the above conditions have been checked // Append subsequent partial JSON fragments to the string builder - if (JsonFeedbackMessageIsIncoming) + if (_jsonFeedbackMessageIsIncoming) { - JsonMessage.Append(message); + _jsonMessage.Append(message); //Debug.Console(1, this, "Building JSON:\n{0}", JsonMessage.ToString()); return; @@ -706,18 +700,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(1, this, "Non-JSON response: '{0}'", message); } - JsonCurlyBraceCounter = 0; // reset on non-JSON response + _jsonCurlyBraceCounter = 0; // reset on non-JSON response - if (!SyncState.InitialSyncComplete) + if (!_syncState.InitialSyncComplete) { switch (message.Trim().ToLower()) // remove the whitespace { case "*r login successful": { - SyncState.LoginMessageReceived(); + _syncState.LoginMessageReceived(); // Fire up a thread to send the intial commands. - CrestronInvoke.BeginInvoke((o) => + CrestronInvoke.BeginInvoke(o => { Thread.Sleep(100); // disable echo of commands @@ -755,7 +749,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var message = JObject.Parse(trimmedResponse); - eZoomRoomResponseType eType = + var eType = (eZoomRoomResponseType) Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value(), true); @@ -816,12 +810,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom PhonebookSyncState.PhonebookRootEntriesReceived(); PhonebookSyncState.SetPhonebookHasFolders(false); PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); - } - var directoryResults = new CodecDirectory(); - - directoryResults = + var directoryResults = zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); DirectoryRoot = directoryResults; @@ -916,28 +907,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } else if (responseObj["Added Contact"] != null) { - var newContact = - JsonConvert.DeserializeObject( - responseObj["Updated Contact"].ToString()); + var jToken = responseObj["Updated Contact"]; + if (jToken != null) + { + var newContact = + JsonConvert.DeserializeObject( + jToken.ToString()); - // Add a new contact - Status.Phonebook.Contacts.Add(newContact); + // Add a new contact + Status.Phonebook.Contacts.Add(newContact); + } } break; } case "bookingslistresult": { - if (!SyncState.InitialSyncComplete) + if (!_syncState.InitialSyncComplete) { - SyncState.LastQueryResponseReceived(); + _syncState.LastQueryResponseReceived(); } - var codecBookings = new List(); - - codecBookings = - JsonConvert.DeserializeObject>( - responseObj.ToString()); + var codecBookings = JsonConvert.DeserializeObject>( + responseObj.ToString()); if (codecBookings != null && codecBookings.Count > 0) { @@ -969,13 +961,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (incomingCall != null) { - var newCall = new CodecActiveCallItem(); - - newCall.Direction = eCodecCallDirection.Incoming; - newCall.Status = eCodecCallStatus.Ringing; - newCall.Type = eCodecCallType.Unknown; - newCall.Name = incomingCall.callerName; - newCall.Id = incomingCall.callerJID; + var newCall = new CodecActiveCallItem + { + Direction = eCodecCallDirection.Incoming, + Status = eCodecCallStatus.Ringing, + Type = eCodecCallType.Unknown, + Name = incomingCall.callerName, + Id = incomingCall.callerJID + }; ActiveCalls.Add(newCall); @@ -996,14 +989,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (existingCall != null) { - if (!incomingCall.accepted) - { - existingCall.Status = eCodecCallStatus.Disconnected; - } - else - { - existingCall.Status = eCodecCallStatus.Connecting; - } + existingCall.Status = !incomingCall.accepted + ? eCodecCallStatus.Disconnected + : eCodecCallStatus.Connecting; OnCallStatusChange(existingCall); } @@ -1087,9 +1075,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { case "login": { - SyncState.LoginMessageReceived(); + _syncState.LoginMessageReceived(); - if (!SyncState.InitialQueryMessagesWereSent) + if (!_syncState.InitialQueryMessagesWereSent) { SetUpSyncQueries(); } @@ -1157,7 +1145,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras); - if (!SyncState.CamerasHaveBeenSetUp) + if (!_syncState.CamerasHaveBeenSetUp) { SetUpCameras(); } @@ -1213,26 +1201,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// private void UpdateCallStatus() { - zStatus.eCallStatus callStatus; - if (Status.Call != null) { - callStatus = Status.Call.Status; + var callStatus = Status.Call.Status; // If not currently in a meeting, intialize the call object if (callStatus != zStatus.eCallStatus.IN_MEETING || callStatus != zStatus.eCallStatus.CONNECTING_MEETING) { - Status.Call = new zStatus.Call(); - Status.Call.Status = callStatus; // set the status after initializing the object + Status.Call = new zStatus.Call {Status = callStatus}; } if (ActiveCalls.Count == 0) { if (callStatus == zStatus.eCallStatus.CONNECTING_MEETING) { - var newCall = new CodecActiveCallItem(); - - newCall.Status = eCodecCallStatus.Connecting; + var newCall = new CodecActiveCallItem {Status = eCodecCallStatus.Connecting}; ActiveCalls.Add(newCall); @@ -1317,12 +1300,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void MuteOff() { - SetVolume((ushort) PreviousVolumeLevel); + SetVolume((ushort) _previousVolumeLevel); } public override void MuteOn() { - PreviousVolumeLevel = Configuration.Audio.Output.Volume; // Store the previous level for recall + _previousVolumeLevel = Configuration.Audio.Output.Volume; // Store the previous level for recall SetVolume(0); } @@ -1484,6 +1467,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom throw new NotImplementedException(); } + /// /// Call when directory results are updated /// /// @@ -1495,7 +1479,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var handler = DirectoryResultReturned; if (handler != null) { - handler(this, new DirectoryEventArgs() + handler(this, new DirectoryEventArgs { Directory = result, DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue @@ -1531,7 +1515,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom UpdateFarEndCameras(); } - SyncState.CamerasSetUp(); + _syncState.CamerasSetUp(); } /// @@ -1570,10 +1554,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { return Status.SystemUnit.MeetingNumber; } - else - { - return string.Empty; - } + return string.Empty; } } @@ -1585,10 +1566,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { return Status.Call.Info.meeting_list_item.third_party.h323_address; } - else - { - return string.Empty; - } + return string.Empty; } } @@ -1600,10 +1578,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { return Status.SystemUnit.RoomInfo.AccountEmail; } - else - { - return string.Empty; - } + return string.Empty; } } @@ -1620,10 +1595,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { return Status.Call.Info.dialIn; } - else - { - return string.Empty; - } + return string.Empty; } } @@ -1635,10 +1607,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { return Status.Call.Info.meeting_list_item.third_party.sip_address; } - else - { - return string.Empty; - } + return string.Empty; } } } @@ -1648,24 +1617,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// public class ZoomRoomSyncState : IKeyed { - private readonly ZoomRoom Parent; - private readonly CrestronQueue SyncQueries; - private bool _InitialSyncComplete; + private readonly ZoomRoom _parent; + private readonly CrestronQueue _syncQueries; + private bool _initialSyncComplete; public ZoomRoomSyncState(string key, ZoomRoom parent) { - Parent = parent; + _parent = parent; Key = key; - SyncQueries = new CrestronQueue(50); + _syncQueries = new CrestronQueue(50); CodecDisconnected(); } public bool InitialSyncComplete { - get { return _InitialSyncComplete; } + get { return _initialSyncComplete; } private set { - if (value == true) + if (value) { var handler = InitialSyncCompleted; if (handler != null) @@ -1673,7 +1642,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom handler(this, new EventArgs()); } } - _InitialSyncComplete = value; + _initialSyncComplete = value; } } @@ -1700,11 +1669,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void DequeueQueries() { - while (!SyncQueries.IsEmpty) + while (!_syncQueries.IsEmpty) { - var query = SyncQueries.Dequeue(); + var query = _syncQueries.Dequeue(); - Parent.SendText(query); + _parent.SendText(query); } InitialQueryMessagesSent(); @@ -1712,7 +1681,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void AddQueryToQueue(string query) { - SyncQueries.Enqueue(query); + _syncQueries.Enqueue(query); } public void LoginMessageReceived() @@ -1745,7 +1714,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void CodecDisconnected() { - SyncQueries.Clear(); + _syncQueries.Clear(); LoginMessageWasReceived = false; InitialQueryMessagesWereSent = false; LastQueryResponseWasReceived = false; @@ -1772,7 +1741,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { public ZoomRoomFactory() { - TypeNames = new List() {"zoomroom"}; + TypeNames = new List {"zoomroom"}; } public override EssentialsDevice BuildDevice(DeviceConfig dc) From 88263ccc77ef8a80381d4d6a9b19bea033d42220 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 23 Sep 2020 15:54:11 -0600 Subject: [PATCH 10/42] finished up with some things --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 53 ++++++++ .../Essentials Devices Common.csproj | 1 + .../VideoCodec/Interfaces/IHasParticipants.cs | 59 +++++++++ .../VideoCodec/VideoCodecBase.cs | 83 ++++++++++++ .../VideoCodec/ZoomRoom/ResponseObjects.cs | 20 ++- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 122 +++++++++++------- 6 files changed, 288 insertions(+), 50 deletions(-) create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasParticipants.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index b1c46717..dc2fe6c7 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -562,6 +562,59 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("SourceShareStart")] public JoinDataComplete SourceShareStart = + new JoinDataComplete(new JoinData {JoinNumber = 201, JoinSpan = 1}, + new JoinMetadata + { + Description = "Start Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareEnd")] + public JoinDataComplete SourceShareEnd = + new JoinDataComplete(new JoinData { JoinNumber = 202, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Stop Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("AutoShareWhileInCall")] public JoinDataComplete SourceShareAutoStart = + new JoinDataComplete(new JoinData {JoinNumber = 203, JoinSpan = 1}, + new JoinMetadata + { + Description = "When high, will autostart sharing when a call is joined", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CurrentSource")] public JoinDataComplete CurrentSource = new JoinDataComplete(new JoinData{JoinNumber = 201, JoinSpan = 1}, + new JoinMetadata + { + Description = "Current Source", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentParticipants")] public JoinDataComplete CurrentParticipants = + new JoinDataComplete(new JoinData{JoinNumber = 151, JoinSpan = 1}, + new JoinMetadata() + { + Description = "Current Participants XSig", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("ParticipantCount")] public JoinDataComplete ParticipantCount = new JoinDataComplete(new JoinData{JoinNumber = 151, JoinSpan = 1}, + new JoinMetadata + { + Description = "Current Participant Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof (VideoCodecControllerJoinMap)) { } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index d3d468fc..94988b7b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -120,6 +120,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasParticipants.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasParticipants.cs new file mode 100644 index 00000000..e0f1d1a3 --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasParticipants.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + public interface IHasParticipants + { + CodecParticipants Participants { get; } + } + + public interface IHasParticipantVideoMute:IHasParticipants + { + void MuteVideoForParticipant(int userId); + void UnmuteVideoForParticipant(int userId); + void ToggleVideoForParticipant(int userId); + } + + public interface IHasParticipantAudioMute:IHasParticipantVideoMute + { + void MuteAudioForParticipant(int userId); + void UnmuteAudioForParticipant(int userId); + void ToggleAudioForParticipant(int userId); + } + + public class CodecParticipants + { + private List _currentParticipants; + + public List CurrentParticipants { + get { return _currentParticipants; } + set + { + _currentParticipants = value; + var handler = ParticipantsListHasChanged; + + if(handler == null) return; + + handler(this, new EventArgs()); + } + } + + public event EventHandler ParticipantsListHasChanged; + + public CodecParticipants() + { + _currentParticipants = new List(); + } + } + + public class Participant + { + public bool IsHost { get; set; } + public string Name { get; set; } + public bool CanMuteVideo { get; set; } + public bool CanUnmuteVideo { get; set; } + public bool VideoMuteFb { get; set; } + public bool AudioMuteFb { get; set; } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index fb330049..87ac8581 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -16,6 +16,7 @@ using PepperDash.Essentials.Core.Devices; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; +using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; using PepperDash_Essentials_Core.Bridges.JoinMaps; using Feedback = PepperDash.Essentials.Core.Feedback; @@ -25,6 +26,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced { private const int XSigEncoding = 28591; + private readonly byte[] _clearBytes = XSigHelpers.ClearOutputs(); protected VideoCodecBase(DeviceConfig config) : base(config) { @@ -287,6 +289,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecCallControlsToApi(trilist, joinMap); + LinkVideoCodecContentSharingToApi(trilist, joinMap); + if (codec is IHasCodecCameras) { LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap); @@ -317,8 +321,85 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { LinkVideoCodecScheduleToApi(codec as IHasScheduleAwareness, trilist, joinMap); } + + if (codec is IHasParticipants) + { + LinkVideoCodecParticipantsToApi(codec as IHasParticipants, trilist, joinMap); + } } + private void LinkVideoCodecParticipantsToApi(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + codec.Participants.ParticipantsListHasChanged += (sender, args) => + { + string participantsXSig; + if (codec.Participants.CurrentParticipants.Count == 0) + { + participantsXSig = Encoding.GetEncoding(XSigEncoding).GetString(_clearBytes, 0, _clearBytes.Length); + trilist.SetString(joinMap.CurrentParticipants.JoinNumber, participantsXSig); + trilist.SetUshort(joinMap.ParticipantCount.JoinNumber, (ushort)codec.Participants.CurrentParticipants.Count); + return; + } + + participantsXSig = Encoding.GetEncoding(XSigEncoding).GetString(_clearBytes, 0, _clearBytes.Length); + + trilist.SetString(joinMap.CurrentParticipants.JoinNumber, participantsXSig); + + participantsXSig = UpdateParticipantsXSig(codec.Participants.CurrentParticipants); + + trilist.SetString(joinMap.CurrentParticipants.JoinNumber, participantsXSig); + + trilist.SetUshort(joinMap.ParticipantCount.JoinNumber, (ushort) codec.Participants.CurrentParticipants.Count); + }; + } + + private string UpdateParticipantsXSig(List currentParticipants) + { + const int maxParticipants = 255; + const int maxDigitals = 5; + const int maxStrings = 1; + const int offset = maxDigitals + maxStrings; + var digitalIndex = maxStrings * maxParticipants; //15 + var stringIndex = 0; + var meetingIndex = 0; + + var tokenArray = new XSigToken[maxParticipants * offset]; + + foreach (var participant in currentParticipants) + { + if (meetingIndex > maxParticipants * offset) break; + + //digitals + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, participant.AudioMuteFb); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, participant.VideoMuteFb); + tokenArray[digitalIndex + 2] = new XSigDigitalToken(digitalIndex + 3, participant.CanMuteVideo); + tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, participant.CanUnmuteVideo); + tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, participant.IsHost); + + //serials + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, participant.Name); + + digitalIndex += maxDigitals; + meetingIndex += offset; + stringIndex += maxStrings; + } + + return GetXSigString(tokenArray); + } + + private void LinkVideoCodecContentSharingToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + SharingContentIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SourceShareStart.JoinNumber]); + SharingContentIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.SourceShareEnd.JoinNumber]); + + SharingSourceFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentSource.JoinNumber]); + + trilist.SetSigFalseAction(joinMap.SourceShareStart.JoinNumber, StartSharing); + trilist.SetSigFalseAction(joinMap.SourceShareEnd.JoinNumber, StopSharing); + + trilist.SetBoolSigAction(joinMap.SourceShareAutoStart.JoinNumber, (b) => AutoShareContentWhileInCall = b); + } + private void LinkVideoCodecScheduleToApi(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { trilist.SetSigFalseAction(joinMap.UpdateMeetings.JoinNumber, codec.GetSchedule); @@ -341,6 +422,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec Dial(codec.CodecSchedule.Meetings[0]); } }); + + trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort) codec.CodecSchedule.Meetings.Count); }; } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index c81a47cb..3425e45b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -11,6 +11,7 @@ using PepperDash.Essentials.Devices.Common.Codec; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { @@ -909,7 +910,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// public class zCommand { - public partial class BookingsListResult + public class BookingsListResult { [JsonProperty("accessRole")] public string AccessRole { get; set; } @@ -1072,6 +1073,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { HandStatus = new HandStatus(); } + + public static List GetGenericParticipantListFromParticipantsResult( + List participants) + { + return + participants.Select( + p => + new Participant + { + Name = p.UserName, + IsHost = p.IsHost, + CanMuteVideo = p.IsVideoCanMuteByHost, + CanUnmuteVideo = p.IsVideoCanUnmuteByHost, + AudioMuteFb = p.AudioStatusState == "AUDIO_MUTED", + VideoMuteFb = p.VideoStatusIsSending + }).ToList(); + } } public class CallinCountryList diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 045d6482..14ef2d55 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -14,12 +14,13 @@ using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; +using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, IRouting, - IHasScheduleAwareness, IHasCodecCameras + IHasScheduleAwareness, IHasCodecCameras, IHasParticipants { private const uint DefaultMeetingDurationMin = 30; private const string Delimiter = "\x0D\x0A"; @@ -94,6 +95,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Cameras = new List(); SetUpDirectory(); + + Participants = new CodecParticipants(); } public CommunicationGather PortGather { get; private set; } @@ -827,51 +830,61 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Debug.Console(1, this, "JTokenType: {0}", responseObj.Type); - if (responseObj.Type == JTokenType.Array) + switch (responseObj.Type) { - // if the type is array this must be the complete list - Status.Call.Participants = - JsonConvert.DeserializeObject>( - responseObj.ToString()); - } - else if (responseObj.Type == JTokenType.Object) - { - // this is a single participant event notification - - var participant = - JsonConvert.DeserializeObject(responseObj.ToString()); - - if (participant != null) + case JTokenType.Array: + Status.Call.Participants = + JsonConvert.DeserializeObject>( + responseObj.ToString()); + break; + case JTokenType.Object: { - if (participant.Event == "ZRCUserChangedEventLeftMeeting" || - participant.Event == "ZRCUserChangedEventUserInfoUpdated") - { - var existingParticipant = - Status.Call.Participants.FirstOrDefault( - p => p.UserId.Equals(participant.UserId)); + // this is a single participant event notification - if (existingParticipant != null) + var participant = + JsonConvert.DeserializeObject(responseObj.ToString()); + + if (participant != null) + { + switch (participant.Event) { - if (participant.Event == "ZRCUserChangedEventLeftMeeting") + case "ZRCUserChangedEventUserInfoUpdated": + case "ZRCUserChangedEventLeftMeeting": { - // Remove participant - Status.Call.Participants.Remove(existingParticipant); - } - else if (participant.Event == "ZRCUserChangedEventUserInfoUpdated") - { - // Update participant - JsonConvert.PopulateObject(responseObj.ToString(), - existingParticipant); + 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": + Status.Call.Participants.Add(participant); + break; } } - else if (participant.Event == "ZRCUserChangedEventJoinedMeeting") - { - Status.Call.Participants.Add(participant); - } } + break; } + var participants = + zCommand.ListParticipant.GetGenericParticipantListFromParticipantsResult( + Status.Call.Participants); + + Participants.CurrentParticipants = participants; + PrintCurrentCallParticipants(); break; @@ -1019,6 +1032,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom OnCallStatusChange(activeCall); } } + var emptyList = new List(); + Participants.CurrentParticipants = emptyList; } UpdateCallStatus(); @@ -1175,16 +1190,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void PrintCurrentCallParticipants() { - if (Debug.Level > 0) + if (Debug.Level <= 0) { - Debug.Console(1, this, "****************************Call Participants***************************"); - foreach (var participant in Status.Call.Participants) - { - Debug.Console(1, this, "Name: {0} Audio: {1} IsHost: {2}", participant.UserName, - participant.AudioStatusState, participant.IsHost); - } - Debug.Console(1, this, "************************************************************************"); + return; } + + Debug.Console(1, this, "****************************Call Participants***************************"); + foreach (var participant in Participants.CurrentParticipants) + { + Debug.Console(1, this, "Name: {0} Audio: {1} IsHost: {2}", participant.Name, + participant.AudioMuteFb, participant.IsHost); + } + Debug.Console(1, this, "************************************************************************"); } /// @@ -1226,13 +1243,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { var existingCall = ActiveCalls.FirstOrDefault(c => !c.Status.Equals(eCodecCallStatus.Ringing)); - if (callStatus == zStatus.eCallStatus.IN_MEETING) + switch (callStatus) { - existingCall.Status = eCodecCallStatus.Connected; - } - else if (callStatus == zStatus.eCallStatus.NOT_IN_MEETING) - { - existingCall.Status = eCodecCallStatus.Disconnected; + case zStatus.eCallStatus.IN_MEETING: + existingCall.Status = eCodecCallStatus.Connected; + break; + case zStatus.eCallStatus.NOT_IN_MEETING: + existingCall.Status = eCodecCallStatus.Disconnected; + break; } OnCallStatusChange(existingCall); @@ -1525,6 +1543,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { // TODO: set up far end cameras for the current call } + + #region Implementation of IHasParticipants + + public CodecParticipants Participants { get; private set; } + + #endregion } /// From 6a79f41367c6e79f071272498e97e3efe576c0c5 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 23 Sep 2020 16:10:39 -0600 Subject: [PATCH 11/42] Add Online updates. --- .../VideoCodec/VideoCodecBase.cs | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 87ac8581..521aa8dc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -326,7 +326,43 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { LinkVideoCodecParticipantsToApi(codec as IHasParticipants, trilist, joinMap); } - } + + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; + + if (codec is IHasDirectory) + { + (codec as IHasDirectory).SetCurrentDirectoryToRoot(); + } + + if (codec is IHasScheduleAwareness) + { + (codec as IHasScheduleAwareness).GetSchedule(); + } + + if (codec is IHasParticipants) + { + UpdateParticipantsXSig((codec as IHasParticipants).Participants.CurrentParticipants); + } + + if (codec is IHasCameraAutoMode) + { + trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true); + + (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.InvokeFireUpdate(); + } + + if (codec is IHasCodecSelfView) + { + (codec as IHasCodecSelfView).SelfviewIsOnFeedback.InvokeFireUpdate(); + } + + SharingContentIsOnFeedback.InvokeFireUpdate(); + + UpdateCallStatusXSig(); + }; + } private void LinkVideoCodecParticipantsToApi(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { From aa38b13adfc674cd30e73949135aa0e8c336de0d Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 24 Sep 2020 15:52:40 -0600 Subject: [PATCH 12/42] add online status link --- .../VideoCodec/VideoCodecBase.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 521aa8dc..7684a33f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -285,12 +285,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec Debug.Console(1, this, "Linking to Trilist {0}", trilist.ID.ToString("X")); + + LinkVideoCodecDtmfToApi(trilist, joinMap); LinkVideoCodecCallControlsToApi(trilist, joinMap); LinkVideoCodecContentSharingToApi(trilist, joinMap); + if (codec is ICommunicationMonitor) + { + LinkVideoCodecCommMonitorToApi(codec as ICommunicationMonitor, trilist, joinMap); + } + if (codec is IHasCodecCameras) { LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap); @@ -364,6 +371,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec }; } + private void LinkVideoCodecCommMonitorToApi(ICommunicationMonitor codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + codec.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + } + private void LinkVideoCodecParticipantsToApi(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { codec.Participants.ParticipantsListHasChanged += (sender, args) => From 97701ef3c4c865d6b40d3a03d7639aae2de67cc0 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 25 Sep 2020 16:00:17 -0600 Subject: [PATCH 13/42] add privacy & volume controls to VC Join Map --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 87 +++++++++++++++++++ .../VideoCodec/VideoCodecBase.cs | 32 +++++++ .../VideoCodec/ZoomRoom/ZoomRoom.cs | 5 +- 3 files changed, 123 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index dc2fe6c7..035e2bff 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -615,6 +615,93 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Analog }); + [JoinName("MicMuteOn")] public JoinDataComplete MicMuteOn = + new JoinDataComplete(new JoinData {JoinNumber = 171, JoinSpan = 1}, + new JoinMetadata + { + Description = "Mic Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteOff")] public JoinDataComplete MicMuteOff = + new JoinDataComplete(new JoinData {JoinNumber = 172, JoinSpan = 1}, + new JoinMetadata + { + Description = "Mic Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteToggle")] public JoinDataComplete MicMuteToggle = + new JoinDataComplete(new JoinData {JoinNumber = 173, JoinSpan = 1}, + new JoinMetadata + { + Description = "Mic Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteOn")] + public JoinDataComplete VolumeMuteOn = + new JoinDataComplete(new JoinData { JoinNumber = 176, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Volume Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteOff")] + public JoinDataComplete VolumeMuteOff = + new JoinDataComplete(new JoinData { JoinNumber = 177, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Volume Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteToggle")] + public JoinDataComplete VolumeMuteToggle = + new JoinDataComplete(new JoinData { JoinNumber = 178, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Volume Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeUp")] public JoinDataComplete VolumeUp = + new JoinDataComplete(new JoinData {JoinNumber = 174, JoinSpan = 1}, + new JoinMetadata + { + Description = "Volume Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeDown")] + public JoinDataComplete VolumeDown = + new JoinDataComplete(new JoinData { JoinNumber = 175, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Volume Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeLevel")] + public JoinDataComplete VolumeLevel = + new JoinDataComplete(new JoinData { JoinNumber = 174, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Volume Level", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof (VideoCodecControllerJoinMap)) { } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 7684a33f..b7602b3b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -293,6 +293,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecContentSharingToApi(trilist, joinMap); + LinkVideoCodecPrivacyToApi(trilist, joinMap); + + LinkVideoCodecVolumeToApi(trilist, joinMap); + if (codec is ICommunicationMonitor) { LinkVideoCodecCommMonitorToApi(codec as ICommunicationMonitor, trilist, joinMap); @@ -371,6 +375,34 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec }; } + private void LinkVideoCodecVolumeToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMuteOn.JoinNumber]); + MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]); + + trilist.SetSigFalseAction(joinMap.VolumeMuteOn.JoinNumber, MuteOn); + trilist.SetSigFalseAction(joinMap.VolumeMuteOff.JoinNumber, MuteOff); + trilist.SetSigFalseAction(joinMap.VolumeMuteToggle.JoinNumber, MuteToggle); + + VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.VolumeLevel.JoinNumber]); + + trilist.SetBoolSigAction(joinMap.VolumeUp.JoinNumber, VolumeUp); + trilist.SetBoolSigAction(joinMap.VolumeDown.JoinNumber, VolumeDown); + + trilist.SetUShortSigAction(joinMap.VolumeLevel.JoinNumber, SetVolume); + + } + + private void LinkVideoCodecPrivacyToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + PrivacyModeIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.MicMuteOn.JoinNumber]); + PrivacyModeIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.MicMuteOff.JoinNumber]); + + trilist.SetSigFalseAction(joinMap.MicMuteOn.JoinNumber, PrivacyModeOn); + trilist.SetSigFalseAction(joinMap.MicMuteOff.JoinNumber, PrivacyModeOff); + trilist.SetSigFalseAction(joinMap.MicMuteToggle.JoinNumber, PrivacyModeToggle); + } + private void LinkVideoCodecCommMonitorToApi(ICommunicationMonitor codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { codec.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 14ef2d55..6113db4a 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -26,6 +26,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private const string Delimiter = "\x0D\x0A"; private readonly CrestronQueue _receiveQueue; + private readonly Thread _receiveThread; private readonly ZoomRoomSyncState _syncState; @@ -1340,13 +1341,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } + + /// /// Increments the voluem /// /// public override void VolumeUp(bool pressRelease) { - // TODO: Implment volume increment that calls SetVolume() + // TODO: Implment volume decrement that calls SetVolume() } /// From 33c3822b7cf2db69bea331e24f7b1cc0036624e3 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 28 Sep 2020 14:53:02 -0600 Subject: [PATCH 14/42] fix join type for hook state --- .../Bridges/JoinMaps/VideoCodecControllerJoinMap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 035e2bff..147bc840 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -447,7 +447,7 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps { Description = "Current Hook State", JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial + JoinType = eJoinType.Digital }); [JoinName("IncomingAnswer")] public JoinDataComplete IncomingAnswer = From c8e3f752dbb6056c187e17e28fc8a8cfd06569d1 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 28 Sep 2020 19:15:39 -0600 Subject: [PATCH 15/42] added properties to support dynamic time before meeting start for warnings --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 8 ++++++++ .../Codec/iHasScheduleAwareness.cs | 14 ++++++++++++-- .../VideoCodec/VideoCodecBase.cs | 10 +++++++--- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 14 +++++++++++++- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 3 ++- 5 files changed, 42 insertions(+), 7 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 147bc840..77c19ca4 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -701,6 +701,14 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Analog }); + [JoinName("MinutesBeforeMeetingStart")] public JoinDataComplete MinutesBeforeMeetingStart = + new JoinDataComplete(new JoinData {JoinNumber = 41, JoinSpan = 1}, + new JoinMetadata + { + Description = "Minutes before meeting start that a meeting is joinable", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof (VideoCodecControllerJoinMap)) { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs index 57839471..43cc0343 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs @@ -30,7 +30,15 @@ namespace PepperDash.Essentials.Devices.Common.Codec public event EventHandler MeetingsListHasChanged; - /// + private int _meetingWarningMinutes = 5; + + public int MeetingWarningMinutes + { + get { return _meetingWarningMinutes; } + set { _meetingWarningMinutes = value; } + } + + /// /// Setter triggers MeetingsListHasChanged event /// public List Meetings @@ -102,6 +110,8 @@ namespace PepperDash.Essentials.Devices.Common.Codec { public TimeSpan MeetingWarningMinutes = TimeSpan.FromMinutes(5); + public int MinutesBeforeMeeting; + public string Id { get; set; } public string Organizer { get; set; } public string Title { get; set; } @@ -134,7 +144,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec { get { - return StartTime.AddMinutes(-5) <= DateTime.Now + return StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now && DateTime.Now <= EndTime; //.AddMinutes(-5); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index b7602b3b..e91de18f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -484,6 +484,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { trilist.SetSigFalseAction(joinMap.UpdateMeetings.JoinNumber, codec.GetSchedule); + trilist.SetUShortSigAction(joinMap.MinutesBeforeMeetingStart.JoinNumber, (i) => + { + codec.CodecSchedule.MeetingWarningMinutes = i; + }); + codec.CodecSchedule.MeetingsListHasChanged += (sender, args) => { var clearBytes = XSigHelpers.ClearOutputs(); @@ -532,9 +537,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec * Serials * Organizer - 1 * Title - 2 - * Agenda - 3 - * Start Time - 4 - * End Time - 5 + * Start Time - 3 + * End Time - 4 */ foreach(var meeting in meetings) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index 3425e45b..2c33317e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -946,8 +946,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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 Cisco bookings response ans converts them to the generic class + /// Extracts the necessary meeting values from the Zoom bookings response and converts them to the generic class /// /// /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 6113db4a..3a57bb43 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -947,7 +947,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (codecBookings != null && codecBookings.Count > 0) { - CodecSchedule.Meetings = zCommand.GetGenericMeetingsFromBookingResult(codecBookings); + CodecSchedule.Meetings = zCommand.GetGenericMeetingsFromBookingResult( + codecBookings, CodecSchedule.MeetingWarningMinutes); } break; From b286008403dacba1df91366ccb882fe3ee209ed3 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 28 Sep 2020 19:17:09 -0600 Subject: [PATCH 16/42] fix signal direction --- .../Bridges/JoinMaps/VideoCodecControllerJoinMap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 77c19ca4..e28edecf 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -266,7 +266,7 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps new JoinMetadata { Description = "Directory Line Selected FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); From 72515a79ca51ba89a2052c7bc7c2cae62432ed35 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 29 Sep 2020 12:08:29 -0600 Subject: [PATCH 17/42] fixes and additions --- .../VideoCodec/VideoCodecBase.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index e91de18f..66b977cc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -523,7 +523,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec const int maxMeetings = 3; const int maxDigitals = 1; - const int maxStrings = 4; + const int maxStrings = 6; const int offset = maxDigitals + maxStrings; var digitalIndex = maxStrings*maxMeetings; //15 var stringIndex = 0; @@ -537,12 +537,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec * Serials * Organizer - 1 * Title - 2 + * Start Date - 3 * Start Time - 3 + * End Date - 4 * End Time - 4 */ foreach(var meeting in meetings) { + if (meetingIndex >= maxMeetings*offset) + { + break; + } var currentTime = DateTime.Now; if(meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue; @@ -555,8 +561,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //serials tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer); tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, meeting.Title); - tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString("MM/dd/yyyy h:mm")); - tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.EndTime.ToString("MM/dd/yyyy h:mm")); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToShortDateString()); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToShortTimeString()); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 4, meeting.EndTime.ToShortDateString()); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToShortTimeString()); digitalIndex += maxDigitals; meetingIndex += offset; From 1e6d65fe53fd42b316ed96d68a7f16f64f5bc813 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 29 Sep 2020 13:24:53 -0600 Subject: [PATCH 18/42] changing some things to check for updates to meetings list --- .../Codec/iHasScheduleAwareness.cs | 21 ++++---- .../VideoCodec/VideoCodecBase.cs | 49 +++++++++++-------- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 4 +- 3 files changed, 42 insertions(+), 32 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs index 43cc0343..5275ab03 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs @@ -24,7 +24,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec public class CodecScheduleAwareness { - List _Meetings; + List _meetings; public event EventHandler MeetingEventChange; @@ -45,11 +45,11 @@ namespace PepperDash.Essentials.Devices.Common.Codec { get { - return _Meetings; + return _meetings; } set { - _Meetings = value; + _meetings = value; var handler = MeetingsListHasChanged; if (handler != null) @@ -59,13 +59,13 @@ namespace PepperDash.Essentials.Devices.Common.Codec } } - private CTimer ScheduleChecker; + private CTimer _scheduleChecker; public CodecScheduleAwareness() { Meetings = new List(); - ScheduleChecker = new CTimer(CheckSchedule, null, 1000, 1000); + _scheduleChecker = new CTimer(CheckSchedule, null, 1000, 1000); } private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting) @@ -82,9 +82,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec // Iterate the meeting list and check if any meeting need to do anythingk const double meetingTimeEpsilon = 0.0001; - foreach (Meeting m in Meetings) + foreach (var m in Meetings) { - eMeetingEventChangeType changeType = eMeetingEventChangeType.Unkown; + var changeType = eMeetingEventChangeType.Unkown; if (m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes) // Meeting is about to start changeType = eMeetingEventChangeType.MeetingStartWarning; @@ -108,14 +108,17 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public class Meeting { - public TimeSpan MeetingWarningMinutes = TimeSpan.FromMinutes(5); - public int MinutesBeforeMeeting; public string Id { get; set; } public string Organizer { get; set; } public string Title { get; set; } public string Agenda { get; set; } + + public TimeSpan MeetingWarningMinutes + { + get { return TimeSpan.FromMinutes(MinutesBeforeMeeting); } + } public TimeSpan TimeToMeetingStart { get diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 66b977cc..5dc9c258 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -489,27 +489,38 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec codec.CodecSchedule.MeetingWarningMinutes = i; }); - codec.CodecSchedule.MeetingsListHasChanged += (sender, args) => - { - var clearBytes = XSigHelpers.ClearOutputs(); + codec.CodecSchedule.MeetingsListHasChanged += (sender, args) => UpdateMeetingsList(codec, trilist, joinMap); - trilist.SetString(joinMap.Schedule.JoinNumber, - Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - - var meetingsData = UpdateMeetingsListXSig(codec.CodecSchedule.Meetings); - - trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData); - - trilist.SetSigFalseAction(joinMap.DialMeeting.JoinNumber, () => + codec.CodecSchedule.MeetingEventChange += + (sender, args) => { - if (codec.CodecSchedule.Meetings[0].Joinable) + if (args.ChangeType == eMeetingEventChangeType.MeetingStartWarning) { - Dial(codec.CodecSchedule.Meetings[0]); + UpdateMeetingsList(codec, trilist, joinMap); } - }); + }; + } - trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort) codec.CodecSchedule.Meetings.Count); - }; + private void UpdateMeetingsList(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + var clearBytes = XSigHelpers.ClearOutputs(); + + trilist.SetString(joinMap.Schedule.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + + var meetingsData = UpdateMeetingsListXSig(codec.CodecSchedule.Meetings); + + trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData); + + trilist.SetSigFalseAction(joinMap.DialMeeting.JoinNumber, () => + { + if (codec.CodecSchedule.Meetings[0].Joinable) + { + Dial(codec.CodecSchedule.Meetings[0]); + } + }); + + trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)codec.CodecSchedule.Meetings.Count); } private string UpdateMeetingsListXSig(List meetings) @@ -545,15 +556,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec foreach(var meeting in meetings) { - if (meetingIndex >= maxMeetings*offset) - { - break; - } var currentTime = DateTime.Now; if(meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue; - if (meetingIndex > maxMeetings*offset) break; + if (meetingIndex >= maxMeetings*offset) break; //digitals tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, meeting.Joinable); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 3a57bb43..4dbe2355 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -843,7 +843,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // this is a single participant event notification var participant = - JsonConvert.DeserializeObject(responseObj.ToString()); + JsonConvert.DeserializeObject( + responseObj.ToString()); if (participant != null) { @@ -1343,7 +1344,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } - /// /// Increments the voluem /// From b502007fff420f987271f1b603771e8529c778da Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 29 Sep 2020 14:41:55 -0600 Subject: [PATCH 19/42] Changes to keep from clearing meeting list --- .../VideoCodec/VideoCodecBase.cs | 70 +++++++++++-------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 5dc9c258..8c159105 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -133,16 +133,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { get { - bool value; - - if (ActiveCalls != null) - { - value = ActiveCalls.Any(c => c.IsActiveCall); - } - else - { - value = false; - } + var value = ActiveCalls != null && ActiveCalls.Any(c => c.IsActiveCall); return value; } } @@ -503,12 +494,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec private void UpdateMeetingsList(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { - var clearBytes = XSigHelpers.ClearOutputs(); + var currentTime = DateTime.Now; + var currentMeetings = + codec.CodecSchedule.Meetings.Where(m => m.StartTime >= currentTime || m.EndTime >= currentTime).ToList(); - trilist.SetString(joinMap.Schedule.JoinNumber, - Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - - var meetingsData = UpdateMeetingsListXSig(codec.CodecSchedule.Meetings); + var meetingsData = UpdateMeetingsListXSig(currentMeetings); trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData); @@ -520,21 +510,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } }); - trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)codec.CodecSchedule.Meetings.Count); + trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)currentMeetings.Count); } private string UpdateMeetingsListXSig(List meetings) { - /*const int maxCalls = 8; - const int maxStrings = 5; - const int offset = 6; - var callIndex = 0; - var digitalIndex = maxStrings*maxCalls; - */ - const int maxMeetings = 3; - const int maxDigitals = 1; - const int maxStrings = 6; + const int maxDigitals = 2; + const int maxStrings = 7; const int offset = maxDigitals + maxStrings; var digitalIndex = maxStrings*maxMeetings; //15 var stringIndex = 0; @@ -544,16 +527,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /* * Digitals * IsJoinable - 1 + * IsDialable - 2 * * Serials * Organizer - 1 * Title - 2 * Start Date - 3 - * Start Time - 3 - * End Date - 4 - * End Time - 4 + * Start Time - 4 + * End Date - 5 + * End Time - 6 */ + foreach(var meeting in meetings) { var currentTime = DateTime.Now; @@ -564,20 +549,43 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //digitals tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, meeting.Joinable); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, meeting.Id != "0"); //serials tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer); tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, meeting.Title); tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToShortDateString()); - tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToShortTimeString()); - tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 4, meeting.EndTime.ToShortDateString()); - tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToShortTimeString()); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToShortTimeString()); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToShortDateString()); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToShortTimeString()); + tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, meeting.Id); + digitalIndex += maxDigitals; meetingIndex += offset; stringIndex += maxStrings; } + while (meetingIndex < maxMeetings*offset) + { + digitalIndex += maxDigitals; + meetingIndex += offset; + stringIndex += maxStrings; + + //digitals + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); + + //serials + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); + tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, String.Empty); + } + return GetXSigString(tokenArray); } From 753b4e69ee24bd89038fa644de4b7e9359ea6c55 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 29 Sep 2020 15:08:33 -0600 Subject: [PATCH 20/42] add constructor to CodecScheduleAwareness to chang refresh timer --- .../Codec/iHasScheduleAwareness.cs | 7 +++++++ .../VideoCodec/ZoomRoom/ZoomRoom.cs | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs index 5275ab03..7d6acdc2 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs @@ -68,6 +68,13 @@ namespace PepperDash.Essentials.Devices.Common.Codec _scheduleChecker = new CTimer(CheckSchedule, null, 1000, 1000); } + public CodecScheduleAwareness(long pollTime) + { + Meetings = new List(); + + _scheduleChecker = new CTimer(CheckSchedule, null, pollTime, pollTime); + } + private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting) { var handler = MeetingEventChange; diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 4dbe2355..efb7b94e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -22,6 +22,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom IRouting, IHasScheduleAwareness, IHasCodecCameras, IHasParticipants { + private const long MeetingRefreshTimer = 60000; private const uint DefaultMeetingDurationMin = 30; private const string Delimiter = "\x0D\x0A"; private readonly CrestronQueue _receiveQueue; @@ -89,7 +90,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); - CodecSchedule = new CodecScheduleAwareness(); + CodecSchedule = new CodecScheduleAwareness(MeetingRefreshTimer); SetUpFeedbackActions(); From 3c794849bd60c65100bf38866d9b7bfd768d348e Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 29 Sep 2020 15:22:32 -0600 Subject: [PATCH 21/42] added a couple of debugging statements --- .../Essentials Devices Common/VideoCodec/VideoCodecBase.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 8c159105..445147ac 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -545,7 +545,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if(meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue; - if (meetingIndex >= maxMeetings*offset) break; + if (meetingIndex >= maxMeetings*offset) + { + Debug.Console(2, this, "Max Meetings reached"); + break;} //digitals tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, meeting.Joinable); @@ -568,6 +571,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec while (meetingIndex < maxMeetings*offset) { + Debug.Console(2, this, "Clearing unused data. Meeting Index: {0} MaxMeetings * Offset: {1}", + meetingIndex, maxMeetings*offset); digitalIndex += maxDigitals; meetingIndex += offset; stringIndex += maxStrings; From cb661313c25933571020d200d2da39c0a6474c8a Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 29 Sep 2020 17:21:17 -0500 Subject: [PATCH 22/42] Fixes for indexing form xsig --- .../VideoCodec/VideoCodecBase.cs | 11 ++++++----- packages.config | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 445147ac..d78b43b5 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -573,9 +573,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { Debug.Console(2, this, "Clearing unused data. Meeting Index: {0} MaxMeetings * Offset: {1}", meetingIndex, maxMeetings*offset); - digitalIndex += maxDigitals; - meetingIndex += offset; - stringIndex += maxStrings; //digitals tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); @@ -588,8 +585,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); - tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, String.Empty); - } + tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, String.Empty); + + digitalIndex += maxDigitals; + meetingIndex += offset; + stringIndex += maxStrings; + } return GetXSigString(tokenArray); } diff --git a/packages.config b/packages.config index 296413b6..c138dd1b 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From 741b401d8c2fe8d54e4cb9f8ee27c3aa6755c14a Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 30 Sep 2020 08:52:16 -0600 Subject: [PATCH 23/42] fix PepperDash Core version --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index c138dd1b..439c0438 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From d6133905b2d18667255e583f31a6f4fc1b7200e2 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 30 Sep 2020 09:00:56 -0600 Subject: [PATCH 24/42] really fix pepperdash core version --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index 439c0438..40078601 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From 4b9d7d1a1f4cd7e0284196672e6bbe6c1b64e374 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 30 Sep 2020 11:21:13 -0600 Subject: [PATCH 25/42] adjust queue size --- .../Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index efb7b94e..ae372b72 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -45,7 +45,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var props = JsonConvert.DeserializeObject(config.Properties.ToString()); // The queue that will collect the repsonses in the order they are received - _receiveQueue = new CrestronQueue(25); + _receiveQueue = new CrestronQueue(1024); // The thread responsible for dequeuing and processing the messages _receiveThread = new Thread(o => ProcessQueue(), null) {Priority = Thread.eThreadPriority.MediumPriority}; From e365944dc38ab7d6fb84e6a7c2c7cc54fe4a0669 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 30 Sep 2020 13:55:40 -0600 Subject: [PATCH 26/42] add config object to stop downloading large phonebooks --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 14 ++++++++++---- .../ZoomRoom/ZoomRoomPropertiesConfig.cs | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index ae372b72..a142534e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -39,10 +39,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private int _previousVolumeLevel; private CameraBase _selectedCamera; + private readonly ZoomRoomPropertiesConfig _props; + public ZoomRoom(DeviceConfig config, IBasicCommunication comm) : base(config) { - var props = JsonConvert.DeserializeObject(config.Properties.ToString()); + _props = JsonConvert.DeserializeObject(config.Properties.ToString()); // The queue that will collect the repsonses in the order they are received _receiveQueue = new CrestronQueue(1024); @@ -52,10 +54,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Communication = comm; - if (props.CommunicationMonitorProperties != null) + if (_props.CommunicationMonitorProperties != null) { CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, - props.CommunicationMonitorProperties); + _props.CommunicationMonitorProperties); } else { @@ -625,7 +627,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // zCommand - _syncState.AddQueryToQueue("zCommand Phonebook List Offset: 0 Limit: 512"); + if (!_props.DisablePhonebookAutoDownload) + { + _syncState.AddQueryToQueue("zCommand Phonebook List Offset: 0 Limit: 512"); + } + _syncState.AddQueryToQueue("zCommand Bookings List"); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs index d60b63c2..f9249c5a 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs @@ -12,5 +12,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public class ZoomRoomPropertiesConfig { public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; } + + public bool DisablePhonebookAutoDownload { get; set; } } } \ No newline at end of file From e784c08f8084d87165417163778f3b8b4634b47b Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 30 Sep 2020 15:47:32 -0600 Subject: [PATCH 27/42] Add camera off and auto stuff to Zoom Room --- .../VideoCodec/VideoCodecBase.cs | 27 ++++++-- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 22 ++++++- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 61 ++++++++++++++++--- .../ZoomRoom/ZoomRoomPropertiesConfig.cs | 2 + 4 files changed, 98 insertions(+), 14 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index d78b43b5..b4022232 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -60,8 +60,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public List ActiveCalls { get; set; } - public bool ShowSelfViewByDefault { get; protected set; } - + public bool ShowSelfViewByDefault { get; protected set; } + + protected bool SupportsCameraOff; + protected bool SupportsCameraAutoMode; public bool IsReady { get; protected set; } @@ -305,8 +307,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (codec is IHasCameraAutoMode) { - trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true); + trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, SupportsCameraAutoMode); LinkVideoCodecCameraModeToApi(codec as IHasCameraAutoMode, trilist, joinMap); + } + + if (codec is IHasCameraOff) + { + trilist.SetBool(joinMap.CameraSupportsOffMode.JoinNumber, SupportsCameraOff); + LinkVideoCodecCameraOffToApi(codec as IHasCameraOff, trilist, joinMap); } if (codec is IHasCodecLayouts) @@ -364,8 +372,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec UpdateCallStatusXSig(); }; - } - + } + + private void LinkVideoCodecCameraOffToApi(IHasCameraOff codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + codec.CameraIsOffFeedback.LinkInputSig(trilist.BooleanInput[joinMap.CameraModeOff.JoinNumber]); + + trilist.SetSigFalseAction(joinMap.CameraModeOff.JoinNumber, codec.CameraOff); + } + private void LinkVideoCodecVolumeToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMuteOn.JoinNumber]); @@ -767,6 +782,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.BooleanInput[joinMap.CameraModeManual.JoinNumber]); } + + private void LinkVideoCodecSelfviewToApi(IHasCodecSelfView codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index 2c33317e..0bb0b524 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -86,6 +86,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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() { @@ -93,6 +94,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Audio = new zConfiguration.Audio(); Video = new zConfiguration.Video(); Client = new zConfiguration.Client(); + Camera = new zConfiguration.Camera(); } } @@ -698,9 +700,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public bool OptimizeVideoSharing { get; set; } } - public class Camera + public class Camera : NotifiableObject { - public bool Mute { get; set; } + private bool _mute; + + public bool Mute + { + get + { + return _mute; + } + set + { + if (value != _mute) + { + _mute = value; + NotifyPropertyChanged("Mute"); + } + } + } } public class Microphone : NotifiableObject diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index a142534e..f4d6a7c3 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -20,7 +20,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, IRouting, - IHasScheduleAwareness, IHasCodecCameras, IHasParticipants + IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraAutoMode { private const long MeetingRefreshTimer = 60000; private const uint DefaultMeetingDurationMin = 30; @@ -92,6 +92,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); + CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc); + CodecSchedule = new CodecScheduleAwareness(MeetingRefreshTimer); SetUpFeedbackActions(); @@ -101,6 +103,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SetUpDirectory(); Participants = new CodecParticipants(); + + SupportsCameraOff = _props.SupportsCameraOff; + SupportsCameraAutoMode = _props.SupportsCameraAutoMode; } public CommunicationGather PortGather { get; private set; } @@ -174,6 +179,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom get { return () => !Configuration.Video.HideConfSelfVideo; } } + protected Func CameraIsOffFeedbackFunc + { + get { return () => !Configuration.Camera.Mute; } + } + + protected Func SelfviewPipPositionFeedbackFunc { get { return () => ""; } @@ -415,6 +426,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } }; + Configuration.Camera.PropertyChanged += (o, a) => + { + if (a.PropertyName != "Mute") return; + + CameraIsOffFeedback.FireUpdate(); + }; + Status.Call.Sharing.PropertyChanged += (o, a) => { if (a.PropertyName == "State") @@ -961,13 +979,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom break; } - case "bookings": + case "bookings updated": { - // Bookings have been updated, trigger a query to retreive the new bookings - if (responseObj["Updated"] != null) - { - GetBookings(); - } + GetBookings(); break; } @@ -1560,6 +1574,39 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public CodecParticipants Participants { get; private set; } #endregion + + #region Implementation of IHasCameraOff + + public BoolFeedback CameraIsOffFeedback { get; private set; } + + public void CameraOff() + { + SendText("zCommand Call Camera Mute: On"); + } + + #endregion + + #region Implementation of IHasCameraAutoMode + //Zoom doesn't support camera auto modes. Setting this to just unmute video + public void CameraAutoModeOn() + { + 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("zCommand 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 } /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs index f9249c5a..4e2545ec 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs @@ -14,5 +14,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; } public bool DisablePhonebookAutoDownload { get; set; } + public bool SupportsCameraAutoMode { get; set; } + public bool SupportsCameraOff { get; set; } } } \ No newline at end of file From b500b9f6cc8fe41bba59e86f03fde2a147ca1404 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 30 Sep 2020 16:26:48 -0600 Subject: [PATCH 28/42] Add feedbacks for Camera Auto Mode --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index f4d6a7c3..24554a23 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -94,6 +94,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc); + CameraAutoModeIsOnFeedback = new BoolFeedback(CameraAutoModeIsOnFeedbackFunc); + CodecSchedule = new CodecScheduleAwareness(MeetingRefreshTimer); SetUpFeedbackActions(); @@ -181,9 +183,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom protected Func CameraIsOffFeedbackFunc { - get { return () => !Configuration.Camera.Mute; } + get { return () => Configuration.Camera.Mute; } } + protected Func CameraAutoModeIsOnFeedbackFunc + { + get { return () => !Configuration.Camera.Mute; } + } protected Func SelfviewPipPositionFeedbackFunc { From 95016c3ec682a0cbb44b93b3c12a2ac5962c8af7 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Oct 2020 10:07:08 -0600 Subject: [PATCH 29/42] fix camera mute command --- .../PepperDashEssentialsBase/Bridges/BridgeBase.cs | 2 +- .../Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs index 13d1948a..b85e6948 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs @@ -316,7 +316,7 @@ namespace PepperDash.Essentials.Core.Bridges { Debug.Console(1, "Factory Attempting to create new EiscApiAdvanced Device"); - var controlProperties = dc.Properties["control"].ToObject(); + var controlProperties = CommFactory.GetControlPropertiesConfig(dc); switch (dc.Type) { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 24554a23..b192b4af 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -1587,7 +1587,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void CameraOff() { - SendText("zCommand Call Camera Mute: On"); + SendText("zConfiguration Call Camera Mute: On"); } #endregion @@ -1602,7 +1602,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom //Zoom doesn't support camera auto modes. Setting this to just unmute video public void CameraAutoModeOff() { - SendText("zCommand Call Camera Mute: Off"); + SendText("zConfiguration Call Camera Mute: Off"); } public void CameraAutoModeToggle() From d50ad7345dd6f946e121698aac23b7685f15c6eb Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Oct 2020 10:37:31 -0600 Subject: [PATCH 30/42] fix ZoomRoomCamera Timer --- .../VideoCodec/ZoomRoom/ZoomRoomCamera.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs index 4fa377ae..464c8b9a 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs @@ -79,8 +79,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom void StartContinueTimer() { - if(ContinueTimer == null) - ContinueTimer = new CTimer((o) => SendContinueAction(LastAction), ContinueTime); + if (ContinueTimer == null) + ContinueTimer = new CTimer((o) => SendContinueAction(LastAction), null, ContinueTime, ContinueTime); } void SendContinueAction(eZoomRoomCameraAction action) From c0e3da92141676b19223be27455133396cb201cd Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Oct 2020 12:15:54 -0600 Subject: [PATCH 31/42] fix for EiscApiAdvanced loading --- .../PepperDashEssentialsBase/Bridges/BridgeBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs index b85e6948..151b5461 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs @@ -318,7 +318,7 @@ namespace PepperDash.Essentials.Core.Bridges var controlProperties = CommFactory.GetControlPropertiesConfig(dc); - switch (dc.Type) + switch (dc.Type.ToLower()) { case "eiscapiadv": case "eiscapiadvanced": From 34440af1c50a1f0e043e2097c470a9712af058b1 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Oct 2020 13:25:33 -0600 Subject: [PATCH 32/42] fix for updating call status when in meeting & call is already connected --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index b192b4af..764898ca 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -1260,9 +1260,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (ActiveCalls.Count == 0) { - if (callStatus == zStatus.eCallStatus.CONNECTING_MEETING) + if (callStatus == zStatus.eCallStatus.CONNECTING_MEETING || callStatus == zStatus.eCallStatus.IN_MEETING ) { - var newCall = new CodecActiveCallItem {Status = eCodecCallStatus.Connecting}; + var newStatus = eCodecCallStatus.Unknown; + + switch (callStatus) + { + case zStatus.eCallStatus.CONNECTING_MEETING: + newStatus = eCodecCallStatus.Connecting; + break; + case zStatus.eCallStatus.IN_MEETING: + newStatus = eCodecCallStatus.Connected; + break; + } + + var newCall = new CodecActiveCallItem {Status = newStatus}; ActiveCalls.Add(newCall); From 27382a6be11d1473454e78d0259b10bcf4973cd5 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Oct 2020 14:40:13 -0600 Subject: [PATCH 33/42] various fixes --- .../VideoCodec/VideoCodecBase.cs | 8 +++++-- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 23 +++++++++++++++---- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 6 +++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index b4022232..6874e049 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -368,7 +368,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec (codec as IHasCodecSelfView).SelfviewIsOnFeedback.InvokeFireUpdate(); } - SharingContentIsOnFeedback.InvokeFireUpdate(); + SharingContentIsOnFeedback.InvokeFireUpdate(); + + trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); UpdateCallStatusXSig(); }; @@ -698,7 +700,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec () => Dial(trilist.StringOutput[joinMap.CurrentDialString.JoinNumber].StringValue)); //End All calls for now - trilist.SetSigFalseAction(joinMap.EndCall.JoinNumber, EndAllCalls); + trilist.SetSigFalseAction(joinMap.EndCall.JoinNumber, EndAllCalls); + + trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); CallStatusChange += (sender, args) => { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index 0bb0b524..f49f6281 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -702,20 +702,35 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public class Camera : NotifiableObject { + private string _muteState; private bool _mute; public bool Mute + { + get { return _mute; } + set + { + if (value == _mute) return; + + _mute = value; + NotifyPropertyChanged("Mute"); + } + } + + [JsonProperty("mute")] + public string MuteState { get { - return _mute; + return _muteState; } set { - if (value != _mute) + if (value != _muteState) { - _mute = value; - NotifyPropertyChanged("Mute"); + _muteState = value; + + Mute = _muteState == "on"; } } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 764898ca..657a27c8 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -657,6 +657,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } _syncState.AddQueryToQueue("zCommand Bookings List"); + _syncState.AddQueryToQueue("zCommand Call ListParticipants"); _syncState.StartSync(); @@ -757,6 +758,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Thread.Sleep(100); SendText("zFeedback Register Op: ex Path: /Event/InfoResult/info/callout_country_list"); Thread.Sleep(100); + + if (!_props.DisablePhonebookAutoDownload) + { + SendText("zFeedback Register "); + } // switch to json format SendText("format json"); }); From decdaf9f1f5e88b79b3cdd535376edd90dd2078b Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 2 Oct 2020 16:58:18 -0600 Subject: [PATCH 34/42] lots of updates --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 366 ++++++++++-------- .../IHasFarEndContentStatus.cs | 7 + .../PepperDash_Essentials_Core.csproj | 1 + .../Essentials Devices Common.csproj | 1 + .../Interfaces/IHasSelfviewPosition.cs | 14 + .../VideoCodec/VideoCodecBase.cs | 198 ++++++++-- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 50 +-- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 133 ++++++- .../VideoCodec/ZoomRoom/ZoomRoomCamera.cs | 31 +- .../ZoomRoom/ZoomRoomPropertiesConfig.cs | 9 + packages.config | 2 +- 11 files changed, 568 insertions(+), 244 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IHasFarEndContentStatus.cs create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index e28edecf..7e71ec22 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -36,6 +36,15 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("CameraLayoutStringFb")] public JoinDataComplete CameraLayoutStringFb = + new JoinDataComplete(new JoinData {JoinNumber = 141, JoinSpan = 1}, + new JoinMetadata + { + Description = "Current Layout Fb", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + [JoinName("CameraModeAuto")] public JoinDataComplete CameraModeAuto = new JoinDataComplete(new JoinData {JoinNumber = 131, JoinSpan = 1}, new JoinMetadata @@ -90,6 +99,15 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("CameraPresetNames")] public JoinDataComplete CameraPresetNames = + new JoinDataComplete(new JoinData {JoinNumber = 121, JoinSpan = 1}, + new JoinMetadata + { + Description = "Camera Preset Names - XSIG, max of 15", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + [JoinName("CameraPresetSelect")] public JoinDataComplete CameraPresetSelect = new JoinDataComplete(new JoinData {JoinNumber = 121, JoinSpan = 1}, new JoinMetadata @@ -99,13 +117,13 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Analog }); - [JoinName("CameraPresetNames")] public JoinDataComplete CameraPresetNames = + [JoinName("CameraPresetSave")] public JoinDataComplete CameraPresetSave = new JoinDataComplete(new JoinData {JoinNumber = 121, JoinSpan = 1}, new JoinMetadata { - Description = "Camera Preset Names - XSIG, max of 15", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial + Description = "Save Selected Preset", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital }); [JoinName("CameraSelfView")] public JoinDataComplete CameraSelfView = @@ -189,12 +207,30 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); - [JoinName("DirectoryHasChanged")] public JoinDataComplete DirectoryHasChanged = - new JoinDataComplete(new JoinData {JoinNumber = 103, JoinSpan = 1}, + [JoinName("CurrentParticipants")] public JoinDataComplete CurrentParticipants = + new JoinDataComplete(new JoinData {JoinNumber = 151, JoinSpan = 1}, + new JoinMetadata() + { + Description = "Current Participants XSig", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentSource")] public JoinDataComplete CurrentSource = + new JoinDataComplete(new JoinData {JoinNumber = 201, JoinSpan = 1}, new JoinMetadata { - Description = "Directory has changed FB", + Description = "Current Source", JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DialMeeting")] public JoinDataComplete DialMeeting = + new JoinDataComplete(new JoinData {JoinNumber = 161, JoinSpan = 1}, + new JoinMetadata + { + Description = "Join first joinable meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); @@ -252,6 +288,15 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("DirectoryHasChanged")] public JoinDataComplete DirectoryHasChanged = + new JoinDataComplete(new JoinData {JoinNumber = 103, JoinSpan = 1}, + new JoinMetadata + { + Description = "Directory has changed FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("DirectoryIsRoot")] public JoinDataComplete DirectoryIsRoot = new JoinDataComplete(new JoinData {JoinNumber = 102, JoinSpan = 1}, new JoinMetadata @@ -495,37 +540,12 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("SpeedDialStart")] public JoinDataComplete SpeedDialStart = - new JoinDataComplete(new JoinData {JoinNumber = 41, JoinSpan = 4}, + + [JoinName("ManualDial")] public JoinDataComplete ManualDial = + new JoinDataComplete(new JoinData {JoinNumber = 71, JoinSpan = 1}, new JoinMetadata { - Description = "Speed Dial", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Schedule")] public JoinDataComplete Schedule = - new JoinDataComplete(new JoinData {JoinNumber = 102, JoinSpan = 1}, - new JoinMetadata - { - Description = "Schedule Data - XSIG", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DialMeeting")] public JoinDataComplete DialMeeting = new JoinDataComplete(new JoinData{JoinNumber=161, JoinSpan = 1}, - new JoinMetadata - { - Description = "Join first joinable meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("UpdateMeetings")] public JoinDataComplete UpdateMeetings = - new JoinDataComplete(new JoinData {JoinNumber = 162, JoinSpan = 1}, - new JoinMetadata - { - Description = "Update Meetings", + Description = "Dial manual string", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); @@ -539,82 +559,15 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Analog }); - - [JoinName("CameraLayoutStringFb")] - public JoinDataComplete CameraLayoutStringFb = - new JoinDataComplete(new JoinData { JoinNumber = 141, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Layout Fb", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - - - - [JoinName("ManualDial")] public JoinDataComplete ManualDial = - new JoinDataComplete(new JoinData {JoinNumber = 71, JoinSpan = 1}, + [JoinName("MicMuteOff")] public JoinDataComplete MicMuteOff = + new JoinDataComplete(new JoinData {JoinNumber = 172, JoinSpan = 1}, new JoinMetadata { - Description = "Dial manual string", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceShareStart")] public JoinDataComplete SourceShareStart = - new JoinDataComplete(new JoinData {JoinNumber = 201, JoinSpan = 1}, - new JoinMetadata - { - Description = "Start Sharing & Feedback", + Description = "Mic Mute Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("SourceShareEnd")] - public JoinDataComplete SourceShareEnd = - new JoinDataComplete(new JoinData { JoinNumber = 202, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Stop Sharing & Feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("AutoShareWhileInCall")] public JoinDataComplete SourceShareAutoStart = - new JoinDataComplete(new JoinData {JoinNumber = 203, JoinSpan = 1}, - new JoinMetadata - { - Description = "When high, will autostart sharing when a call is joined", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CurrentSource")] public JoinDataComplete CurrentSource = new JoinDataComplete(new JoinData{JoinNumber = 201, JoinSpan = 1}, - new JoinMetadata - { - Description = "Current Source", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentParticipants")] public JoinDataComplete CurrentParticipants = - new JoinDataComplete(new JoinData{JoinNumber = 151, JoinSpan = 1}, - new JoinMetadata() - { - Description = "Current Participants XSig", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("ParticipantCount")] public JoinDataComplete ParticipantCount = new JoinDataComplete(new JoinData{JoinNumber = 151, JoinSpan = 1}, - new JoinMetadata - { - Description = "Current Participant Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - [JoinName("MicMuteOn")] public JoinDataComplete MicMuteOn = new JoinDataComplete(new JoinData {JoinNumber = 171, JoinSpan = 1}, new JoinMetadata @@ -624,15 +577,6 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("MicMuteOff")] public JoinDataComplete MicMuteOff = - new JoinDataComplete(new JoinData {JoinNumber = 172, JoinSpan = 1}, - new JoinMetadata - { - Description = "Mic Mute Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("MicMuteToggle")] public JoinDataComplete MicMuteToggle = new JoinDataComplete(new JoinData {JoinNumber = 173, JoinSpan = 1}, new JoinMetadata @@ -642,35 +586,150 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("VolumeMuteOn")] - public JoinDataComplete VolumeMuteOn = - new JoinDataComplete(new JoinData { JoinNumber = 176, JoinSpan = 1 }, + [JoinName("MinutesBeforeMeetingStart")] public JoinDataComplete MinutesBeforeMeetingStart = + new JoinDataComplete(new JoinData {JoinNumber = 41, JoinSpan = 1}, + new JoinMetadata + { + Description = "Minutes before meeting start that a meeting is joinable", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("ParticipantCount")] public JoinDataComplete ParticipantCount = + new JoinDataComplete(new JoinData {JoinNumber = 151, JoinSpan = 1}, + new JoinMetadata + { + Description = "Current Participant Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("Schedule")] public JoinDataComplete Schedule = + new JoinDataComplete(new JoinData {JoinNumber = 102, JoinSpan = 1}, + new JoinMetadata + { + Description = "Schedule Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("AutoShareWhileInCall")] public JoinDataComplete SourceShareAutoStart = + new JoinDataComplete(new JoinData {JoinNumber = 203, JoinSpan = 1}, + new JoinMetadata + { + Description = "When high, will autostart sharing when a call is joined", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareEnd")] public JoinDataComplete SourceShareEnd = + new JoinDataComplete(new JoinData {JoinNumber = 202, JoinSpan = 1}, + new JoinMetadata + { + Description = "Stop Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareStart")] public JoinDataComplete SourceShareStart = + new JoinDataComplete(new JoinData {JoinNumber = 201, JoinSpan = 1}, + new JoinMetadata + { + Description = "Start Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RecievingContent")] public JoinDataComplete RecievingContent = + new JoinDataComplete(new JoinData {JoinNumber = 204, JoinSpan = 1}, + new JoinMetadata + { + Description = "Recieving content from the far end", + JoinType = eJoinType.Digital, + JoinCapabilities = eJoinCapabilities.ToSIMPL + }); + + [JoinName("SelfviewPosition")] public JoinDataComplete SelfviewPosition = + new JoinDataComplete(new JoinData {JoinNumber = 211, JoinSpan = 1}, + new JoinMetadata + { + Description = "advance selfview position", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SelfviewPositionFb")] + public JoinDataComplete SelfviewPositionFb = + new JoinDataComplete(new JoinData { JoinNumber = 211, JoinSpan = 1 }, new JoinMetadata { - Description = "Volume Mute On", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital + Description = "advance selfview position", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial }); - [JoinName("VolumeMuteOff")] - public JoinDataComplete VolumeMuteOff = - new JoinDataComplete(new JoinData { JoinNumber = 177, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Mute Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("SpeedDialStart")] public JoinDataComplete SpeedDialStart = + new JoinDataComplete(new JoinData {JoinNumber = 41, JoinSpan = 4}, + new JoinMetadata + { + Description = "Speed Dial", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("VolumeMuteToggle")] - public JoinDataComplete VolumeMuteToggle = - new JoinDataComplete(new JoinData { JoinNumber = 178, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Mute Toggle", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("UpdateMeetings")] public JoinDataComplete UpdateMeetings = + new JoinDataComplete(new JoinData {JoinNumber = 162, JoinSpan = 1}, + new JoinMetadata + { + Description = "Update Meetings", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeDown")] public JoinDataComplete VolumeDown = + new JoinDataComplete(new JoinData {JoinNumber = 175, JoinSpan = 1}, + new JoinMetadata + { + Description = "Volume Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeLevel")] public JoinDataComplete VolumeLevel = + new JoinDataComplete(new JoinData {JoinNumber = 174, JoinSpan = 1}, + new JoinMetadata + { + Description = "Volume Level", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("VolumeMuteOff")] public JoinDataComplete VolumeMuteOff = + new JoinDataComplete(new JoinData {JoinNumber = 177, JoinSpan = 1}, + new JoinMetadata + { + Description = "Volume Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteOn")] public JoinDataComplete VolumeMuteOn = + new JoinDataComplete(new JoinData {JoinNumber = 176, JoinSpan = 1}, + new JoinMetadata + { + Description = "Volume Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteToggle")] public JoinDataComplete VolumeMuteToggle = + new JoinDataComplete(new JoinData {JoinNumber = 178, JoinSpan = 1}, + new JoinMetadata + { + Description = "Volume Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); [JoinName("VolumeUp")] public JoinDataComplete VolumeUp = new JoinDataComplete(new JoinData {JoinNumber = 174, JoinSpan = 1}, @@ -681,35 +740,6 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("VolumeDown")] - public JoinDataComplete VolumeDown = - new JoinDataComplete(new JoinData { JoinNumber = 175, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeLevel")] - public JoinDataComplete VolumeLevel = - new JoinDataComplete(new JoinData { JoinNumber = 174, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Level", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("MinutesBeforeMeetingStart")] public JoinDataComplete MinutesBeforeMeetingStart = - new JoinDataComplete(new JoinData {JoinNumber = 41, JoinSpan = 1}, - new JoinMetadata - { - Description = "Minutes before meeting start that a meeting is joinable", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof (VideoCodecControllerJoinMap)) { } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IHasFarEndContentStatus.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IHasFarEndContentStatus.cs new file mode 100644 index 00000000..21bde91f --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IHasFarEndContentStatus.cs @@ -0,0 +1,7 @@ +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +{ + public interface IHasFarEndContentStatus + { + BoolFeedback ReceivingContent { get; } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 3bd74bdc..7524c8d7 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -196,6 +196,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index 94988b7b..f115f401 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -121,6 +121,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs new file mode 100644 index 00000000..5360b80a --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs @@ -0,0 +1,14 @@ +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; + +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +{ + public interface IHasSelfviewPosition + { + StringFeedback SelfviewPipPositionFeedback { get; } + + void SelfviewPipPositionSet(CodecCommandWithLabel position); + + void SelfviewPipPositionToggle(); + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 6874e049..1e9e96cd 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -12,7 +12,8 @@ using PepperDash.Core.WebApi.Presets; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; -using PepperDash.Essentials.Core.Devices; +using PepperDash.Essentials.Core.Devices; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; @@ -198,7 +199,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// /// /// - protected void OnCallStatusChange(CodecActiveCallItem item) + protected virtual void OnCallStatusChange(CodecActiveCallItem item) { var handler = CallStatusChange; if (handler != null) @@ -320,6 +321,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (codec is IHasCodecLayouts) { LinkVideoCodecCameraLayoutsToApi(codec as IHasCodecLayouts, trilist, joinMap); + } + + if (codec is IHasSelfviewPosition) + { + LinkVideoCodecSelfviewPositionToApi(codec as IHasSelfviewPosition, trilist, joinMap); } if (codec is IHasDirectory) @@ -335,6 +341,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (codec is IHasParticipants) { LinkVideoCodecParticipantsToApi(codec as IHasParticipants, trilist, joinMap); + } + + if (codec is IHasFarEndContentStatus) + { + (codec as IHasFarEndContentStatus).ReceivingContent.LinkInputSig(trilist.BooleanInput[joinMap.RecievingContent.JoinNumber]); } trilist.OnlineStatusChange += (device, args) => @@ -360,15 +371,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true); - (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.InvokeFireUpdate(); + (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); } if (codec is IHasCodecSelfView) { - (codec as IHasCodecSelfView).SelfviewIsOnFeedback.InvokeFireUpdate(); + (codec as IHasCodecSelfView).SelfviewIsOnFeedback.FireUpdate(); + } + + if (codec is IHasCameraAutoMode) + { + (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); + } + + if (codec is IHasCameraOff) + { + (codec as IHasCameraOff).CameraIsOffFeedback.FireUpdate(); } - SharingContentIsOnFeedback.InvokeFireUpdate(); + SharingContentIsOnFeedback.FireUpdate(); trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); @@ -376,11 +397,53 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec }; } + private void LinkVideoCodecSelfviewPositionToApi(IHasSelfviewPosition codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + trilist.SetSigFalseAction(joinMap.SelfviewPosition.JoinNumber, codec.SelfviewPipPositionToggle); + + codec.SelfviewPipPositionFeedback.LinkInputSig(trilist.StringInput[joinMap.SelfviewPositionFb.JoinNumber]); + } + private void LinkVideoCodecCameraOffToApi(IHasCameraOff codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { - codec.CameraIsOffFeedback.LinkInputSig(trilist.BooleanInput[joinMap.CameraModeOff.JoinNumber]); - trilist.SetSigFalseAction(joinMap.CameraModeOff.JoinNumber, codec.CameraOff); + + codec.CameraIsOffFeedback.OutputChange += (o, a) => + { + if (a.BoolValue) + { + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); + return; + } + + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + + var autoCodec = codec as IHasCameraAutoMode; + + if (autoCodec == null) return; + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoCodec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoCodec.CameraAutoModeIsOnFeedback.BoolValue); + }; + + if (codec.CameraIsOffFeedback.BoolValue) + { + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); + return; + } + + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + + var autoModeCodec = codec as IHasCameraAutoMode; + + if (autoModeCodec == null) return; + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue); } private void LinkVideoCodecVolumeToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) @@ -779,15 +842,56 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { trilist.SetSigFalseAction(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeOn); - trilist.SetSigFalseAction(joinMap.CameraModeManual.JoinNumber, codec.CameraAutoModeOff); - - codec.CameraAutoModeIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.CameraModeAuto.JoinNumber]); - codec.CameraAutoModeIsOnFeedback.LinkComplementInputSig( - trilist.BooleanInput[joinMap.CameraModeManual.JoinNumber]); + trilist.SetSigFalseAction(joinMap.CameraModeManual.JoinNumber, codec.CameraAutoModeOff); + + codec.CameraAutoModeIsOnFeedback.OutputChange += (o, a) => + { + var offCodec = codec as IHasCameraOff; + + if (offCodec != null) + { + if (offCodec.CameraIsOffFeedback.BoolValue) + { + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); + return; + } + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + return; + } + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + }; + + var offModeCodec = codec as IHasCameraOff; + + if (offModeCodec != null) + { + if (offModeCodec.CameraIsOffFeedback.BoolValue) + { + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); + return; + } + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + return; + } + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); } - - private void LinkVideoCodecSelfviewToApi(IHasCodecSelfView codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { @@ -875,9 +979,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { var i = (ushort) codec.Cameras.FindIndex((c) => c.Key == args.SelectedCamera.Key); - trilist.SetUshort(joinMap.CameraPresetSelect.JoinNumber, i); - - if (codec is IHasCodecRoomPresets) + if (codec is IHasCodecRoomPresets) { return; } @@ -890,25 +992,59 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec var cam = args.SelectedCamera as IHasCameraPresets; SetCameraPresetNames(cam.Presets); - (args.SelectedCamera as IHasCameraPresets).PresetsListHasChanged += (o, eventArgs) => SetCameraPresetNames(cam.Presets); - }; + (args.SelectedCamera as IHasCameraPresets).PresetsListHasChanged += (o, eventArgs) => SetCameraPresetNames(cam.Presets); + + trilist.SetUShortSigAction(joinMap.CameraPresetSelect.JoinNumber, + (a) => + { + cam.PresetSelect(a); + trilist.SetUshort(joinMap.CameraPresetSelect.JoinNumber, a); + }); + + trilist.SetSigFalseAction(joinMap.CameraPresetSave.JoinNumber, + () => + { + cam.PresetStore(trilist.UShortOutput[joinMap.CameraPresetSelect.JoinNumber].UShortValue, + String.Empty); + trilist.PulseBool(joinMap.CameraPresetSave.JoinNumber, 3000); + }); + }; + + if (!(codec is IHasCodecRoomPresets)) return; + + var presetCodec = codec as IHasCodecRoomPresets; + + presetCodec.CodecRoomPresetsListHasChanged += + (sender, args) => SetCameraPresetNames(presetCodec.NearEndPresets); //Camera Presets - trilist.SetUShortSigAction(joinMap.CameraPresetSelect.JoinNumber, (i) => - { - if (codec.SelectedCamera == null) return; - - var cam = codec.SelectedCamera as IHasCameraPresets; - - if (cam == null) return; - - cam.PresetSelect(i); + trilist.SetUShortSigAction(joinMap.CameraPresetSelect.JoinNumber, (i) => + { + presetCodec.CodecRoomPresetSelect(i); trilist.SetUshort(joinMap.CameraPresetSelect.JoinNumber, i); - }); + }); + + trilist.SetSigFalseAction(joinMap.CameraPresetSave.JoinNumber, + () => + { + presetCodec.CodecRoomPresetStore( + trilist.UShortOutput[joinMap.CameraPresetSelect.JoinNumber].UShortValue, String.Empty); + trilist.PulseBool(joinMap.CameraPresetSave.JoinNumber, 3000); + }); + } + + private string SetCameraPresetNames(IEnumerable presets) + { + return SetCameraPresetNames(presets.Select(p => p.Description).ToList()); + } + + private string SetCameraPresetNames(IEnumerable presets) + { + return SetCameraPresetNames(presets.Select(p => p.Description).ToList()); } - private string SetCameraPresetNames(List presets) + private string SetCameraPresetNames(ICollection presets) { var i = 1; //start index for xsig; @@ -916,7 +1052,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec foreach (var preset in presets) { - var cameraPreset = new XSigSerialToken(i, preset.Description); + var cameraPreset = new XSigSerialToken(i, preset); tokenArray[i - 1] = cameraPreset; i++; } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index f49f6281..5f316523 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -370,7 +370,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public CallRecordInfo CallRecordInfo { get; set; } - public zCommand.InfoResult Info { get; set; } + private zCommand.InfoResult _info; + + public zCommand.InfoResult Info + { + get + { + return _info; + } + set + { + _info = value; + NotifyPropertyChanged("Info"); + } + } public Call() { @@ -702,7 +715,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public class Camera : NotifiableObject { - private string _muteState; private bool _mute; public bool Mute @@ -710,30 +722,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom get { return _mute; } set { + Debug.Console(1, "Camera Mute response received: {0}", value); + if (value == _mute) return; - + _mute = value; NotifyPropertyChanged("Mute"); } } - - [JsonProperty("mute")] - public string MuteState - { - get - { - return _muteState; - } - set - { - if (value != _muteState) - { - _muteState = value; - - Mute = _muteState == "on"; - } - } - } } public class Microphone : NotifiableObject @@ -787,12 +783,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom DownLeft } - public class Layout + public class Layout:NotifiableObject { public bool ShareThumb { get; set; } public eLayoutStyle Style { get; set; } public eLayoutSize Size { get; set; } - public eLayoutPosition Position { get; set; } + + private eLayoutPosition _position; + public eLayoutPosition Position { + get { return _position; } + set + { + _position = value; + NotifyPropertyChanged("Position"); + } } } public class Lock diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 657a27c8..1b7e6ec4 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -11,16 +11,18 @@ 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.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, IHasCameraAutoMode + IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraAutoMode, IHasFarEndContentStatus, IHasSelfviewPosition { private const long MeetingRefreshTimer = 60000; private const uint DefaultMeetingDurationMin = 30; @@ -98,6 +100,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom CodecSchedule = new CodecScheduleAwareness(MeetingRefreshTimer); + ReceivingContent = new BoolFeedback(FarEndIsSharingContentFeedbackFunc); + + SelfviewPipPositionFeedback = new StringFeedback(SelfviewPipPositionFeedbackFunc); + SetUpFeedbackActions(); Cameras = new List(); @@ -152,7 +158,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom protected Func FarEndIsSharingContentFeedbackFunc { - get { return () => false; } + get { return () => Status.Call.Sharing.State == zEvent.eSharingState.Receiving; } } protected override Func MuteFeedbackFunc @@ -183,17 +189,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom protected Func CameraIsOffFeedbackFunc { - get { return () => Configuration.Camera.Mute; } + get { return () => Configuration.Call.Camera.Mute; } } protected Func CameraAutoModeIsOnFeedbackFunc { - get { return () => !Configuration.Camera.Mute; } + get { return () => false; } } protected Func SelfviewPipPositionFeedbackFunc { - get { return () => ""; } + get { return () => _currentSelfviewPipPosition.Command; } } protected Func LocalLayoutFeedbackFunc @@ -432,11 +438,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } }; - Configuration.Camera.PropertyChanged += (o, a) => + 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) => + { + if (a.PropertyName != "Position") return; + + ComputeSelfviewPipStatus(); + + SelfviewPipPositionFeedback.FireUpdate(); }; Status.Call.Sharing.PropertyChanged += (o, a) => @@ -444,6 +462,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (a.PropertyName == "State") { SharingContentIsOnFeedback.FireUpdate(); + ReceivingContent.FireUpdate(); + } + }; + + Status.Call.PropertyChanged += (o, a) => + { + if (a.PropertyName == "Info") + { + Debug.Console(1, this, "Updating Call Status"); + UpdateCallStatus(); } }; @@ -658,6 +686,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom _syncState.AddQueryToQueue("zCommand Bookings List"); _syncState.AddQueryToQueue("zCommand Call ListParticipants"); + _syncState.AddQueryToQueue("zCommand Call Info"); _syncState.StartSync(); @@ -670,6 +699,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void ProcessMessage(string message) { // Counts the curly braces + if (message.Contains("client_loop: send disconnect: Broken pipe")) + { + Debug.Console(0, 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++; @@ -759,9 +796,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SendText("zFeedback Register Op: ex Path: /Event/InfoResult/info/callout_country_list"); Thread.Sleep(100); - if (!_props.DisablePhonebookAutoDownload) + if (_props.DisablePhonebookAutoDownload) { - SendText("zFeedback Register "); + SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); } // switch to json format SendText("format json"); @@ -841,6 +878,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { switch (topKey.ToLower()) { + case "inforesult": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Info); + break; + } case "phonebooklistresult": { JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); @@ -1160,6 +1202,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { JsonConvert.PopulateObject(responseObj.ToString(), Status.Sharing); + SetLayout(); + break; } case "numberofscreens": @@ -1224,6 +1268,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } + private void SetLayout() + { + 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 + { + SendText(String.Format("zconfiguration call layout style: {0}", + _props.DefaultCallLayout)); + } + } + public void PrintCurrentCallParticipants() { if (Debug.Level <= 0) @@ -1329,6 +1391,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(1, this, "**************************************************************************"); } + protected override void OnCallStatusChange(CodecActiveCallItem item) + { + base.OnCallStatusChange(item); + + if (_props.AutoDefaultLayouts) + { + SetLayout(); + } + } public override void StartSharing() { throw new NotImplementedException(); @@ -1631,6 +1702,52 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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("DownLeft", "Lower Left"), + new CodecCommandWithLabel("DownRight", "Lower Right") + }; + + void ComputeSelfviewPipStatus() + { + _currentSelfviewPipPosition = + SelfviewPipPositions.FirstOrDefault( + p => p.Command.ToLower().Equals(Configuration.Call.Layout.Position.ToString())); + } + #endregion } /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs index 464c8b9a..7a3abdaa 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs @@ -68,7 +68,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// /// Builds the command and triggers the parent ZoomRoom to send it /// - /// /// /// void SendCommand(eZoomRoomCameraState state, eZoomRoomCameraAction action) @@ -86,16 +85,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom void SendContinueAction(eZoomRoomCameraAction action) { SendCommand(eZoomRoomCameraState.Continue, action); - ContinueTimer.Reset(); } void StopContinueTimer() { - if (ContinueTimer != null) + if (ContinueTimer == null) { - ContinueTimer.Stop(); - ContinueTimer.Dispose(); + return; } + + ContinueTimer.Stop(); + ContinueTimer.Dispose(); + ContinueTimer = null; } #region IHasCameraPtzControl Members @@ -111,22 +112,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void PanLeft() { - if (!isMoving) + if (isMoving) { - SendCommand(eZoomRoomCameraState.Start, eZoomRoomCameraAction.Left); - StartContinueTimer(); - isPanning = true; + return; } + + SendCommand(eZoomRoomCameraState.Start, eZoomRoomCameraAction.Left); + StartContinueTimer(); + isPanning = true; } public void PanRight() { - if (!isMoving) + if (isMoving) { - SendCommand(eZoomRoomCameraState.Start, eZoomRoomCameraAction.Right); - StartContinueTimer(); - isPanning = true; + return; } + + SendCommand(eZoomRoomCameraState.Start, eZoomRoomCameraAction.Right); + StartContinueTimer(); + isPanning = true; } public void PanStop() diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs index 4e2545ec..38238023 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs @@ -16,5 +16,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public bool DisablePhonebookAutoDownload { get; set; } public bool SupportsCameraAutoMode { get; set; } public bool SupportsCameraOff { get; set; } + + //if true, the layouts will be set automatically when sharing starts/ends or a call is joined + public bool AutoDefaultLayouts { get; set; } + + /* This layout will be selected when Sharing starts (either from Far end or locally)*/ + public string DefaultSharingLayout { get; set; } + + //This layout will be selected when a call is connected and no content is being shared + public string DefaultCallLayout { get; set; } } } \ No newline at end of file diff --git a/packages.config b/packages.config index 40078601..296413b6 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From ad4a6e938344e36c5c1326ba5cfb52a63c4e5386 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 6 Oct 2020 16:59:27 -0400 Subject: [PATCH 35/42] Fixes for UpdateCallStatusXSig() method --- .../VideoCodec/VideoCodecBase.cs | 414 +++++++++--------- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 2 +- 2 files changed, 216 insertions(+), 200 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 1e9e96cd..ef9c4e1f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -12,8 +12,8 @@ using PepperDash.Core.WebApi.Presets; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; -using PepperDash.Essentials.Core.Devices; -using PepperDash.Essentials.Core.DeviceTypeInterfaces; +using PepperDash.Essentials.Core.Devices; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; @@ -61,9 +61,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public List ActiveCalls { get; set; } - public bool ShowSelfViewByDefault { get; protected set; } - - protected bool SupportsCameraOff; + public bool ShowSelfViewByDefault { get; protected set; } + + protected bool SupportsCameraOff; protected bool SupportsCameraAutoMode; public bool IsReady { get; protected set; } @@ -310,22 +310,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, SupportsCameraAutoMode); LinkVideoCodecCameraModeToApi(codec as IHasCameraAutoMode, trilist, joinMap); - } - - if (codec is IHasCameraOff) - { - trilist.SetBool(joinMap.CameraSupportsOffMode.JoinNumber, SupportsCameraOff); - LinkVideoCodecCameraOffToApi(codec as IHasCameraOff, trilist, joinMap); + } + + if (codec is IHasCameraOff) + { + trilist.SetBool(joinMap.CameraSupportsOffMode.JoinNumber, SupportsCameraOff); + LinkVideoCodecCameraOffToApi(codec as IHasCameraOff, trilist, joinMap); } if (codec is IHasCodecLayouts) { LinkVideoCodecCameraLayoutsToApi(codec as IHasCodecLayouts, trilist, joinMap); - } - - if (codec is IHasSelfviewPosition) - { - LinkVideoCodecSelfviewPositionToApi(codec as IHasSelfviewPosition, trilist, joinMap); + } + + if (codec is IHasSelfviewPosition) + { + LinkVideoCodecSelfviewPositionToApi(codec as IHasSelfviewPosition, trilist, joinMap); } if (codec is IHasDirectory) @@ -341,11 +341,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (codec is IHasParticipants) { LinkVideoCodecParticipantsToApi(codec as IHasParticipants, trilist, joinMap); - } - - if (codec is IHasFarEndContentStatus) - { - (codec as IHasFarEndContentStatus).ReceivingContent.LinkInputSig(trilist.BooleanInput[joinMap.RecievingContent.JoinNumber]); + } + + if (codec is IHasFarEndContentStatus) + { + (codec as IHasFarEndContentStatus).ReceivingContent.LinkInputSig(trilist.BooleanInput[joinMap.RecievingContent.JoinNumber]); } trilist.OnlineStatusChange += (device, args) => @@ -377,75 +377,75 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (codec is IHasCodecSelfView) { (codec as IHasCodecSelfView).SelfviewIsOnFeedback.FireUpdate(); - } - - if (codec is IHasCameraAutoMode) - { - (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); - } - - if (codec is IHasCameraOff) - { - (codec as IHasCameraOff).CameraIsOffFeedback.FireUpdate(); } - SharingContentIsOnFeedback.FireUpdate(); - + if (codec is IHasCameraAutoMode) + { + (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); + } + + if (codec is IHasCameraOff) + { + (codec as IHasCameraOff).CameraIsOffFeedback.FireUpdate(); + } + + SharingContentIsOnFeedback.FireUpdate(); + trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); - UpdateCallStatusXSig(); + trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); }; - } - - private void LinkVideoCodecSelfviewPositionToApi(IHasSelfviewPosition codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) - { - trilist.SetSigFalseAction(joinMap.SelfviewPosition.JoinNumber, codec.SelfviewPipPositionToggle); - - codec.SelfviewPipPositionFeedback.LinkInputSig(trilist.StringInput[joinMap.SelfviewPositionFb.JoinNumber]); - } - - private void LinkVideoCodecCameraOffToApi(IHasCameraOff codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) - { - trilist.SetSigFalseAction(joinMap.CameraModeOff.JoinNumber, codec.CameraOff); - - codec.CameraIsOffFeedback.OutputChange += (o, a) => - { - if (a.BoolValue) - { - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); - return; - } - - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); - - var autoCodec = codec as IHasCameraAutoMode; - - if (autoCodec == null) return; - - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoCodec.CameraAutoModeIsOnFeedback.BoolValue); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoCodec.CameraAutoModeIsOnFeedback.BoolValue); - }; - - if (codec.CameraIsOffFeedback.BoolValue) - { - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); - return; - } - - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); - - var autoModeCodec = codec as IHasCameraAutoMode; - - if (autoModeCodec == null) return; - - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue); - } - + } + + private void LinkVideoCodecSelfviewPositionToApi(IHasSelfviewPosition codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + trilist.SetSigFalseAction(joinMap.SelfviewPosition.JoinNumber, codec.SelfviewPipPositionToggle); + + codec.SelfviewPipPositionFeedback.LinkInputSig(trilist.StringInput[joinMap.SelfviewPositionFb.JoinNumber]); + } + + private void LinkVideoCodecCameraOffToApi(IHasCameraOff codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + trilist.SetSigFalseAction(joinMap.CameraModeOff.JoinNumber, codec.CameraOff); + + codec.CameraIsOffFeedback.OutputChange += (o, a) => + { + if (a.BoolValue) + { + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); + return; + } + + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + + var autoCodec = codec as IHasCameraAutoMode; + + if (autoCodec == null) return; + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoCodec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoCodec.CameraAutoModeIsOnFeedback.BoolValue); + }; + + if (codec.CameraIsOffFeedback.BoolValue) + { + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); + return; + } + + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + + var autoModeCodec = codec as IHasCameraAutoMode; + + if (autoModeCodec == null) return; + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue); + } + private void LinkVideoCodecVolumeToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMuteOn.JoinNumber]); @@ -665,11 +665,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); - tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, String.Empty); - - digitalIndex += maxDigitals; - meetingIndex += offset; - stringIndex += maxStrings; + tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, String.Empty); + + digitalIndex += maxDigitals; + meetingIndex += offset; + stringIndex += maxStrings; } return GetXSigString(tokenArray); @@ -763,8 +763,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec () => Dial(trilist.StringOutput[joinMap.CurrentDialString.JoinNumber].StringValue)); //End All calls for now - trilist.SetSigFalseAction(joinMap.EndCall.JoinNumber, EndAllCalls); - + trilist.SetSigFalseAction(joinMap.EndCall.JoinNumber, EndAllCalls); + trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); CallStatusChange += (sender, args) => @@ -779,9 +779,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetSigFalseAction(joinMap.IncomingReject.JoinNumber, () => RejectCall(args.CallItem)); } - var callStatusXsig = UpdateCallStatusXSig(); - - trilist.SetString(joinMap.CurrentCallData.JoinNumber, callStatusXsig); + trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); }; } @@ -790,26 +788,44 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec const int maxCalls = 8; const int maxStrings = 5; const int offset = 6; - var callIndex = 0; - var digitalIndex = maxStrings*maxCalls; - - - var tokenArray = new XSigToken[ActiveCalls.Count*offset]; //set array size for number of calls * pieces of info + var stringIndex = 0; + var digitalIndex = maxStrings * maxCalls; + var arrayIndex = 0; + + var tokenArray = new XSigToken[maxCalls*offset]; //set array size for number of calls * pieces of info foreach (var call in ActiveCalls) { - var arrayIndex = callIndex; + if (arrayIndex >= maxCalls * offset) + break; //digitals tokenArray[arrayIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall); //serials - tokenArray[arrayIndex + 1] = new XSigSerialToken(callIndex + 1, call.Name ?? String.Empty); - tokenArray[arrayIndex + 2] = new XSigSerialToken(callIndex + 2, call.Number ?? String.Empty); - tokenArray[arrayIndex + 3] = new XSigSerialToken(callIndex + 3, call.Direction.ToString()); - tokenArray[arrayIndex + 4] = new XSigSerialToken(callIndex + 4, call.Type.ToString()); - tokenArray[arrayIndex + 5] = new XSigSerialToken(callIndex + 5, call.Status.ToString()); + tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); + tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, call.Number ?? String.Empty); + tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); + tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); + tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); - callIndex += offset; + arrayIndex += offset; + stringIndex += maxStrings; + digitalIndex++; + } + while (digitalIndex < maxCalls) + { + //digitals + tokenArray[arrayIndex] = new XSigDigitalToken(digitalIndex + 1, false); + + //serials + tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty); + tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 4, String.Empty); + tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 5, String.Empty); + + arrayIndex += offset; + stringIndex += maxStrings; digitalIndex++; } @@ -842,54 +858,54 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { trilist.SetSigFalseAction(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeOn); - trilist.SetSigFalseAction(joinMap.CameraModeManual.JoinNumber, codec.CameraAutoModeOff); - - codec.CameraAutoModeIsOnFeedback.OutputChange += (o, a) => - { - var offCodec = codec as IHasCameraOff; - - if (offCodec != null) - { - if (offCodec.CameraIsOffFeedback.BoolValue) - { - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); - return; - } - - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); - return; - } - - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); - }; - - var offModeCodec = codec as IHasCameraOff; - - if (offModeCodec != null) - { - if (offModeCodec.CameraIsOffFeedback.BoolValue) - { - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); - return; - } - - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); - return; - } - - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + trilist.SetSigFalseAction(joinMap.CameraModeManual.JoinNumber, codec.CameraAutoModeOff); + + codec.CameraAutoModeIsOnFeedback.OutputChange += (o, a) => + { + var offCodec = codec as IHasCameraOff; + + if (offCodec != null) + { + if (offCodec.CameraIsOffFeedback.BoolValue) + { + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); + return; + } + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + return; + } + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + }; + + var offModeCodec = codec as IHasCameraOff; + + if (offModeCodec != null) + { + if (offModeCodec.CameraIsOffFeedback.BoolValue) + { + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); + return; + } + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + return; + } + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); } private void LinkVideoCodecSelfviewToApi(IHasCodecSelfView codec, BasicTriList trilist, @@ -979,7 +995,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { var i = (ushort) codec.Cameras.FindIndex((c) => c.Key == args.SelectedCamera.Key); - if (codec is IHasCodecRoomPresets) + if (codec is IHasCodecRoomPresets) { return; } @@ -992,56 +1008,56 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec var cam = args.SelectedCamera as IHasCameraPresets; SetCameraPresetNames(cam.Presets); - (args.SelectedCamera as IHasCameraPresets).PresetsListHasChanged += (o, eventArgs) => SetCameraPresetNames(cam.Presets); - - trilist.SetUShortSigAction(joinMap.CameraPresetSelect.JoinNumber, - (a) => - { - cam.PresetSelect(a); - trilist.SetUshort(joinMap.CameraPresetSelect.JoinNumber, a); - }); - - trilist.SetSigFalseAction(joinMap.CameraPresetSave.JoinNumber, - () => - { - cam.PresetStore(trilist.UShortOutput[joinMap.CameraPresetSelect.JoinNumber].UShortValue, - String.Empty); - trilist.PulseBool(joinMap.CameraPresetSave.JoinNumber, 3000); - }); - }; - - if (!(codec is IHasCodecRoomPresets)) return; - - var presetCodec = codec as IHasCodecRoomPresets; - - presetCodec.CodecRoomPresetsListHasChanged += + (args.SelectedCamera as IHasCameraPresets).PresetsListHasChanged += (o, eventArgs) => SetCameraPresetNames(cam.Presets); + + trilist.SetUShortSigAction(joinMap.CameraPresetSelect.JoinNumber, + (a) => + { + cam.PresetSelect(a); + trilist.SetUshort(joinMap.CameraPresetSelect.JoinNumber, a); + }); + + trilist.SetSigFalseAction(joinMap.CameraPresetSave.JoinNumber, + () => + { + cam.PresetStore(trilist.UShortOutput[joinMap.CameraPresetSelect.JoinNumber].UShortValue, + String.Empty); + trilist.PulseBool(joinMap.CameraPresetSave.JoinNumber, 3000); + }); + }; + + if (!(codec is IHasCodecRoomPresets)) return; + + var presetCodec = codec as IHasCodecRoomPresets; + + presetCodec.CodecRoomPresetsListHasChanged += (sender, args) => SetCameraPresetNames(presetCodec.NearEndPresets); //Camera Presets - trilist.SetUShortSigAction(joinMap.CameraPresetSelect.JoinNumber, (i) => - { + trilist.SetUShortSigAction(joinMap.CameraPresetSelect.JoinNumber, (i) => + { presetCodec.CodecRoomPresetSelect(i); trilist.SetUshort(joinMap.CameraPresetSelect.JoinNumber, i); - }); - - trilist.SetSigFalseAction(joinMap.CameraPresetSave.JoinNumber, - () => - { - presetCodec.CodecRoomPresetStore( - trilist.UShortOutput[joinMap.CameraPresetSelect.JoinNumber].UShortValue, String.Empty); - trilist.PulseBool(joinMap.CameraPresetSave.JoinNumber, 3000); + }); + + trilist.SetSigFalseAction(joinMap.CameraPresetSave.JoinNumber, + () => + { + presetCodec.CodecRoomPresetStore( + trilist.UShortOutput[joinMap.CameraPresetSelect.JoinNumber].UShortValue, String.Empty); + trilist.PulseBool(joinMap.CameraPresetSave.JoinNumber, 3000); }); - } - - private string SetCameraPresetNames(IEnumerable presets) - { - return SetCameraPresetNames(presets.Select(p => p.Description).ToList()); - } - - private string SetCameraPresetNames(IEnumerable presets) - { - return SetCameraPresetNames(presets.Select(p => p.Description).ToList()); + } + + private string SetCameraPresetNames(IEnumerable presets) + { + return SetCameraPresetNames(presets.Select(p => p.Description).ToList()); + } + + private string SetCameraPresetNames(IEnumerable presets) + { + return SetCameraPresetNames(presets.Select(p => p.Description).ToList()); } private string SetCameraPresetNames(ICollection presets) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 1b7e6ec4..6cb62a34 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -1402,7 +1402,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } public override void StartSharing() { - throw new NotImplementedException(); + SendText("zCommand Call Sharing HDMI Start"); } /// From f4fb9cd17312c9f38731d81f743607d1bd3a7507 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 7 Oct 2020 12:45:05 -0600 Subject: [PATCH 36/42] add fix for sharing status not updating add fix for clearing participants list on meeting end --- .../VideoCodec/VideoCodecBase.cs | 23 +++++++++++---- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 29 ++++++++++++++++++- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index ef9c4e1f..05e17895 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -484,6 +484,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec codec.Participants.ParticipantsListHasChanged += (sender, args) => { string participantsXSig; + if (codec.Participants.CurrentParticipants.Count == 0) { participantsXSig = Encoding.GetEncoding(XSigEncoding).GetString(_clearBytes, 0, _clearBytes.Length); @@ -492,10 +493,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec return; } - participantsXSig = Encoding.GetEncoding(XSigEncoding).GetString(_clearBytes, 0, _clearBytes.Length); - - trilist.SetString(joinMap.CurrentParticipants.JoinNumber, participantsXSig); - participantsXSig = UpdateParticipantsXSig(codec.Participants.CurrentParticipants); trilist.SetString(joinMap.CurrentParticipants.JoinNumber, participantsXSig); @@ -518,7 +515,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec foreach (var participant in currentParticipants) { - if (meetingIndex > maxParticipants * offset) break; + if (meetingIndex >= maxParticipants * offset) break; //digitals tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, participant.AudioMuteFb); @@ -534,6 +531,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec meetingIndex += offset; stringIndex += maxStrings; } + + while (meetingIndex < maxParticipants*offset) + { + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); + tokenArray[digitalIndex + 2] = new XSigDigitalToken(digitalIndex + 3, false); + tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, false); + tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, false); + + //serials + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); + + digitalIndex += maxDigitals; + meetingIndex += offset; + stringIndex += maxStrings; + } return GetXSigString(tokenArray); } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 6cb62a34..e6cc3fc2 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -399,6 +399,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SetIsReady(); } + private void SetUpCallFeedbackActions() + { + Status.Call.Sharing.PropertyChanged += (o, a) => + { + if (a.PropertyName == "State") + { + SharingContentIsOnFeedback.FireUpdate(); + ReceivingContent.FireUpdate(); + } + }; + + Status.Call.PropertyChanged += (o, a) => + { + if (a.PropertyName == "Info") + { + Debug.Console(1, this, "Updating Call Status"); + UpdateCallStatus(); + } + }; + } /// /// Subscribes to the PropertyChanged events on the state objects and fires the corresponding feedbacks. @@ -1324,6 +1344,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (callStatus != zStatus.eCallStatus.IN_MEETING || callStatus != zStatus.eCallStatus.CONNECTING_MEETING) { Status.Call = new zStatus.Call {Status = callStatus}; + + SetUpCallFeedbackActions(); } if (ActiveCalls.Count == 0) @@ -1387,8 +1409,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom ActiveCalls.Remove(call); } } - Debug.Console(1, this, "**************************************************************************"); + + //clear participants list after call cleanup + if (ActiveCalls.Count == 0) + { + Participants.CurrentParticipants = new List(); + } } protected override void OnCallStatusChange(CodecActiveCallItem item) From c58a1874cac77faccc3d16c82f7f50eae21f87c2 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Wed, 7 Oct 2020 15:41:04 -0400 Subject: [PATCH 37/42] Limits max video participant list size to 50 --- .../Essentials Devices Common/VideoCodec/VideoCodecBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 05e17895..494eea04 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -503,7 +503,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec private string UpdateParticipantsXSig(List currentParticipants) { - const int maxParticipants = 255; + const int maxParticipants = 50; const int maxDigitals = 5; const int maxStrings = 1; const int offset = maxDigitals + maxStrings; From 5f1b92ca623a35e11c0c589e56c13b3ef1599c0c Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Thu, 8 Oct 2020 11:43:12 -0400 Subject: [PATCH 38/42] Adds additional check for if DisablePhonebookAutoDownload is true to CustomActivate method. Fixes issue where layout was not being set properly on sharing end. --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index e6cc3fc2..1849f0ea 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -552,9 +552,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { CrestronConsole.AddNewConsoleCommand(SetCommDebug, "SetCodecCommDebug", "0 for Off, 1 for on", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 512"), - "GetZoomRoomContacts", "Triggers a refresh of the codec phonebook", - ConsoleAccessLevelEnum.AccessOperator); + if (!_props.DisablePhonebookAutoDownload) + { + CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 512"), + "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); @@ -816,7 +820,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SendText("zFeedback Register Op: ex Path: /Event/InfoResult/info/callout_country_list"); Thread.Sleep(100); - if (_props.DisablePhonebookAutoDownload) + if (!_props.DisablePhonebookAutoDownload) { SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); } @@ -1062,6 +1066,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom case "sharingstate": { JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing); + + SetLayout(); break; } @@ -1222,8 +1228,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { JsonConvert.PopulateObject(responseObj.ToString(), Status.Sharing); - SetLayout(); - break; } case "numberofscreens": @@ -1758,6 +1762,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SelfviewPipPositionSet(SelfviewPipPositions[nextPipPositionIndex]); } + else + { + SelfviewPipPositionSet(SelfviewPipPositions[0]); + } } public List SelfviewPipPositions = new List() From 28e8a1fb11c81440d328d60138b2bbcae4145213 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Thu, 8 Oct 2020 14:40:44 -0400 Subject: [PATCH 39/42] Fixes for selfview feedback. Rearranges order to happen in clockwise motion --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 1849f0ea..578e3dae 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -1762,25 +1762,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SelfviewPipPositionSet(SelfviewPipPositions[nextPipPositionIndex]); } - else - { - SelfviewPipPositionSet(SelfviewPipPositions[0]); - } } public List SelfviewPipPositions = new List() { new CodecCommandWithLabel("UpLeft", "Center Left"), new CodecCommandWithLabel("UpRight", "Center Right"), - new CodecCommandWithLabel("DownLeft", "Lower Left"), - new CodecCommandWithLabel("DownRight", "Lower Right") + new CodecCommandWithLabel("DownRight", "Lower Right"), + new CodecCommandWithLabel("DownLeft", "Lower Left") }; void ComputeSelfviewPipStatus() { _currentSelfviewPipPosition = SelfviewPipPositions.FirstOrDefault( - p => p.Command.ToLower().Equals(Configuration.Call.Layout.Position.ToString())); + p => p.Command.ToLower().Equals(Configuration.Call.Layout.Position.ToString().ToLower())); } #endregion } From cdc9cdbe95b58379a1008aa3e8d4626e93b96bdf Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Thu, 8 Oct 2020 15:25:51 -0400 Subject: [PATCH 40/42] Adds joining meetings 2 and 3 if meetings exist --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 26 ++++++++++++++++--- .../VideoCodec/VideoCodecBase.cs | 16 +++++++++--- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 7e71ec22..50813700 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -225,15 +225,35 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); - [JoinName("DialMeeting")] public JoinDataComplete DialMeeting = + [JoinName("DialMeeting1")] public JoinDataComplete DialMeeting1 = new JoinDataComplete(new JoinData {JoinNumber = 161, JoinSpan = 1}, new JoinMetadata { - Description = "Join first joinable meeting", + Description = "Join first meeting", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DialMeeting2")] + public JoinDataComplete DialMeeting2 = + new JoinDataComplete(new JoinData { JoinNumber = 162, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Join second meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting3")] + public JoinDataComplete DialMeeting3 = + new JoinDataComplete(new JoinData { JoinNumber = 163, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Join third meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("DirectoryDialSelectedLine")] public JoinDataComplete DirectoryDialSelectedLine = new JoinDataComplete(new JoinData {JoinNumber = 106, JoinSpan = 1}, new JoinMetadata @@ -678,7 +698,7 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); [JoinName("UpdateMeetings")] public JoinDataComplete UpdateMeetings = - new JoinDataComplete(new JoinData {JoinNumber = 162, JoinSpan = 1}, + new JoinDataComplete(new JoinData {JoinNumber = 160, JoinSpan = 1}, new JoinMetadata { Description = "Update Meetings", diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 494eea04..b0f6395d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -595,12 +595,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData); - trilist.SetSigFalseAction(joinMap.DialMeeting.JoinNumber, () => + trilist.SetSigFalseAction(joinMap.DialMeeting1.JoinNumber, () => { - if (codec.CodecSchedule.Meetings[0].Joinable) - { + if(codec.CodecSchedule.Meetings[0] != null) Dial(codec.CodecSchedule.Meetings[0]); - } + }); + trilist.SetSigFalseAction(joinMap.DialMeeting2.JoinNumber, () => + { + if (codec.CodecSchedule.Meetings[1] != null) + Dial(codec.CodecSchedule.Meetings[1]); + }); + trilist.SetSigFalseAction(joinMap.DialMeeting3.JoinNumber, () => + { + if (codec.CodecSchedule.Meetings[2] != null) + Dial(codec.CodecSchedule.Meetings[2]); }); trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)currentMeetings.Count); From 1676f5a9560335e0543c1cb8716a46b779bb6e4b Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 8 Oct 2020 17:09:59 -0600 Subject: [PATCH 41/42] add phone call logic and commands to Zoom Room --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 40 +++++++++ .../DeviceTypeInterfaces/IHasPhoneDialing.cs | 14 +++ .../PepperDash_Essentials_Core.csproj | 1 + .../VideoCodec/VideoCodecBase.cs | 21 +++++ .../VideoCodec/ZoomRoom/ResponseObjects.cs | 80 +++++++++++++++++ .../VideoCodec/ZoomRoom/ZoomRoom.cs | 87 ++++++++++++++++--- 6 files changed, 232 insertions(+), 11 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IHasPhoneDialing.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 50813700..8054a077 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -760,6 +760,46 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("DialPhoneCall")] + public JoinDataComplete DialPhone = + new JoinDataComplete(new JoinData { JoinNumber = 72, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Dial Phone", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PhoneHookState")] + public JoinDataComplete PhoneHookState = + new JoinDataComplete(new JoinData { JoinNumber = 72, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Dial Phone", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("EndPhoneCall")] + public JoinDataComplete HangUpPhone = + new JoinDataComplete(new JoinData { JoinNumber = 73, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Hang Up PHone", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PhoneString")] + public JoinDataComplete PhoneDialString = + new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Phone Dial String", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof (VideoCodecControllerJoinMap)) { } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IHasPhoneDialing.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IHasPhoneDialing.cs new file mode 100644 index 00000000..2b7af8ad --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IHasPhoneDialing.cs @@ -0,0 +1,14 @@ +using PepperDash.Essentials.Core; + +namespace PepperDash_Essentials_Core.DeviceTypeInterfaces +{ + public interface IHasPhoneDialing + { + BoolFeedback PhoneOffHookFeedback { get; } + StringFeedback CallerIdNameFeedback { get; } + StringFeedback CallerIdNumberFeedback { get; } + void DialPhoneCall(string number); + void EndPhoneCall(); + void SendDtmfToPhone(string digit); + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 7524c8d7..9cc4365f 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -197,6 +197,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index b0f6395d..8b7b3bce 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -19,6 +19,7 @@ using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; using PepperDash_Essentials_Core.Bridges.JoinMaps; +using PepperDash_Essentials_Core.DeviceTypeInterfaces; using Feedback = PepperDash.Essentials.Core.Feedback; namespace PepperDash.Essentials.Devices.Common.VideoCodec @@ -348,6 +349,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec (codec as IHasFarEndContentStatus).ReceivingContent.LinkInputSig(trilist.BooleanInput[joinMap.RecievingContent.JoinNumber]); } + if (codec is IHasPhoneDialing) + { + LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap); + } + trilist.OnlineStatusChange += (device, args) => { if (!args.DeviceOnLine) return; @@ -389,6 +395,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec (codec as IHasCameraOff).CameraIsOffFeedback.FireUpdate(); } + if (codec is IHasPhoneDialing) + { + (codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate(); + } + SharingContentIsOnFeedback.FireUpdate(); trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); @@ -397,6 +408,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec }; } + private void LinkVideoCodecPhoneToApi(IHasPhoneDialing codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + codec.PhoneOffHookFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PhoneHookState.JoinNumber]); + + trilist.SetSigFalseAction(joinMap.DialPhone.JoinNumber, + () => codec.DialPhoneCall(trilist.StringOutput[joinMap.PhoneDialString.JoinNumber].StringValue)); + + trilist.SetSigFalseAction(joinMap.HangUpPhone.JoinNumber, codec.EndPhoneCall); + } + private void LinkVideoCodecSelfviewPositionToApi(IHasSelfviewPosition codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { trilist.SetSigFalseAction(joinMap.SelfviewPosition.JoinNumber, codec.SelfviewPipPositionToggle); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index 5f316523..45c4193c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -58,6 +58,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public List AudioInputs { get; set; } public List AudioOuputs { get; set; } public List Cameras { get; set; } + public zEvent.PhoneCallStatus PhoneCall { get; set; } public ZoomRoomStatus() { @@ -74,6 +75,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom AudioInputs = new List(); AudioOuputs = new List(); Cameras = new List(); + PhoneCall = new zEvent.PhoneCallStatus(); } } @@ -700,6 +702,84 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom [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; + } + } + + public bool OffHook + { + get { return _offHook; } + set + { + if (value == _offHook) return; + + _offHook = value; + NotifyPropertyChanged("OffHook"); + } + } + } + + public enum ePhoneCallStatus + { + PhoneCallStatus_Terminated, + PhoneCallStatus_Accepted, + PhoneCallStatus_InCall, + PhoneCallStatus_Init, + } } /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 578e3dae..b8d29077 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -17,12 +17,14 @@ 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; +using PepperDash_Essentials_Core.DeviceTypeInterfaces; namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, IRouting, - IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraAutoMode, IHasFarEndContentStatus, IHasSelfviewPosition + IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraAutoMode, + IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing { private const long MeetingRefreshTimer = 60000; private const uint DefaultMeetingDurationMin = 30; @@ -114,6 +116,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SupportsCameraOff = _props.SupportsCameraOff; SupportsCameraAutoMode = _props.SupportsCameraAutoMode; + + PhoneOffHookFeedback = new BoolFeedback(PhoneOffHookFeedbackFunc); + CallerIdNameFeedback = new StringFeedback(CallerIdNameFeedbackFunc); + CallerIdNumberFeedback = new StringFeedback(CallerIdNumberFeedbackFunc); } public CommunicationGather PortGather { get; private set; } @@ -195,7 +201,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom protected Func CameraAutoModeIsOnFeedbackFunc { get { return () => false; } - } + } protected Func SelfviewPipPositionFeedbackFunc { @@ -506,6 +512,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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; + } + }; } private void SetUpDirectory() @@ -555,8 +583,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (!_props.DisablePhonebookAutoDownload) { CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 512"), - "GetZoomRoomContacts", "Triggers a refresh of the codec phonebook", - ConsoleAccessLevelEnum.AccessOperator); + "GetZoomRoomContacts", "Triggers a refresh of the codec phonebook", + ConsoleAccessLevelEnum.AccessOperator); } CrestronConsole.AddNewConsoleCommand(s => GetBookings(), "GetZoomRoomBookings", @@ -1066,7 +1094,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom case "sharingstate": { JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing); - + SetLayout(); break; @@ -1181,6 +1209,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom break; } + case "phonecallstatus": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall); + break; + } default: { break; @@ -1294,8 +1327,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void SetLayout() { - if(!_props.AutoDefaultLayouts) return; - + if (!_props.AutoDefaultLayouts) return; + if ( (Status.Call.Sharing.State == zEvent.eSharingState.Receiving || Status.Call.Sharing.State == zEvent.eSharingState.Sending)) @@ -1354,7 +1387,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (ActiveCalls.Count == 0) { - if (callStatus == zStatus.eCallStatus.CONNECTING_MEETING || callStatus == zStatus.eCallStatus.IN_MEETING ) + if (callStatus == zStatus.eCallStatus.CONNECTING_MEETING || + callStatus == zStatus.eCallStatus.IN_MEETING) { var newStatus = eCodecCallStatus.Unknown; @@ -1431,6 +1465,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SetLayout(); } } + public override void StartSharing() { SendText("zCommand Call Sharing HDMI Start"); @@ -1633,7 +1668,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void SendDtmf(string s) { - throw new NotImplementedException(); + SendDtmfToPhone(s); } /// @@ -1713,6 +1748,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom #endregion #region Implementation of IHasCameraAutoMode + //Zoom doesn't support camera auto modes. Setting this to just unmute video public void CameraAutoModeOn() { @@ -1757,7 +1793,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { var nextPipPositionIndex = SelfviewPipPositions.IndexOf(_currentSelfviewPipPosition) + 1; - if (nextPipPositionIndex >= SelfviewPipPositions.Count) // Check if we need to loop back to the first item in the list + if (nextPipPositionIndex >= SelfviewPipPositions.Count) + // Check if we need to loop back to the first item in the list nextPipPositionIndex = 0; SelfviewPipPositionSet(SelfviewPipPositions[nextPipPositionIndex]); @@ -1772,12 +1809,40 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom new CodecCommandWithLabel("DownLeft", "Lower Left") }; - void ComputeSelfviewPipStatus() + private void ComputeSelfviewPipStatus() { _currentSelfviewPipPosition = SelfviewPipPositions.FirstOrDefault( p => p.Command.ToLower().Equals(Configuration.Call.Layout.Position.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 } From 1ea80c3fabefda3446124fb848e505397905052f Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Mon, 12 Oct 2020 12:58:22 -0400 Subject: [PATCH 42/42] Adds phone call ringing status to zoom phone status enum --- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index 45c4193c..4f4eddbc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -756,7 +756,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom _status = value; OffHook = _status == ePhoneCallStatus.PhoneCallStatus_Accepted || _status == ePhoneCallStatus.PhoneCallStatus_InCall || - _status == ePhoneCallStatus.PhoneCallStatus_Init; + _status == ePhoneCallStatus.PhoneCallStatus_Init || + _status == ePhoneCallStatus.PhoneCallStatus_Ringing; } } @@ -775,6 +776,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public enum ePhoneCallStatus { + PhoneCallStatus_Ringing, PhoneCallStatus_Terminated, PhoneCallStatus_Accepted, PhoneCallStatus_InCall,