From 6bdda5451b46f809bd69f22cd2e98addf38e743f Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 17 Aug 2021 15:14:02 -0500 Subject: [PATCH 01/59] Updated UpdateCallStatus method to fix call status references previously looking at Status.Call.Sharing.State. Added else statement to 'if(ActiveCalls.Count == 0)' used to cleanup after calls that refreshs the participant list. Added GetCurrentCallParticipant method used to poll the participant list. --- .../VideoCodec/Interfaces/IHasParticipants.cs | 170 +++++++++--------- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 156 +++++++++++----- 2 files changed, 204 insertions(+), 122 deletions(-) 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 index f6d32149..361e0cae 100644 --- 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 @@ -1,100 +1,108 @@ using System; using System.Collections.Generic; +using PepperDash.Core; using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces { - /// - /// Describes a device that has call participants - /// - public interface IHasParticipants - { - CodecParticipants Participants { get; } - } + /// + /// Describes a device that has call participants + /// + public interface IHasParticipants + { + CodecParticipants Participants { get; } + } - /// - /// Describes the ability to mute and unmute a participant's video in a meeting - /// - public interface IHasParticipantVideoMute:IHasParticipants - { - void MuteVideoForParticipant(int userId); - void UnmuteVideoForParticipant(int userId); - void ToggleVideoForParticipant(int userId); - } + /// + /// Describes the ability to mute and unmute a participant's video in a meeting + /// + public interface IHasParticipantVideoMute : IHasParticipants + { + void MuteVideoForParticipant(int userId); + void UnmuteVideoForParticipant(int userId); + void ToggleVideoForParticipant(int userId); + } - /// - /// Describes the ability to mute and unmute a participant's audio in a meeting - /// - public interface IHasParticipantAudioMute : IHasParticipantVideoMute - { - void MuteAudioForParticipant(int userId); - void UnmuteAudioForParticipant(int userId); - void ToggleAudioForParticipant(int userId); - } + /// + /// Describes the ability to mute and unmute a participant's audio in a meeting + /// + public interface IHasParticipantAudioMute : IHasParticipantVideoMute + { + void MuteAudioForParticipant(int userId); + void UnmuteAudioForParticipant(int userId); + void ToggleAudioForParticipant(int userId); + } - /// - /// Describes the ability to pin and unpin a participant in a meeting - /// - public interface IHasParticipantPinUnpin : IHasParticipants - { - IntFeedback NumberOfScreensFeedback { get; } - int ScreenIndexToPinUserTo { get; } + /// + /// Describes the ability to pin and unpin a participant in a meeting + /// + public interface IHasParticipantPinUnpin : IHasParticipants + { + IntFeedback NumberOfScreensFeedback { get; } + int ScreenIndexToPinUserTo { get; } - void PinParticipant(int userId, int screenIndex); - void UnPinParticipant(int userId); - void ToggleParticipantPinState(int userId, int screenIndex); - } + void PinParticipant(int userId, int screenIndex); + void UnPinParticipant(int userId); + void ToggleParticipantPinState(int userId, int screenIndex); + } - public class CodecParticipants - { - private List _currentParticipants; - - public List CurrentParticipants { - get { return _currentParticipants; } - set - { - _currentParticipants = value; - OnParticipantsChanged(); - } - } + public class CodecParticipants + { + private List _currentParticipants; - public event EventHandler ParticipantsListHasChanged; + public List CurrentParticipants + { + get { return _currentParticipants; } + set + { + _currentParticipants = value; + foreach (var participant in _currentParticipants) + { + Debug.Console(1, "[CurrentParticipants] participant UserId: {0} Name: {1} IsHost: {2}", participant.UserId, participant.Name, participant.IsHost); + } + OnParticipantsChanged(); + } + } - public CodecParticipants() - { - _currentParticipants = new List(); - } + public event EventHandler ParticipantsListHasChanged; - public void OnParticipantsChanged() - { - var handler = ParticipantsListHasChanged; + public CodecParticipants() + { + _currentParticipants = new List(); + } - if (handler == null) return; + public void OnParticipantsChanged() + { + var handler = ParticipantsListHasChanged; - handler(this, new EventArgs()); - } - } + Debug.Console(1, "[OnParticipantsChanged] Event Fired - handler is {0}", handler == null ? "null" : "not null"); - /// - /// Represents a call participant - /// - public class Participant - { - public int UserId { get; set; } - 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; } - public bool HandIsRaisedFb { get; set; } - public bool IsPinnedFb { get; set; } - public int ScreenIndexIsPinnedToFb { get; set; } + if (handler == null) return; - public Participant() - { - // Initialize to -1 (no screen) - ScreenIndexIsPinnedToFb = -1; - } - } + handler(this, new EventArgs()); + } + } + + /// + /// Represents a call participant + /// + public class Participant + { + public int UserId { get; set; } + 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; } + public bool HandIsRaisedFb { get; set; } + public bool IsPinnedFb { get; set; } + public int ScreenIndexIsPinnedToFb { get; set; } + + public Participant() + { + // Initialize to -1 (no screen) + ScreenIndexIsPinnedToFb = -1; + } + } } \ 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 9398f2c9..bd8d1215 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 @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO.Ports; using System.Linq; using System.Text; using Crestron.SimplSharp; @@ -763,12 +764,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (s == "1") { CommDebuggingIsOn = true; - Debug.Console(0, this, "Comm Debug Enabled."); + Debug.Console(1, this, "Comm Debug Enabled."); } else { CommDebuggingIsOn = false; - Debug.Console(0, this, "Comm Debug Disabled."); + Debug.Console(1, this, "Comm Debug Disabled."); } } @@ -876,7 +877,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // Counts the curly braces if (message.Contains("client_loop: send disconnect: Broken pipe")) { - Debug.Console(0, this, Debug.ErrorLogLevel.Error, + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Zoom Room Controller or App connected. Essentials will NOT control the Zoom Room until it is disconnected."); return; @@ -966,7 +967,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SendText("echo off"); Thread.Sleep(100); // set feedback exclusions - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list"); + 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); @@ -1110,6 +1111,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (participant != null) { + Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} **********************************", participant.Event); + Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} - UserId: {1} Name: {2} IsHost: {3}", + participant.Event, participant.UserId, participant.UserName, participant.IsHost); + switch (participant.Event) { case "ZRCUserChangedEventUserInfoUpdated": @@ -1135,9 +1140,36 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } break; case "ZRCUserChangedEventJoinedMeeting": - Status.Call.Participants.Add(participant); + { + var existingParticipant = + Status.Call.Participants.FirstOrDefault(p => p.UserId.Equals(participant.UserId)); + + // found matching participant.UserId + if (existingParticipant != null) + { + Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...updating matching UserId participant with UserId: {1} UserName: {2}", + participant.Event, participant.UserId, participant.UserName); + + JsonConvert.PopulateObject(responseObj.ToString(), existingParticipant); + } + else + { + Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...adding participant with UserId: {1} UserName: {2}", + participant.Event, participant.UserId, participant.UserName); + + Status.Call.Participants.Add(participant); + + //var emptyList = new List(); + //Participants.CurrentParticipants = emptyList; + + //GetCurrentCallParticipants(); + } + break; + } } + + Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ***********************************", participant.Event); } } break; @@ -1148,7 +1180,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Status.Call.Participants); Participants.CurrentParticipants = participants; - PrintCurrentCallParticipants(); break; @@ -1282,23 +1313,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var disconnectEvent = JsonConvert.DeserializeObject(responseObj.ToString()); + Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect ********************************************"); + Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect - disconnectEvent.Successful: {0}", disconnectEvent.Successful); + if (disconnectEvent.Successful) { if (ActiveCalls.Count > 0) - { + { var activeCall = ActiveCalls.FirstOrDefault(c => c.IsActiveCall); - + if (activeCall != null) { + Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect - ActiveCalls.Count: {0} activeCall.Id: {1}, activeCall.Number: {2} activeCall.Name: {3}, activeCall.IsActive: {4}", ActiveCalls.Count, activeCall.Id, activeCall.Number, activeCall.Name, activeCall.IsActiveCall); activeCall.Status = eCodecCallStatus.Disconnected; OnCallStatusChange(activeCall); } - } + } + var emptyList = new List(); Participants.CurrentParticipants = emptyList; + //Participants.OnParticipantsChanged(); } + Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect ********************************************"); + UpdateCallStatus(); break; } @@ -1431,6 +1470,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { JsonConvert.PopulateObject(responseObj.ToString(), Status.Call); + Debug.Console(1, this, "[DeserializeResponse] zStatus.call - Status.Call.Info.meeting_id: {0} Status.Call.Info.meeting_list_item.meetingName: {1}", Status.Call.Info.meeting_id, Status.Call.Info.meeting_list_item.meetingName); + foreach (var participant in Status.Call.Participants) + { + Debug.Console(1, this, "[DeserializeResponse] zStatus.call - Status.Call.Participants participant.UserId: {0} participant.UserName: {1}", participant.UserId, participant.UserName); + } + UpdateCallStatus(); break; @@ -1536,12 +1581,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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, "UserId: {3} Name: {0} Audio: {1} IsHost: {2}", + participant.Name, participant.AudioMuteFb, participant.IsHost, participant.UserId); } Debug.Console(1, this, "************************************************************************"); } + public void GetCurrentCallParticipants() + { + SendText("zCommand Call ListParticipants"); + } + /// /// Retrieves bookings list /// @@ -1557,16 +1607,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void UpdateCallStatus() { Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", - Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); + Status.Call != null ? Status.Call.Status.ToString() : "no call"); + + //var emptyList = new List(); if (Status.Call != null) { var callStatus = Status.Call.Status; - // If not currently in a meeting, intialize the call object + // If not crrently in a meeting, intialize the call object if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING) { - Debug.Console(1, this, "Creating new Status.Call object"); + Debug.Console(1, this, "[UpdateCallStatus] Creating new Status.Call object"); Status.Call = new zStatus.Call { Status = callStatus }; OnCallStatusChange( new CodecActiveCallItem() { Status = eCodecCallStatus.Disconnected }); @@ -1583,7 +1635,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom switch (callStatus) { - case zStatus.eCallStatus.CONNECTING_MEETING: + case zStatus.eCallStatus.CONNECTING_MEETING: newStatus = eCodecCallStatus.Connecting; break; case zStatus.eCallStatus.IN_MEETING: @@ -1591,28 +1643,38 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom break; } - var newCall = new CodecActiveCallItem - { - Name = Status.Call.Info.meeting_list_item.meetingName, - Number = Status.Call.Info.meeting_id, - Id = Status.Call.Info.meeting_id, - Status = newStatus, - Type = eCodecCallType.Video, - }; + if (!string.IsNullOrEmpty(Status.Call.Info.meeting_id)) + { + var newCall = new CodecActiveCallItem + { + Name = Status.Call.Info.meeting_list_item.meetingName, + Number = Status.Call.Info.meeting_list_item.meetingNumber, + Id = Status.Call.Info.meeting_id, + Status = newStatus, + Type = eCodecCallType.Video, + }; - ActiveCalls.Add(newCall); + //Participants.CurrentParticipants = emptyList; - Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", - Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); + ActiveCalls.Add(newCall); - OnCallStatusChange(newCall); + Debug.Console(1, this, "[UpdateCallStatus] IF w/ meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}", + Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); + + OnCallStatusChange(newCall); + } + else + { + Debug.Console(1, this, "[UpdateCallStatus] IF w/o meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}", + Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); + + //Participants.CurrentParticipants = emptyList; + } } - - } else { - var existingCall = ActiveCalls.FirstOrDefault(c => !c.Status.Equals(eCodecCallStatus.Ringing)); + var existingCall = ActiveCalls.FirstOrDefault(c => !c.Status.Equals(eCodecCallStatus.Ringing)); switch (callStatus) { @@ -1620,18 +1682,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom existingCall.Status = eCodecCallStatus.Connected; break; case zStatus.eCallStatus.NOT_IN_MEETING: + //Participants.CurrentParticipants = emptyList; existingCall.Status = eCodecCallStatus.Disconnected; - break; + break; + //default: + // Participants.CurrentParticipants = emptyList; + // break; } - Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", - Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); + Debug.Console(1, this, "[UpdateCallStatus] ELSE ActiveCalls.Count == {1} - Current Call Status: {0}", + Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); OnCallStatusChange(existingCall); } } - Debug.Console(1, this, "*************************** Active Calls ********************************"); + Debug.Console(1, this, "[UpdateCallStatus] Active Calls ------------------------------"); // Clean up any disconnected calls left in the list for (int i = 0; i < ActiveCalls.Count; i++) @@ -1639,26 +1705,34 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var call = ActiveCalls[i]; Debug.Console(1, this, - @"Name: {0} - ID: {1} + @"ID: {1} + Number: {5} + Name: {0} IsActive: {2} Status: {3} - Direction: {4}", call.Name, call.Id, call.IsActiveCall, call.Status, call.Direction); + Direction: {4} + IsActiveCall: {6}", call.Name, call.Id, call.IsActiveCall, call.Status, call.Direction, call.Number, call.IsActiveCall); if (!call.IsActiveCall) { - Debug.Console(1, this, "***** Removing Inactive Call: {0} *****", call.Name); + Debug.Console(1, this, "[UpdateCallStatus] Removing Inactive call.Id: {1} call.Name: {0}", call.Name, call.Id); ActiveCalls.Remove(call); } } - Debug.Console(1, this, "**************************************************************************"); + Debug.Console(1, this, "[UpdateCallStatus] Active Calls ------------------------------"); //clear participants list after call cleanup if (ActiveCalls.Count == 0) { - var emptyList = new List(); + var emptyList = new List(); Participants.CurrentParticipants = emptyList; } + else + { + var emptyList = new List(); + Participants.CurrentParticipants = emptyList; + GetCurrentCallParticipants(); + } } protected override void OnCallStatusChange(CodecActiveCallItem item) @@ -1666,7 +1740,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom base.OnCallStatusChange(item); Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}", - Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); + Status.Call != null ? Status.Call.Status.ToString() : "no call"); if (_props.AutoDefaultLayouts) { From c4f6afa412fdd92abc447c191d9d1ed64718b2e9 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 17 Aug 2021 15:56:57 -0500 Subject: [PATCH 02/59] Fixed debug references used for call status that were printing Status.Call.Sharing.State. Added GetCurrentCallParticipants method to referesh participant list. Updated UpdateCallStatus to resolve issue with duplicate participants when admitted from the waiting room. --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 491 +++++++++--------- 1 file changed, 233 insertions(+), 258 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 bd8d1215..0e1d31fb 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 @@ -33,11 +33,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private const uint DefaultMeetingDurationMin = 30; private const string Delimiter = "\x0D\x0A"; - private readonly GenericQueue _receiveQueue; - //private readonly CrestronQueue _receiveQueue; + private readonly GenericQueue _receiveQueue; + //private readonly CrestronQueue _receiveQueue; - //private readonly Thread _receiveThread; + //private readonly Thread _receiveThread; private readonly ZoomRoomSyncState _syncState; public bool CommDebuggingIsOn; @@ -55,7 +55,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { _props = JsonConvert.DeserializeObject(config.Properties.ToString()); - _receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 512); + _receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 512); Communication = comm; @@ -95,9 +95,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, null, this); - Output2 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, - eRoutingSignalType.Video, - eRoutingPortConnectionType.DisplayPort, null, this); + Output2 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, + eRoutingSignalType.Video, + eRoutingPortConnectionType.DisplayPort, null, this); SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); @@ -115,7 +115,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // TODO: #714 [ ] SelfviewPipSizeFeedback SelfviewPipSizeFeedback = new StringFeedback(SelfviewPipSizeFeedbackFunc); - + SetUpFeedbackActions(); Cameras = new List(); @@ -158,18 +158,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { get { - return () => - { - var scaledVol = CrestronEnvironment.ScaleWithLimits(Configuration.Audio.Output.Volume, 100, 0, 65535, 0); + return () => + { + var scaledVol = CrestronEnvironment.ScaleWithLimits(Configuration.Audio.Output.Volume, 100, 0, 65535, 0); - if (Configuration.Audio.Output.Volume != 0) - { - Debug.Console(2, this, "Storing previous volume level as: {0}, scaled: {1}", Configuration.Audio.Output.Volume, scaledVol); - _previousVolumeLevel = scaledVol; // Store the previous level for recall - } + if (Configuration.Audio.Output.Volume != 0) + { + Debug.Console(2, this, "Storing previous volume level as: {0}, scaled: {1}", Configuration.Audio.Output.Volume, scaledVol); + _previousVolumeLevel = scaledVol; // Store the previous level for recall + } - return scaledVol; - }; + return scaledVol; + }; } } @@ -267,7 +267,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public RoutingInputPort CodecOsdIn { get; private set; } public RoutingOutputPort Output1 { get; private set; } - public RoutingOutputPort Output2 { get; private set; } + public RoutingOutputPort Output2 { get; private set; } #region ICommunicationMonitor Members @@ -367,16 +367,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public CodecDirectory CurrentDirectoryResult { get { return _currentDirectoryResult; } - private set - { - _currentDirectoryResult = value; + private set + { + _currentDirectoryResult = value; - Debug.Console(2, this, "CurrentDirectoryResult Updated. ResultsFolderId: {0}", _currentDirectoryResult.ResultsFolderId); + Debug.Console(2, this, "CurrentDirectoryResult Updated. ResultsFolderId: {0}", _currentDirectoryResult.ResultsFolderId); - CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); + CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); - OnDirectoryResultReturned(_currentDirectoryResult); - } + OnDirectoryResultReturned(_currentDirectoryResult); + } } public CodecPhonebookSyncState PhonebookSyncState { get; private set; } @@ -411,8 +411,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { DirectoryBrowseHistoryStack.Clear(); - CurrentDirectoryResult = DirectoryRoot; - } + CurrentDirectoryResult = DirectoryRoot; + } public void GetDirectoryParentFolderContents() { @@ -423,8 +423,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var currentDirectory = DirectoryBrowseHistoryStack.Pop(); - CurrentDirectoryResult = currentDirectory; - } + CurrentDirectoryResult = currentDirectory; + } public BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; private set; } @@ -553,44 +553,44 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom break; } case "Size": - { - // TODO: #714 [ ] SetupFeedbackActions >> Size - ComputeSelfviewPipSizeStatus(); + { + // TODO: #714 [ ] SetupFeedbackActions >> Size + ComputeSelfviewPipSizeStatus(); - SelfviewPipSizeFeedback.FireUpdate(); + SelfviewPipSizeFeedback.FireUpdate(); - break; - } + break; + } } }; - // This is to deal with incorrect object structure coming back from the Zoom Room on v 5.6.3 - Configuration.Client.Call.Layout.PropertyChanged += (o,a) => - { - switch (a.PropertyName) - { - case "Position": - { - ComputeSelfviewPipPositionStatus(); + // This is to deal with incorrect object structure coming back from the Zoom Room on v 5.6.3 + Configuration.Client.Call.Layout.PropertyChanged += (o, a) => + { + switch (a.PropertyName) + { + case "Position": + { + ComputeSelfviewPipPositionStatus(); - SelfviewPipPositionFeedback.FireUpdate(); + SelfviewPipPositionFeedback.FireUpdate(); - break; - } - case "ShareThumb": - { - ContentSwappedWithThumbnailFeedback.FireUpdate(); - break; - } - case "Style": - { - LocalLayoutFeedback.FireUpdate(); - break; - } + break; + } + case "ShareThumb": + { + ContentSwappedWithThumbnailFeedback.FireUpdate(); + break; + } + case "Style": + { + LocalLayoutFeedback.FireUpdate(); + break; + } - } - }; + } + }; Status.Call.Sharing.PropertyChanged += (o, a) => { @@ -690,11 +690,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void SetUpDirectory() { - DirectoryRoot = new CodecDirectory() { ResultsFolderId = "root" }; + DirectoryRoot = new CodecDirectory() { ResultsFolderId = "root" }; - CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => CurrentDirectoryResult.ResultsFolderId != "root"); + CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => CurrentDirectoryResult.ResultsFolderId != "root"); - CurrentDirectoryResult = DirectoryRoot; + CurrentDirectoryResult = DirectoryRoot; DirectoryBrowseHistory = new List(); DirectoryBrowseHistoryStack = new Stack(); @@ -709,7 +709,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // Set up output ports OutputPorts.Add(Output1); - OutputPorts.Add(Output2); + OutputPorts.Add(Output2); } /// @@ -967,12 +967,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SendText("echo off"); Thread.Sleep(100); // set feedback exclusions - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list"); + SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list"); Thread.Sleep(100); SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list"); Thread.Sleep(100); - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist"); - Thread.Sleep(100); + SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist"); + Thread.Sleep(100); if (!_props.DisablePhonebookAutoDownload) { @@ -1063,13 +1063,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } case "phonebooklistresult": { - // This result will always be the complete contents of the directory and never - // A subset of the results via a search + // This result will always be the complete contents of the directory and never + // A subset of the results via a search JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); - var directoryResults = - zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); + var directoryResults = + zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); if (!PhonebookSyncState.InitialSyncComplete) { @@ -1079,12 +1079,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); } - if (directoryResults.ResultsFolderId != "root") - { - directoryResults.ResultsFolderId = "root"; - } + if (directoryResults.ResultsFolderId != "root") + { + directoryResults.ResultsFolderId = "root"; + } - DirectoryRoot = directoryResults; + DirectoryRoot = directoryResults; CurrentDirectoryResult = directoryResults; @@ -1114,7 +1114,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} **********************************", participant.Event); Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} - UserId: {1} Name: {2} IsHost: {3}", participant.Event, participant.UserId, participant.UserName, participant.IsHost); - + switch (participant.Event) { case "ZRCUserChangedEventUserInfoUpdated": @@ -1140,35 +1140,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } break; case "ZRCUserChangedEventJoinedMeeting": - { - var existingParticipant = - Status.Call.Participants.FirstOrDefault(p => p.UserId.Equals(participant.UserId)); - - // found matching participant.UserId - if (existingParticipant != null) { - Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...updating matching UserId participant with UserId: {1} UserName: {2}", - participant.Event, participant.UserId, participant.UserName); - - JsonConvert.PopulateObject(responseObj.ToString(), existingParticipant); - } - else - { - Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...adding participant with UserId: {1} UserName: {2}", - participant.Event, participant.UserId, participant.UserName); + var existingParticipant = + Status.Call.Participants.FirstOrDefault(p => p.UserId.Equals(participant.UserId)); + + if (existingParticipant != null) + { + Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...updating matching UserId participant with UserId: {1} UserName: {2}", + participant.Event, participant.UserId, participant.UserName); - Status.Call.Participants.Add(participant); - - //var emptyList = new List(); - //Participants.CurrentParticipants = emptyList; - - //GetCurrentCallParticipants(); - } + JsonConvert.PopulateObject(responseObj.ToString(), existingParticipant); + } + else + { + Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...adding participant with UserId: {1} UserName: {2}", + participant.Event, participant.UserId, participant.UserName); - break; - } + Status.Call.Participants.Add(participant); + } + + break; + } } - + Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ***********************************", participant.Event); } } @@ -1319,9 +1313,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (disconnectEvent.Successful) { if (ActiveCalls.Count > 0) - { + { var activeCall = ActiveCalls.FirstOrDefault(c => c.IsActiveCall); - + if (activeCall != null) { Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect - ActiveCalls.Count: {0} activeCall.Id: {1}, activeCall.Number: {2} activeCall.Name: {3}, activeCall.IsActive: {4}", ActiveCalls.Count, activeCall.Id, activeCall.Number, activeCall.Name, activeCall.IsActiveCall); @@ -1329,11 +1323,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom OnCallStatusChange(activeCall); } - } - - var emptyList = new List(); - Participants.CurrentParticipants = emptyList; - //Participants.OnParticipantsChanged(); + } } Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect ********************************************"); @@ -1388,24 +1378,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { var status = responseObj.ToObject(); - Debug.Console(1, this, "Pin Status notification for UserId: {0}, ScreenIndex: {1}", status.PinnedUserId, status.ScreenIndex); + Debug.Console(1, this, "Pin Status notification for UserId: {0}, ScreenIndex: {1}", status.PinnedUserId, status.ScreenIndex); - Participant alreadyPinnedParticipant = null; + Participant alreadyPinnedParticipant = null; - // Check for a participant already pinned to the same screen index. - if (status.PinnedUserId > 0) - { - alreadyPinnedParticipant = Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); + // Check for a participant already pinned to the same screen index. + if (status.PinnedUserId > 0) + { + alreadyPinnedParticipant = Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); - // Make sure that the already pinned participant isn't the same ID as for this message. If true, clear the pinned fb. - if (alreadyPinnedParticipant != null && alreadyPinnedParticipant.UserId != status.PinnedUserId) - { - Debug.Console(1, this, "Participant: {0} with id: {1} already pinned to screenIndex {2}. Clearing pinned fb.", - alreadyPinnedParticipant.Name, alreadyPinnedParticipant.UserId, alreadyPinnedParticipant.ScreenIndexIsPinnedToFb); - alreadyPinnedParticipant.IsPinnedFb = false; - alreadyPinnedParticipant.ScreenIndexIsPinnedToFb = -1; - } - } + // Make sure that the already pinned participant isn't the same ID as for this message. If true, clear the pinned fb. + if (alreadyPinnedParticipant != null && alreadyPinnedParticipant.UserId != status.PinnedUserId) + { + Debug.Console(1, this, "Participant: {0} with id: {1} already pinned to screenIndex {2}. Clearing pinned fb.", + alreadyPinnedParticipant.Name, alreadyPinnedParticipant.UserId, alreadyPinnedParticipant.ScreenIndexIsPinnedToFb); + alreadyPinnedParticipant.IsPinnedFb = false; + alreadyPinnedParticipant.ScreenIndexIsPinnedToFb = -1; + } + } var participant = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(status.PinnedUserId)); @@ -1425,7 +1415,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } else if (participant != null) { - Debug.Console(2, this, "Unpinning {0} with id: {1} from screen index: {2}", participant.Name, participant.UserId, status.ScreenIndex); + Debug.Console(2, this, "Unpinning {0} with id: {1} from screen index: {2}", participant.Name, participant.UserId, status.ScreenIndex); participant.IsPinnedFb = false; participant.ScreenIndexIsPinnedToFb = -1; } @@ -1475,7 +1465,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Debug.Console(1, this, "[DeserializeResponse] zStatus.call - Status.Call.Participants participant.UserId: {0} participant.UserName: {1}", participant.UserId, participant.UserName); } - + UpdateCallStatus(); break; @@ -1571,27 +1561,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } + /// + /// Retrieves the current call participants list + /// + public void GetCurrentCallParticipants() + { + SendText("zCommand Call ListParticipants"); + } + + /// + /// Prints the current call particiapnts list + /// public void PrintCurrentCallParticipants() { - if (Debug.Level <= 0) - { - return; - } + if (Debug.Level <= 0) return; Debug.Console(1, this, "*************************** Call Participants **************************"); foreach (var participant in Participants.CurrentParticipants) { - Debug.Console(1, this, "UserId: {3} Name: {0} Audio: {1} IsHost: {2}", + Debug.Console(1, this, "UserId: {3} Name: {0} Audio: {1} IsHost: {2}", participant.Name, participant.AudioMuteFb, participant.IsHost, participant.UserId); } Debug.Console(1, this, "************************************************************************"); } - public void GetCurrentCallParticipants() - { - SendText("zCommand Call ListParticipants"); - } - /// /// Retrieves bookings list /// @@ -1609,8 +1602,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", Status.Call != null ? Status.Call.Status.ToString() : "no call"); - //var emptyList = new List(); - if (Status.Call != null) { var callStatus = Status.Call.Status; @@ -1621,7 +1612,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(1, this, "[UpdateCallStatus] Creating new Status.Call object"); Status.Call = new zStatus.Call { Status = callStatus }; - OnCallStatusChange( new CodecActiveCallItem() { Status = eCodecCallStatus.Disconnected }); + OnCallStatusChange(new CodecActiveCallItem() { Status = eCodecCallStatus.Disconnected }); SetUpCallFeedbackActions(); } @@ -1635,7 +1626,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom switch (callStatus) { - case zStatus.eCallStatus.CONNECTING_MEETING: + case zStatus.eCallStatus.CONNECTING_MEETING: newStatus = eCodecCallStatus.Connecting; break; case zStatus.eCallStatus.IN_MEETING: @@ -1654,8 +1645,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Type = eCodecCallType.Video, }; - //Participants.CurrentParticipants = emptyList; - ActiveCalls.Add(newCall); Debug.Console(1, this, "[UpdateCallStatus] IF w/ meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}", @@ -1667,14 +1656,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Debug.Console(1, this, "[UpdateCallStatus] IF w/o meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}", Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); - - //Participants.CurrentParticipants = emptyList; } } } else { - var existingCall = ActiveCalls.FirstOrDefault(c => !c.Status.Equals(eCodecCallStatus.Ringing)); + var existingCall = ActiveCalls.FirstOrDefault(c => !c.Status.Equals(eCodecCallStatus.Ringing)); switch (callStatus) { @@ -1682,12 +1669,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom existingCall.Status = eCodecCallStatus.Connected; break; case zStatus.eCallStatus.NOT_IN_MEETING: - //Participants.CurrentParticipants = emptyList; existingCall.Status = eCodecCallStatus.Disconnected; - break; - //default: - // Participants.CurrentParticipants = emptyList; - // break; + break; } Debug.Console(1, this, "[UpdateCallStatus] ELSE ActiveCalls.Count == {1} - Current Call Status: {0}", @@ -1722,17 +1705,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(1, this, "[UpdateCallStatus] Active Calls ------------------------------"); //clear participants list after call cleanup - if (ActiveCalls.Count == 0) - { - var emptyList = new List(); - Participants.CurrentParticipants = emptyList; - } - else - { - var emptyList = new List(); - Participants.CurrentParticipants = emptyList; - GetCurrentCallParticipants(); - } + var emptyList = new List(); + Participants.CurrentParticipants = emptyList; + if (ActiveCalls.Count > 0) GetCurrentCallParticipants(); } protected override void OnCallStatusChange(CodecActiveCallItem item) @@ -1785,7 +1760,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void MuteOff() { - Debug.Console(2, this, "Unmuting to previous level: {0}", _previousVolumeLevel); + Debug.Console(2, this, "Unmuting to previous level: {0}", _previousVolumeLevel); SetVolume((ushort)_previousVolumeLevel); } @@ -1877,7 +1852,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom LinkVideoCodecToApi(this, trilist, joinMap); - LinkZoomRoomToApi(trilist, joinMap); + LinkZoomRoomToApi(trilist, joinMap); } /// @@ -1907,7 +1882,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom trilist.SetString(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip.ToString()); trilist.SetString(joinMap.LayoutShareAllIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.ShareAll.ToString()); }; - + trilist.SetSigFalseAction(joinMap.SwapContentWithThumbnail.JoinNumber, () => layoutsCodec.SwapContentWithThumbnail()); layoutsCodec.CanSwapContentWithThumbnailFeedback.LinkInputSig(trilist.BooleanInput[joinMap.CanSwapContentWithThumbnail.JoinNumber]); @@ -1932,7 +1907,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } }); - layoutsCodec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); + layoutsCodec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); } var pinCodec = this as IHasParticipantPinUnpin; @@ -1953,7 +1928,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { try { - var size = (zConfiguration.eLayoutSize)Enum.Parse(typeof(zConfiguration.eLayoutSize), s, true); + var size = (zConfiguration.eLayoutSize)Enum.Parse(typeof(zConfiguration.eLayoutSize), s, true); var cmd = SelfviewPipSizes.FirstOrDefault(c => c.Command.Equals(size.ToString())); SelfviewPipSizeSet(cmd); } @@ -1971,7 +1946,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (!args.DeviceOnLine) return; ComputeAvailableLayouts(); - layoutsCodec.LocalLayoutFeedback.FireUpdate(); + layoutsCodec.LocalLayoutFeedback.FireUpdate(); layoutsCodec.CanSwapContentWithThumbnailFeedback.FireUpdate(); layoutsCodec.ContentSwappedWithThumbnailFeedback.FireUpdate(); layoutsCodec.LayoutViewIsOnFirstPageFeedback.FireUpdate(); @@ -1979,7 +1954,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom pinCodec.NumberOfScreensFeedback.FireUpdate(); layoutSizeCodec.SelfviewPipSizeFeedback.FireUpdate(); }; - } + } public override void ExecuteSwitch(object selector) { @@ -2089,43 +2064,43 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// private void OnDirectoryResultReturned(CodecDirectory result) { - try - { - Debug.Console(2, this, "OnDirectoryResultReturned"); + try + { + Debug.Console(2, this, "OnDirectoryResultReturned"); - var directoryResult = new CodecDirectory(); + var directoryResult = new CodecDirectory(); - // If result is Root, create a copy and filter out contacts whose parent folder is not root - if (!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue) - { - Debug.Console(2, this, "Filtering DirectoryRoot to remove contacts for display"); + // If result is Root, create a copy and filter out contacts whose parent folder is not root + if (!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue) + { + Debug.Console(2, this, "Filtering DirectoryRoot to remove contacts for display"); - directoryResult.ResultsFolderId = result.ResultsFolderId; - directoryResult.AddFoldersToDirectory(result.Folders); - directoryResult.AddContactsToDirectory(result.Contacts.Where((c) => c.ParentFolderId == result.ResultsFolderId).ToList()); - } - else - { - directoryResult = result; - } + directoryResult.ResultsFolderId = result.ResultsFolderId; + directoryResult.AddFoldersToDirectory(result.Folders); + directoryResult.AddContactsToDirectory(result.Contacts.Where((c) => c.ParentFolderId == result.ResultsFolderId).ToList()); + } + else + { + directoryResult = result; + } - Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0}", !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); + Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0}", !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); - // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology - var handler = DirectoryResultReturned; - if (handler != null) - { - handler(this, new DirectoryEventArgs - { - Directory = directoryResult, - DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue - }); - } - } - catch (Exception e) - { - Debug.Console(2, this, "Error: {0}", e); - } + // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology + var handler = DirectoryResultReturned; + if (handler != null) + { + handler(this, new DirectoryEventArgs + { + Directory = directoryResult, + DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue + }); + } + } + catch (Exception e) + { + Debug.Console(2, this, "Error: {0}", e); + } //PrintDirectory(result); } @@ -2141,15 +2116,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom foreach (var cam in Status.Cameras) { - // Known Issue: - // Crestron UC engine systems seem to report an item in the cameras list that represnts the USB bridge device. - // If we know the name and it's reliably consistent, we could ignore it here... + // Known Issue: + // Crestron UC engine systems seem to report an item in the cameras list that represnts the USB bridge device. + // If we know the name and it's reliably consistent, we could ignore it here... - if (cam.Name.IndexOf("HD-CONV-USB") > -1) - { - // Skip this as it's the Crestron USB box, not a real camera - continue; - } + if (cam.Name.IndexOf("HD-CONV-USB") > -1) + { + // Skip this as it's the Crestron USB box, not a real camera + continue; + } var camera = new ZoomRoomCamera(cam.id, cam.Name, this); @@ -2517,7 +2492,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom availableLayouts |= zConfiguration.eLayoutStyle.Strip; } - Debug.Console(1, this, "availablelayouts: {0}", availableLayouts); + Debug.Console(1, this, "availablelayouts: {0}", availableLayouts); var handler = AvailableLayoutsChanged; if (handler != null) @@ -2564,68 +2539,68 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom #region IHasCodecLayouts Members - private Func LocalLayoutFeedbackFunc - { - get - { - return () => - { - if (Configuration.Call.Layout.Style != zConfiguration.eLayoutStyle.None) - return Configuration.Call.Layout.Style.ToString(); - else - return Configuration.Client.Call.Layout.Style.ToString(); - }; - } - } + private Func LocalLayoutFeedbackFunc + { + get + { + return () => + { + if (Configuration.Call.Layout.Style != zConfiguration.eLayoutStyle.None) + return Configuration.Call.Layout.Style.ToString(); + else + return Configuration.Client.Call.Layout.Style.ToString(); + }; + } + } public StringFeedback LocalLayoutFeedback { get; private set; } public void LocalLayoutToggle() { - var currentLayout = LocalLayoutFeedback.StringValue; + var currentLayout = LocalLayoutFeedback.StringValue; - var eCurrentLayout = (int)Enum.Parse(typeof(zConfiguration.eLayoutStyle), currentLayout, true); + var eCurrentLayout = (int)Enum.Parse(typeof(zConfiguration.eLayoutStyle), currentLayout, true); - var nextLayout = GetNextLayout(eCurrentLayout); + var nextLayout = GetNextLayout(eCurrentLayout); - if (nextLayout != zConfiguration.eLayoutStyle.None) - { - SetLayout(nextLayout); - } + if (nextLayout != zConfiguration.eLayoutStyle.None) + { + SetLayout(nextLayout); + } } - /// - /// Tries to get the next available layout - /// - /// - /// - private zConfiguration.eLayoutStyle GetNextLayout(int currentLayout) - { - if (AvailableLayouts == zConfiguration.eLayoutStyle.None) - { - return zConfiguration.eLayoutStyle.None; - } + /// + /// Tries to get the next available layout + /// + /// + /// + private zConfiguration.eLayoutStyle GetNextLayout(int currentLayout) + { + if (AvailableLayouts == zConfiguration.eLayoutStyle.None) + { + return zConfiguration.eLayoutStyle.None; + } - zConfiguration.eLayoutStyle nextLayout; + zConfiguration.eLayoutStyle nextLayout; - if (((zConfiguration.eLayoutStyle)currentLayout & zConfiguration.eLayoutStyle.ShareAll) == zConfiguration.eLayoutStyle.ShareAll) - { - nextLayout = zConfiguration.eLayoutStyle.Gallery; - } - else - { - nextLayout = (zConfiguration.eLayoutStyle)(currentLayout << 1); - } + if (((zConfiguration.eLayoutStyle)currentLayout & zConfiguration.eLayoutStyle.ShareAll) == zConfiguration.eLayoutStyle.ShareAll) + { + nextLayout = zConfiguration.eLayoutStyle.Gallery; + } + else + { + nextLayout = (zConfiguration.eLayoutStyle)(currentLayout << 1); + } - if ((AvailableLayouts & nextLayout) == nextLayout) - { - return nextLayout; - } - else - { - return GetNextLayout((int)nextLayout); - } - } + if ((AvailableLayouts & nextLayout) == nextLayout) + { + return nextLayout; + } + else + { + return GetNextLayout((int)nextLayout); + } + } public void LocalLayoutToggleSingleProminent() { @@ -2635,7 +2610,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void MinMaxLayoutToggle() { throw new NotImplementedException(); - } + } #endregion From 3fa2954ca06db3a41b9c3d42c6ad7db768a92232 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 17 Aug 2021 16:46:24 -0500 Subject: [PATCH 03/59] style: Updated formatting for ZoomRoom.cs and IHasParticipants.cs --- .../VideoCodec/Interfaces/IHasParticipants.cs | 6 - .../VideoCodec/ZoomRoom/ZoomRoom.cs | 1352 +++++++++-------- 2 files changed, 705 insertions(+), 653 deletions(-) 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 index 361e0cae..d8c0c55c 100644 --- 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 @@ -56,10 +56,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces set { _currentParticipants = value; - foreach (var participant in _currentParticipants) - { - Debug.Console(1, "[CurrentParticipants] participant UserId: {0} Name: {1} IsHost: {2}", participant.UserId, participant.Name, participant.IsHost); - } OnParticipantsChanged(); } } @@ -75,8 +71,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces { var handler = ParticipantsListHasChanged; - Debug.Console(1, "[OnParticipantsChanged] Event Fired - handler is {0}", handler == null ? "null" : "not null"); - if (handler == null) return; handler(this, new EventArgs()); 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 0e1d31fb..701ce6f2 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 @@ -1,16 +1,13 @@ using System; using System.Collections.Generic; -using System.IO.Ports; using System.Linq; using System.Text; using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; using Crestron.SimplSharpPro.CrestronThread; using Crestron.SimplSharpPro.DeviceSupport; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PepperDash.Core; -using PepperDash.Core.Intersystem.Tokens; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; @@ -27,7 +24,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, IRouting, IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, - IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, IHasParticipantAudioMute, IHasSelfviewSize + IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, + IHasParticipantAudioMute, IHasSelfviewSize { private const long MeetingRefreshTimer = 60000; private const uint DefaultMeetingDurationMin = 30; @@ -84,7 +82,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); - PortGather = new CommunicationGather(Communication, "\x0A") { IncludeDelimiter = true }; + PortGather = new CommunicationGather(Communication, "\x0A") {IncludeDelimiter = true}; PortGather.LineReceived += Port_LineReceived; CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, @@ -124,7 +122,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Participants = new CodecParticipants(); - SupportsCameraOff = true; // Always allow turning off the camera for zoom calls? + SupportsCameraOff = true; // Always allow turning off the camera for zoom calls? SupportsCameraAutoMode = _props.SupportsCameraAutoMode; PhoneOffHookFeedback = new BoolFeedback(PhoneOffHookFeedbackFunc); @@ -139,7 +137,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom ContentSwappedWithThumbnailFeedback = new BoolFeedback(ContentSwappedWithThumbnailFeedbackFunc); NumberOfScreensFeedback = new IntFeedback(NumberOfScreensFeedbackFunc); - } public CommunicationGather PortGather { get; private set; } @@ -164,7 +161,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (Configuration.Audio.Output.Volume != 0) { - Debug.Console(2, this, "Storing previous volume level as: {0}, scaled: {1}", Configuration.Audio.Output.Volume, scaledVol); + Debug.Console(2, this, "Storing previous volume level as: {0}, scaled: {1}", Configuration.Audio.Output.Volume, + scaledVol); _previousVolumeLevel = scaledVol; // Store the previous level for recall } @@ -371,7 +369,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { _currentDirectoryResult = value; - Debug.Console(2, this, "CurrentDirectoryResult Updated. ResultsFolderId: {0}", _currentDirectoryResult.ResultsFolderId); + Debug.Console(2, this, "CurrentDirectoryResult Updated. ResultsFolderId: {0}", + _currentDirectoryResult.ResultsFolderId); CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); @@ -391,12 +390,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom DirectoryBrowseHistoryStack.Clear(); CurrentDirectoryResult = directoryResults; - } public void GetDirectoryFolderContents(string folderId) { - var directoryResults = new CodecDirectory { ResultsFolderId = folderId }; + var directoryResults = new CodecDirectory {ResultsFolderId = folderId}; directoryResults.AddContactsToDirectory( DirectoryRoot.CurrentDirectoryResults.FindAll(c => c.ParentFolderId.Equals(folderId))); @@ -404,7 +402,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom DirectoryBrowseHistoryStack.Push(_currentDirectoryResult); CurrentDirectoryResult = directoryResults; - } public void SetCurrentDirectoryToRoot() @@ -535,33 +532,32 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom switch (a.PropertyName) { case "Position": - { - ComputeSelfviewPipPositionStatus(); + { + ComputeSelfviewPipPositionStatus(); - SelfviewPipPositionFeedback.FireUpdate(); + SelfviewPipPositionFeedback.FireUpdate(); - break; - } + break; + } case "ShareThumb": - { - ContentSwappedWithThumbnailFeedback.FireUpdate(); - break; - } + { + ContentSwappedWithThumbnailFeedback.FireUpdate(); + break; + } case "Style": - { - LocalLayoutFeedback.FireUpdate(); - break; - } + { + LocalLayoutFeedback.FireUpdate(); + break; + } case "Size": - { - // TODO: #714 [ ] SetupFeedbackActions >> Size - ComputeSelfviewPipSizeStatus(); + { + // TODO: #714 [ ] SetupFeedbackActions >> Size + ComputeSelfviewPipSizeStatus(); - SelfviewPipSizeFeedback.FireUpdate(); - - break; - } + SelfviewPipSizeFeedback.FireUpdate(); + break; + } } }; @@ -571,24 +567,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom switch (a.PropertyName) { case "Position": - { - ComputeSelfviewPipPositionStatus(); + { + ComputeSelfviewPipPositionStatus(); - SelfviewPipPositionFeedback.FireUpdate(); + SelfviewPipPositionFeedback.FireUpdate(); - break; - } + break; + } case "ShareThumb": - { - ContentSwappedWithThumbnailFeedback.FireUpdate(); - break; - } + { + ContentSwappedWithThumbnailFeedback.FireUpdate(); + break; + } case "Style": - { - LocalLayoutFeedback.FireUpdate(); - break; - } - + { + LocalLayoutFeedback.FireUpdate(); + break; + } } }; @@ -652,45 +647,45 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom case "can_switch_speaker_view": case "can_switch_wall_view": case "can_switch_share_on_all_screens": - { - ComputeAvailableLayouts(); - break; - } + { + ComputeAvailableLayouts(); + break; + } case "is_in_first_page": - { - LayoutViewIsOnFirstPageFeedback.FireUpdate(); - break; - } + { + LayoutViewIsOnFirstPageFeedback.FireUpdate(); + break; + } case "is_in_last_page": - { - LayoutViewIsOnLastPageFeedback.FireUpdate(); - break; - } - //case "video_type": - // { - // It appears as though the actual value we want to watch is Configuration.Call.Layout.Style - // LocalLayoutFeedback.FireUpdate(); - // break; - // } + { + LayoutViewIsOnLastPageFeedback.FireUpdate(); + break; + } + //case "video_type": + // { + // It appears as though the actual value we want to watch is Configuration.Call.Layout.Style + // LocalLayoutFeedback.FireUpdate(); + // break; + // } } }; Status.NumberOfScreens.PropertyChanged += (o, a) => + { + switch (a.PropertyName) { - switch (a.PropertyName) + case "NumberOfScreens": { - case "NumberOfScreens": - { - NumberOfScreensFeedback.FireUpdate(); - break; - } + NumberOfScreensFeedback.FireUpdate(); + break; } - }; + } + }; } private void SetUpDirectory() { - DirectoryRoot = new CodecDirectory() { ResultsFolderId = "root" }; + DirectoryRoot = new CodecDirectory() {ResultsFolderId = "root"}; CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => CurrentDirectoryResult.ResultsFolderId != "root"); @@ -698,7 +693,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom DirectoryBrowseHistory = new List(); DirectoryBrowseHistoryStack = new Stack(); - } private void SetUpRouting() @@ -896,7 +890,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom //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 + // Check for the beginning of a new JSON message { _jsonFeedbackMessageIsIncoming = true; _jsonCurlyBraceCounter = 1; // reset the counter for each new message @@ -913,7 +907,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom return; } if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + Delimiter) - // Check for the end of a JSON message + // Check for the end of a JSON message { _jsonMessage.Append(message); @@ -956,34 +950,34 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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); + SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist"); + Thread.Sleep(100); - // Fire up a thread to send the intial commands. - CrestronInvoke.BeginInvoke(o => + if (!_props.DisablePhonebookAutoDownload) { - Thread.Sleep(100); - // disable echo of commands - SendText("echo off"); - Thread.Sleep(100); - // set feedback exclusions - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list"); - Thread.Sleep(100); - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list"); - Thread.Sleep(100); - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist"); - Thread.Sleep(100); + SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); + } + // switch to json format + SendText("format json"); + }); - if (!_props.DisablePhonebookAutoDownload) - { - SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); - } - // switch to json format - SendText("format json"); - }); - - break; - } + break; + } } } } @@ -1007,7 +1001,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var eType = (eZoomRoomResponseType) - Enum.Parse(typeof(eZoomRoomResponseType), message["type"].Value(), true); + Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value(), true); var topKey = message["topKey"].Value(); @@ -1018,523 +1012,545 @@ 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 "inforesult": { - case "inforesult": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Info); - break; - } - case "phonebooklistresult": - { - // This result will always be the complete contents of the directory and never - // A subset of the results via a search - - JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); - - var directoryResults = - zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); - - if (!PhonebookSyncState.InitialSyncComplete) - { - PhonebookSyncState.InitialPhonebookFoldersReceived(); - PhonebookSyncState.PhonebookRootEntriesReceived(); - PhonebookSyncState.SetPhonebookHasFolders(true); - PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); - } - - if (directoryResults.ResultsFolderId != "root") - { - directoryResults.ResultsFolderId = "root"; - } - - DirectoryRoot = directoryResults; - - CurrentDirectoryResult = directoryResults; - - break; - } - case "listparticipantsresult": - { - Debug.Console(1, this, "JTokenType: {0}", responseObj.Type); - - switch (responseObj.Type) - { - case JTokenType.Array: - Status.Call.Participants = - JsonConvert.DeserializeObject>( - responseObj.ToString()); - break; - case JTokenType.Object: - { - // this is a single participant event notification - - var participant = - JsonConvert.DeserializeObject( - responseObj.ToString()); - - if (participant != null) - { - Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} **********************************", participant.Event); - Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} - UserId: {1} Name: {2} IsHost: {3}", - participant.Event, participant.UserId, participant.UserName, participant.IsHost); - - switch (participant.Event) - { - case "ZRCUserChangedEventUserInfoUpdated": - case "ZRCUserChangedEventLeftMeeting": - { - var existingParticipant = - Status.Call.Participants.FirstOrDefault( - p => p.UserId.Equals(participant.UserId)); - - if (existingParticipant != null) - { - switch (participant.Event) - { - case "ZRCUserChangedEventLeftMeeting": - Status.Call.Participants.Remove(existingParticipant); - break; - case "ZRCUserChangedEventUserInfoUpdated": - JsonConvert.PopulateObject(responseObj.ToString(), - existingParticipant); - break; - } - } - } - break; - case "ZRCUserChangedEventJoinedMeeting": - { - var existingParticipant = - Status.Call.Participants.FirstOrDefault(p => p.UserId.Equals(participant.UserId)); - - if (existingParticipant != null) - { - Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...updating matching UserId participant with UserId: {1} UserName: {2}", - participant.Event, participant.UserId, participant.UserName); - - JsonConvert.PopulateObject(responseObj.ToString(), existingParticipant); - } - else - { - Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...adding participant with UserId: {1} UserName: {2}", - participant.Event, participant.UserId, participant.UserName); - - Status.Call.Participants.Add(participant); - } - - break; - } - } - - Debug.Console(1, this, "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ***********************************", participant.Event); - } - } - break; - } - - var participants = - zCommand.ListParticipant.GetGenericParticipantListFromParticipantsResult( - Status.Call.Participants); - - Participants.CurrentParticipants = participants; - PrintCurrentCallParticipants(); - - break; - } - default: - { - break; - } + JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Info); + break; } - break; - } - case eZoomRoomResponseType.zEvent: - { - switch (topKey.ToLower()) + case "phonebooklistresult": { - case "phonebook": - { - if (responseObj["Updated Contact"] != null) - { - var updatedContact = - JsonConvert.DeserializeObject( - responseObj["Updated Contact"].ToString()); + // This result will always be the complete contents of the directory and never + // A subset of the results via a search - var existingContact = - Status.Phonebook.Contacts.FirstOrDefault(c => c.Jid.Equals(updatedContact.Jid)); + JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); - if (existingContact != null) - { - // Update existing contact - JsonConvert.PopulateObject(responseObj["Updated Contact"].ToString(), - existingContact); - } - } - else if (responseObj["Added Contact"] != null) - { - var jToken = responseObj["Updated Contact"]; - if (jToken != null) - { - var newContact = - JsonConvert.DeserializeObject( - jToken.ToString()); + var directoryResults = + zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); - // Add a new contact - Status.Phonebook.Contacts.Add(newContact); - } - } + if (!PhonebookSyncState.InitialSyncComplete) + { + PhonebookSyncState.InitialPhonebookFoldersReceived(); + PhonebookSyncState.PhonebookRootEntriesReceived(); + PhonebookSyncState.SetPhonebookHasFolders(true); + PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); + } + if (directoryResults.ResultsFolderId != "root") + { + directoryResults.ResultsFolderId = "root"; + } + + DirectoryRoot = directoryResults; + + CurrentDirectoryResult = directoryResults; + + break; + } + case "listparticipantsresult": + { + Debug.Console(1, this, "JTokenType: {0}", responseObj.Type); + + switch (responseObj.Type) + { + case JTokenType.Array: + Status.Call.Participants = + JsonConvert.DeserializeObject>( + responseObj.ToString()); break; - } - case "bookingslistresult": + case JTokenType.Object: { - if (!_syncState.InitialSyncComplete) - { - _syncState.LastQueryResponseReceived(); - } + // this is a single participant event notification - var codecBookings = JsonConvert.DeserializeObject>( - responseObj.ToString()); - - if (codecBookings != null && codecBookings.Count > 0) - { - CodecSchedule.Meetings = zCommand.GetGenericMeetingsFromBookingResult( - codecBookings, CodecSchedule.MeetingWarningMinutes); - } - - break; - } - case "bookings updated": - { - GetBookings(); - - break; - } - case "sharingstate": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing); - - SetLayout(); - - break; - } - case "incomingcallindication": - { - var incomingCall = - JsonConvert.DeserializeObject(responseObj.ToString()); - - if (incomingCall != null) - { - var newCall = new CodecActiveCallItem - { - Direction = eCodecCallDirection.Incoming, - Status = eCodecCallStatus.Ringing, - Type = eCodecCallType.Video, - Name = incomingCall.callerName, - Id = incomingCall.callerJID - }; - - ActiveCalls.Add(newCall); - - OnCallStatusChange(newCall); - } - - break; - } - case "treatedincomingcallindication": - { - var incomingCall = - JsonConvert.DeserializeObject(responseObj.ToString()); - - if (incomingCall != null) - { - var existingCall = - ActiveCalls.FirstOrDefault(c => c.Id.Equals(incomingCall.callerJID)); - - if (existingCall != null) - { - existingCall.Status = !incomingCall.accepted - ? eCodecCallStatus.Disconnected - : eCodecCallStatus.Connecting; - - OnCallStatusChange(existingCall); - } - - UpdateCallStatus(); - } - - break; - } - case "calldisconnect": - { - var disconnectEvent = - JsonConvert.DeserializeObject(responseObj.ToString()); - - Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect ********************************************"); - Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect - disconnectEvent.Successful: {0}", disconnectEvent.Successful); - - if (disconnectEvent.Successful) - { - if (ActiveCalls.Count > 0) - { - var activeCall = ActiveCalls.FirstOrDefault(c => c.IsActiveCall); - - if (activeCall != null) - { - Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect - ActiveCalls.Count: {0} activeCall.Id: {1}, activeCall.Number: {2} activeCall.Name: {3}, activeCall.IsActive: {4}", ActiveCalls.Count, activeCall.Id, activeCall.Number, activeCall.Name, activeCall.IsActiveCall); - activeCall.Status = eCodecCallStatus.Disconnected; - - OnCallStatusChange(activeCall); - } - } - } - - Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect ********************************************"); - - UpdateCallStatus(); - break; - } - case "callconnecterror": - { - UpdateCallStatus(); - break; - } - case "videounmuterequest": - { - // 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; - } - case "phonecallstatus": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall); - break; - } - case "pinstatusofscreennotification": - { - var status = responseObj.ToObject(); - - Debug.Console(1, this, "Pin Status notification for UserId: {0}, ScreenIndex: {1}", status.PinnedUserId, status.ScreenIndex); - - Participant alreadyPinnedParticipant = null; - - // Check for a participant already pinned to the same screen index. - if (status.PinnedUserId > 0) - { - alreadyPinnedParticipant = Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); - - // Make sure that the already pinned participant isn't the same ID as for this message. If true, clear the pinned fb. - if (alreadyPinnedParticipant != null && alreadyPinnedParticipant.UserId != status.PinnedUserId) - { - Debug.Console(1, this, "Participant: {0} with id: {1} already pinned to screenIndex {2}. Clearing pinned fb.", - alreadyPinnedParticipant.Name, alreadyPinnedParticipant.UserId, alreadyPinnedParticipant.ScreenIndexIsPinnedToFb); - alreadyPinnedParticipant.IsPinnedFb = false; - alreadyPinnedParticipant.ScreenIndexIsPinnedToFb = -1; - } - } - - var participant = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(status.PinnedUserId)); + var participant = + JsonConvert.DeserializeObject( + responseObj.ToString()); if (participant != null) { - participant.IsPinnedFb = true; - participant.ScreenIndexIsPinnedToFb = status.ScreenIndex; - } - else - { - participant = Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); + Debug.Console(1, this, + "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} **********************************", + participant.Event); + Debug.Console(1, this, + "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} - UserId: {1} Name: {2} IsHost: {3}", + participant.Event, participant.UserId, participant.UserName, participant.IsHost); - if (participant == null && alreadyPinnedParticipant == null) + switch (participant.Event) { - Debug.Console(1, this, "no matching participant found by pinned_user_id: {0} or screen_index: {1}", status.PinnedUserId, status.ScreenIndex); - return; - } - else if (participant != null) - { - Debug.Console(2, this, "Unpinning {0} with id: {1} from screen index: {2}", participant.Name, participant.UserId, status.ScreenIndex); - participant.IsPinnedFb = false; - participant.ScreenIndexIsPinnedToFb = -1; + case "ZRCUserChangedEventUserInfoUpdated": + case "ZRCUserChangedEventLeftMeeting": + { + var existingParticipant = + Status.Call.Participants.FirstOrDefault( + p => p.UserId.Equals(participant.UserId)); + + if (existingParticipant != null) + { + switch (participant.Event) + { + case "ZRCUserChangedEventLeftMeeting": + Status.Call.Participants.Remove(existingParticipant); + break; + case "ZRCUserChangedEventUserInfoUpdated": + JsonConvert.PopulateObject(responseObj.ToString(), + existingParticipant); + break; + } + } + } + break; + case "ZRCUserChangedEventJoinedMeeting": + { + var existingParticipant = + Status.Call.Participants.FirstOrDefault(p => p.UserId.Equals(participant.UserId)); + + if (existingParticipant != null) + { + Debug.Console(1, this, + "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...updating matching UserId participant with UserId: {1} UserName: {2}", + participant.Event, participant.UserId, participant.UserName); + + JsonConvert.PopulateObject(responseObj.ToString(), existingParticipant); + } + else + { + Debug.Console(1, this, + "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...adding participant with UserId: {1} UserName: {2}", + participant.Event, participant.UserId, participant.UserName); + + Status.Call.Participants.Add(participant); + } + + break; + } } + + Debug.Console(1, this, + "[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ***********************************", + participant.Event); } - - // fire the event as we've modified the participants list - Participants.OnParticipantsChanged(); - - break; } - default: - { break; - } + } + + var participants = + zCommand.ListParticipant.GetGenericParticipantListFromParticipantsResult( + Status.Call.Participants); + + Participants.CurrentParticipants = participants; + PrintCurrentCallParticipants(); + + break; } - break; - } - case eZoomRoomResponseType.zStatus: - { - switch (topKey.ToLower()) + default: { - case "login": - { - _syncState.LoginMessageReceived(); - - if (!_syncState.InitialQueryMessagesWereSent) - { - SetUpSyncQueries(); - } - - JsonConvert.PopulateObject(responseObj.ToString(), Status.Login); - - break; - } - case "systemunit": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit); - - break; - } - case "call": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call); - - Debug.Console(1, this, "[DeserializeResponse] zStatus.call - Status.Call.Info.meeting_id: {0} Status.Call.Info.meeting_list_item.meetingName: {1}", Status.Call.Info.meeting_id, Status.Call.Info.meeting_list_item.meetingName); - foreach (var participant in Status.Call.Participants) - { - Debug.Console(1, this, "[DeserializeResponse] zStatus.call - Status.Call.Participants participant.UserId: {0} participant.UserName: {1}", participant.UserId, participant.UserName); - } - - UpdateCallStatus(); - - break; - } - case "capabilities": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Capabilities); - break; - } - case "sharing": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Sharing); - - break; - } - case "numberofscreens": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.NumberOfScreens); - break; - } - case "video": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Video); - break; - } - case "camerashare": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.CameraShare); - break; - } - case "layout": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Layout); - break; - } - case "audio input line": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.AudioInputs); - break; - } - case "audio output line": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.AudioOuputs); - break; - } - case "video camera line": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras); - - if (!_syncState.CamerasHaveBeenSetUp) - { - SetUpCameras(); - } - - break; - } - default: - { - break; - } + break; } - - break; } - default: + break; + } + case eZoomRoomResponseType.zEvent: + { + switch (topKey.ToLower()) { - Debug.Console(1, "Unknown Response Type:"); - break; + 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) + { + // Update existing contact + JsonConvert.PopulateObject(responseObj["Updated Contact"].ToString(), + existingContact); + } + } + else if (responseObj["Added Contact"] != null) + { + var jToken = responseObj["Updated Contact"]; + if (jToken != null) + { + var newContact = + JsonConvert.DeserializeObject( + jToken.ToString()); + + // Add a new contact + Status.Phonebook.Contacts.Add(newContact); + } + } + + break; + } + case "bookingslistresult": + { + if (!_syncState.InitialSyncComplete) + { + _syncState.LastQueryResponseReceived(); + } + + var codecBookings = JsonConvert.DeserializeObject>( + responseObj.ToString()); + + if (codecBookings != null && codecBookings.Count > 0) + { + CodecSchedule.Meetings = zCommand.GetGenericMeetingsFromBookingResult( + codecBookings, CodecSchedule.MeetingWarningMinutes); + } + + break; + } + case "bookings updated": + { + GetBookings(); + + break; + } + case "sharingstate": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing); + + SetLayout(); + + break; + } + case "incomingcallindication": + { + var incomingCall = + JsonConvert.DeserializeObject(responseObj.ToString()); + + if (incomingCall != null) + { + var newCall = new CodecActiveCallItem + { + Direction = eCodecCallDirection.Incoming, + Status = eCodecCallStatus.Ringing, + Type = eCodecCallType.Video, + Name = incomingCall.callerName, + Id = incomingCall.callerJID + }; + + ActiveCalls.Add(newCall); + + OnCallStatusChange(newCall); + } + + break; + } + case "treatedincomingcallindication": + { + var incomingCall = + JsonConvert.DeserializeObject(responseObj.ToString()); + + if (incomingCall != null) + { + var existingCall = + ActiveCalls.FirstOrDefault(c => c.Id.Equals(incomingCall.callerJID)); + + if (existingCall != null) + { + existingCall.Status = !incomingCall.accepted + ? eCodecCallStatus.Disconnected + : eCodecCallStatus.Connecting; + + OnCallStatusChange(existingCall); + } + + UpdateCallStatus(); + } + + break; + } + case "calldisconnect": + { + var disconnectEvent = + JsonConvert.DeserializeObject(responseObj.ToString()); + + Debug.Console(1, this, + "[DeserializeResponse] zEvent.calldisconnect ********************************************"); + Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect - disconnectEvent.Successful: {0}", + disconnectEvent.Successful); + + if (disconnectEvent.Successful) + { + if (ActiveCalls.Count > 0) + { + var activeCall = ActiveCalls.FirstOrDefault(c => c.IsActiveCall); + + if (activeCall != null) + { + Debug.Console(1, this, + "[DeserializeResponse] zEvent.calldisconnect - ActiveCalls.Count: {0} activeCall.Id: {1}, activeCall.Number: {2} activeCall.Name: {3}, activeCall.IsActive: {4}", + ActiveCalls.Count, activeCall.Id, activeCall.Number, activeCall.Name, activeCall.IsActiveCall); + activeCall.Status = eCodecCallStatus.Disconnected; + + OnCallStatusChange(activeCall); + } + } + } + + Debug.Console(1, this, + "[DeserializeResponse] zEvent.calldisconnect ********************************************"); + + UpdateCallStatus(); + break; + } + case "callconnecterror": + { + UpdateCallStatus(); + break; + } + case "videounmuterequest": + { + // 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; + } + case "phonecallstatus": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall); + break; + } + case "pinstatusofscreennotification": + { + var status = responseObj.ToObject(); + + Debug.Console(1, this, "Pin Status notification for UserId: {0}, ScreenIndex: {1}", status.PinnedUserId, + status.ScreenIndex); + + Participant alreadyPinnedParticipant = null; + + // Check for a participant already pinned to the same screen index. + if (status.PinnedUserId > 0) + { + alreadyPinnedParticipant = + Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); + + // Make sure that the already pinned participant isn't the same ID as for this message. If true, clear the pinned fb. + if (alreadyPinnedParticipant != null && alreadyPinnedParticipant.UserId != status.PinnedUserId) + { + Debug.Console(1, this, "Participant: {0} with id: {1} already pinned to screenIndex {2}. Clearing pinned fb.", + alreadyPinnedParticipant.Name, alreadyPinnedParticipant.UserId, + alreadyPinnedParticipant.ScreenIndexIsPinnedToFb); + alreadyPinnedParticipant.IsPinnedFb = false; + alreadyPinnedParticipant.ScreenIndexIsPinnedToFb = -1; + } + } + + var participant = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(status.PinnedUserId)); + + if (participant != null) + { + participant.IsPinnedFb = true; + participant.ScreenIndexIsPinnedToFb = status.ScreenIndex; + } + else + { + participant = + Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); + + if (participant == null && alreadyPinnedParticipant == null) + { + Debug.Console(1, this, "no matching participant found by pinned_user_id: {0} or screen_index: {1}", + status.PinnedUserId, status.ScreenIndex); + return; + } + else if (participant != null) + { + Debug.Console(2, this, "Unpinning {0} with id: {1} from screen index: {2}", participant.Name, + participant.UserId, status.ScreenIndex); + participant.IsPinnedFb = false; + participant.ScreenIndexIsPinnedToFb = -1; + } + } + + // fire the event as we've modified the participants list + Participants.OnParticipantsChanged(); + + break; + } + default: + { + break; + } } + break; + } + case eZoomRoomResponseType.zStatus: + { + switch (topKey.ToLower()) + { + case "login": + { + _syncState.LoginMessageReceived(); + + if (!_syncState.InitialQueryMessagesWereSent) + { + SetUpSyncQueries(); + } + + JsonConvert.PopulateObject(responseObj.ToString(), Status.Login); + + break; + } + case "systemunit": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit); + + break; + } + case "call": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Call); + + Debug.Console(1, this, + "[DeserializeResponse] zStatus.call - Status.Call.Info.meeting_id: {0} Status.Call.Info.meeting_list_item.meetingName: {1}", + Status.Call.Info.meeting_id, Status.Call.Info.meeting_list_item.meetingName); + foreach (var participant in Status.Call.Participants) + { + Debug.Console(1, this, + "[DeserializeResponse] zStatus.call - Status.Call.Participants participant.UserId: {0} participant.UserName: {1}", + participant.UserId, participant.UserName); + } + + UpdateCallStatus(); + + break; + } + case "capabilities": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Capabilities); + break; + } + case "sharing": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Sharing); + + break; + } + case "numberofscreens": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.NumberOfScreens); + break; + } + case "video": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Video); + break; + } + case "camerashare": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.CameraShare); + break; + } + case "layout": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Layout); + break; + } + case "audio input line": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.AudioInputs); + break; + } + case "audio output line": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.AudioOuputs); + break; + } + case "video camera line": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras); + + if (!_syncState.CamerasHaveBeenSetUp) + { + SetUpCameras(); + } + + break; + } + default: + { + break; + } + } + + break; + } + default: + { + Debug.Console(1, "Unknown Response Type:"); + break; + } } } catch (Exception ex) @@ -1610,9 +1626,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING) { Debug.Console(1, this, "[UpdateCallStatus] Creating new Status.Call object"); - Status.Call = new zStatus.Call { Status = callStatus }; + Status.Call = new zStatus.Call {Status = callStatus}; - OnCallStatusChange(new CodecActiveCallItem() { Status = eCodecCallStatus.Disconnected }); + OnCallStatusChange(new CodecActiveCallItem() {Status = eCodecCallStatus.Disconnected}); SetUpCallFeedbackActions(); } @@ -1620,7 +1636,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (ActiveCalls.Count == 0) { if (callStatus == zStatus.eCallStatus.CONNECTING_MEETING || - callStatus == zStatus.eCallStatus.IN_MEETING) + callStatus == zStatus.eCallStatus.IN_MEETING) { var newStatus = eCodecCallStatus.Unknown; @@ -1694,7 +1710,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom IsActive: {2} Status: {3} Direction: {4} - IsActiveCall: {6}", call.Name, call.Id, call.IsActiveCall, call.Status, call.Direction, call.Number, call.IsActiveCall); + IsActiveCall: {6}", call.Name, call.Id, call.IsActiveCall, call.Status, call.Direction, call.Number, + call.IsActiveCall); if (!call.IsActiveCall) { @@ -1761,12 +1778,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void MuteOff() { Debug.Console(2, this, "Unmuting to previous level: {0}", _previousVolumeLevel); - SetVolume((ushort)_previousVolumeLevel); + SetVolume((ushort) _previousVolumeLevel); } public override void MuteOn() { - SetVolume(0); } @@ -1868,13 +1884,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom layoutsCodec.AvailableLayoutsChanged += (o, a) => { trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery - == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Gallery)); + == + (a.AvailableLayouts & + zConfiguration.eLayoutStyle.Gallery)); trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Speaker - == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Speaker)); + == + (a.AvailableLayouts & + zConfiguration.eLayoutStyle.Speaker)); trilist.SetBool(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip - == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Strip)); + == + (a.AvailableLayouts & zConfiguration.eLayoutStyle.Strip)); trilist.SetBool(joinMap.LayoutShareAllIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.ShareAll - == (a.AvailableLayouts & zConfiguration.eLayoutStyle.ShareAll)); + == + (a.AvailableLayouts & + zConfiguration.eLayoutStyle.ShareAll)); // pass the names used to set the layout through the bridge trilist.SetString(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery.ToString()); @@ -1885,27 +1908,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom trilist.SetSigFalseAction(joinMap.SwapContentWithThumbnail.JoinNumber, () => layoutsCodec.SwapContentWithThumbnail()); - layoutsCodec.CanSwapContentWithThumbnailFeedback.LinkInputSig(trilist.BooleanInput[joinMap.CanSwapContentWithThumbnail.JoinNumber]); - layoutsCodec.ContentSwappedWithThumbnailFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SwapContentWithThumbnail.JoinNumber]); + layoutsCodec.CanSwapContentWithThumbnailFeedback.LinkInputSig( + trilist.BooleanInput[joinMap.CanSwapContentWithThumbnail.JoinNumber]); + layoutsCodec.ContentSwappedWithThumbnailFeedback.LinkInputSig( + trilist.BooleanInput[joinMap.SwapContentWithThumbnail.JoinNumber]); - layoutsCodec.LayoutViewIsOnFirstPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnFirstPage.JoinNumber]); + layoutsCodec.LayoutViewIsOnFirstPageFeedback.LinkInputSig( + trilist.BooleanInput[joinMap.LayoutIsOnFirstPage.JoinNumber]); layoutsCodec.LayoutViewIsOnLastPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnLastPage.JoinNumber]); trilist.SetSigFalseAction(joinMap.LayoutTurnToNextPage.JoinNumber, () => layoutsCodec.LayoutTurnNextPage()); trilist.SetSigFalseAction(joinMap.LayoutTurnToPreviousPage.JoinNumber, () => layoutsCodec.LayoutTurnPreviousPage()); trilist.SetSigFalseAction(joinMap.GetAvailableLayouts.JoinNumber, () => layoutsCodec.GetAvailableLayouts()); trilist.SetStringSigAction(joinMap.GetSetCurrentLayout.JoinNumber, (s) => + { + try { - try - { - var style = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle), s, true); - SetLayout(style); - } - catch (Exception e) - { - Debug.Console(1, this, "Unable to parse '{0}' to zConfiguration.eLayoutStyle: {1}", s, e); - } - }); + var style = (zConfiguration.eLayoutStyle) Enum.Parse(typeof (zConfiguration.eLayoutStyle), s, true); + SetLayout(style); + } + catch (Exception e) + { + Debug.Console(1, this, "Unable to parse '{0}' to zConfiguration.eLayoutStyle: {1}", s, e); + } + }); layoutsCodec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); } @@ -1928,7 +1954,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { try { - var size = (zConfiguration.eLayoutSize)Enum.Parse(typeof(zConfiguration.eLayoutSize), s, true); + var size = (zConfiguration.eLayoutSize) Enum.Parse(typeof (zConfiguration.eLayoutSize), s, true); var cmd = SelfviewPipSizes.FirstOrDefault(c => c.Command.Equals(size.ToString())); SelfviewPipSizeSet(cmd); } @@ -2077,14 +2103,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom directoryResult.ResultsFolderId = result.ResultsFolderId; directoryResult.AddFoldersToDirectory(result.Folders); - directoryResult.AddContactsToDirectory(result.Contacts.Where((c) => c.ParentFolderId == result.ResultsFolderId).ToList()); + directoryResult.AddContactsToDirectory( + result.Contacts.Where((c) => c.ParentFolderId == result.ResultsFolderId).ToList()); } else { directoryResult = result; } - Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0}", !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); + Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0}", + !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology var handler = DirectoryResultReturned; @@ -2228,7 +2256,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom #region IHasParticipantPinUnpin Members - private Func NumberOfScreensFeedbackFunc { get { return () => Status.NumberOfScreens.NumOfScreens; } } + private Func NumberOfScreensFeedbackFunc + { + get { return () => Status.NumberOfScreens.NumOfScreens; } + } public IntFeedback NumberOfScreensFeedback { get; private set; } @@ -2353,12 +2384,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } public List SelfviewPipPositions = new List() - { - new CodecCommandWithLabel("UpLeft", "Center Left"), - new CodecCommandWithLabel("UpRight", "Center Right"), - new CodecCommandWithLabel("DownRight", "Lower Right"), - new CodecCommandWithLabel("DownLeft", "Lower Left") - }; + { + new CodecCommandWithLabel("UpLeft", "Center Left"), + new CodecCommandWithLabel("UpRight", "Center Right"), + new CodecCommandWithLabel("DownRight", "Lower Right"), + new CodecCommandWithLabel("DownLeft", "Lower Left") + }; private void ComputeSelfviewPipPositionStatus() { @@ -2370,6 +2401,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom #endregion // TODO: #714 [ ] Implementation of IHasSelfviewPipSize + #region Implementation of IHasSelfviewPipSize private CodecCommandWithLabel _currentSelfviewPipSize; @@ -2396,13 +2428,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } public List SelfviewPipSizes = new List() - { - new CodecCommandWithLabel("Off", "Off"), - new CodecCommandWithLabel("Size1", "Size 1"), - new CodecCommandWithLabel("Size2", "Size 2"), - new CodecCommandWithLabel("Size3", "Size 3"), + { + new CodecCommandWithLabel("Off", "Off"), + new CodecCommandWithLabel("Size1", "Size 1"), + new CodecCommandWithLabel("Size2", "Size 2"), + new CodecCommandWithLabel("Size3", "Size 3"), new CodecCommandWithLabel("Strip", "Strip") - }; + }; private void ComputeSelfviewPipSizeStatus() { @@ -2411,14 +2443,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom p => p.Command.ToLower().Equals(Configuration.Call.Layout.Size.ToString().ToLower())); } - #endregion #region Implementation of IHasPhoneDialing - private Func PhoneOffHookFeedbackFunc { get { return () => Status.PhoneCall.OffHook; } } - private Func CallerIdNameFeedbackFunc { get { return () => Status.PhoneCall.PeerDisplayName; } } - private Func CallerIdNumberFeedbackFunc { get { return () => Status.PhoneCall.PeerNumber; } } + 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; } @@ -2445,10 +2487,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public event EventHandler AvailableLayoutsChanged; - private Func LayoutViewIsOnFirstPageFeedbackFunc { get { return () => Status.Layout.is_In_First_Page; } } - private Func LayoutViewIsOnLastPageFeedbackFunc { get { return () => Status.Layout.is_In_Last_Page; } } - private Func CanSwapContentWithThumbnailFeedbackFunc { get { return () => Status.Layout.can_Switch_Floating_Share_Content; } } - private Func ContentSwappedWithThumbnailFeedbackFunc { get { return () => Configuration.Call.Layout.ShareThumb; } } + private Func LayoutViewIsOnFirstPageFeedbackFunc + { + get { return () => Status.Layout.is_In_First_Page; } + } + + private Func LayoutViewIsOnLastPageFeedbackFunc + { + get { return () => Status.Layout.is_In_Last_Page; } + } + + private Func CanSwapContentWithThumbnailFeedbackFunc + { + get { return () => Status.Layout.can_Switch_Floating_Share_Content; } + } + + private Func ContentSwappedWithThumbnailFeedbackFunc + { + get { return () => Configuration.Call.Layout.ShareThumb; } + } public BoolFeedback LayoutViewIsOnFirstPageFeedback { get; private set; } @@ -2497,7 +2554,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var handler = AvailableLayoutsChanged; if (handler != null) { - handler(this, new LayoutInfoChangedEventArgs() { AvailableLayouts = availableLayouts }); + handler(this, new LayoutInfoChangedEventArgs() {AvailableLayouts = availableLayouts}); } AvailableLayouts = availableLayouts; @@ -2518,7 +2575,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { if (CanSwapContentWithThumbnailFeedback.BoolValue) { - var oppositeValue = ContentSwappedWithThumbnailFeedback.BoolValue ? "on" : "off"; // Get the value based on the opposite of the current state + var oppositeValue = ContentSwappedWithThumbnailFeedback.BoolValue ? "on" : "off"; + // Get the value based on the opposite of the current state // TODO: #697 [*] Need to verify the ternary above and make sure that the correct on/off value is being send based on the true/false value of the feedback // to toggle the state SendText(String.Format("zConfiguration Call Layout ShareThumb: {0}", oppositeValue)); @@ -2544,12 +2602,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom get { return () => - { - if (Configuration.Call.Layout.Style != zConfiguration.eLayoutStyle.None) - return Configuration.Call.Layout.Style.ToString(); - else - return Configuration.Client.Call.Layout.Style.ToString(); - }; + { + if (Configuration.Call.Layout.Style != zConfiguration.eLayoutStyle.None) + return Configuration.Call.Layout.Style.ToString(); + else + return Configuration.Client.Call.Layout.Style.ToString(); + }; } } @@ -2559,7 +2617,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { var currentLayout = LocalLayoutFeedback.StringValue; - var eCurrentLayout = (int)Enum.Parse(typeof(zConfiguration.eLayoutStyle), currentLayout, true); + var eCurrentLayout = (int) Enum.Parse(typeof (zConfiguration.eLayoutStyle), currentLayout, true); var nextLayout = GetNextLayout(eCurrentLayout); @@ -2583,13 +2641,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom zConfiguration.eLayoutStyle nextLayout; - if (((zConfiguration.eLayoutStyle)currentLayout & zConfiguration.eLayoutStyle.ShareAll) == zConfiguration.eLayoutStyle.ShareAll) + if (((zConfiguration.eLayoutStyle) currentLayout & zConfiguration.eLayoutStyle.ShareAll) == + zConfiguration.eLayoutStyle.ShareAll) { nextLayout = zConfiguration.eLayoutStyle.Gallery; } else { - nextLayout = (zConfiguration.eLayoutStyle)(currentLayout << 1); + nextLayout = (zConfiguration.eLayoutStyle) (currentLayout << 1); } if ((AvailableLayouts & nextLayout) == nextLayout) @@ -2598,7 +2657,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } else { - return GetNextLayout((int)nextLayout); + return GetNextLayout((int) nextLayout); } } @@ -2613,7 +2672,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } #endregion - } /// @@ -2814,7 +2872,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void CheckSyncStatus() { if (LoginMessageWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived && - CamerasHaveBeenSetUp) + CamerasHaveBeenSetUp) { InitialSyncComplete = true; Debug.Console(1, this, "Initial Codec Sync Complete!"); @@ -2830,7 +2888,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 b9479bab7001bddd48cbf4800c3732bcd7134658 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 17 Aug 2021 16:50:35 -0600 Subject: [PATCH 04/59] refactor: Rename `Initialize` to `InitializeRoom` --- PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs | 4 ++-- PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs | 4 ++-- PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs b/PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs index d58f6ac7..d3812feb 100644 --- a/PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs +++ b/PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs @@ -207,7 +207,7 @@ namespace PepperDash.Essentials DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls; - Initialize(); + InitializeRoom(); } catch (Exception e) { @@ -215,7 +215,7 @@ namespace PepperDash.Essentials } } - void Initialize() + void InitializeRoom() { if (DefaultAudioDevice is IBasicVolumeControls) DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls; diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs index 7a57e9c1..3123f20f 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs @@ -156,7 +156,7 @@ namespace PepperDash.Essentials DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IRoutingSinkWithSwitching; - Initialize(); + InitializeRoom(); } catch (Exception e) { @@ -164,7 +164,7 @@ namespace PepperDash.Essentials } } - void Initialize() + void InitializeRoom() { if (DefaultAudioDevice is IBasicVolumeControls) DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls; diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index b2450abe..f2b17526 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -226,7 +226,7 @@ namespace PepperDash.Essentials DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls; - Initialize(); + InitializeRoom(); } catch (Exception e) { @@ -234,7 +234,7 @@ namespace PepperDash.Essentials } } - void Initialize() + void InitializeRoom() { try { From 92f4d37cd640c4a22e1a56169447fab268736da3 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 17 Aug 2021 16:52:11 -0600 Subject: [PATCH 05/59] refactor: Clean up Room Interfaces to help with ambiguities --- .../Room/Types/IEssentialsHuddleSpaceRoom.cs | 8 ++------ .../PepperDashEssentialsBase/Room/IEssentialsRoom.cs | 3 +-- .../AudioCodec/Interfaces/IHasAudioCodec.cs | 3 +-- .../VideoCodec/Interfaces/IHasVideoCodec.cs | 8 +------- 4 files changed, 5 insertions(+), 17 deletions(-) diff --git a/PepperDashEssentials/Room/Types/IEssentialsHuddleSpaceRoom.cs b/PepperDashEssentials/Room/Types/IEssentialsHuddleSpaceRoom.cs index efc126f6..45074fb7 100644 --- a/PepperDashEssentials/Room/Types/IEssentialsHuddleSpaceRoom.cs +++ b/PepperDashEssentials/Room/Types/IEssentialsHuddleSpaceRoom.cs @@ -17,7 +17,7 @@ using PepperDash.Core; namespace PepperDash.Essentials { - public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay + public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IHasDefaultDisplay { bool ExcludeFromGlobalFunctions { get; } @@ -31,7 +31,7 @@ namespace PepperDash.Essentials } public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange, - IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback + IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay { EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; } @@ -39,10 +39,6 @@ namespace PepperDash.Essentials IHasScheduleAwareness ScheduleSource { get; } - BoolFeedback InCallFeedback { get; } - - BoolFeedback PrivacyModeIsOnFeedback { get; } - string DefaultCodecRouteString { get; } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/IEssentialsRoom.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/IEssentialsRoom.cs index e83c4b2f..5f94a5cd 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/IEssentialsRoom.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/IEssentialsRoom.cs @@ -15,7 +15,7 @@ namespace PepperDash.Essentials.Core /// /// Describes the basic functionality of an EssentialsRoom /// - public interface IEssentialsRoom : IKeyName, IReconfigurableDevice + public interface IEssentialsRoom : IKeyName, IReconfigurableDevice, IRunDefaultPresentRoute { BoolFeedback OnFeedback { get; } @@ -56,7 +56,6 @@ namespace PepperDash.Essentials.Core void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes); void PowerOnToDefaultOrLastSource(); - bool RunDefaultPresentRoute(); void SetDefaultLevels(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/AudioCodec/Interfaces/IHasAudioCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/AudioCodec/Interfaces/IHasAudioCodec.cs index e4cb5ee4..b6fa079d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/AudioCodec/Interfaces/IHasAudioCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/AudioCodec/Interfaces/IHasAudioCodec.cs @@ -11,10 +11,9 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec /// /// For rooms that have audio codec /// - public interface IHasAudioCodec + public interface IHasAudioCodec:IHasInCallFeedback { AudioCodecBase AudioCodec { get; } - BoolFeedback InCallFeedback { get; } ///// ///// Make this more specific diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasVideoCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasVideoCodec.cs index 1d0f4850..d8494334 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasVideoCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasVideoCodec.cs @@ -11,10 +11,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// /// For rooms that have video codec /// - public interface IHasVideoCodec + public interface IHasVideoCodec:IHasInCallFeedback,IPrivacy { VideoCodecBase VideoCodec { get; } - BoolFeedback InCallFeedback { get; } ///// ///// Make this more specific @@ -26,11 +25,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// IntFeedback CallTypeFeedback { get; } - /// - /// - /// - BoolFeedback PrivacyModeIsOnFeedback { get; } - /// /// When something in the room is sharing with the far end or through other means /// From 36a41ac4770e528e126c698b3017368ce4d6fc3a Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 17 Aug 2021 16:41:23 -0600 Subject: [PATCH 06/59] fix(essentials): #792 refactors logic to show/hide SelectASourceVisible subpage --- .../EssentialsHuddlePanelAvFunctionsDriver.cs | 1 + ...entialsHuddleVtc1PanelAvFunctionsDriver.cs | 47 +++++++++++++++---- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs index a0d5947c..78a06301 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs @@ -918,6 +918,7 @@ namespace PepperDash.Essentials TriList.BooleanInput[StartPageVisibleJoin].BoolValue = true; TriList.BooleanInput[UIBoolJoin.VolumeSingleMute1Visible].BoolValue = false; TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = false; + TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; } } diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 55a4a16c..8082a6cb 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -633,7 +633,10 @@ namespace PepperDash.Essentials var callMode = CurrentMode == UiDisplayMode.Call; TriList.SetBool(StartPageVisibleJoin, startMode ? true : false); + TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, presentationMode ? true : false); + if (!presentationMode) + TriList.SetBool(UIBoolJoin.SelectASourceVisible, false); CallButtonSig.BoolValue = callMode && CurrentRoom.ShutdownType == eShutdownType.None; @@ -674,19 +677,19 @@ namespace PepperDash.Essentials // Run default source when room is off and share is pressed if (!CurrentRoom.OnFeedback.BoolValue) { - if (!CurrentRoom.OnFeedback.BoolValue) - { - // If there's no default, show UI elements - if (!(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute()) - TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); - } - } + // If there's no default, show UI elements + if (!(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute()) + TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); + } else // room is on show what's active or select a source if nothing is yet active { - if(CurrentRoom.CurrentSourceInfo == null || CurrentRoom.CurrentSourceInfoKey == CurrentRoom.DefaultCodecRouteString) + if(CurrentRoom.CurrentSourceInfo == null || (CurrentRoom.VideoCodec != null && CurrentRoom.CurrentSourceInfo.SourceDevice.Key == CurrentRoom.VideoCodec.OsdSource.Key)) TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); else if (CurrentSourcePageManager != null) + { + TriList.SetBool(UIBoolJoin.SelectASourceVisible, false); CurrentSourcePageManager.Show(); + } } CurrentMode = UiDisplayMode.Presentation; SetupSourceList(); @@ -1131,6 +1134,30 @@ namespace PepperDash.Essentials /// void CurrentRoom_CurrentSingleSourceChange(SourceListItem info, ChangeType type) { + Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange"); + + // Show the Select a source subpage + if (TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue) + { + Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange SourceStagingBarVisisble: true"); + + if (_CurrentRoom.CurrentSourceInfo == null || (_CurrentRoom.VideoCodec != null && _CurrentRoom.CurrentSourceInfo.SourceDevice.Key == _CurrentRoom.VideoCodec.OsdSource.Key)) + { + Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange Showing SelectASourceVisible"); + TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); + } + else + { + TriList.SetBool(UIBoolJoin.SelectASourceVisible, false); + Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange Hiding SelectASourceVisible"); + } + } + else + { + Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange Hiding SelectASourceVisible"); + TriList.SetBool(UIBoolJoin.SelectASourceVisible, false); + } + if (_CurrentRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue && _CurrentRoom.CurrentSourceInfo != null) TriList.StringInput[UIStringJoin.CallSharedSourceNameText].StringValue = _CurrentRoom.CurrentSourceInfo.PreferredName; } @@ -1228,12 +1255,12 @@ namespace PepperDash.Essentials var value = _CurrentRoom.OnFeedback.BoolValue; TriList.BooleanInput[UIBoolJoin.RoomIsOn].BoolValue = value; - TriList.BooleanInput[StartPageVisibleJoin].BoolValue = !value; + //TriList.BooleanInput[StartPageVisibleJoin].BoolValue = !value; if (value) //ON { SetupActivityFooterWhenRoomOn(); - TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; + //TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; TriList.BooleanInput[UIBoolJoin.VolumeDualMute1Visible].BoolValue = true; } From 9a1a23c88a9c6cb5a478b9e6a6d0cc63a39cf6c1 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 17 Aug 2021 22:23:41 -0600 Subject: [PATCH 07/59] fix: Instantiate Availability class when --- .../Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index 8184289e..c1cd92cf 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -327,6 +327,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public SpeakerTrack() { Status = new Status2(); + Availability = new Availability(); } } From 6a1671aae1e77b5c682ccca78ea74f0170345682 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 17 Aug 2021 22:25:18 -0600 Subject: [PATCH 08/59] ci: Remove PR trigger --- .github/workflows/docker.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a74ca03e..94c45937 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -8,12 +8,9 @@ on: - bugfix/* - release/* - development - pull_request: - branches: - - development env: - # solution path doesn't need slashes unless there it is multiple folders deep + # solution path doesn't need slashes unless it is multiple folders deep # solution name does not include extension. .sln is assumed SOLUTION_PATH: PepperDashEssentials SOLUTION_FILE: PepperDashEssentials From dbdaedcca3446028128e181057ab694f4dcca1c8 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 18 Aug 2021 13:25:26 -0600 Subject: [PATCH 09/59] feat(essentials): #800 Adds IPasswordPrompt --- .../DeviceTypeInterfaces/IPasswordPrompt.cs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs new file mode 100644 index 00000000..be23725c --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Essentials.Core +{ + /// + /// Describes the functionality required to prompt a user to enter a password + /// + public interface IPasswordPrompt + { + /// + /// Notifies when a password is required or is entered incorrectly + /// + event EventHandler PasswordRequired; + + /// + /// Submits the password + /// + /// + void SubmitPassword(string password); + } + + public class PasswordPromptEventArgs : EventArgs + { + /// + /// Indicates if the last submitted password was incorrect + /// + bool LastAttemptWasIncorrect { get; private set; } + + /// + /// Indicates that the login attempt has failed + /// + bool LoginAttemptFailed { get; private set; } + + /// + /// Indicates that the process was cancelled and the prompt should be dismissed + /// + bool LoginAttemptCancelled { get; private set; } + + /// + /// A message to be displayed to the user + /// + string Message { get; private set; } + + public PasswordPromptEventArgs(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) + { + LastAttemptWasIncorrect = lastAttemptIncorrect; + LoginAttemptFailed = loginFailed; + LoginAttemptCancelled = loginCancelled; + Message = message; + } + } +} \ No newline at end of file From f8129fe7ae108137e910ee778dd2c0718ec82871 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 18 Aug 2021 13:35:48 -0600 Subject: [PATCH 10/59] feat(essentials): #800 adds public access modifier on properties --- .../DeviceTypeInterfaces/IPasswordPrompt.cs | 8 ++++---- .../PepperDash_Essentials_Core.csproj | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs index be23725c..6ecdd775 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs @@ -28,22 +28,22 @@ namespace PepperDash.Essentials.Core /// /// Indicates if the last submitted password was incorrect /// - bool LastAttemptWasIncorrect { get; private set; } + public bool LastAttemptWasIncorrect { get; private set; } /// /// Indicates that the login attempt has failed /// - bool LoginAttemptFailed { get; private set; } + public bool LoginAttemptFailed { get; private set; } /// /// Indicates that the process was cancelled and the prompt should be dismissed /// - bool LoginAttemptCancelled { get; private set; } + public bool LoginAttemptCancelled { get; private set; } /// /// A message to be displayed to the user /// - string Message { get; private set; } + public string Message { get; private set; } public PasswordPromptEventArgs(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 36992629..85c66a13 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -203,6 +203,7 @@ + From f298b5cc41ef9545203ca7ca307aa6154f2806b7 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 18 Aug 2021 14:45:16 -0600 Subject: [PATCH 11/59] feat(essentials): Implements IPasswordPrompt on ZoomRoom --- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 9 ++++ .../VideoCodec/ZoomRoom/ZoomRoom.cs | 47 +++++++++++++++++-- 2 files changed, 53 insertions(+), 3 deletions(-) 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 c116a4a8..d07476dd 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 @@ -927,6 +927,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom PhoneCallStatus_InCall, PhoneCallStatus_Init, } + + public class MeetingNeedsPassword + { + [JsonProperty("needsPassword")] + public bool NeedsPassword { get; set; } + + [JsonProperty("wrongAndRetry")] + public bool WrongAndRetry { get; set; } + } } /// 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 701ce6f2..05602001 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 @@ -25,7 +25,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom IRouting, IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, - IHasParticipantAudioMute, IHasSelfviewSize + IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt { private const long MeetingRefreshTimer = 60000; private const uint DefaultMeetingDurationMin = 30; @@ -45,6 +45,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private StringBuilder _jsonMessage; private int _previousVolumeLevel; private CameraBase _selectedCamera; + private string _lastDialedMeetingNumber; private readonly ZoomRoomPropertiesConfig _props; @@ -1349,7 +1350,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } case "meetingneedspassword": { - // TODO: notify user to enter a password + var meetingNeedsPassword = + responseObj.ToObject(); + + if (meetingNeedsPassword.NeedsPassword) + { + var prompt = "Password required to join this meeting. Please enter the meeting password."; + + OnPasswordRequired(meetingNeedsPassword.WrongAndRetry, false, false, prompt); + } + break; } case "needwaitforhost": @@ -2041,9 +2051,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void Dial(string number) { + _lastDialedMeetingNumber = number; SendText(string.Format("zCommand Dial Join meetingNumber: {0}", number)); } + /// + /// Dials a meeting with a password + /// + /// + /// + public void Dial(string number, string password) + { + SendText(string.Format("zCommand Dial Join meetingNumber: {0} password: {1}", number, password)); + } + /// /// Invites a contact to either a new meeting (if not already in a meeting) or the current meeting. /// Currently only invites a single user @@ -2672,7 +2693,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } #endregion - } + + #region IPasswordPrompt Members + + public event EventHandler PasswordRequired; + + public void SubmitPassword(string password) + { + Dial(_lastDialedMeetingNumber, password); + } + + void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) + { + var handler = PasswordRequired; + if (handler != null) + { + handler(this, new PasswordPromptEventArgs(lastAttemptIncorrect, loginFailed, loginCancelled, message)); + } + } + + #endregion + } /// /// Zoom Room specific info object From dad986414c097901f0babed38aa945d456cb42ed Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 18 Aug 2021 17:55:04 -0600 Subject: [PATCH 12/59] feat(essentials): Updated EssentialsVideoCodecUIDriver to display password prompt when joining password protected meeting --- .../UI/JoinConstants/UIBoolJoin.cs | 19 +++ .../UI/JoinConstants/UIStringlJoin.cs | 8 + .../VC/EssentialsVideoCodecUiDriver.cs | 160 +++++++++++++++++- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 6 + 4 files changed, 191 insertions(+), 2 deletions(-) diff --git a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs index 81be9002..dd454d97 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs @@ -948,5 +948,24 @@ namespace PepperDash.Essentials /// 15214 /// public const uint PinDialogDot4 = 15214; + + // Password Prompt Dialog ************************** + + /// + /// 15301 + /// + public const uint PasswordPromptDialogVisible = 15301; + /// + /// 15302 + /// + public const uint PasswordPromptTextPress = 15302; + /// + /// 15306 + /// + public const uint PasswordPromptCancelPress = 15306; + /// + /// 15307 + /// + public const uint PasswordPromptErrorVisible = 15307; } } \ No newline at end of file diff --git a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs index 9b2b8a95..67a5c6e2 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs @@ -118,6 +118,14 @@ namespace PepperDash.Essentials //----- through 3120 + /// + /// 3201 + /// + public const uint PasswordPromptMessageText = 3201; + /// + /// 3202 + /// + public const uint PasswordPromptPasswordText = 3202; /// /// 3812 diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index 612f7eeb..f92e0114 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -83,6 +83,9 @@ namespace PepperDash.Essentials.UIDrivers.VC StringBuilder SearchStringBuilder = new StringBuilder(); BoolFeedback SearchStringBackspaceVisibleFeedback; + StringFeedback PasswordStringFeedback; + StringBuilder PasswordStringBuilder = new StringBuilder(); + ModalDialog IncomingCallModal; eKeypadMode KeypadMode; @@ -180,8 +183,22 @@ namespace PepperDash.Essentials.UIDrivers.VC }); SearchStringFeedback.LinkInputSig(triList.StringInput[UIStringJoin.CodecDirectorySearchEntryText]); - SetupDirectoryList(); + PasswordStringFeedback = new StringFeedback(() => + { + if (PasswordStringBuilder.Length > 0) + { + Parent.Keyboard.EnableGoButton(); + return PasswordStringBuilder.ToString(); + } + else + { + Parent.Keyboard.DisableGoButton(); + return "Tap for keyboard"; + } + }); + PasswordStringFeedback.LinkInputSig(triList.StringInput[UIStringJoin.PasswordPromptPasswordText]); + SetupDirectoryList(); SearchStringBackspaceVisibleFeedback = new BoolFeedback(() => SearchStringBuilder.Length > 0); SearchStringBackspaceVisibleFeedback.LinkInputSig(triList.BooleanInput[UIBoolJoin.VCDirectoryBackspaceVisible]); @@ -199,6 +216,12 @@ namespace PepperDash.Essentials.UIDrivers.VC triList.SetSigHeldAction(UIBoolJoin.VCDirectoryBackspacePress, 500, StartSearchBackspaceRepeat, StopSearchBackspaceRepeat, SearchKeypadBackspacePress); + + if (Codec is IPasswordPrompt) + { + SetupPasswordPrompt(); + } + } catch (Exception e) { @@ -1328,7 +1351,21 @@ namespace PepperDash.Essentials.UIDrivers.VC /// void RevealKeyboard() { - if (VCControlsInterlock.CurrentJoin == UIBoolJoin.VCKeypadWithFavoritesVisible && KeypadMode == eKeypadMode.Dial) + if (_passwordPromptDialogVisible) + { + Debug.Console(2, "Attaching Keyboard to PasswordPromptDialog"); + DetachDialKeyboard(); + DetachSearchKeyboard(); + var kb = Parent.Keyboard; + kb.KeyPress -= Keyboard_PasswordKeyPress; + kb.KeyPress += Keyboard_PasswordKeyPress; + kb.HideAction = this.DetachPasswordKeyboard; + kb.GoButtonText = "Submit"; + kb.GoButtonVisible = true; + PasswordStringCheckEnables(); + kb.Show(); + } + else if (VCControlsInterlock.CurrentJoin == UIBoolJoin.VCKeypadWithFavoritesVisible && KeypadMode == eKeypadMode.Dial) { var kb = Parent.Keyboard; kb.KeyPress -= Keyboard_DialKeyPress; @@ -1350,6 +1387,7 @@ namespace PepperDash.Essentials.UIDrivers.VC SearchStringKeypadCheckEnables(); kb.Show(); } + } /// @@ -1405,6 +1443,32 @@ namespace PepperDash.Essentials.UIDrivers.VC } } + /// + /// Event handler for keyboard dialing + /// + void Keyboard_PasswordKeyPress(object sender, PepperDash.Essentials.Core.Touchpanels.Keyboards.KeyboardControllerPressEventArgs e) + { + if (_passwordPromptDialogVisible) + { + if (e.Text != null) + PasswordStringBuilder.Append(e.Text); + else + { + if (e.SpecialKey == KeyboardSpecialKey.Backspace) + PasswordKeypadBackspacePress(); + else if (e.SpecialKey == KeyboardSpecialKey.Clear) + PasswordKeypadClear(); + else if (e.SpecialKey == KeyboardSpecialKey.GoButton) + { + (Codec as IPasswordPrompt).SubmitPassword(PasswordStringBuilder.ToString()); + HidePasswordPrompt(); + } + } + PasswordStringFeedback.FireUpdate(); + PasswordStringCheckEnables(); + } + } + /// /// Call /// @@ -1418,6 +1482,11 @@ namespace PepperDash.Essentials.UIDrivers.VC Parent.Keyboard.KeyPress -= Keyboard_SearchKeyPress; } + void DetachPasswordKeyboard() + { + Parent.Keyboard.KeyPress -= Keyboard_PasswordKeyPress; + } + /// /// Shows the camera controls subpage /// @@ -1671,6 +1740,40 @@ namespace PepperDash.Essentials.UIDrivers.VC Parent.Keyboard.DisableGoButton(); } + /// + /// Clears the Password keypad + /// + void PasswordKeypadClear() + { + PasswordStringBuilder.Remove(0, SearchStringBuilder.Length); + PasswordStringFeedback.FireUpdate(); + PasswordStringCheckEnables(); + + } + + /// + /// + /// + void PasswordKeypadBackspacePress() + { + PasswordStringBuilder.Remove(PasswordStringBuilder.Length - 1, 1); + + PasswordStringFeedback.FireUpdate(); + PasswordStringCheckEnables(); + } + + /// + /// Checks the enabled states of various elements around the keypad + /// + void PasswordStringCheckEnables() + { + var textIsEntered = PasswordStringBuilder.Length > 0; + if (textIsEntered) + Parent.Keyboard.EnableGoButton(); + else + Parent.Keyboard.DisableGoButton(); + } + /// /// Returns the text value for the keypad dial entry field @@ -1716,5 +1819,58 @@ namespace PepperDash.Essentials.UIDrivers.VC Dial = 0, DTMF } + + void SetupPasswordPrompt() + { + var passwordPromptCodec = Codec as IPasswordPrompt; + + passwordPromptCodec.PasswordRequired += new EventHandler(passwordPromptCodec_PasswordRequired); + + TriList.SetSigFalseAction(UIBoolJoin.PasswordPromptCancelPress, HidePasswordPrompt); + TriList.SetSigFalseAction(UIBoolJoin.PasswordPromptTextPress, RevealKeyboard); + } + + void passwordPromptCodec_PasswordRequired(object sender, PasswordPromptEventArgs e) + { + if (e.LoginAttemptCancelled) + { + HidePasswordPrompt(); + return; + } + + if (!string.IsNullOrEmpty(e.Message)) + { + TriList.SetString(UIStringJoin.PasswordPromptMessageText, e.Message); + } + + if (e.LoginAttemptFailed) + { + // TODO: Show a message modal to indicate the login attempt failed + return; + } + + TriList.SetBool(UIBoolJoin.PasswordPromptErrorVisible, e.LastAttemptWasIncorrect); + + ShowPasswordPrompt(); + } + + private bool _passwordPromptDialogVisible; + + void ShowPasswordPrompt() + { + // Clear out any previous data + PasswordStringBuilder.Remove(0, PasswordStringBuilder.Length); + + _passwordPromptDialogVisible = true; + TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible); + RevealKeyboard(); + } + + void HidePasswordPrompt() + { + _passwordPromptDialogVisible = false; + Parent.Keyboard.Hide(); + TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible); + } } } \ 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 05602001..ce4ff852 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 @@ -1359,6 +1359,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom OnPasswordRequired(meetingNeedsPassword.WrongAndRetry, false, false, prompt); } + else + { + OnPasswordRequired(false, false, true, ""); + } break; } @@ -2062,6 +2066,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// public void Dial(string number, string password) { + Debug.Console(2, this, "Dialing meeting number: {0} with password: {1}", number, password); SendText(string.Format("zCommand Dial Join meetingNumber: {0} password: {1}", number, password)); } @@ -2700,6 +2705,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void SubmitPassword(string password) { + Debug.Console(2, this, "Password Submitted: {0}", password); Dial(_lastDialedMeetingNumber, password); } From 62fcf3856f17496001867e9877352c6d139ab83d Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 19 Aug 2021 09:37:21 -0600 Subject: [PATCH 13/59] fix(essentials): Minor update to clear out previous password text when displaying password prompt --- .../UIDrivers/VC/EssentialsVideoCodecUiDriver.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index f92e0114..ebec4568 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -193,7 +193,7 @@ namespace PepperDash.Essentials.UIDrivers.VC else { Parent.Keyboard.DisableGoButton(); - return "Tap for keyboard"; + return ""; } }); PasswordStringFeedback.LinkInputSig(triList.StringInput[UIStringJoin.PasswordPromptPasswordText]); @@ -1859,7 +1859,7 @@ namespace PepperDash.Essentials.UIDrivers.VC void ShowPasswordPrompt() { // Clear out any previous data - PasswordStringBuilder.Remove(0, PasswordStringBuilder.Length); + PasswordKeypadClear(); _passwordPromptDialogVisible = true; TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible); From 621205e65c42b08d24dab8e6aedd9a2ddfa4def8 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 19 Aug 2021 12:04:11 -0600 Subject: [PATCH 14/59] fix(essentials): Hides password prompt on successful call connection --- .../UIDrivers/VC/EssentialsVideoCodecUiDriver.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index ebec4568..6dba53f5 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -322,6 +322,7 @@ namespace PepperDash.Essentials.UIDrivers.VC { case eCodecCallStatus.Connected: // fire at SRL item + HidePasswordPrompt(); KeypadMode = eKeypadMode.DTMF; DialStringBuilder.Remove(0, DialStringBuilder.Length); DialStringFeedback.FireUpdate(); @@ -1868,9 +1869,12 @@ namespace PepperDash.Essentials.UIDrivers.VC void HidePasswordPrompt() { - _passwordPromptDialogVisible = false; - Parent.Keyboard.Hide(); - TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible); + if (_passwordPromptDialogVisible) + { + _passwordPromptDialogVisible = false; + Parent.Keyboard.Hide(); + TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible); + } } } } \ No newline at end of file From 8bf4b0d568326679a781b0dc9cfd1fe99c90f128 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 19 Aug 2021 12:49:11 -0600 Subject: [PATCH 15/59] fix(essentails): Increase phonebook list limit to 10000 --- .../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 ce4ff852..6b9db714 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 @@ -852,7 +852,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (!_props.DisablePhonebookAutoDownload) { - _syncState.AddQueryToQueue("zCommand Phonebook List Offset: 0 Limit: 512"); + _syncState.AddQueryToQueue("zCommand Phonebook List Offset: 0 Limit: 10000"); } _syncState.AddQueryToQueue("zCommand Bookings List"); From b2331fa1e544328fe824e2a4a12e93a650690be6 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 19 Aug 2021 14:14:14 -0600 Subject: [PATCH 16/59] feat(essentials): Adds IsInvitableContact property with getter to DirectoryContact --- .../Essentials Devices Common/Codec/iHasDirectory.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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 29a46466..38946759 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 @@ -209,7 +209,14 @@ namespace PepperDash.Essentials.Devices.Common.Codec [JsonProperty("title")] public string Title { get; set; } - + [JsonProperty("isInvitableContact")] + public bool IsInvitableContact + { + get + { + return this is IInvitableContact; + } + } [JsonProperty("contactMethods")] public List ContactMethods { get; set; } From f922b871a16dc6320e684a560a782dc2e7065f31 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 19 Aug 2021 14:57:00 -0600 Subject: [PATCH 17/59] refactor(essentials): Switches from zoom specific contact class to generic InvitableDirectoryContact class --- .../Codec/iHasDirectory.cs | 21 +++++++++++-------- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 10 +-------- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 2 +- 3 files changed, 14 insertions(+), 19 deletions(-) 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 38946759..b2ccb29c 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 @@ -160,7 +160,19 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public interface IInvitableContact { + bool IsInvitableContact { get; } + } + public class InvitableDirectoryContact : DirectoryContact, IInvitableContact + { + [JsonProperty("isInvitableContact")] + public bool IsInvitableContact + { + get + { + return this is IInvitableContact; + } + } } /// @@ -209,15 +221,6 @@ namespace PepperDash.Essentials.Devices.Common.Codec [JsonProperty("title")] public string Title { get; set; } - [JsonProperty("isInvitableContact")] - public bool IsInvitableContact - { - get - { - return this is IInvitableContact; - } - } - [JsonProperty("contactMethods")] public List ContactMethods { get; set; } 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 d07476dd..28073eb8 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 @@ -236,14 +236,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } - /// - /// Used to be able to inplement IInvitableContact on DirectoryContact - /// - public class ZoomDirectoryContact : DirectoryContact, IInvitableContact - { - - } - public class Phonebook { [JsonProperty("Contacts")] @@ -302,7 +294,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom foreach (Contact c in zoomContacts) { - var contact = new ZoomDirectoryContact { Name = c.ScreenName, ContactId = c.Jid }; + var contact = new InvitableDirectoryContact { Name = c.ScreenName, ContactId = c.Jid }; contact.ContactMethods.Add(new ContactMethod() { Number = c.Jid, Device = eContactMethodDevice.Video, CallType = eContactMethodCallType.Video, ContactMethodId = c.Jid }); 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 6b9db714..9bcdd44b 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 @@ -2077,7 +2077,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// public override void Dial(IInvitableContact contact) { - var ic = contact as zStatus.ZoomDirectoryContact; + var ic = contact as InvitableDirectoryContact; if (ic != null) { From 0014dd7a1448033a5020867f06da8ec843b28863 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 19 Aug 2021 15:19:19 -0600 Subject: [PATCH 18/59] feat(essentials): #801 Adds IHasStartMeeting interface and implments on ZoomRoom --- .../VideoCodec/Interfaces/IHasStartMeeting.cs | 25 +++++++++++++++++++ .../VideoCodec/ZoomRoom/ZoomRoom.cs | 22 ++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStartMeeting.cs diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStartMeeting.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStartMeeting.cs new file mode 100644 index 00000000..a01ec099 --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStartMeeting.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + /// + /// Describes the ability to start an ad-hoc meeting + /// + public interface IHasStartMeeting + { + /// + /// The default meeting duration in minutes + /// + uint DefaultMeetingDurationMin { get; } + + /// + /// Start an ad-hoc meeting for the specified duration + /// + /// + void StartMeeting(uint duration); + } +} \ 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 9bcdd44b..4712f12d 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 @@ -25,10 +25,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom IRouting, IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, - IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt + IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting { private const long MeetingRefreshTimer = 60000; - private const uint DefaultMeetingDurationMin = 30; + public uint DefaultMeetingDurationMin { get; private set; } + private const string Delimiter = "\x0D\x0A"; private readonly GenericQueue _receiveQueue; @@ -52,6 +53,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public ZoomRoom(DeviceConfig config, IBasicCommunication comm) : base(config) { + DefaultMeetingDurationMin = 30; + _props = JsonConvert.DeserializeObject(config.Properties.ToString()); _receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 512); @@ -2095,6 +2098,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } + + /// + /// Starts a PMI Meeting for the specified duration (or default meeting duration if 0 is specified) + /// + /// duration of meeting + public void StartMeeting(uint duration) + { + uint dur = DefaultMeetingDurationMin; + + if (duration > 0) + dur = duration; + + SendText(string.Format("zCommand Dial StartPmi Duration: {0}", dur); + } + public override void EndCall(CodecActiveCallItem call) { SendText("zCommand Call Disconnect"); From 540a00861cc9ee265d6118b7c0bce2a1966641e2 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 19 Aug 2021 16:02:24 -0600 Subject: [PATCH 19/59] fix(essentials): Adds missing file in .csproj --- .../Essentials Devices Common.csproj | 1 + .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 4 ++++ .../Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs | 4 ++-- 3 files changed, 7 insertions(+), 2 deletions(-) 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 21821d22..75d01b0f 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 @@ -123,6 +123,7 @@ + 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 d31fbda1..4db4084c 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 @@ -736,6 +736,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } + /// + /// Appends the delimiter and send the command to the codec + /// + /// public void SendText(string command) { if (CommDebuggingIsOn) 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 4712f12d..83597081 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 @@ -734,7 +734,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom ConsoleAccessLevelEnum.AccessOperator); if (!_props.DisablePhonebookAutoDownload) { - CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 512"), + CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 10000"), "GetZoomRoomContacts", "Triggers a refresh of the codec phonebook", ConsoleAccessLevelEnum.AccessOperator); } @@ -2110,7 +2110,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (duration > 0) dur = duration; - SendText(string.Format("zCommand Dial StartPmi Duration: {0}", dur); + SendText(string.Format("zCommand Dial StartPmi Duration: {0}", dur)); } public override void EndCall(CodecActiveCallItem call) From 4444328600ecb720f8e5ce1b6bde9abdecadca0a Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 26 Aug 2021 16:48:56 -0600 Subject: [PATCH 20/59] fix(essentials): #804 #805 Updates to prevent attempting to access null AudioSourceFeedback property on 4kz TX models --- .../Transmitters/DmTx4kz202CController.cs | 680 +++++++++--------- .../Transmitters/DmTx4kz302CController.cs | 6 +- 2 files changed, 343 insertions(+), 343 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs index da1685cc..a241d60d 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs @@ -1,40 +1,40 @@ -using Crestron.SimplSharpPro; -using System; -using System.Linq; -//using Crestron.SimplSharpPro.DeviceSupport; -using Crestron.SimplSharpPro.DeviceSupport; -using Crestron.SimplSharpPro.DM; -using Crestron.SimplSharpPro.DM.Endpoints; -using Crestron.SimplSharpPro.DM.Endpoints.Transmitters; - -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Bridges; - -namespace PepperDash.Essentials.DM -{ - using eVst = eX02VideoSourceType; +using Crestron.SimplSharpPro; +using System; +using System.Linq; +//using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.DM; +using Crestron.SimplSharpPro.DM.Endpoints; +using Crestron.SimplSharpPro.DM.Endpoints.Transmitters; + +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; + +namespace PepperDash.Essentials.DM +{ + using eVst = eX02VideoSourceType; using eAst = eX02AudioSourceType; - public class DmTx4kz202CController : DmTxControllerBase, ITxRoutingWithFeedback, - IIROutputPorts, IComPorts - { - public DmTx4kz202C Tx { get; private set; } - - public RoutingInputPortWithVideoStatuses HdmiIn1 { get; private set; } - public RoutingInputPortWithVideoStatuses HdmiIn2 { get; private set; } - public RoutingOutputPort DmOut { get; private set; } - public RoutingOutputPort HdmiLoopOut { get; private set; } - - public override StringFeedback ActiveVideoInputFeedback { get; protected set; } - public IntFeedback VideoSourceNumericFeedback { get; protected set; } - public IntFeedback AudioSourceNumericFeedback { get; protected set; } - public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; } - public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; } - public BoolFeedback Hdmi1VideoSyncFeedback { get; protected set; } - public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; } - - //public override IntFeedback HdcpSupportAllFeedback { get; protected set; } + public class DmTx4kz202CController : DmTxControllerBase, ITxRoutingWithFeedback, + IIROutputPorts, IComPorts + { + public DmTx4kz202C Tx { get; private set; } + + public RoutingInputPortWithVideoStatuses HdmiIn1 { get; private set; } + public RoutingInputPortWithVideoStatuses HdmiIn2 { get; private set; } + public RoutingOutputPort DmOut { get; private set; } + public RoutingOutputPort HdmiLoopOut { get; private set; } + + public override StringFeedback ActiveVideoInputFeedback { get; protected set; } + public IntFeedback VideoSourceNumericFeedback { get; protected set; } + public IntFeedback AudioSourceNumericFeedback { get; protected set; } + public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; } + public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; } + public BoolFeedback Hdmi1VideoSyncFeedback { get; protected set; } + public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; } + + //public override IntFeedback HdcpSupportAllFeedback { get; protected set; } //public override ushort HdcpSupportCapability { get; protected set; } //IroutingNumericEvent public event EventHandler NumericSwitchChange; @@ -47,48 +47,48 @@ namespace PepperDash.Essentials.DM { var newEvent = NumericSwitchChange; if (newEvent != null) newEvent(this, e); - } - - - - /// - /// Helps get the "real" inputs, including when in Auto - /// - public eX02VideoSourceType ActualActiveVideoInput - { - get - { - if (Tx.VideoSourceFeedback != eVst.Auto) - return Tx.VideoSourceFeedback; - - if (Tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue) - return eVst.Hdmi1; - - return Tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue ? eVst.Hdmi2 : eVst.AllDisabled; - } - } - public RoutingPortCollection InputPorts - { - get - { - return new RoutingPortCollection - { - HdmiIn1, - HdmiIn2, - AnyVideoInput - }; - } - } - public RoutingPortCollection OutputPorts - { - get - { - return new RoutingPortCollection { DmOut, HdmiLoopOut }; - } - } - public DmTx4kz202CController(string key, string name, DmTx4kz202C tx) - : base(key, name, tx) - { + } + + + + /// + /// Helps get the "real" inputs, including when in Auto + /// + public eX02VideoSourceType ActualActiveVideoInput + { + get + { + if (Tx.VideoSourceFeedback != eVst.Auto) + return Tx.VideoSourceFeedback; + + if (Tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue) + return eVst.Hdmi1; + + return Tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue ? eVst.Hdmi2 : eVst.AllDisabled; + } + } + public RoutingPortCollection InputPorts + { + get + { + return new RoutingPortCollection + { + HdmiIn1, + HdmiIn2, + AnyVideoInput + }; + } + } + public RoutingPortCollection OutputPorts + { + get + { + return new RoutingPortCollection { DmOut, HdmiLoopOut }; + } + } + public DmTx4kz202CController(string key, string name, DmTx4kz202C tx) + : base(key, name, tx) + { Tx = tx; HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1, @@ -104,208 +104,208 @@ namespace PepperDash.Essentials.DM FeedbackMatchObject = eVst.Hdmi2 }; - ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput", - () => ActualActiveVideoInput.ToString()); - - - - Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent; - Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent; - Tx.BaseEvent += Tx_BaseEvent; - Tx.OnlineStatusChange += Tx_OnlineStatusChange; - - VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback); - - //Return VideoSourceFeedback here as DM-TX-4KZ-202-C does not support audio breakaway - AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback); - - HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability", () => (int)tx.HdmiInputs[1].HdcpCapabilityFeedback); - - HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability", () => (int)tx.HdmiInputs[2].HdcpCapabilityFeedback); - - HdcpStateFeedback = - new IntFeedback( - () => - tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback - ? (int)tx.HdmiInputs[1].HdcpCapabilityFeedback - : (int)tx.HdmiInputs[2].HdcpCapabilityFeedback); - - HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support; - - Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue); - - Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue); - - var combinedFuncs = new VideoStatusFuncsWrapper - { - HdcpActiveFeedbackFunc = () => - (ActualActiveVideoInput == eVst.Hdmi1 - && tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue) - || (ActualActiveVideoInput == eVst.Hdmi2 - && tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue), - - HdcpStateFeedbackFunc = () => - { - if (ActualActiveVideoInput == eVst.Hdmi1) - return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString(); - if (ActualActiveVideoInput == eVst.Hdmi2) - return tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString(); - return ""; - }, - - VideoResolutionFeedbackFunc = () => - { - if (ActualActiveVideoInput == eVst.Hdmi1) - return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString(); - if (ActualActiveVideoInput == eVst.Hdmi2) - return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString(); - return ""; - }, - VideoSyncFeedbackFunc = () => - (ActualActiveVideoInput == eVst.Hdmi1 - && tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue) - || (ActualActiveVideoInput == eVst.Hdmi2 - && tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue) - - }; - - AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn, - eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this, combinedFuncs); - - DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.DmCat, null, this); - HdmiLoopOut = new RoutingOutputPort(DmPortName.HdmiLoopOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - - - AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback, - AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback, - AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback, - AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback, HdmiIn2HdcpCapabilityFeedback, - Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback); - - // Set Ports for CEC - HdmiIn1.Port = Tx.HdmiInputs[1]; - HdmiIn2.Port = Tx.HdmiInputs[2]; - HdmiLoopOut.Port = Tx.HdmiOutput; - DmOut.Port = Tx.DmOutput; - } - - - - public override bool CustomActivate() - { - // Link up all of these damned events to the various RoutingPorts via a helper handler - Tx.HdmiInputs[1].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn1, a.EventId); - Tx.HdmiInputs[1].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn1, a.EventId); - - Tx.HdmiInputs[2].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn2, a.EventId); - Tx.HdmiInputs[2].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn2, a.EventId); - - // Base does register and sets up comm monitoring. - return base.CustomActivate(); - } - - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = GetDmTxJoinMap(joinStart, joinMapKey); - - if (Hdmi1VideoSyncFeedback != null) - { - Hdmi1VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input1VideoSyncStatus.JoinNumber]); - } - if (Hdmi2VideoSyncFeedback != null) - { - Hdmi2VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input2VideoSyncStatus.JoinNumber]); - } - - LinkDmTxToApi(this, trilist, joinMap, bridge); - } - - public void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type) - { - Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input); - - switch (type) - { - case eRoutingSignalType.Video: - switch (input) - { - case 0: - { - ExecuteSwitch(eVst.Auto, null, type); - break; - } - case 1: - { - ExecuteSwitch(HdmiIn1.Selector, null, type); - break; - } - case 2: - { - ExecuteSwitch(HdmiIn2.Selector, null, type); - break; - } - case 3: - { - ExecuteSwitch(eVst.AllDisabled, null, type); - break; - } - } - break; - case eRoutingSignalType.Audio: - switch (input) - { - case 0: - { - ExecuteSwitch(eAst.Auto, null, type); - break; - } - case 1: - { - ExecuteSwitch(eAst.Hdmi1, null, type); - break; - } - case 2: - { - ExecuteSwitch(eAst.Hdmi2, null, type); - break; - } - case 3: - { - ExecuteSwitch(eAst.AllDisabled, null, type); - break; - } - } - break; - } - } - - public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) - { - if ((signalType & eRoutingSignalType.Video) == eRoutingSignalType.Video) - Tx.VideoSource = (eVst)inputSelector; - if(((signalType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio)) - Debug.Console(2, this, "Unable to execute audio-only switch for tx {0}", Key); - } - - void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args) - { - Debug.Console(2, "{0} event {1} stream {2}", Tx.ToString(), inputStream.ToString(), args.EventId.ToString()); - - switch (args.EventId) - { - case EndpointInputStreamEventIds.HdcpSupportOffFeedbackEventId: - case EndpointInputStreamEventIds.HdcpSupportOnFeedbackEventId: - case EndpointInputStreamEventIds.HdcpCapabilityFeedbackEventId: - if (inputStream == Tx.HdmiInputs[1]) HdmiIn1HdcpCapabilityFeedback.FireUpdate(); - if (inputStream == Tx.HdmiInputs[2]) HdmiIn2HdcpCapabilityFeedback.FireUpdate(); - break; - case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId: - if (inputStream == Tx.HdmiInputs[1]) Hdmi1VideoSyncFeedback.FireUpdate(); - if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate(); - break; - } + ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput", + () => ActualActiveVideoInput.ToString()); + + + + Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent; + Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent; + Tx.BaseEvent += Tx_BaseEvent; + Tx.OnlineStatusChange += Tx_OnlineStatusChange; + + VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback); + + //Return VideoSourceFeedback here as DM-TX-4KZ-202-C does not support audio breakaway + AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback); + + HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability", () => (int)tx.HdmiInputs[1].HdcpCapabilityFeedback); + + HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability", () => (int)tx.HdmiInputs[2].HdcpCapabilityFeedback); + + HdcpStateFeedback = + new IntFeedback( + () => + tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback + ? (int)tx.HdmiInputs[1].HdcpCapabilityFeedback + : (int)tx.HdmiInputs[2].HdcpCapabilityFeedback); + + HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support; + + Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue); + + Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue); + + var combinedFuncs = new VideoStatusFuncsWrapper + { + HdcpActiveFeedbackFunc = () => + (ActualActiveVideoInput == eVst.Hdmi1 + && tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue) + || (ActualActiveVideoInput == eVst.Hdmi2 + && tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue), + + HdcpStateFeedbackFunc = () => + { + if (ActualActiveVideoInput == eVst.Hdmi1) + return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString(); + if (ActualActiveVideoInput == eVst.Hdmi2) + return tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString(); + return ""; + }, + + VideoResolutionFeedbackFunc = () => + { + if (ActualActiveVideoInput == eVst.Hdmi1) + return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString(); + if (ActualActiveVideoInput == eVst.Hdmi2) + return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString(); + return ""; + }, + VideoSyncFeedbackFunc = () => + (ActualActiveVideoInput == eVst.Hdmi1 + && tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue) + || (ActualActiveVideoInput == eVst.Hdmi2 + && tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue) + + }; + + AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn, + eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this, combinedFuncs); + + DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmCat, null, this); + HdmiLoopOut = new RoutingOutputPort(DmPortName.HdmiLoopOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, null, this); + + + AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback, + AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback, + AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback, + AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback, HdmiIn2HdcpCapabilityFeedback, + Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback); + + // Set Ports for CEC + HdmiIn1.Port = Tx.HdmiInputs[1]; + HdmiIn2.Port = Tx.HdmiInputs[2]; + HdmiLoopOut.Port = Tx.HdmiOutput; + DmOut.Port = Tx.DmOutput; + } + + + + public override bool CustomActivate() + { + // Link up all of these damned events to the various RoutingPorts via a helper handler + Tx.HdmiInputs[1].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn1, a.EventId); + Tx.HdmiInputs[1].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn1, a.EventId); + + Tx.HdmiInputs[2].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn2, a.EventId); + Tx.HdmiInputs[2].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn2, a.EventId); + + // Base does register and sets up comm monitoring. + return base.CustomActivate(); + } + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = GetDmTxJoinMap(joinStart, joinMapKey); + + if (Hdmi1VideoSyncFeedback != null) + { + Hdmi1VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input1VideoSyncStatus.JoinNumber]); + } + if (Hdmi2VideoSyncFeedback != null) + { + Hdmi2VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input2VideoSyncStatus.JoinNumber]); + } + + LinkDmTxToApi(this, trilist, joinMap, bridge); + } + + public void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type) + { + Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input); + + switch (type) + { + case eRoutingSignalType.Video: + switch (input) + { + case 0: + { + ExecuteSwitch(eVst.Auto, null, type); + break; + } + case 1: + { + ExecuteSwitch(HdmiIn1.Selector, null, type); + break; + } + case 2: + { + ExecuteSwitch(HdmiIn2.Selector, null, type); + break; + } + case 3: + { + ExecuteSwitch(eVst.AllDisabled, null, type); + break; + } + } + break; + case eRoutingSignalType.Audio: + switch (input) + { + case 0: + { + ExecuteSwitch(eAst.Auto, null, type); + break; + } + case 1: + { + ExecuteSwitch(eAst.Hdmi1, null, type); + break; + } + case 2: + { + ExecuteSwitch(eAst.Hdmi2, null, type); + break; + } + case 3: + { + ExecuteSwitch(eAst.AllDisabled, null, type); + break; + } + } + break; + } + } + + public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) + { + if ((signalType & eRoutingSignalType.Video) == eRoutingSignalType.Video) + Tx.VideoSource = (eVst)inputSelector; + if(((signalType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio)) + Debug.Console(2, this, "Unable to execute audio-only switch for tx {0}", Key); + } + + void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args) + { + Debug.Console(2, "{0} event {1} stream {2}", Tx.ToString(), inputStream.ToString(), args.EventId.ToString()); + + switch (args.EventId) + { + case EndpointInputStreamEventIds.HdcpSupportOffFeedbackEventId: + case EndpointInputStreamEventIds.HdcpSupportOnFeedbackEventId: + case EndpointInputStreamEventIds.HdcpCapabilityFeedbackEventId: + if (inputStream == Tx.HdmiInputs[1]) HdmiIn1HdcpCapabilityFeedback.FireUpdate(); + if (inputStream == Tx.HdmiInputs[2]) HdmiIn2HdcpCapabilityFeedback.FireUpdate(); + break; + case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId: + if (inputStream == Tx.HdmiInputs[1]) Hdmi1VideoSyncFeedback.FireUpdate(); + if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate(); + break; + } } void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args) @@ -313,7 +313,7 @@ namespace PepperDash.Essentials.DM var localVideoInputPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback); var localAudioInputPort = - InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback); + InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback); ActiveVideoInputFeedback.FireUpdate(); VideoSourceNumericFeedback.FireUpdate(); @@ -338,68 +338,68 @@ namespace PepperDash.Essentials.DM OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video)); break; case EndpointTransmitterBase.AudioSourceFeedbackEventId: - var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback); - Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback); + var localInputAudioPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback); + Debug.Console(2, this, " Audio Source: {0}", Tx.VideoSourceFeedback); AudioSourceNumericFeedback.FireUpdate(); OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio)); break; } - } - - /// - /// Relays the input stream change to the appropriate RoutingInputPort. - /// - void FowardInputStreamChange(RoutingInputPortWithVideoStatuses inputPort, int eventId) - { - if (eventId != EndpointInputStreamEventIds.SyncDetectedFeedbackEventId) - { - return; - } - inputPort.VideoStatus.VideoSyncFeedback.FireUpdate(); - AnyVideoInput.VideoStatus.VideoSyncFeedback.FireUpdate(); - } - - /// - /// Relays the VideoAttributes change to a RoutingInputPort - /// - void ForwardVideoAttributeChange(RoutingInputPortWithVideoStatuses inputPort, int eventId) - { - //// LOCATION: Crestron.SimplSharpPro.DM.VideoAttributeEventIds - //Debug.Console(2, this, "VideoAttributes_AttributeChange event id={0} from {1}", - // args.EventId, (sender as VideoAttributesEnhanced).Owner.GetType()); - switch (eventId) - { - case VideoAttributeEventIds.HdcpActiveFeedbackEventId: - inputPort.VideoStatus.HdcpActiveFeedback.FireUpdate(); - AnyVideoInput.VideoStatus.HdcpActiveFeedback.FireUpdate(); - break; - case VideoAttributeEventIds.HdcpStateFeedbackEventId: - inputPort.VideoStatus.HdcpStateFeedback.FireUpdate(); - AnyVideoInput.VideoStatus.HdcpStateFeedback.FireUpdate(); - break; - case VideoAttributeEventIds.HorizontalResolutionFeedbackEventId: - case VideoAttributeEventIds.VerticalResolutionFeedbackEventId: - inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate(); - AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate(); - break; - case VideoAttributeEventIds.FramesPerSecondFeedbackEventId: - inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate(); - AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate(); - break; - } - } - - - - - #region IIROutputPorts Members - public CrestronCollection IROutputPorts { get { return Tx.IROutputPorts; } } - public int NumberOfIROutputPorts { get { return Tx.NumberOfIROutputPorts; } } - #endregion - - #region IComPorts Members - public CrestronCollection ComPorts { get { return Tx.ComPorts; } } - public int NumberOfComPorts { get { return Tx.NumberOfComPorts; } } - #endregion - } + } + + /// + /// Relays the input stream change to the appropriate RoutingInputPort. + /// + void FowardInputStreamChange(RoutingInputPortWithVideoStatuses inputPort, int eventId) + { + if (eventId != EndpointInputStreamEventIds.SyncDetectedFeedbackEventId) + { + return; + } + inputPort.VideoStatus.VideoSyncFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.VideoSyncFeedback.FireUpdate(); + } + + /// + /// Relays the VideoAttributes change to a RoutingInputPort + /// + void ForwardVideoAttributeChange(RoutingInputPortWithVideoStatuses inputPort, int eventId) + { + //// LOCATION: Crestron.SimplSharpPro.DM.VideoAttributeEventIds + //Debug.Console(2, this, "VideoAttributes_AttributeChange event id={0} from {1}", + // args.EventId, (sender as VideoAttributesEnhanced).Owner.GetType()); + switch (eventId) + { + case VideoAttributeEventIds.HdcpActiveFeedbackEventId: + inputPort.VideoStatus.HdcpActiveFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.HdcpActiveFeedback.FireUpdate(); + break; + case VideoAttributeEventIds.HdcpStateFeedbackEventId: + inputPort.VideoStatus.HdcpStateFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.HdcpStateFeedback.FireUpdate(); + break; + case VideoAttributeEventIds.HorizontalResolutionFeedbackEventId: + case VideoAttributeEventIds.VerticalResolutionFeedbackEventId: + inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate(); + break; + case VideoAttributeEventIds.FramesPerSecondFeedbackEventId: + inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate(); + break; + } + } + + + + + #region IIROutputPorts Members + public CrestronCollection IROutputPorts { get { return Tx.IROutputPorts; } } + public int NumberOfIROutputPorts { get { return Tx.NumberOfIROutputPorts; } } + #endregion + + #region IComPorts Members + public CrestronCollection ComPorts { get { return Tx.ComPorts; } } + public int NumberOfComPorts { get { return Tx.NumberOfComPorts; } } + #endregion + } } \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs index fb8f3ac5..70df8259 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs @@ -339,7 +339,7 @@ namespace PepperDash.Essentials.DM var localVideoInputPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback); var localAudioInputPort = - InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback); + InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback); ActiveVideoInputFeedback.FireUpdate(); VideoSourceNumericFeedback.FireUpdate(); @@ -364,8 +364,8 @@ namespace PepperDash.Essentials.DM OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video)); break; case EndpointTransmitterBase.AudioSourceFeedbackEventId: - var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback); - Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback); + var localInputAudioPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback); + Debug.Console(2, this, " Audio Source: {0}", Tx.VideoSourceFeedback); AudioSourceNumericFeedback.FireUpdate(); OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio)); break; From c84ec4c899abc153f3788e3f00fbda8281e1fb46 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 26 Aug 2021 17:09:46 -0600 Subject: [PATCH 21/59] fix(essentials): #806 switches method to print times for consistent 12h format fix(essentials): #806 Updates more uses of ToShortTimeString() fix(essentials): #806 fixes for VideoCodecUIDriver fix(essentials): #806 final fixes for time format --- .../EssentialsHuddleVtc1PanelAvFunctionsDriver.cs | 15 +++++++++------ .../UIDrivers/VC/EssentialsVideoCodecUiDriver.cs | 3 ++- .../PepperDashEssentialsBase/Global/Global.cs | 5 +++++ .../VideoCodec/VideoCodecBase.cs | 8 ++++---- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 8082a6cb..77810c6c 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Collections.Generic; +using System.Globalization; using Crestron.SimplSharp; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.UI; @@ -470,7 +471,7 @@ namespace PepperDash.Essentials Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*", CurrentRoom.OnFeedback.BoolValue, LastMeetingDismissedId, - lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToShortTimeString() : ""); + lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : ""); var meeting = meetings.LastOrDefault(m => m.Joinable); if (CurrentRoom.OnFeedback.BoolValue @@ -487,9 +488,11 @@ namespace PepperDash.Essentials } else { + + TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Upcoming meeting"); - TriList.SetString(UIStringJoin.NextMeetingStartTimeText, meeting.StartTime.ToShortTimeString()); - TriList.SetString(UIStringJoin.NextMeetingEndTimeText, meeting.EndTime.ToShortTimeString()); + TriList.SetString(UIStringJoin.NextMeetingStartTimeText, meeting.StartTime.ToString("t", Global.Culture)); + TriList.SetString(UIStringJoin.NextMeetingEndTimeText, meeting.EndTime.ToString("t", Global.Culture)); TriList.SetString(UIStringJoin.NextMeetingTitleText, meeting.Title); TriList.SetString(UIStringJoin.NextMeetingNameText, meeting.Organizer); TriList.SetString(UIStringJoin.NextMeetingButtonLabel, "Join"); @@ -512,7 +515,7 @@ namespace PepperDash.Essentials // indexOf = 3, 4 meetings : if (indexOfNext < meetings.Count) TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, - meetings[indexOfNext].StartTime.ToShortTimeString()); + meetings[indexOfNext].StartTime.ToString("t", Global.Culture)); else TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, "No more meetings today"); @@ -1209,8 +1212,8 @@ namespace PepperDash.Essentials foreach (var m in CurrentRoom.ScheduleSource.CodecSchedule.Meetings) { i++; - MeetingOrContactMethodModalSrl.StringInputSig(i, 1).StringValue = m.StartTime.ToShortTimeString(); - MeetingOrContactMethodModalSrl.StringInputSig(i, 2).StringValue = m.EndTime.ToShortTimeString(); + MeetingOrContactMethodModalSrl.StringInputSig(i, 1).StringValue = m.StartTime.ToString("t", Global.Culture); + MeetingOrContactMethodModalSrl.StringInputSig(i, 2).StringValue = m.EndTime.ToString("t", Global.Culture); MeetingOrContactMethodModalSrl.StringInputSig(i, 3).StringValue = m.Title; MeetingOrContactMethodModalSrl.StringInputSig(i, 4).StringValue = string.Format("
{0}",m.Organizer); MeetingOrContactMethodModalSrl.StringInputSig(i, 5).StringValue = "Join"; diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index 6dba53f5..f3f707c3 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Globalization; using System.Text.RegularExpressions; using Crestron.SimplSharp; using Crestron.SimplSharpPro; @@ -1008,7 +1009,7 @@ namespace PepperDash.Essentials.UIDrivers.VC // if it's today, show a simpler string string timeText = null; if (c.StartTime.Date == DateTime.Now.Date) - timeText = c.StartTime.ToShortTimeString(); + timeText = c.StartTime.ToString("t", Global.Culture); else if (c.StartTime == DateTime.MinValue) timeText = ""; else diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs index aa71c1f7..121bc9b7 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs @@ -1,5 +1,6 @@ using System; using System.Text.RegularExpressions; +using System.Globalization; using Crestron.SimplSharp; using System.Collections.Generic; using Crestron.SimplSharp.CrestronIO; @@ -28,6 +29,10 @@ namespace PepperDash.Essentials.Core public static eCrestronSeries ProcessorSeries { get { return CrestronEnvironment.ProgramCompatibility; } } + // TODO: consider making this configurable later + public static IFormatProvider Culture = CultureInfo.CreateSpecificCulture("en-US"); + + /// /// The file path prefix to the folder containing configuration files /// 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 c5cff74e..d34c9e3b 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 @@ -836,10 +836,10 @@ ScreenIndexIsPinnedTo: {8} (a{17}) //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 + 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 + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString("t", Global.Culture)); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToString("t", Global.Culture)); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToString("t", Global.Culture)); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToString("t", Global.Culture)); tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, meeting.Id); From 47035d83861299191dea088251cd7973efff5009 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 26 Aug 2021 17:38:49 -0600 Subject: [PATCH 22/59] fix(essentials): Attempt to catch case where meeting popup may not be dismissed if the room is on and the meeting is no longer joinable --- .../EssentialsHuddleVtc1PanelAvFunctionsDriver.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 77810c6c..2d5bd1dd 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -477,6 +477,10 @@ namespace PepperDash.Essentials if (CurrentRoom.OnFeedback.BoolValue && lastMeetingDismissed == meeting) { + // meeting no longer joinable, hide popup + if(meeting == null) + HideNextMeetingPopup(); + return; } From bfd383dfc7279991426233d96a70eafdf0dd5c51 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 27 Aug 2021 09:48:43 -0600 Subject: [PATCH 23/59] fix(essentials): Minor fixes for MockVc to make behavior more consistent with real hardware --- .../VC/EssentialsVideoCodecUiDriver.cs | 12 ++++++------ .../VideoCodec/MockVC/MockVC.cs | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index f3f707c3..097ea1c1 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -127,12 +127,6 @@ namespace PepperDash.Essentials.UIDrivers.VC codec.CallStatusChange += new EventHandler(Codec_CallStatusChange); - // If the codec is ready, then get the values we want, otherwise wait - if (Codec.IsReady) - Codec_IsReady(); - else - codec.IsReadyChange += (o, a) => Codec_IsReady(); - //InCall = new BoolFeedback(() => false); LocalPrivacyIsMuted = new BoolFeedback(() => false); @@ -223,6 +217,12 @@ namespace PepperDash.Essentials.UIDrivers.VC SetupPasswordPrompt(); } + + // If the codec is ready, then get the values we want, otherwise wait + if (Codec.IsReady) + Codec_IsReady(); + else + codec.IsReadyChange += (o, a) => Codec_IsReady(); } catch (Exception e) { 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 ca199957..78302fcc 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 @@ -78,6 +78,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec SetupCameras(); + CreateOsdSource(); + SetIsReady(); } @@ -117,6 +119,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } bool _StandbyIsOn; + /// + /// Creates the fake OSD source, and connects it's AudioVideo output to the CodecOsdIn input + /// to enable routing + /// + private void CreateOsdSource() + { + OsdSource = new DummyRoutingInputsDevice(Key + "[osd]"); + DeviceManager.AddDevice(OsdSource); + var tl = new TieLine(OsdSource.AudioVideoOutputPort, CodecOsdIn); + TieLineCollection.Default.Add(tl); + + //foreach(var input in Status.Video. + } /// /// Dials, yo! @@ -567,6 +582,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec void SetupCameras() { + SupportsCameraAutoMode = true; + + SupportsCameraOff = false; + Cameras = new List(); var internalCamera = new MockVCCamera(Key + "-camera1", "Near End", this); From 532f3ba2370336349d9e6eadc62538de9ec065cc Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 27 Aug 2021 17:57:21 -0600 Subject: [PATCH 24/59] feat(essentails): #811 Adds IHasMeetingInfo, implements on ZoomRoom and updates UI drivers #812 --- .../UI/JoinConstants/UIBoolJoin.cs | 19 ++++ .../UI/JoinConstants/UIStringlJoin.cs | 17 +++ .../Essentials/EssentialsHeaderDriver.cs | 6 +- ...entialsHuddleVtc1PanelAvFunctionsDriver.cs | 64 +++++++++-- .../VC/EssentialsVideoCodecUiDriver.cs | 37 +++++- .../Essentials Devices Common.csproj | 1 + .../VideoCodec/Interfaces/IHasMeetingInfo.cs | 51 +++++++++ .../VideoCodec/Interfaces/IHasParticipants.cs | 9 ++ .../VideoCodec/Interfaces/IHasStartMeeting.cs | 5 + .../VideoCodec/ZoomRoom/ResponseObjects.cs | 52 ++++++++- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 107 +++++++++++++++++- 11 files changed, 345 insertions(+), 23 deletions(-) create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs diff --git a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs index dd454d97..d1fb6697 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs @@ -49,6 +49,15 @@ namespace PepperDash.Essentials /// 1006 /// public const uint CallEndAllConfirmVisible = 1006; + /// + /// 1007 + /// + public const uint MeetingPasswordVisible = 1007; + /// + /// 1008 + /// + public const uint MeetingLeavePress = 1008; + @@ -153,6 +162,11 @@ namespace PepperDash.Essentials public const uint VCFavoriteVisibleStart = 1221; // RANGE IN USE public const uint VCFavoriteVisibleEnd = 1225; + + /// + /// 1230 + /// + public const uint VCStagingMeetNowPress = 1230; /// /// 1231 /// @@ -844,6 +858,11 @@ namespace PepperDash.Essentials /// 15067 ///
public const uint NotificationRibbonVisible = 15067; + /// + /// 15068 + /// + public const uint HeaderMeetingInfoVisible = 15068; + /// /// 15083 - Press for Call help desk on AC/VC /// diff --git a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs index 67a5c6e2..45a2d3ea 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs @@ -27,6 +27,23 @@ namespace PepperDash.Essentials /// 1004 ///
public const uint CallSharedSourceNameText = 1004; + /// + /// 1005 + /// + public const uint MeetingIdText = 1005; + /// + /// 1006 + /// + public const uint MeetingHostText = 1006; + /// + /// 1007 + /// + public const uint MeetingPasswordText = 1007; + /// + /// 1008 + /// + public const uint MeetingNameText = 1008; + /// diff --git a/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs b/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs index 818498d7..8cff13c2 100644 --- a/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs +++ b/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs @@ -164,7 +164,7 @@ namespace PepperDash.Essentials CallCaretVisible = tempJoin + 10; TriList.SetSigFalseAction(tempJoin, () => { - avDriver.ShowActiveCallsList(); + avDriver.ShowActiveCallsListOrMeetingInfo(); if(avDriver.CurrentRoom.InCallFeedback.BoolValue) CaretInterlock.ShowInterlocked(CallCaretVisible); }); @@ -256,7 +256,7 @@ namespace PepperDash.Essentials TriList.SetSigFalseAction(UIBoolJoin.HeaderCallStatusLabelPress, () => { - avDriver.ShowActiveCallsList(); + avDriver.ShowActiveCallsListOrMeetingInfo(); if (avDriver.CurrentRoom.InCallFeedback.BoolValue) CaretInterlock.ShowInterlocked(CallCaretVisible); }); @@ -354,6 +354,8 @@ namespace PepperDash.Essentials headerPopupShown = true; else if (e.NewJoin == UIBoolJoin.HeaderActiveCallsListVisible) headerPopupShown = true; + else if (e.NewJoin == UIBoolJoin.HeaderMeetingInfoVisible) + headerPopupShown = true; else if (e.NewJoin == UIBoolJoin.HelpPageVisible) headerPopupShown = true; else if (e.NewJoin == UIBoolJoin.MeetingsOrContacMethodsListVisible) diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 2d5bd1dd..7ff0e7f5 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -14,6 +14,7 @@ using PepperDash.Essentials.Core.PageManagers; using PepperDash.Essentials.Room.Config; using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.VideoCodec; +using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; namespace PepperDash.Essentials { @@ -99,6 +100,9 @@ namespace PepperDash.Essentials /// public SubpageReferenceList MeetingOrContactMethodModalSrl { get; set; } + public uint CallListOrMeetingInfoPopoverVisibilityJoin { get; private set; } + + /// /// The list of buttons on the header. Managed with visibility only /// @@ -351,15 +355,17 @@ namespace PepperDash.Essentials /// /// Allows PopupInterlock to be toggled if the calls list is already visible, or if the codec is in a call /// - public void ShowActiveCallsList() + public void ShowActiveCallsListOrMeetingInfo() { TriList.SetBool(UIBoolJoin.CallEndAllConfirmVisible, true); - if(PopupInterlock.CurrentJoin == UIBoolJoin.HeaderActiveCallsListVisible) - PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.HeaderActiveCallsListVisible); + + + if(PopupInterlock.CurrentJoin == CallListOrMeetingInfoPopoverVisibilityJoin) + PopupInterlock.ShowInterlockedWithToggle(CallListOrMeetingInfoPopoverVisibilityJoin); else { - if((CurrentRoom.ScheduleSource as VideoCodecBase).IsInCall) - PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.HeaderActiveCallsListVisible); + if(CurrentRoom.VideoCodec.IsInCall) + PopupInterlock.ShowInterlockedWithToggle(CallListOrMeetingInfoPopoverVisibilityJoin); } } @@ -948,6 +954,18 @@ namespace PepperDash.Essentials _CurrentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingFeedback_OutputChange; _CurrentRoom.IsCoolingDownFeedback.OutputChange -= CurrentRoom_IsCoolingDownFeedback_OutputChange; _CurrentRoom.InCallFeedback.OutputChange -= CurrentRoom_InCallFeedback_OutputChange; + + var scheduleAwareCodec = _CurrentRoom.VideoCodec as IHasScheduleAwareness; + if (scheduleAwareCodec != null) + { + scheduleAwareCodec.CodecSchedule.MeetingsListHasChanged -= CodecSchedule_MeetingsListHasChanged; + } + + var meetingInfoCodec = _CurrentRoom.VideoCodec as IHasMeetingInfo; + if (meetingInfoCodec != null) + { + meetingInfoCodec.MeetingInfoChanged -= meetingInfoCodec_MeetingInfoChanged; + } } _CurrentRoom = room; @@ -980,9 +998,23 @@ namespace PepperDash.Essentials _CurrentRoom.CurrentSourceChange += CurrentRoom_SourceInfoChange; RefreshSourceInfo(); - if (_CurrentRoom.VideoCodec is IHasScheduleAwareness) + + var scheduleAwareCodec = _CurrentRoom.VideoCodec as IHasScheduleAwareness; + if (scheduleAwareCodec != null) { - (_CurrentRoom.VideoCodec as IHasScheduleAwareness).CodecSchedule.MeetingsListHasChanged += CodecSchedule_MeetingsListHasChanged; + scheduleAwareCodec.CodecSchedule.MeetingsListHasChanged += CodecSchedule_MeetingsListHasChanged; + } + + var meetingInfoCodec = _CurrentRoom.VideoCodec as IHasMeetingInfo; + if (meetingInfoCodec != null) + { + meetingInfoCodec.MeetingInfoChanged += new EventHandler(meetingInfoCodec_MeetingInfoChanged); + + CallListOrMeetingInfoPopoverVisibilityJoin = UIBoolJoin.HeaderMeetingInfoVisible; + } + else + { + CallListOrMeetingInfoPopoverVisibilityJoin = UIBoolJoin.HeaderActiveCallsListVisible; } CallSharingInfoVisibleFeedback = new BoolFeedback(() => _CurrentRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue); @@ -994,7 +1026,8 @@ namespace PepperDash.Essentials if (_CurrentRoom != null) _CurrentRoom.CurrentSourceChange += new SourceInfoChangeHandler(CurrentRoom_CurrentSingleSourceChange); - TriList.SetSigFalseAction(UIBoolJoin.CallStopSharingPress, () => _CurrentRoom.RunRouteAction("codecOsd", _CurrentRoom.SourceListKey)); + // Moved to EssentialsVideoCodecUiDriver + //TriList.SetSigFalseAction(UIBoolJoin.CallStopSharingPress, () => _CurrentRoom.RunRouteAction("codecOsd", _CurrentRoom.SourceListKey)); (Parent as EssentialsPanelMainInterfaceDriver).HeaderDriver.SetupHeaderButtons(this, CurrentRoom); } @@ -1005,6 +1038,19 @@ namespace PepperDash.Essentials } } + void meetingInfoCodec_MeetingInfoChanged(object sender, MeetingInfoEventArgs e) + { + TriList.SetString(UIStringJoin.MeetingIdText, e.Info.Id); + TriList.SetString(UIStringJoin.MeetingHostText, e.Info.Host); + TriList.SetString(UIStringJoin.MeetingNameText, e.Info.Name); + + TriList.SetString(UIStringJoin.MeetingPasswordText, e.Info.Password); + // Show the password fields if one is present + TriList.SetBool(UIBoolJoin.MeetingPasswordVisible, string.IsNullOrEmpty(e.Info.Password) ? false : true); + + TriList.SetString(UIStringJoin.CallSharedSourceNameText, e.Info.ShareStatus); + } + void SetCurrentRoom(IEssentialsHuddleVtc1Room room) { if (_CurrentRoom == room) return; @@ -1514,6 +1560,8 @@ namespace PepperDash.Essentials ///
void PrepareForCodecIncomingCall(); + uint CallListOrMeetingInfoPopoverVisibilityJoin { get; } + SubpageReferenceList MeetingOrContactMethodModalSrl { get; } } } diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index 097ea1c1..a48fc7a9 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -15,6 +15,7 @@ using PepperDash.Essentials.Core.SmartObjects; using PepperDash.Essentials.Core.Touchpanels.Keyboards; using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.VideoCodec; +using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; using PepperDash.Essentials.Devices.Common.Cameras; namespace PepperDash.Essentials.UIDrivers.VC @@ -422,8 +423,8 @@ namespace PepperDash.Essentials.UIDrivers.VC ActiveCallsSRL.Count = (ushort)activeList.Count; // If Active Calls list is visible and codec is not in a call, hide the list - if (!Codec.IsInCall && Parent.PopupInterlock.CurrentJoin == UIBoolJoin.HeaderActiveCallsListVisible) - Parent.PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.HeaderActiveCallsListVisible); + if (!Codec.IsInCall && Parent.PopupInterlock.CurrentJoin == Parent.CallListOrMeetingInfoPopoverVisibilityJoin) + Parent.PopupInterlock.ShowInterlockedWithToggle(Parent.CallListOrMeetingInfoPopoverVisibilityJoin); } /// @@ -514,15 +515,19 @@ namespace PepperDash.Essentials.UIDrivers.VC TriList.SetSigFalseAction(UIBoolJoin.VCStagingRecentsPress, ShowRecents); TriList.SetSigFalseAction(UIBoolJoin.VCStagingCameraPress, ShowCameraControls); TriList.SetSigFalseAction(UIBoolJoin.VCStagingConnectPress, ConnectPress); + TriList.SetSigFalseAction(UIBoolJoin.VCStagingMeetNowPress, MeetNowPress); + TriList.SetSigFalseAction(UIBoolJoin.CallStopSharingPress, CallStopSharingPress); + TriList.SetSigFalseAction(UIBoolJoin.CallEndPress, () => { if (Codec.ActiveCalls.Count > 1) { - Parent.PopupInterlock.ShowInterlocked(UIBoolJoin.HeaderActiveCallsListVisible); + Parent.PopupInterlock.ShowInterlocked(Parent.CallListOrMeetingInfoPopoverVisibilityJoin); } else Codec.EndAllCalls(); }); + TriList.SetSigFalseAction(UIBoolJoin.CallEndAllConfirmPress, () => { Parent.PopupInterlock.HideAndClear(); @@ -1566,6 +1571,22 @@ namespace PepperDash.Essentials.UIDrivers.VC StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingRecentsPress); } + /// + /// Meet Now button + /// + void MeetNowPress() + { + var startMeetingCodec = Codec as IHasStartMeeting; + if (startMeetingCodec != null) + { + startMeetingCodec.StartMeeting(startMeetingCodec.DefaultMeetingDurationMin); + } + else + { + Debug.Console(2, "Codce does not implment IHasStartMeeting. Cannot meet now"); + } + } + /// /// Connect call button /// @@ -1576,6 +1597,16 @@ namespace PepperDash.Essentials.UIDrivers.VC Codec.Dial(DialStringBuilder.ToString()); } + /// + /// Stop Sharing button + /// + void CallStopSharingPress() + { + Codec.StopSharing(); + Parent.CurrentRoom.RunRouteAction("codecOsd", Parent.CurrentRoom.SourceListKey); + } + + /// /// /// 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 75d01b0f..cff1e4c0 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/IHasMeetingInfo.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs new file mode 100644 index 00000000..46a10b99 --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + /// + /// Describes a device that provides meeting information (like a ZoomRoom) + /// + public interface IHasMeetingInfo + { + event EventHandler MeetingInfoChanged; + + MeetingInfo MeetingInfo { get; } + } + + /// + /// Represents the information about a meeting in progress + /// Currently used for Zoom meetings + /// + public class MeetingInfo + { + public string Id { get; private set; } + public string Name { get; private set; } + public string Host { get; set; } + public string Password { get; private set; } + public string ShareStatus { get; private set; } + + public MeetingInfo(string id, string name, string host, string password, string shareStatus) + { + Id = id; + Name = name; + Host = host; + Password = password; + ShareStatus = shareStatus; + } + } + + public class MeetingInfoEventArgs : EventArgs + { + public MeetingInfo Info { get; private set; } + + public MeetingInfoEventArgs(MeetingInfo info) + { + Info = info; + } + + } +} \ No newline at end of file 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 index d8c0c55c..46b1391b 100644 --- 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 @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Collections.Generic; using PepperDash.Core; using PepperDash.Essentials.Core; @@ -60,6 +61,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces } } + public Participant Host + { + get + { + return _currentParticipants.FirstOrDefault(p => p.IsHost); + } + } + public event EventHandler ParticipantsListHasChanged; public CodecParticipants() diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStartMeeting.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStartMeeting.cs index a01ec099..6af59534 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStartMeeting.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStartMeeting.cs @@ -21,5 +21,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces /// /// void StartMeeting(uint duration); + + /// + /// Leaves a meeting without ending it + /// + void LeaveMeeting(); } } \ No newline at end of file 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 28073eb8..c42d7eee 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 @@ -431,6 +431,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { private string _dispState; private string _password; + private bool _isAirHostClientConnected; + private bool _isSharingBlackMagic; + private bool _isDirectPresentationConnected; + public string directPresentationPairingCode { get; set; } /// @@ -452,11 +456,51 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } } - public bool isAirHostClientConnected { get; set; } + + public bool isAirHostClientConnected + { + get { return _isAirHostClientConnected; } + set + { + if (value != _isAirHostClientConnected) + { + _isAirHostClientConnected = value; + NotifyPropertyChanged("isAirHostClientConnected"); + } + } + } + public bool isBlackMagicConnected { get; set; } public bool isBlackMagicDataAvailable { get; set; } - public bool isDirectPresentationConnected { get; set; } - public bool isSharingBlackMagic { get; set; } + + public bool isDirectPresentationConnected + { + get { return _isDirectPresentationConnected; } + set + { + if (value != _isDirectPresentationConnected) + { + _isDirectPresentationConnected = value; + NotifyPropertyChanged("isDirectPresentationConnected"); + } + } + } + + public bool isSharingBlackMagic + { + get { return _isSharingBlackMagic; } + set + { + if (value != _isSharingBlackMagic) + { + _isSharingBlackMagic = value; + NotifyPropertyChanged("isSharingBlackMagic"); + } + } + } + + + /// /// IOS Airplay code /// @@ -779,7 +823,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private bool _paused; private eSharingState _state; - public bool IsSharing; + public bool IsSharing { get; private set; } [JsonProperty("paused")] public bool Paused 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 83597081..0a12e25f 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 @@ -25,7 +25,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom IRouting, IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, - IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting + IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo { private const long MeetingRefreshTimer = 60000; public uint DefaultMeetingDurationMin { get; private set; } @@ -470,6 +470,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { SharingContentIsOnFeedback.FireUpdate(); ReceivingContent.FireUpdate(); + + // Update the share status of the meeting info + var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, GetSharingStatus()); + MeetingInfo = meetingInfo; } }; @@ -618,6 +622,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom break; case "password": break; + case "isAirHostClientConnected": + case "isDirectPresentationConnected": + case "isSharingBlackMagic": + { + // Update the share status of the meeting info + var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, GetSharingStatus()); + MeetingInfo = meetingInfo; + break; + } } }; @@ -957,9 +970,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { _syncState.LoginMessageReceived(); + // Fire up a thread to send the intial commands. CrestronInvoke.BeginInvoke(o => { + // Currently the feedback exclusions don't work when using the API in JSON response mode + // But leave these here in case the API gets updated in the future + + Thread.Sleep(100); // disable echo of commands SendText("echo off"); @@ -1179,6 +1197,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Status.Call.Participants); Participants.CurrentParticipants = participants; + + // Update the share status of the meeting info + var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, MeetingInfo.ShareStatus); + MeetingInfo = meetingInfo; + PrintCurrentCallParticipants(); break; @@ -1642,7 +1665,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // If not crrently in a meeting, intialize the call object if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING) { - Debug.Console(1, this, "[UpdateCallStatus] Creating new Status.Call object"); + //Debug.Console(1, this, "[UpdateCallStatus] Creating new Status.Call object"); Status.Call = new zStatus.Call {Status = callStatus}; OnCallStatusChange(new CodecActiveCallItem() {Status = eCodecCallStatus.Disconnected}); @@ -1680,15 +1703,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom ActiveCalls.Add(newCall); - Debug.Console(1, this, "[UpdateCallStatus] IF w/ meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}", - Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); + //Debug.Console(1, this, "[UpdateCallStatus] IF w/ meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}", + //Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); OnCallStatusChange(newCall); } else { - Debug.Console(1, this, "[UpdateCallStatus] IF w/o meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}", - Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); + //Debug.Console(1, this, "[UpdateCallStatus] IF w/o meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}", + //Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); } } } @@ -1748,6 +1771,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { base.OnCallStatusChange(item); + if (item.Status == eCodecCallStatus.Connected) + { + + var host = ""; + + if (Participants.Host != null) + host = Participants.Host.Name; + + MeetingInfo = new MeetingInfo( + Status.Call.Info.meeting_id, + Status.Call.Info.meeting_list_item.meetingName, + host, + Status.Call.Info.meeting_password, + GetSharingStatus() + ); + } + Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}", Status.Call != null ? Status.Call.Status.ToString() : "no call"); @@ -1757,6 +1797,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } + private string GetSharingStatus() + { + string sharingState = "None"; + + if (Status.Call.Sharing.State == zEvent.eSharingState.Receiving) + { + sharingState = "Receiving Content"; + } + if (Status.Sharing.isAirHostClientConnected) + { + sharingState = "Sharing AirPlay"; + } + if (Status.Sharing.isDirectPresentationConnected) + { + sharingState = "Sharing Laptop"; + } + if (Status.Sharing.isSharingBlackMagic) + { + sharingState = "Sharing HDMI Source"; + } + + return sharingState; + } + public override void StartSharing() { SendText("zCommand Call Sharing HDMI Start"); @@ -2113,6 +2177,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SendText(string.Format("zCommand Dial StartPmi Duration: {0}", dur)); } + public void LeaveMeeting() + { + SendText("zCommand Call Leave"); + } + public override void EndCall(CodecActiveCallItem call) { SendText("zCommand Call Disconnect"); @@ -2737,6 +2806,32 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } #endregion + + #region IHasMeetingInfo Members + + public event EventHandler MeetingInfoChanged; + + private MeetingInfo _meetingInfo; + + public MeetingInfo MeetingInfo + { + get { return _meetingInfo; } + private set + { + if (value != _meetingInfo) + { + _meetingInfo = value; + + var handler = MeetingInfoChanged; + if (handler != null) + { + handler(this, new MeetingInfoEventArgs(_meetingInfo)); + } + } + } + } + + #endregion } /// From 0a1af098308d6921ded9fe174be7eecda94e08dd Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 30 Aug 2021 12:07:09 -0600 Subject: [PATCH 25/59] fix(essentials): Disables dial feedback phone formatting if codec is IHasStartMeeting --- .../UIDrivers/VC/EssentialsVideoCodecUiDriver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index a48fc7a9..326ea1f5 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -152,7 +152,7 @@ namespace PepperDash.Essentials.UIDrivers.VC // Return formatted when dialing, straight digits when in call DialStringFeedback = new StringFeedback(() => { - if (KeypadMode == eKeypadMode.Dial) + if (KeypadMode == eKeypadMode.Dial && !(Codec is IHasStartMeeting)) return GetFormattedDialString(DialStringBuilder.ToString()); else return DialStringBuilder.ToString(); From 3edb0145d0d61f025a6ce8218a5b13213344bfc7 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 30 Aug 2021 15:00:13 -0600 Subject: [PATCH 26/59] fix(essentials): Adds JsonProperty attributes to MeetingInfo properties for serialization --- .../VideoCodec/Interfaces/IHasMeetingInfo.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs index 46a10b99..4f1744b9 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Text; using Crestron.SimplSharp; +using Newtonsoft.Json; + namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces { /// @@ -22,10 +24,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces /// public class MeetingInfo { + [JsonProperty("id")] public string Id { get; private set; } + [JsonProperty("name")] public string Name { get; private set; } + [JsonProperty("host")] public string Host { get; set; } + [JsonProperty("password")] public string Password { get; private set; } + [JsonProperty("shareStatus")] public string ShareStatus { get; private set; } public MeetingInfo(string id, string name, string host, string password, string shareStatus) From 8af7b4b1dba6ec064dbd5415fa35ffdeaba752bb Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 30 Aug 2021 17:48:37 -0600 Subject: [PATCH 27/59] feat(essentials): Adds IsHost property to MeetingInfo to determine if the room is the host --- .../VC/EssentialsVideoCodecUiDriver.cs | 1 + .../VideoCodec/Interfaces/IHasMeetingInfo.cs | 5 +++- .../VideoCodec/Interfaces/IHasParticipants.cs | 1 + .../VideoCodec/ZoomRoom/ResponseObjects.cs | 1 + .../VideoCodec/ZoomRoom/ZoomRoom.cs | 26 ++++++++++++++++--- 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index 326ea1f5..ac0611d6 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -152,6 +152,7 @@ namespace PepperDash.Essentials.UIDrivers.VC // Return formatted when dialing, straight digits when in call DialStringFeedback = new StringFeedback(() => { + // Format the number feedback if in dial mode and the codec is not IHasStartMeeting (ZoomRoom) if (KeypadMode == eKeypadMode.Dial && !(Codec is IHasStartMeeting)) return GetFormattedDialString(DialStringBuilder.ToString()); else diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs index 4f1744b9..b49733ad 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs @@ -34,14 +34,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces public string Password { get; private set; } [JsonProperty("shareStatus")] public string ShareStatus { get; private set; } + [JsonProperty("isHost")] + public Boolean IsHost { get; private set; } - public MeetingInfo(string id, string name, string host, string password, string shareStatus) + public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost) { Id = id; Name = name; Host = host; Password = password; ShareStatus = shareStatus; + IsHost = IsHost; } } 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 index 46b1391b..409ccd89 100644 --- 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 @@ -93,6 +93,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces { public int UserId { get; set; } public bool IsHost { get; set; } + public bool IsMyself { get; set; } public string Name { get; set; } public bool CanMuteVideo { get; set; } public bool CanUnmuteVideo { get; set; } 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 c42d7eee..aac45f51 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 @@ -1489,6 +1489,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom UserId = p.UserId, Name = p.UserName, IsHost = p.IsHost, + IsMyself = p.IsMyself, CanMuteVideo = p.IsVideoCanMuteByHost, CanUnmuteVideo = p.IsVideoCanUnmuteByHost, AudioMuteFb = p.AudioStatusState == "AUDIO_MUTED", 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 0a12e25f..a51555df 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 @@ -472,7 +472,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom ReceivingContent.FireUpdate(); // Update the share status of the meeting info - var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, GetSharingStatus()); + var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself()); MeetingInfo = meetingInfo; } }; @@ -627,7 +627,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom case "isSharingBlackMagic": { // Update the share status of the meeting info - var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, GetSharingStatus()); + var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself()); MeetingInfo = meetingInfo; break; } @@ -1199,7 +1199,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Participants.CurrentParticipants = participants; // Update the share status of the meeting info - var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, MeetingInfo.ShareStatus); + var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, MeetingInfo.ShareStatus, GetIsHostMyself()); MeetingInfo = meetingInfo; PrintCurrentCallParticipants(); @@ -1784,7 +1784,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Status.Call.Info.meeting_list_item.meetingName, host, Status.Call.Info.meeting_password, - GetSharingStatus() + GetSharingStatus(), + GetIsHostMyself() ); } @@ -1821,6 +1822,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom return sharingState; } + /// + /// Will return true if the host is myself (this zoom room) + /// + /// + private bool GetIsHostMyself() + { + var host = Participants.Host; + + if(host == null) + { + Debug.Console(2, this, "Host is currently null"); + return false; + } + Debug.Console(2, this, "Host is: {0} myself?: {1}", host.Name, host.IsMyself); + return host.IsMyself; + } + public override void StartSharing() { SendText("zCommand Call Sharing HDMI Start"); From a54cd9e1df3685f786dba017c27e89afdf04793a Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 31 Aug 2021 10:13:56 -0600 Subject: [PATCH 28/59] feat(essentials): minor syntax updates --- .../VideoCodec/Interfaces/IHasMeetingInfo.cs | 2 +- .../Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs index b49733ad..a2d08a34 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs @@ -29,7 +29,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces [JsonProperty("name")] public string Name { get; private set; } [JsonProperty("host")] - public string Host { get; set; } + public string Host { get; private set; } [JsonProperty("password")] public string Password { get; private set; } [JsonProperty("shareStatus")] 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 a51555df..379b1621 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 @@ -1835,7 +1835,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(2, this, "Host is currently null"); return false; } - Debug.Console(2, this, "Host is: {0} myself?: {1}", host.Name, host.IsMyself); + Debug.Console(2, this, "Host is: '{0}' IsMyself?: {1}", host.Name, host.IsMyself); return host.IsMyself; } From adec25104cb40202df9f75c459254f3389f51ab0 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 31 Aug 2021 16:40:04 -0600 Subject: [PATCH 29/59] feat(essentials): Updates to UI to deal with sharing feedback with no external sources. Adds End/Leave meeting button logic on meeting info subpage --- .../UI/JoinConstants/UIBoolJoin.cs | 9 +++---- .../UI/JoinConstants/UIStringlJoin.cs | 7 +++++- ...entialsHuddleVtc1PanelAvFunctionsDriver.cs | 24 +++++++++++++++++-- .../VC/EssentialsVideoCodecUiDriver.cs | 22 +++++++++++++++++ .../VideoCodec/Interfaces/IHasMeetingInfo.cs | 2 +- 5 files changed, 56 insertions(+), 8 deletions(-) diff --git a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs index d1fb6697..1a127000 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs @@ -61,6 +61,7 @@ namespace PepperDash.Essentials + // Audio Conference /// /// 1101 @@ -766,10 +767,10 @@ namespace PepperDash.Essentials /// 15044 Close button for source modal overlay /// public const uint SourceBackgroundOverlayClosePress = 15044; - ///// - ///// 15045 - Visibility for the bar containing call navigation button list - ///// - //public const uint CallStagingBarVisible = 15045; + /// + /// 15045 + /// + public const uint ZoomRoomContentSharingVisible = 15045; /// /// 15046 /// diff --git a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs index 45a2d3ea..38a86fbb 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs @@ -42,7 +42,12 @@ namespace PepperDash.Essentials /// /// 1008 /// - public const uint MeetingNameText = 1008; + public const uint MeetingLeaveText = 1008; + /// + /// 1009 + /// + public const uint MeetingNameText = 1009; + diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 7ff0e7f5..3eb78613 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -181,6 +181,8 @@ namespace PepperDash.Essentials private UiDisplayMode _currentMode; + private uint _sourceListCount; + /// /// The mode showing. Presentation or call. /// @@ -647,9 +649,24 @@ namespace PepperDash.Essentials TriList.SetBool(StartPageVisibleJoin, startMode ? true : false); - TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, presentationMode ? true : false); + if (presentationMode && CurrentRoom.VideoCodec is IHasMeetingInfo && _sourceListCount < 2) + { + // For now, if this is a Zoom Room and there are no shareable sources just display the informational subpage + TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, false); + TriList.SetBool(UIBoolJoin.ZoomRoomContentSharingVisible, true); + } + else + { + // Otherwise, show the staging bar + TriList.SetBool(UIBoolJoin.ZoomRoomContentSharingVisible, false); + TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, presentationMode ? true : false); + + } if (!presentationMode) + { + TriList.SetBool(UIBoolJoin.ZoomRoomContentSharingVisible, false); TriList.SetBool(UIBoolJoin.SelectASourceVisible, false); + } CallButtonSig.BoolValue = callMode && CurrentRoom.ShutdownType == eShutdownType.None; @@ -1049,6 +1066,8 @@ namespace PepperDash.Essentials TriList.SetBool(UIBoolJoin.MeetingPasswordVisible, string.IsNullOrEmpty(e.Info.Password) ? false : true); TriList.SetString(UIStringJoin.CallSharedSourceNameText, e.Info.ShareStatus); + + TriList.SetString(UIStringJoin.MeetingLeaveText, e.Info.IsHost ? "End Meeting" : "Leave Meeting"); } void SetCurrentRoom(IEssentialsHuddleVtc1Room room) @@ -1164,7 +1183,8 @@ namespace PepperDash.Essentials Debug.Console(1, "**** KEY {0}", kvp.Key); } - SourceStagingSrl.Count = (ushort)(i - 1); + _sourceListCount = (i - 1); + SourceStagingSrl.Count = (ushort)_sourceListCount; } } diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index ac0611d6..7ec44346 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -534,6 +534,28 @@ namespace PepperDash.Essentials.UIDrivers.VC Parent.PopupInterlock.HideAndClear(); Codec.EndAllCalls(); }); + + var meetingInfoCodec = Codec as IHasMeetingInfo; + if (meetingInfoCodec != null) + { + TriList.SetSigFalseAction(UIBoolJoin.MeetingLeavePress, () => + { + Parent.PopupInterlock.HideAndClear(); + + if (meetingInfoCodec.MeetingInfo.IsHost) + { + Codec.EndAllCalls(); + } + else + { + var startMeetingCodec = Codec as IHasStartMeeting; + if (startMeetingCodec != null) + { + startMeetingCodec.LeaveMeeting(); + } + } + }); + } } void SetupCameraControls() diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs index a2d08a34..236fde80 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs @@ -44,7 +44,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces Host = host; Password = password; ShareStatus = shareStatus; - IsHost = IsHost; + IsHost = isHost; } } From 8539a6b79c3c0d60689c3c6a1249f25311631d67 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 31 Aug 2021 18:18:24 -0600 Subject: [PATCH 30/59] fix(essentials): minor fixes to UI oddities --- ...entialsHuddleVtc1PanelAvFunctionsDriver.cs | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 3eb78613..09443d45 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -181,6 +181,14 @@ namespace PepperDash.Essentials private UiDisplayMode _currentMode; + private bool _isZoomRoomWithNoExternalSources + { + get + { + return CurrentRoom.VideoCodec is Essentials.Devices.Common.VideoCodec.ZoomRoom.ZoomRoom && _sourceListCount <= 1; + } + } + private uint _sourceListCount; /// @@ -649,7 +657,7 @@ namespace PepperDash.Essentials TriList.SetBool(StartPageVisibleJoin, startMode ? true : false); - if (presentationMode && CurrentRoom.VideoCodec is IHasMeetingInfo && _sourceListCount < 2) + if (presentationMode &&_isZoomRoomWithNoExternalSources) { // For now, if this is a Zoom Room and there are no shareable sources just display the informational subpage TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, false); @@ -704,25 +712,39 @@ namespace PepperDash.Essentials if (VCDriver.IsVisible) VCDriver.Hide(); HideNextMeetingPopup(); - // Run default source when room is off and share is pressed - if (!CurrentRoom.OnFeedback.BoolValue) - { - // If there's no default, show UI elements - if (!(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute()) - TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); - } - else // room is on show what's active or select a source if nothing is yet active + + + if (_isZoomRoomWithNoExternalSources) { - if(CurrentRoom.CurrentSourceInfo == null || (CurrentRoom.VideoCodec != null && CurrentRoom.CurrentSourceInfo.SourceDevice.Key == CurrentRoom.VideoCodec.OsdSource.Key)) - TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); - else if (CurrentSourcePageManager != null) + (CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute(); + // For now, if this is a Zoom Room and there are no shareable sources just display the informational subpage + TriList.SetBool(UIBoolJoin.ZoomRoomContentSharingVisible, true); + + if (CurrentSourcePageManager != null) + CurrentSourcePageManager.Hide(); + } + else + { + // Run default source when room is off and share is pressed + if (!CurrentRoom.OnFeedback.BoolValue) { - TriList.SetBool(UIBoolJoin.SelectASourceVisible, false); - CurrentSourcePageManager.Show(); + // If there's no default, show UI elements + if (!(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute()) + TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); } + else // room is on show what's active or select a source if nothing is yet active + { + if (CurrentRoom.CurrentSourceInfo == null || (CurrentRoom.VideoCodec != null && CurrentRoom.CurrentSourceInfo.SourceDevice.Key == CurrentRoom.VideoCodec.OsdSource.Key)) + TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); + else if (CurrentSourcePageManager != null) + { + TriList.SetBool(UIBoolJoin.SelectASourceVisible, false); + CurrentSourcePageManager.Show(); + } + } + SetupSourceList(); } CurrentMode = UiDisplayMode.Presentation; - SetupSourceList(); } /// @@ -761,7 +783,7 @@ namespace PepperDash.Essentials /// void ShowCurrentSource() { - if (CurrentRoom.CurrentSourceInfo == null) + if (CurrentRoom.CurrentSourceInfo == null || _isZoomRoomWithNoExternalSources) return; CurrentMode = UiDisplayMode.Presentation; From 9a1b069e2400a84e43560f0023a703fadc06f71d Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Thu, 2 Sep 2021 08:21:37 -0500 Subject: [PATCH 31/59] feat: Added debug statements to sensor set and sensitivity methods. fix: Replaced SetSigTrueAction and SetSigFalseAction calling SetEnable state with a single SetBoolSigAction. --- .../PartitionSensor/GlsPartitionSensorController.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorController.cs index b0b58f34..bd67dfec 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorController.cs @@ -126,6 +126,7 @@ namespace PepperDash.Essentials.Core public void SetEnableState(bool state) { + Debug.Console(2, this, "Sensor is {0}, SetEnableState: {1}", _partitionSensor == null ? "null" : "not null", state); if (_partitionSensor == null) return; @@ -134,6 +135,7 @@ namespace PepperDash.Essentials.Core public void IncreaseSensitivity() { + Debug.Console(2, this, "Sensor is {0}, IncreaseSensitivity", _partitionSensor == null ? "null" : "not null"); if (_partitionSensor == null) return; @@ -142,6 +144,7 @@ namespace PepperDash.Essentials.Core public void DecreaseSensitivity() { + Debug.Console(2, this, "Sensor is {0}, DecreaseSensitivity", _partitionSensor == null ? "null" : "not null"); if (_partitionSensor == null) return; @@ -150,6 +153,7 @@ namespace PepperDash.Essentials.Core public void SetSensitivity(ushort value) { + Debug.Console(2, this, "Sensor is {0}, SetSensitivity: {1}", _partitionSensor == null ? "null" : "not null", value); if (_partitionSensor == null) return; @@ -177,8 +181,7 @@ namespace PepperDash.Essentials.Core Debug.Console(0, this, "Linking to Bridge Type {0}", GetType().Name); // link input from simpl - trilist.SetSigTrueAction(joinMap.Enable.JoinNumber, () => SetEnableState(true)); - trilist.SetSigFalseAction(joinMap.Enable.JoinNumber, () => SetEnableState(false)); + trilist.SetBoolSigAction(joinMap.Enable.JoinNumber, SetEnableState); trilist.SetSigTrueAction(joinMap.IncreaseSensitivity.JoinNumber, IncreaseSensitivity); trilist.SetSigTrueAction(joinMap.DecreaseSensitivity.JoinNumber, DecreaseSensitivity); trilist.SetUShortSigAction(joinMap.Sensitivity.JoinNumber, SetSensitivity); From 9b64b7b7f38bb88e5b1b91edeb194bb5f8542f21 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 7 Sep 2021 11:40:27 -0600 Subject: [PATCH 32/59] fix:(Essentials) Created MeetingInfo Object if it didn't previously exist --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 379b1621..d146ec4e 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 @@ -626,6 +626,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom case "isDirectPresentationConnected": case "isSharingBlackMagic": { + Debug.Console(2, this, "Updating sharing status: {0}", a.PropertyName); + + if (MeetingInfo == null) + { + MeetingInfo = new MeetingInfo("", "", "", "", + GetSharingStatus(), GetIsHostMyself()); + } // Update the share status of the meeting info var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself()); MeetingInfo = meetingInfo; @@ -1828,6 +1835,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// private bool GetIsHostMyself() { + if (Participants.CurrentParticipants.Count == 0) + { + Debug.Console(2, this, "No current participants"); + return false; + } + var host = Participants.Host; if(host == null) From d50027cc826d41f71a606262f5d625e14af00353 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 7 Sep 2021 17:33:53 -0600 Subject: [PATCH 33/59] feat:(Essentials) Add IHasPresentationOnlyMeeting interface --- .../Essentials Devices Common.csproj | 1 + .../Interfaces/IHasPresentationOnlyMeeting.cs | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs 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 cff1e4c0..fc5f68d4 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 @@ -122,6 +122,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs new file mode 100644 index 00000000..06730d2a --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs @@ -0,0 +1,18 @@ +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + public interface IHasPresentationOnlyMeeting + { + void StartSharingOnlyMeeting(); + void StartSharingOnlyMeeting(eSharingMeetingMode mode); + void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration); + void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration, string password); + void StartNormalMeetingFromSharingOnlyMeeting(); + } + + public enum eSharingMeetingMode + { + None, + Laptop, + Ios, + } +} \ No newline at end of file From c255ae1525056acfcc4534baf5dc04239d61a631 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 7 Sep 2021 18:11:14 -0600 Subject: [PATCH 34/59] feat:(Essentials) Add IsSharingMeeting property --- .../VideoCodec/Interfaces/IHasMeetingInfo.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs index 236fde80..cd9e2906 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs @@ -36,8 +36,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces public string ShareStatus { get; private set; } [JsonProperty("isHost")] public Boolean IsHost { get; private set; } + [JsonProperty("isSharingMeeting")] + public Boolean IsSharingMeeting { get; private set; } - public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost) + public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting) { Id = id; Name = name; @@ -45,6 +47,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces Password = password; ShareStatus = shareStatus; IsHost = isHost; + IsSharingMeeting = isSharingMeeting; } } From 2d0dcd7336697fdc9eeec2a0466abe468fadeee1 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 7 Sep 2021 18:11:48 -0600 Subject: [PATCH 35/59] feat:(Essentials) Add StartLocalPresentMeeting class --- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 4 ++++ 1 file changed, 4 insertions(+) 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 aac45f51..35b6c3b2 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,6 +756,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// public class zEvent { + public class StartLocalPresentMeeting + { + public bool Success { get; set; } + } public class NeedWaitForHost { public bool Wait { get; set; } From 44509dc5ae564ec96973f5a444b784db112818c2 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 7 Sep 2021 18:12:13 -0600 Subject: [PATCH 36/59] feat:(Essentials) Add IsSharingMeeting setting to MeetingInfo --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 64 ++++++++++++++++--- 1 file changed, 54 insertions(+), 10 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 d146ec4e..a426193b 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 @@ -25,7 +25,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom IRouting, IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, - IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo + IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting { private const long MeetingRefreshTimer = 60000; public uint DefaultMeetingDurationMin { get; private set; } @@ -472,7 +472,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom ReceivingContent.FireUpdate(); // Update the share status of the meeting info - var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself()); + var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting); MeetingInfo = meetingInfo; } }; @@ -630,11 +630,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (MeetingInfo == null) { - MeetingInfo = new MeetingInfo("", "", "", "", - GetSharingStatus(), GetIsHostMyself()); + //Ignoring for now, as the CallInfo return will create the appropriate value + return; } // Update the share status of the meeting info - var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself()); + var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting); MeetingInfo = meetingInfo; break; } @@ -1206,7 +1206,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Participants.CurrentParticipants = participants; // Update the share status of the meeting info - var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, MeetingInfo.ShareStatus, GetIsHostMyself()); + var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, MeetingInfo.ShareStatus, GetIsHostMyself(), MeetingInfo.IsSharingMeeting); MeetingInfo = meetingInfo; PrintCurrentCallParticipants(); @@ -1485,6 +1485,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom break; } + case "startlocalpresentmeeting": + { + var result = JsonConvert.DeserializeObject(responseObj.ToString()); + + if (result.Success) + { + MeetingInfo = new MeetingInfo("", "", "", "", "", true, true); + break; + } + + break; + } default: { break; @@ -1776,8 +1788,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom protected override void OnCallStatusChange(CodecActiveCallItem item) { - base.OnCallStatusChange(item); - if (item.Status == eCodecCallStatus.Connected) { @@ -1792,10 +1802,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom host, Status.Call.Info.meeting_password, GetSharingStatus(), - GetIsHostMyself() + GetIsHostMyself(), + !String.Equals(Status.Call.Info.meeting_type,"NORMAL") ); } + base.OnCallStatusChange(item); + Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}", Status.Call != null ? Status.Call.Status.ToString() : "no call"); @@ -2153,6 +2166,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void Dial(string number) { + Debug.Console(2, this, "Dialing number: {0}", number); _lastDialedMeetingNumber = number; SendText(string.Format("zCommand Dial Join meetingNumber: {0}", number)); } @@ -2863,7 +2877,37 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } #endregion - } + + #region Implementation of IHasPresentationOnlyMeeting + + public void StartSharingOnlyMeeting() + { + StartSharingOnlyMeeting(eSharingMeetingMode.None, 30, String.Empty); + } + + public void StartSharingOnlyMeeting(eSharingMeetingMode mode) + { + StartSharingOnlyMeeting(mode, 30, String.Empty); + } + + public void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration) + { + StartSharingOnlyMeeting(mode, duration, String.Empty); + } + + public void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration, string password) + { + SendText(String.Format("zCommand Dial Sharing Duration: {0} DisplayState: {1} Password: {2}", duration, mode, password)); + } + + public void StartNormalMeetingFromSharingOnlyMeeting() + { + Debug.Console(2, this, "Converting Sharing Meeting to Normal Meeting"); + SendText("zCommand call sharing ToNormal"); + } + + #endregion + } /// /// Zoom Room specific info object From f791feb848a17ac5cbbd38a82d35e8e7b62f5215 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 7 Sep 2021 18:12:52 -0600 Subject: [PATCH 37/59] feat:(Essentials) Update UI functionality depending on Zoom Meeting type --- .../Essentials/EssentialsHeaderDriver.cs | 12 +++- ...entialsHuddleVtc1PanelAvFunctionsDriver.cs | 9 ++- .../VC/EssentialsVideoCodecUiDriver.cs | 56 ++++++++++++++++--- 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs b/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs index 8cff13c2..f42b9de2 100644 --- a/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs +++ b/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs @@ -12,6 +12,7 @@ using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.SmartObjects; using PepperDash.Essentials.Core.PageManagers; +using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; using PepperDash.Essentials.Room.Config; using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.VideoCodec; @@ -191,6 +192,8 @@ namespace PepperDash.Essentials return; } + var meetingInfoCodec = codec as IHasMeetingInfo; + // Set mode of header button if (!codec.IsInCall) { @@ -210,8 +213,15 @@ namespace PepperDash.Essentials Debug.Console(1, "Active Call Count: {0}", codec.ActiveCalls.Count); if (codec.ActiveCalls.Count > 0) { - if (codec.ActiveCalls.Count == 1) + if (codec.ActiveCalls.Count == 1 && meetingInfoCodec == null) TriList.SetString(UIStringJoin.HeaderCallStatusLabel, "1 Active Call"); + else if (codec.ActiveCalls.Count == 1 && meetingInfoCodec != null) + { + var headerCallStatusLabel = meetingInfoCodec.MeetingInfo.IsSharingMeeting + ? "Sharing Active" + : "Active Meeting"; + TriList.SetString(UIStringJoin.HeaderCallStatusLabel, headerCallStatusLabel); + } else if (codec.ActiveCalls.Count > 1) TriList.SetString(UIStringJoin.HeaderCallStatusLabel, string.Format("{0} Active Calls", codec.ActiveCalls.Count)); } diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 09443d45..246573a9 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -716,10 +716,17 @@ namespace PepperDash.Essentials if (_isZoomRoomWithNoExternalSources) { - (CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute(); + CurrentRoom.RunDefaultPresentRoute(); // For now, if this is a Zoom Room and there are no shareable sources just display the informational subpage TriList.SetBool(UIBoolJoin.ZoomRoomContentSharingVisible, true); + var presentationMeetingCodec = CurrentRoom.VideoCodec as IHasPresentationOnlyMeeting; + + if (presentationMeetingCodec != null && !CurrentRoom.VideoCodec.IsInCall) + { + presentationMeetingCodec.StartSharingOnlyMeeting(eSharingMeetingMode.Laptop); + } + if (CurrentSourcePageManager != null) CurrentSourcePageManager.Hide(); } diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index 7ec44346..9bbaad6f 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -134,11 +134,12 @@ namespace PepperDash.Essentials.UIDrivers.VC VCControlsInterlock = new JoinedSigInterlock(triList); VCCameraControlModeInterlock = new JoinedSigInterlock(triList); + VCControlsInterlock.HideAndClear(); - if (CodecHasFavorites) + /* if (CodecHasFavorites || codec is IHasZoomRoomLayouts) //Checking for Zoom Room...picked a ZoomRoom specific interface to check for VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadWithFavoritesVisible); else - VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadVisible); + VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadVisible); */ StagingBarsInterlock = new JoinedSigInterlock(triList); if(Codec is IHasCallHistory) @@ -320,6 +321,7 @@ namespace PepperDash.Essentials.UIDrivers.VC void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) { var call = e.CallItem; + var meetingInfoSender = sender as IHasMeetingInfo; switch (e.CallItem.Status) { @@ -354,7 +356,10 @@ namespace PepperDash.Essentials.UIDrivers.VC DialStringBuilder.Remove(0, DialStringBuilder.Length); DialStringFeedback.FireUpdate(); Parent.ShowNotificationRibbon("Disconnected", 2000); + Debug.Console(0, "Setting Connect Button mode to 0"); } + + break; case eCodecCallStatus.Disconnecting: break; @@ -375,12 +380,23 @@ namespace PepperDash.Essentials.UIDrivers.VC ShowIncomingModal(call); break; } - default: - break; } - TriList.UShortInput[UIUshortJoin.VCStagingConnectButtonMode].UShortValue = (ushort)(Codec.IsInCall ? 1 : 0); - - uint stageJoin; + + if (meetingInfoSender != null && Codec.IsInCall) + { + var meetingInfo = meetingInfoSender.MeetingInfo; + + TriList.UShortInput[UIUshortJoin.VCStagingConnectButtonMode].UShortValue = + (ushort) (meetingInfo.IsSharingMeeting ? 2 : 1); + } + else + { + + TriList.UShortInput[UIUshortJoin.VCStagingConnectButtonMode].UShortValue = + (ushort) (Codec.IsInCall ? 1 : 0); + } + + uint stageJoin; if (Codec.IsInCall) stageJoin = UIBoolJoin.VCStagingActivePopoverVisible; else @@ -519,14 +535,35 @@ namespace PepperDash.Essentials.UIDrivers.VC TriList.SetSigFalseAction(UIBoolJoin.VCStagingMeetNowPress, MeetNowPress); TriList.SetSigFalseAction(UIBoolJoin.CallStopSharingPress, CallStopSharingPress); + var meetingInfoCodec = Codec as IHasMeetingInfo; + TriList.SetSigFalseAction(UIBoolJoin.CallEndPress, () => { if (Codec.ActiveCalls.Count > 1) { Parent.PopupInterlock.ShowInterlocked(Parent.CallListOrMeetingInfoPopoverVisibilityJoin); } + else if (meetingInfoCodec != null && Codec.ActiveCalls.Count == 1) + { + var meetingInfo = meetingInfoCodec.MeetingInfo; + + if (meetingInfo != null && meetingInfo.IsSharingMeeting) + { + var presentationMeetingCodec = Codec as IHasPresentationOnlyMeeting; + if (presentationMeetingCodec != null) + { + presentationMeetingCodec.StartNormalMeetingFromSharingOnlyMeeting(); + } + } + else + { + Codec.EndAllCalls(); + } + } else + { Codec.EndAllCalls(); + } }); TriList.SetSigFalseAction(UIBoolJoin.CallEndAllConfirmPress, () => @@ -535,7 +572,7 @@ namespace PepperDash.Essentials.UIDrivers.VC Codec.EndAllCalls(); }); - var meetingInfoCodec = Codec as IHasMeetingInfo; + if (meetingInfoCodec != null) { TriList.SetSigFalseAction(UIBoolJoin.MeetingLeavePress, () => @@ -1801,7 +1838,7 @@ namespace PepperDash.Essentials.UIDrivers.VC /// void PasswordKeypadClear() { - PasswordStringBuilder.Remove(0, SearchStringBuilder.Length); + PasswordStringBuilder.Remove(0, PasswordStringBuilder.Length); PasswordStringFeedback.FireUpdate(); PasswordStringCheckEnables(); @@ -1929,6 +1966,7 @@ namespace PepperDash.Essentials.UIDrivers.VC _passwordPromptDialogVisible = false; Parent.Keyboard.Hide(); TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible); + PasswordKeypadClear(); } } } From 93dfb8780b7753d1255b6ed432b83bf51a020670 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 7 Sep 2021 18:13:18 -0600 Subject: [PATCH 38/59] feat:(Essentials) Add doc info and meeting button text join --- PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs | 5 +++++ PepperDashEssentials/UI/JoinConstants/UIUshortJoin.cs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs index 38a86fbb..6741be35 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs @@ -48,6 +48,11 @@ namespace PepperDash.Essentials /// public const uint MeetingNameText = 1009; + /// + /// 1240 - Used to determine text for meeting start button + /// + public const uint MeetingStartButtonText = 1240; + diff --git a/PepperDashEssentials/UI/JoinConstants/UIUshortJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIUshortJoin.cs index ffc7f19e..73356bf3 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIUshortJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIUshortJoin.cs @@ -7,7 +7,7 @@ { // Video Codec /// - /// 1234: values 0 = Connect, 1 = End + /// 1234: values 0 = Connect, 1 = End, 2 = Start Meeting /// public const uint VCStagingConnectButtonMode = 1234; From 77134f0a3016f423a75bf69c789236f29fa8d447 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 8 Sep 2021 14:15:52 -0600 Subject: [PATCH 39/59] feat:(Essentials_DM) Update AddInputPortWithDebug Adding an `IVideoAttributesBasic` as a parameter for this method relatively easily allows us to get the reported input resolution when it changes. --- .../Chassis/DmChassisController.cs | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs index 8c6b2ced..168e51f3 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs @@ -816,20 +816,47 @@ namespace PepperDash.Essentials.DM /// void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType) { - AddInputPortWithDebug(cardNum, portName, sigType, portType, null); + //Cast is necessary here to determine the correct overload + AddInputPortWithDebug(cardNum, portName, sigType, portType, null, null); + } + + private void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, + eRoutingPortConnectionType portType, ICec cecPort) + { + //Cast is necessary here to determine the correct overload + AddInputPortWithDebug(cardNum, portName, sigType, portType, cecPort, null); } /// - /// Adds InputPort and sets Port as ICec object + /// Adds InputPort and sets Port as ICec object. If videoAttributesBasic is defined, RoutingPort will be RoutingInputPortWithVideoStatuses /// - void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, ICec cecPort) + void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, ICec cecPort, IVideoAttributesBasic videoAttributesBasic) { var portKey = string.Format("inputCard{0}--{1}", cardNum, portName); Debug.Console(2, this, "Adding input port '{0}'", portKey); - var inputPort = new RoutingInputPort(portKey, sigType, portType, Chassis.Inputs[cardNum], this) + + RoutingInputPort inputPort; + + if (videoAttributesBasic != null) { - FeedbackMatchObject = Chassis.Inputs[cardNum] - }; ; + var statusFuncs = new VideoStatusFuncsWrapper + { + VideoResolutionFeedbackFunc = () => videoAttributesBasic.VideoAttributes.GetVideoResolutionString() + }; + inputPort = new RoutingInputPortWithVideoStatuses(portKey, sigType, portType, + Chassis.Inputs[cardNum], this, statusFuncs) + { + FeedbackMatchObject = Chassis.Inputs[cardNum] + }; + } + else + { + inputPort = new RoutingInputPort(portKey, sigType, portType, + Chassis.Inputs[cardNum], this) + { + FeedbackMatchObject = Chassis.Inputs[cardNum] + }; + } if (cecPort != null) inputPort.Port = cecPort; From d00a31e3a62d496464f31ff3b3bca77bfbb5a033 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 8 Sep 2021 14:17:24 -0600 Subject: [PATCH 40/59] feat(Essentials_DM): Add overloads for `AddDmInCardPorts` & `AddHdmiInCardPorts` --- .../Essentials_DM/Chassis/DmChassisController.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs index 168e51f3..3e66af96 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs @@ -672,12 +672,24 @@ namespace PepperDash.Essentials.DM AddInCardHdmiAndAudioLoopPorts(number); } + void AddDmInCardPorts(uint number, ICec cecPort, IVideoAttributesBasic videoAttributes) + { + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, cecPort, videoAttributes); + AddInCardHdmiAndAudioLoopPorts(number); + } + void AddHdmiInCardPorts(uint number, ICec cecPort) { AddInputPortWithDebug(number, "hdmiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, cecPort); AddInCardHdmiAndAudioLoopPorts(number); } + void AddHdmiInCardPorts(uint number, ICec cecPort, IVideoAttributesBasic videoAttributes) + { + AddInputPortWithDebug(number, "hdmiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, cecPort, videoAttributes); + AddInCardHdmiAndAudioLoopPorts(number); + } + void AddInCardHdmiAndAudioLoopPorts(uint number) { AddOutputPortWithDebug(string.Format("inputCard{0}", number), "hdmiLoopOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, From a28a078c4f671246e5c0e0264ecb0fe7adeccf53 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 8 Sep 2021 15:25:43 -0600 Subject: [PATCH 41/59] feat(Essentials_DM): Update all card creation methods to pass appropriate input --- .../Chassis/DmChassisController.cs | 203 +++++++++++------- 1 file changed, 127 insertions(+), 76 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs index 3e66af96..8cd53e33 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs @@ -497,166 +497,189 @@ namespace PepperDash.Essentials.DM { case "dmchd": { - var inputCard = new DmcHd(number, this.Chassis); - var cecPort = inputCard.HdmiInput as ICec; - AddHdmiInCardPorts(number, cecPort); + var inputCard = new DmcHd(number, Chassis); + AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput); } break; case "dmchddsp": { - var inputCard = new DmcHdDsp(number, this.Chassis); - var cecPort = inputCard.HdmiInput as ICec; - AddHdmiInCardPorts(number, cecPort); + var inputCard = new DmcHdDsp(number, Chassis); + AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput); } break; case "dmc4khd": { - var inputCard = new Dmc4kHd(number, this.Chassis); - var cecPort = inputCard.HdmiInput as ICec; - AddHdmiInCardPorts(number, cecPort); + var inputCard = new Dmc4kHd(number, Chassis); + AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput); } break; case "dmc4khddsp": { - var inputCard = new Dmc4kHdDsp(number, this.Chassis); - var cecPort = inputCard.HdmiInput as ICec; - AddHdmiInCardPorts(number, cecPort); + var inputCard = new Dmc4kHdDsp(number, Chassis); + AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput); } break; case "dmc4kzhd": { - var inputCard = new Dmc4kzHd(number, this.Chassis); - var cecPort = inputCard.HdmiInput as ICec; - AddHdmiInCardPorts(number, cecPort); - } + var inputCard = new Dmc4kzHd(number, Chassis); + AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput); break; + } case "dmc4kzhddsp": { - var inputCard = new Dmc4kzHdDsp(number, this.Chassis); - var cecPort = inputCard.HdmiInput as ICec; - AddHdmiInCardPorts(number, cecPort); - } + var inputCard = new Dmc4kzHdDsp(number, Chassis); + AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput); break; + } case "dmcc": { - var inputCard = new DmcC(number, this.Chassis); - var cecPort = inputCard.DmInput as ICec; - AddDmInCardPorts(number, cecPort); + var inputCard = new DmcC(number, Chassis); + //DmInput doesn't implement ICec...cast was resulting in null anyway + AddDmInCardPorts(number, null, inputCard.DmInput); } break; case "dmccdsp": { - var inputCard = new DmcCDsp(number, this.Chassis); - var cecPort = inputCard.DmInput as ICec; - AddDmInCardPorts(number, cecPort); - } + var inputCard = new DmcCDsp(number, Chassis); + //DmInput doesn't implement ICec...cast was resulting in null anyway + AddDmInCardPorts(number, null, inputCard.DmInput); break; + } + case "dmc4kc": { - var inputCard = new Dmc4kC(number, this.Chassis); - var cecPort = inputCard.DmInput as ICec; - AddDmInCardPorts(number, cecPort); - } + var inputCard = new Dmc4kC(number, Chassis); + AddDmInCardPorts(number, inputCard.DmInput,inputCard.DmInput); break; + } + case "dmc4kcdsp": { - var inputCard = new Dmc4kCDsp(number, this.Chassis); - var cecPort = inputCard.DmInput as ICec; - AddDmInCardPorts(number, cecPort); - } + var inputCard = new Dmc4kCDsp(number, Chassis); + AddDmInCardPorts(number, inputCard.DmInput,inputCard.DmInput); break; + } + case "dmc4kzc": { - var inputCard = new Dmc4kzC(number, this.Chassis); - var cecPort = inputCard.DmInput as ICec; - AddDmInCardPorts(number, cecPort); - } + var inputCard = new Dmc4kzC(number, Chassis); + AddDmInCardPorts(number, inputCard.DmInput,inputCard.DmInput); break; + } + case "dmc4kzcdsp": { - var inputCard = new Dmc4kzCDsp(number, this.Chassis); - var cecPort = inputCard.DmInput as ICec; - AddDmInCardPorts(number, cecPort); + var inputCard = new Dmc4kzCDsp(number, Chassis); + AddDmInCardPorts(number, inputCard.DmInput, inputCard.DmInput); + break; } - break; + case "dmccat": - new DmcCat(number, this.Chassis); - AddDmInCardPorts(number); + { + var inputCard = new DmcCat(number, Chassis); + AddDmInCardPorts(number, null, inputCard.DmInput); break; + } case "dmccatdsp": - new DmcCatDsp(number, this.Chassis); - AddDmInCardPorts(number); + { + var inputCard = new DmcCatDsp(number, Chassis); + AddDmInCardPorts(number, null, inputCard.DmInput); break; + } case "dmcs": - new DmcS(number, Chassis); - AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber); + { + var inputCard = new DmcS(number, Chassis); + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber, null, inputCard.DmInput); AddInCardHdmiAndAudioLoopPorts(number); break; + } case "dmcsdsp": - new DmcSDsp(number, Chassis); - AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber); + { + var inputCard = new DmcSDsp(number, Chassis); + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber, null, inputCard.DmInput); AddInCardHdmiAndAudioLoopPorts(number); break; + } case "dmcs2": - new DmcS2(number, Chassis); - AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber); + { + var inputCard = new DmcS2(number, Chassis); + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber, null, inputCard.DmInput); AddInCardHdmiAndAudioLoopPorts(number); break; + } case "dmcs2dsp": - new DmcS2Dsp(number, Chassis); - AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber); + { + var inputCard = new DmcS2Dsp(number, Chassis); + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber, null, inputCard.DmInput); AddInCardHdmiAndAudioLoopPorts(number); break; + } case "dmcsdi": - new DmcSdi(number, Chassis); - AddInputPortWithDebug(number, "sdiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Sdi); + { + var inputCard = new DmcSdi(number, Chassis); + AddInputPortWithDebug(number, "sdiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Sdi, null, inputCard.SdiInput); AddOutputPortWithDebug(string.Format("inputCard{0}", number), "sdiOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Sdi, null); AddInCardHdmiAndAudioLoopPorts(number); break; + } case "dmcdvi": - new DmcDvi(number, Chassis); - AddInputPortWithDebug(number, "dviIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Dvi); + { + var inputCard = new DmcDvi(number, Chassis); + AddInputPortWithDebug(number, "dviIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Dvi, null, inputCard.DviInput); AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); AddInCardHdmiLoopPort(number); break; + } case "dmcvga": - new DmcVga(number, Chassis); - AddInputPortWithDebug(number, "vgaIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Vga); + { + var inputCard = new DmcVga(number, Chassis); + AddInputPortWithDebug(number, "vgaIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, null, inputCard.VgaInput); AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); AddInCardHdmiLoopPort(number); break; + } case "dmcvidbnc": - new DmcVidBnc(number, Chassis); - AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component); + { + var inputCard = new DmcVidBnc(number, Chassis); + AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component, null, inputCard.VideoInput); AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); AddInCardHdmiLoopPort(number); break; + } case "dmcvidrcaa": - new DmcVidRcaA(number, Chassis); - AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component); + { + var inputCard = new DmcVidRcaA(number, Chassis); + AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component, null, inputCard.VideoInput); AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); AddInCardHdmiLoopPort(number); break; + } case "dmcvidrcad": - new DmcVidRcaD(number, Chassis); - AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component); + { + var inputCard = new DmcVidRcaD(number, Chassis); + AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component, null, inputCard.VideoInput); AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio); AddInCardHdmiLoopPort(number); break; + } case "dmcvid4": - new DmcVid4(number, Chassis); + { + var inputCard = new DmcVid4(number, Chassis); AddInputPortWithDebug(number, "compositeIn1", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite); AddInputPortWithDebug(number, "compositeIn2", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite); AddInputPortWithDebug(number, "compositeIn3", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite); AddInputPortWithDebug(number, "compositeIn4", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite); AddInCardHdmiLoopPort(number); break; + } case "dmcstr": - new DmcStr(number, Chassis); - AddInputPortWithDebug(number, "streamIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Streaming); + { + var inputCard = new DmcStr(number, Chassis); + AddInputPortWithDebug(number, "streamIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Streaming, null, inputCard.Source); AddInCardHdmiAndAudioLoopPorts(number); break; + } } } @@ -1089,7 +1112,7 @@ namespace PepperDash.Essentials.DM var inputNumber = Chassis.Outputs[output].VideoOutFeedback == null ? 0 : Chassis. Outputs[output].VideoOutFeedback.Number; - Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, inputNumber, output); + Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", Name, inputNumber, output); if (VideoOutputFeedbacks.ContainsKey(output)) { @@ -1116,7 +1139,7 @@ namespace PepperDash.Essentials.DM var inputNumber = Chassis.Outputs[output].AudioOutFeedback == null ? 0 : Chassis. Outputs[output].AudioOutFeedback.Number; - Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, inputNumber, output); + Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", Name, inputNumber, output); if (AudioOutputFeedbacks.ContainsKey(output)) { @@ -1427,6 +1450,13 @@ namespace PepperDash.Essentials.DM { trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1; } + + var videoStatus = inputPort as RoutingInputPortWithVideoStatuses; + + if (videoStatus != null) + { + videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]); + } } private void LinkStreamInputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) @@ -1467,6 +1497,13 @@ namespace PepperDash.Essentials.DM InputStreamCardStateFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[join]); trilist.UShortInput[join].UShortValue = InputStreamCardStateFeedbacks[ioSlot].UShortValue; + + var videoStatus = inputPort as RoutingInputPortWithVideoStatuses; + + if (videoStatus != null) + { + videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]); + } } private void LinkStreamOutputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) @@ -1603,6 +1640,13 @@ namespace PepperDash.Essentials.DM { trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1; } + + var videoStatus = inputPort as RoutingInputPortWithVideoStatuses; + + if (videoStatus != null) + { + videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]); + } } private void LinkAdvancedTxToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, @@ -1653,6 +1697,13 @@ namespace PepperDash.Essentials.DM trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = (ushort) transmitter.HdcpSupportCapability; + + var videoStatus = txRoutingInputs.InputPorts.Cast().FirstOrDefault((ip) => ip.Key == DmPortName.AnyVideoIn); + + if (videoStatus != null) + { + videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]); + } } private void LinkTxOnlineFeedbackToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, @@ -1935,15 +1986,15 @@ namespace PepperDash.Essentials.DM { var props = JsonConvert.DeserializeObject - (dc.Properties.ToString()); - return PepperDash.Essentials.DM.DmChassisController. + (dc.Properties.ToString()); + return DmChassisController. GetDmChassisController(dc.Key, dc.Name, type, props); } else if (type.StartsWith("dmmd128x") || type.StartsWith("dmmd64x")) { var props = JsonConvert.DeserializeObject - (dc.Properties.ToString()); - return PepperDash.Essentials.DM.DmBladeChassisController. + (dc.Properties.ToString()); + return DmBladeChassisController. GetDmChassisController(dc.Key, dc.Name, type, props); } From db3d96d44828ec68f999d6867369c1ae2679aa89 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 8 Sep 2021 15:26:16 -0600 Subject: [PATCH 42/59] feat(Essentials_DM): Update DmInputEvent handler for input resolution feedback --- .../Essentials_DM/Chassis/DmChassisController.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs index 8cd53e33..7356cec3 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs @@ -1051,6 +1051,18 @@ namespace PepperDash.Essentials.DM Debug.Console(2, this, "No index of {0} found in InputStreamCardStateFeedbacks"); break; } + case DMInputEventIds.ResolutionEventId: + { + var inputPort = + InputPorts.Cast() + .FirstOrDefault((ip) => ip.Key.Contains(String.Format("inputCard{0}", args.Number))); + + if (inputPort != null) + { + inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate(); + } + break; + } default: { Debug.Console(2, this, "DMInputChange fired for Input {0} with Unhandled EventId: {1}", args.Number, args.EventId); From fa6cabe246387cf850d1b34a97191c2b396ee88f Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 9 Sep 2021 07:44:05 -0600 Subject: [PATCH 43/59] refactor(Essentials_DM): Add event IDS and some logging to get resolution feedback --- .../Essentials_DM/Chassis/DmChassisController.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs index 7356cec3..de9a088a 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs @@ -1051,14 +1051,19 @@ namespace PepperDash.Essentials.DM Debug.Console(2, this, "No index of {0} found in InputStreamCardStateFeedbacks"); break; } + case DMInputEventIds.HorizontalResolutionFeedbackEventId: + case DMInputEventIds.VerticalResolutionFeedbackEventId: + case DMInputEventIds.FramesPerSecondFeedbackEventId: case DMInputEventIds.ResolutionEventId: { + Debug.Console(1, this, "Input {0} resolution updated", args.Number); var inputPort = InputPorts.Cast() .FirstOrDefault((ip) => ip.Key.Contains(String.Format("inputCard{0}", args.Number))); if (inputPort != null) { + Debug.Console(1, this, "Updating resolution feedback for input {0}", args.Number); inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate(); } break; From 871894e248105655665d45c79814b798711f7986 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 10 Sep 2021 20:25:21 -0600 Subject: [PATCH 44/59] fix: Fix issue with receiving sharing state In some circumstances, the sharing state can be retrieved prior to participants or meeting info being populated. In those cases, Essentials is now creating an empty meeting object if one doesn't exist, and populating host info with None if no host has been indicated yet. --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 130 ++++++++++++------ 1 file changed, 89 insertions(+), 41 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 a426193b..ead0a66f 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 @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Text; using Crestron.SimplSharp; @@ -464,18 +465,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void SetUpCallFeedbackActions() { - Status.Call.Sharing.PropertyChanged += (o, a) => - { - if (a.PropertyName == "State") - { - SharingContentIsOnFeedback.FireUpdate(); - ReceivingContent.FireUpdate(); - - // Update the share status of the meeting info - var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting); - MeetingInfo = meetingInfo; - } - }; + Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate; Status.Call.PropertyChanged += (o, a) => { @@ -487,6 +477,39 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom }; } + private void HandleSharingStateUpdate(object sender, PropertyChangedEventArgs a) + { + if (a.PropertyName != "State") + { + return; + } + + SharingContentIsOnFeedback.FireUpdate(); + ReceivingContent.FireUpdate(); + try + { + + // Update the share status of the meeting info + if (MeetingInfo == null) + { + var sharingStatus = GetSharingStatus(); + + MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true); + return; + } + + var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None", + MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting); + MeetingInfo = meetingInfo; + } + catch (Exception e) + { + Debug.Console(1, this, "Error processing state property update. {0}", e.Message); + Debug.Console(2, this, e.StackTrace); + MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false); + } + } + /// /// Subscribes to the PropertyChanged events on the state objects and fires the corresponding feedbacks. /// @@ -1614,7 +1637,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } catch (Exception ex) { - Debug.Console(1, this, "Error Deserializing feedback: {0}", ex); + Debug.Console(1, this, "Error Deserializing feedback: {0}", ex.Message); + Debug.Console(2, this, "{0}", ex); + + if (ex.InnerException != null) + { + Debug.Console(1, this,"Error Deserializing feedback inner exception: {0}", ex.InnerException.Message); + Debug.Console(2, this, "{0}", ex.InnerException.StackTrace); + } } } @@ -1822,24 +1852,33 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { string sharingState = "None"; - if (Status.Call.Sharing.State == zEvent.eSharingState.Receiving) + try { - sharingState = "Receiving Content"; - } - if (Status.Sharing.isAirHostClientConnected) - { - sharingState = "Sharing AirPlay"; - } - if (Status.Sharing.isDirectPresentationConnected) - { - sharingState = "Sharing Laptop"; - } - if (Status.Sharing.isSharingBlackMagic) - { - sharingState = "Sharing HDMI Source"; - } + if (Status.Call.Sharing.State == zEvent.eSharingState.Receiving) + { + sharingState = "Receiving Content"; + } + if (Status.Sharing.isAirHostClientConnected) + { + sharingState = "Sharing AirPlay"; + } + if (Status.Sharing.isDirectPresentationConnected) + { + sharingState = "Sharing Laptop"; + } + if (Status.Sharing.isSharingBlackMagic) + { + sharingState = "Sharing HDMI Source"; + } - return sharingState; + return sharingState; + } + catch (Exception e) + { + Debug.Console(1, this, "Exception getting sharing status: {0}", e.Message); + Debug.Console(2, this, "{0}", e.StackTrace); + return sharingState; + } } /// @@ -1848,21 +1887,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// private bool GetIsHostMyself() { - if (Participants.CurrentParticipants.Count == 0) + try { - Debug.Console(2, this, "No current participants"); + if (Participants.CurrentParticipants.Count == 0) + { + Debug.Console(2, this, "No current participants"); + return false; + } + + var host = Participants.Host; + + if(host == null) + { + Debug.Console(2, this, "Host is currently null"); + return false; + } + Debug.Console(2, this, "Host is: '{0}' IsMyself?: {1}", host.Name, host.IsMyself); + return host.IsMyself; + } + catch (Exception e) + { + Debug.Console(1, "Exception getting isHost: {0}", e.Message); + Debug.Console(2, "{0}", e.StackTrace); return false; } - - var host = Participants.Host; - - if(host == null) - { - Debug.Console(2, this, "Host is currently null"); - return false; - } - Debug.Console(2, this, "Host is: '{0}' IsMyself?: {1}", host.Name, host.IsMyself); - return host.IsMyself; } public override void StartSharing() From 0ae38dddfcb3938cb2d7c548f88469543e68c9a1 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Sat, 11 Sep 2021 14:01:07 -0600 Subject: [PATCH 45/59] ci: Update scripts to remove Newtonsoft.Compact.json --- .github/scripts/ZipBuildOutput.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/scripts/ZipBuildOutput.ps1 b/.github/scripts/ZipBuildOutput.ps1 index bf3c9d94..dfc6480d 100644 --- a/.github/scripts/ZipBuildOutput.ps1 +++ b/.github/scripts/ZipBuildOutput.ps1 @@ -8,6 +8,7 @@ $destination = "$($Env:GITHUB_HOME)\output" New-Item -ItemType Directory -Force -Path ($destination) Get-ChildItem ($destination) $exclusions = @(git submodule foreach --quiet 'echo $name') +$exclusions += "Newtonsoft.Compact.Json.dll" # Trying to get any .json schema files (not currently working) # Gets any files with the listed extensions. Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.clz", "*.cpz", "*.cplz", "*.dll", "*.nuspec" | ForEach-Object { From 73e3b049d83d40018bec52dac1ea7b9d2a6225a7 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 13 Sep 2021 08:33:36 -0600 Subject: [PATCH 46/59] build: Update nuspec file for maximum PD Core version --- .../PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec index e736dcbf..c2394428 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec @@ -14,7 +14,7 @@ crestron 3series 4series - + From 4ffea1c98fbe25c48353f544db74d04257d8631d Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 13 Sep 2021 08:43:24 -0600 Subject: [PATCH 47/59] fix: Add step to allow meeting number to be sent when entering password --- .../Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs | 1 + 1 file changed, 1 insertion(+) 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 ead0a66f..b53b871d 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 @@ -2209,6 +2209,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void Dial(Meeting meeting) { Debug.Console(1, this, "Dialing meeting.Id: {0} Title: {1}", meeting.Id, meeting.Title); + _lastDialedMeetingNumber = meeting.Id; SendText(string.Format("zCommand Dial Start meetingNumber: {0}", meeting.Id)); } From fe01842523e2383f00911954d3e31553987e893e Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 16 Sep 2021 07:15:26 -0600 Subject: [PATCH 48/59] fix: Multiple fixes Update to poll meetings every 60 seconds Add property to allow for adjusting when Join button appears Refactor call connected event handler Adjust text for header for sharing-only meeting Add logic to handle waiting for host state --- .../Essentials/EssentialsHeaderDriver.cs | 43 +++-- ...entialsHuddleVtc1PanelAvFunctionsDriver.cs | 158 ++++++++++-------- .../VC/EssentialsVideoCodecUiDriver.cs | 40 ++++- .../Codec/iHasScheduleAwareness.cs | 9 + .../VideoCodec/Interfaces/IHasMeetingInfo.cs | 5 +- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 6 + .../VideoCodec/ZoomRoom/ZoomRoom.cs | 102 ++++++++--- .../ZoomRoom/ZoomRoomPropertiesConfig.cs | 2 + 8 files changed, 249 insertions(+), 116 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs b/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs index f42b9de2..c63af9d5 100644 --- a/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs +++ b/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs @@ -195,22 +195,11 @@ namespace PepperDash.Essentials var meetingInfoCodec = codec as IHasMeetingInfo; // Set mode of header button - if (!codec.IsInCall) - { - HeaderCallButtonIconSig.StringValue = "DND"; - //HeaderCallButton.SetIcon(HeaderListButton.OnHook); - } - else if (codec.ActiveCalls.Any(c => c.Type == eCodecCallType.Video)) - HeaderCallButtonIconSig.StringValue = "Misc-06_Dark"; - //HeaderCallButton.SetIcon(HeaderListButton.Camera); - //TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 2); - else - HeaderCallButtonIconSig.StringValue = "Misc-09_Dark"; - //HeaderCallButton.SetIcon(HeaderListButton.Phone); - //TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 1); + SetHeaderCallIcon(codec); // Set the call status text Debug.Console(1, "Active Call Count: {0}", codec.ActiveCalls.Count); + if (codec.ActiveCalls.Count > 0) { if (codec.ActiveCalls.Count == 1 && meetingInfoCodec == null) @@ -218,8 +207,13 @@ namespace PepperDash.Essentials else if (codec.ActiveCalls.Count == 1 && meetingInfoCodec != null) { var headerCallStatusLabel = meetingInfoCodec.MeetingInfo.IsSharingMeeting - ? "Sharing Active" + ? "Sharing-Only Meeting" : "Active Meeting"; + + headerCallStatusLabel = meetingInfoCodec.MeetingInfo.WaitingForHost + ? "Waiting For Host" + : headerCallStatusLabel; + TriList.SetString(UIStringJoin.HeaderCallStatusLabel, headerCallStatusLabel); } else if (codec.ActiveCalls.Count > 1) @@ -229,6 +223,27 @@ namespace PepperDash.Essentials TriList.SetString(UIStringJoin.HeaderCallStatusLabel, "No Active Calls"); } + private void SetHeaderCallIcon(VideoCodecBase codec) + { + if (!codec.IsInCall) + { + HeaderCallButtonIconSig.StringValue = "DND"; + //HeaderCallButton.SetIcon(HeaderListButton.OnHook); + } + else if (codec.ActiveCalls.Any(c => c.Type == eCodecCallType.Video)) + { + HeaderCallButtonIconSig.StringValue = "Misc-06_Dark"; + } + //HeaderCallButton.SetIcon(HeaderListButton.Camera); + //TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 2); + else + { + HeaderCallButtonIconSig.StringValue = "Misc-09_Dark"; + } + //HeaderCallButton.SetIcon(HeaderListButton.Phone); + //TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 1); + } + /// /// Sets up Header Buttons for the EssentialsHuddleVtc1Room type /// diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 246573a9..67887078 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -471,85 +471,92 @@ namespace PepperDash.Essentials /// void ShowNextMeetingTimerCallback() { + //Update calendar for Zoom. Zoom doesn't automatically update when meetings are in the past + if (_isZoomRoomWithNoExternalSources) + { + CurrentRoom.ScheduleSource.GetSchedule(); + } + // Every 60 seconds, refresh the calendar RefreshMeetingsList(); // check meetings list for the closest, joinable meeting var ss = CurrentRoom.ScheduleSource; var meetings = ss.CodecSchedule.Meetings; - if (meetings.Count > 0) - { - // If the room is off pester the user - // If the room is on, and the meeting is joinable - // and the LastMeetingDismissed != this meeting + if (meetings.Count <= 0) + { + return; + } + // If the room is off pester the user + // If the room is on, and the meeting is joinable + // and the LastMeetingDismissed != this meeting - var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId); - Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*", - CurrentRoom.OnFeedback.BoolValue, - LastMeetingDismissedId, - lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : ""); + var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId); + Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*", + CurrentRoom.OnFeedback.BoolValue, + LastMeetingDismissedId, + lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : ""); - var meeting = meetings.LastOrDefault(m => m.Joinable); - if (CurrentRoom.OnFeedback.BoolValue - && lastMeetingDismissed == meeting) - { - // meeting no longer joinable, hide popup - if(meeting == null) - HideNextMeetingPopup(); + var meeting = meetings.LastOrDefault(m => m.Joinable); + if (CurrentRoom.OnFeedback.BoolValue + && lastMeetingDismissed == meeting) + { + // meeting no longer joinable, hide popup + if(meeting == null) + HideNextMeetingPopup(); - return; - } + return; + } - LastMeetingDismissedId = null; - // Clear the popup when we run out of meetings - if (meeting == null) - { - HideNextMeetingPopup(); - } - else - { + LastMeetingDismissedId = null; + // Clear the popup when we run out of meetings + if (meeting == null) + { + HideNextMeetingPopup(); + } + else + { - TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Upcoming meeting"); - TriList.SetString(UIStringJoin.NextMeetingStartTimeText, meeting.StartTime.ToString("t", Global.Culture)); - TriList.SetString(UIStringJoin.NextMeetingEndTimeText, meeting.EndTime.ToString("t", Global.Culture)); - TriList.SetString(UIStringJoin.NextMeetingTitleText, meeting.Title); - TriList.SetString(UIStringJoin.NextMeetingNameText, meeting.Organizer); - TriList.SetString(UIStringJoin.NextMeetingButtonLabel, "Join"); - TriList.SetSigFalseAction(UIBoolJoin.NextMeetingJoinPress, () => - { - HideNextMeetingPopup(); - PopupInterlock.Hide(); - RoomOnAndDialMeeting(meeting); - }); - TriList.SetString(UIStringJoin.NextMeetingSecondaryButtonLabel, "Show Schedule"); - TriList.SetSigFalseAction(UIBoolJoin.CalendarHeaderButtonPress, () => - { - HideNextMeetingPopup(); - //CalendarPress(); - RefreshMeetingsList(); - PopupInterlock.ShowInterlocked(UIBoolJoin.MeetingsOrContacMethodsListVisible); - }); - var indexOfNext = meetings.IndexOf(meeting) + 1; + TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Upcoming meeting"); + TriList.SetString(UIStringJoin.NextMeetingStartTimeText, meeting.StartTime.ToString("t", Global.Culture)); + TriList.SetString(UIStringJoin.NextMeetingEndTimeText, meeting.EndTime.ToString("t", Global.Culture)); + TriList.SetString(UIStringJoin.NextMeetingTitleText, meeting.Title); + TriList.SetString(UIStringJoin.NextMeetingNameText, meeting.Organizer); + TriList.SetString(UIStringJoin.NextMeetingButtonLabel, "Join"); + TriList.SetSigFalseAction(UIBoolJoin.NextMeetingJoinPress, () => + { + HideNextMeetingPopup(); + PopupInterlock.Hide(); + RoomOnAndDialMeeting(meeting); + }); + TriList.SetString(UIStringJoin.NextMeetingSecondaryButtonLabel, "Show Schedule"); + TriList.SetSigFalseAction(UIBoolJoin.CalendarHeaderButtonPress, () => + { + HideNextMeetingPopup(); + //CalendarPress(); + RefreshMeetingsList(); + PopupInterlock.ShowInterlocked(UIBoolJoin.MeetingsOrContacMethodsListVisible); + }); + var indexOfNext = meetings.IndexOf(meeting) + 1; - // indexOf = 3, 4 meetings : - if (indexOfNext < meetings.Count) - TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, - meetings[indexOfNext].StartTime.ToString("t", Global.Culture)); - else - TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, "No more meetings today"); + // indexOf = 3, 4 meetings : + if (indexOfNext < meetings.Count) + TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, + meetings[indexOfNext].StartTime.ToString("t", Global.Culture)); + else + TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, "No more meetings today"); - TriList.SetSigFalseAction(UIBoolJoin.NextMeetingModalClosePress, () => - { - // Mark the meeting to not re-harass the user - if(CurrentRoom.OnFeedback.BoolValue) - LastMeetingDismissedId = meeting.Id; - HideNextMeetingPopup(); - }); + TriList.SetSigFalseAction(UIBoolJoin.NextMeetingModalClosePress, () => + { + // Mark the meeting to not re-harass the user + if(CurrentRoom.OnFeedback.BoolValue) + LastMeetingDismissedId = meeting.Id; + HideNextMeetingPopup(); + }); - TriList.SetBool(UIBoolJoin.NextMeetingModalVisible, true); - } - } + TriList.SetBool(UIBoolJoin.NextMeetingModalVisible, true); + } } /// @@ -575,19 +582,26 @@ namespace PepperDash.Essentials /// void RoomOnAndDialMeeting(Meeting meeting) { + Debug.Console(1, "[RoomOnAndDialMeeting] Joining meeting [{0}]", meeting); Action dialAction = () => { var d = CurrentRoom.ScheduleSource as VideoCodecBase; if (d != null) { + Debug.Console(1, + "[RoomOnAndDialMeeting] [dialAction] Sending command to codec to join meeting {0}", meeting); d.Dial(meeting); LastMeetingDismissedId = meeting.Id; // To prevent prompts for already-joined call } }; - if (CurrentRoom.OnFeedback.BoolValue) - dialAction(); + if (CurrentRoom.OnFeedback.BoolValue) + { + Debug.Console(1, "[RoomOnAndDialMeeting] Room is on."); + dialAction(); + } else - { + { + Debug.Console(1, "RoomOnAndDialMeeting] Room is off or warming. Registering for Warming Feedback"); // Rig a one-time handler to catch when the room is warmed and then dial call EventHandler oneTimeHandler = null; oneTimeHandler = (o, a) => @@ -1086,13 +1100,18 @@ namespace PepperDash.Essentials void meetingInfoCodec_MeetingInfoChanged(object sender, MeetingInfoEventArgs e) { + if (e.Info == null) + { + return; + } + TriList.SetString(UIStringJoin.MeetingIdText, e.Info.Id); TriList.SetString(UIStringJoin.MeetingHostText, e.Info.Host); TriList.SetString(UIStringJoin.MeetingNameText, e.Info.Name); TriList.SetString(UIStringJoin.MeetingPasswordText, e.Info.Password); // Show the password fields if one is present - TriList.SetBool(UIBoolJoin.MeetingPasswordVisible, string.IsNullOrEmpty(e.Info.Password) ? false : true); + TriList.SetBool(UIBoolJoin.MeetingPasswordVisible, !string.IsNullOrEmpty(e.Info.Password)); TriList.SetString(UIStringJoin.CallSharedSourceNameText, e.Info.ShareStatus); @@ -1302,9 +1321,8 @@ namespace PepperDash.Essentials { // See if this is helpful or if the callback response in the codec class maybe doesn't come it time? // Let's build list from event - // CurrentRoom.ScheduleSource.GetSchedule(); - TriList.SetString(UIStringJoin.MeetingsOrContactMethodListIcon, "Calendar"); + TriList.SetString(UIStringJoin.MeetingsOrContactMethodListIcon, "Calendar"); TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Today's Meetings"); ushort i = 0; diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index 9bbaad6f..cc5ac265 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -327,20 +327,14 @@ namespace PepperDash.Essentials.UIDrivers.VC { case eCodecCallStatus.Connected: // fire at SRL item - HidePasswordPrompt(); - KeypadMode = eKeypadMode.DTMF; - DialStringBuilder.Remove(0, DialStringBuilder.Length); - DialStringFeedback.FireUpdate(); - DialStringTextCheckEnables(); Parent.ShowNotificationRibbon("Connected", 2000); - StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingKeypadPress); - ShowKeypad(); - ((Parent.CurrentRoom as IHasCurrentVolumeControls).CurrentVolumeControls as IBasicVolumeWithFeedback).MuteOff(); + OnCallConnected(); //VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCKeypadVisible); break; case eCodecCallStatus.Connecting: // fire at SRL item Parent.ShowNotificationRibbon("Connecting", 0); + OnCallConnected(); break; case eCodecCallStatus.Dialing: Parent.ShowNotificationRibbon("Connecting", 0); @@ -417,6 +411,36 @@ namespace PepperDash.Essentials.UIDrivers.VC UpdateHeaderActiveCallList(); } + private void OnCallConnected() + { + HidePasswordPrompt(); + KeypadMode = eKeypadMode.DTMF; + DialStringBuilder.Remove(0, DialStringBuilder.Length); + DialStringFeedback.FireUpdate(); + DialStringTextCheckEnables(); + + StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingKeypadPress); + ShowKeypad(); + + UnmuteRoomOnCallConnect(); + } + + private void UnmuteRoomOnCallConnect() + { + var volControl = Parent.CurrentRoom as IHasCurrentVolumeControls; + + if (volControl == null) + { + return; + } + var currentVolControls = volControl.CurrentVolumeControls as IBasicVolumeWithFeedback; + + if (currentVolControls != null) + { + currentVolControls.MuteOff(); + } + } + /// /// Redraws the calls list on the header /// 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 24f1968b..06edf7bf 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 @@ -235,6 +235,15 @@ namespace PepperDash.Essentials.Devices.Common.Codec { Calls = new List(); } + + #region Overrides of Object + + public override string ToString() + { + return String.Format("{0}:{1}: {2}-{3}", Title, Agenda, StartTime, EndTime); + } + + #endregion } public class Call diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs index cd9e2906..0720b319 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs @@ -38,8 +38,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces public Boolean IsHost { get; private set; } [JsonProperty("isSharingMeeting")] public Boolean IsSharingMeeting { get; private set; } + [JsonProperty("waitingForHost")] + public Boolean WaitingForHost { get; private set; } - public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting) + public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost) { Id = id; Name = name; @@ -48,6 +50,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces ShareStatus = shareStatus; IsHost = isHost; IsSharingMeeting = isSharingMeeting; + WaitingForHost = waitingForHost; } } 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 35b6c3b2..e6efd063 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 @@ -59,6 +59,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public List AudioOuputs { get; set; } public List Cameras { get; set; } public zEvent.PhoneCallStatus PhoneCall { get; set; } + public zEvent.NeedWaitForHost NeedWaitForHost { get; set; } public ZoomRoomStatus() { @@ -76,6 +77,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom AudioOuputs = new List(); Cameras = new List(); PhoneCall = new zEvent.PhoneCallStatus(); + NeedWaitForHost = new zEvent.NeedWaitForHost(); } } @@ -1475,6 +1477,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public static List GetGenericParticipantListFromParticipantsResult( List participants) { + if (participants.Count == 0) + { + return new List(); + } //return participants.Select(p => new Participant // { // UserId = p.UserId, 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 b53b871d..7096d894 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 @@ -112,6 +112,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom CodecSchedule = new CodecScheduleAwareness(MeetingRefreshTimer); + if (_props.MinutesBeforeMeetingStart > 0) + { + CodecSchedule.MeetingWarningMinutes = _props.MinutesBeforeMeetingStart; + } + ReceivingContent = new BoolFeedback(FarEndIsSharingContentFeedbackFunc); SelfviewPipPositionFeedback = new StringFeedback(SelfviewPipPositionFeedbackFunc); @@ -494,19 +499,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { var sharingStatus = GetSharingStatus(); - MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true); + MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false); return; } var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None", - MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting); + MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost); MeetingInfo = meetingInfo; } catch (Exception e) { Debug.Console(1, this, "Error processing state property update. {0}", e.Message); Debug.Console(2, this, e.StackTrace); - MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false); + MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false); } } @@ -657,7 +662,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom return; } // Update the share status of the meeting info - var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting); + var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost); MeetingInfo = meetingInfo; break; } @@ -1229,7 +1234,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Participants.CurrentParticipants = participants; // Update the share status of the meeting info - var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, MeetingInfo.ShareStatus, GetIsHostMyself(), MeetingInfo.IsSharingMeeting); + var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, MeetingInfo.ShareStatus, GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost); MeetingInfo = meetingInfo; PrintCurrentCallParticipants(); @@ -1424,15 +1429,40 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } case "needwaitforhost": { - var needWait = - JsonConvert.DeserializeObject(responseObj.ToString()); + Status.NeedWaitForHost = JsonConvert.DeserializeObject(responseObj.ToString()); - if (needWait.Wait) - { - // TODO: notify user to wait for host - } + Debug.Console(1, this, "NeedWaitForHost: {0}", Status.NeedWaitForHost.Wait); - break; + if (Status.NeedWaitForHost.Wait) + { + if (MeetingInfo == null) + { + MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", + GetSharingStatus(), false, false, true); + + UpdateCallStatus(); + break; + } + + MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", + GetSharingStatus(), false, false, true); + + UpdateCallStatus(); + + break; + } + + if (MeetingInfo == null) + { + MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", + GetSharingStatus(), false, false, false); + break; + } + + MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, + GetSharingStatus(), GetIsHostMyself(), false, false); + + break; } case "openvideofailforhoststop": { @@ -1514,7 +1544,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (result.Success) { - MeetingInfo = new MeetingInfo("", "", "", "", "", true, true); + MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost); break; } @@ -1704,8 +1734,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom ///
private void UpdateCallStatus() { - Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", - Status.Call != null ? Status.Call.Status.ToString() : "no call"); + Debug.Console(1, this, + "[UpdateCallStatus] Current Call Status: {0} Active Call Count: {1} Need Wait For Host: {2}", + Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count, Status.NeedWaitForHost.Wait); if (Status.Call != null) { @@ -1750,17 +1781,32 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Type = eCodecCallType.Video, }; + if (!String.IsNullOrEmpty(_lastDialedMeetingNumber)) + { + _lastDialedMeetingNumber = String.Empty; + } ActiveCalls.Add(newCall); - //Debug.Console(1, this, "[UpdateCallStatus] IF w/ meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}", - //Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); - OnCallStatusChange(newCall); - } - else + } else if (String.IsNullOrEmpty(Status.Call.Info.meeting_id) && Status.NeedWaitForHost.Wait) { - //Debug.Console(1, this, "[UpdateCallStatus] IF w/o meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}", - //Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); + var newCall = new CodecActiveCallItem + { + Name = "Waiting For Host", + Number = "Waiting For Host", + Id = "Waiting For Host", + Status = newStatus, + Type = eCodecCallType.Video, + }; + + if (!String.IsNullOrEmpty(_lastDialedMeetingNumber)) + { + _lastDialedMeetingNumber = String.Empty; + } + + ActiveCalls.Add(newCall); + + OnCallStatusChange(newCall); } } } @@ -1771,15 +1817,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom switch (callStatus) { case zStatus.eCallStatus.IN_MEETING: + if (Status.NeedWaitForHost.Wait) + { + Status.NeedWaitForHost.Wait = false; + } existingCall.Status = eCodecCallStatus.Connected; break; case zStatus.eCallStatus.NOT_IN_MEETING: + if (Status.NeedWaitForHost.Wait) + { + Status.NeedWaitForHost.Wait = false; + } existingCall.Status = eCodecCallStatus.Disconnected; break; } Debug.Console(1, this, "[UpdateCallStatus] ELSE ActiveCalls.Count == {1} - Current Call Status: {0}", Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); + OnCallStatusChange(existingCall); } @@ -1833,7 +1888,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Status.Call.Info.meeting_password, GetSharingStatus(), GetIsHostMyself(), - !String.Equals(Status.Call.Info.meeting_type,"NORMAL") + !String.Equals(Status.Call.Info.meeting_type,"NORMAL"), + false ); } 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 38238023..4c9b08c2 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 @@ -25,5 +25,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom //This layout will be selected when a call is connected and no content is being shared public string DefaultCallLayout { get; set; } + + public int MinutesBeforeMeetingStart { get; set; } } } \ No newline at end of file From 9f3a3f64a82a11e4f818044cbc29c11fa3e24c63 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 16 Sep 2021 13:27:09 -0600 Subject: [PATCH 49/59] fix: Update share behavior for Zoom Room --- ...entialsHuddleVtc1PanelAvFunctionsDriver.cs | 22 +++++++++++++++++-- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 10 ++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 67887078..26bdaee9 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -9,6 +9,7 @@ using Crestron.SimplSharpPro.UI; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Core.SmartObjects; using PepperDash.Essentials.Core.PageManagers; using PepperDash.Essentials.Room.Config; @@ -730,16 +731,31 @@ namespace PepperDash.Essentials if (_isZoomRoomWithNoExternalSources) { - CurrentRoom.RunDefaultPresentRoute(); + if (!CurrentRoom.OnFeedback.BoolValue) + { + CurrentRoom.RunDefaultPresentRoute(); + } // For now, if this is a Zoom Room and there are no shareable sources just display the informational subpage TriList.SetBool(UIBoolJoin.ZoomRoomContentSharingVisible, true); var presentationMeetingCodec = CurrentRoom.VideoCodec as IHasPresentationOnlyMeeting; + var farEndContentStatusCodec = CurrentRoom.VideoCodec as IHasFarEndContentStatus; + var receivingContent = false; + + if (farEndContentStatusCodec != null) + { + receivingContent = farEndContentStatusCodec.ReceivingContent.BoolValue; + } if (presentationMeetingCodec != null && !CurrentRoom.VideoCodec.IsInCall) { presentationMeetingCodec.StartSharingOnlyMeeting(eSharingMeetingMode.Laptop); } + else if (CurrentRoom.VideoCodec.IsInCall && !CurrentRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue && + !receivingContent) + { + CurrentRoom.VideoCodec.StartSharing(); + } if (CurrentSourcePageManager != null) CurrentSourcePageManager.Hide(); @@ -755,7 +771,9 @@ namespace PepperDash.Essentials } else // room is on show what's active or select a source if nothing is yet active { - if (CurrentRoom.CurrentSourceInfo == null || (CurrentRoom.VideoCodec != null && CurrentRoom.CurrentSourceInfo.SourceDevice.Key == CurrentRoom.VideoCodec.OsdSource.Key)) + if (CurrentRoom.CurrentSourceInfo == null || + (CurrentRoom.VideoCodec != null && + CurrentRoom.CurrentSourceInfo.SourceDevice.Key == CurrentRoom.VideoCodec.OsdSource.Key)) TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); else if (CurrentSourcePageManager != null) { 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 7096d894..e4a724a2 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 @@ -656,6 +656,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Debug.Console(2, this, "Updating sharing status: {0}", a.PropertyName); + SharingContentIsOnFeedback.FireUpdate(); if (MeetingInfo == null) { //Ignoring for now, as the CallInfo return will create the appropriate value @@ -1979,7 +1980,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom ///
public override void StopSharing() { - SendText("zCommand Call Sharing Disconnect"); + if (Status.Sharing.isSharingBlackMagic) + { + SendText("zCommand Call Sharing HDMI Stop"); + } + else + { + SendText("zCommand Call Sharing Disconnect"); + } } public override void PrivacyModeOn() From 9f1c512909ff48279804dcd33f3bf63600281a46 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Thu, 29 Jul 2021 17:19:54 -0500 Subject: [PATCH 50/59] Updates to HdMdNxM4kEController.cs to implement regex pattern in place of substring on input definitions. Updated HdMdNxM4kEBridgeableController.cs to handle exception when constructing the device. --- .../Chassis/HdMdNxM4kEBridgeableController.cs | 860 +++++++++--------- .../Chassis/HdMdNxM4kEController.cs | 12 +- 2 files changed, 452 insertions(+), 420 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs index b766ac3c..3eece080 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using Newtonsoft.Json; using Crestron.SimplSharp; using Crestron.SimplSharpPro.DeviceSupport; @@ -15,421 +16,446 @@ using PepperDash.Essentials.Core.Config; namespace PepperDash.Essentials.DM.Chassis { - [Description("Wrapper class for all HdMdNxM4E switchers")] - public class HdMdNxM4kEBridgeableController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback - { - private HdMdNxM _Chassis; - private HdMd4x14kE _Chassis4x1; - - //IroutingNumericEvent - public event EventHandler NumericSwitchChange; - - public Dictionary InputNames { get; set; } - public Dictionary OutputNames { get; set; } - - public RoutingPortCollection InputPorts { get; private set; } - public RoutingPortCollection OutputPorts { get; private set; } - - public FeedbackCollection VideoInputSyncFeedbacks { get; private set; } - public FeedbackCollection VideoOutputRouteFeedbacks { get; private set; } - public FeedbackCollection InputNameFeedbacks { get; private set; } - public FeedbackCollection OutputNameFeedbacks { get; private set; } - public FeedbackCollection OutputRouteNameFeedbacks { get; private set; } - public FeedbackCollection InputHdcpEnableFeedback { get; private set; } - public FeedbackCollection DeviceNameFeedback { get; private set; } - public FeedbackCollection AutoRouteFeedback { get; private set; } - - #region Constructor - - public HdMdNxM4kEBridgeableController(string key, string name, HdMdNxM chassis, - HdMdNxM4kEBridgeablePropertiesConfig props) - : base(key, name, chassis) - { - _Chassis = chassis; - var _props = props; - - InputNames = props.Inputs; - OutputNames = props.Outputs; - - VideoInputSyncFeedbacks = new FeedbackCollection(); - VideoOutputRouteFeedbacks = new FeedbackCollection(); - InputNameFeedbacks = new FeedbackCollection(); - OutputNameFeedbacks = new FeedbackCollection(); - OutputRouteNameFeedbacks = new FeedbackCollection(); - InputHdcpEnableFeedback = new FeedbackCollection(); - DeviceNameFeedback = new FeedbackCollection(); - AutoRouteFeedback = new FeedbackCollection(); - - InputPorts = new RoutingPortCollection(); - OutputPorts = new RoutingPortCollection(); - - DeviceNameFeedback.Add(new StringFeedback(this.Name, () => this.Name)); - - if (_Chassis.NumberOfInputs == 1) - { - _Chassis4x1 = _Chassis as HdMd4x14kE; - AutoRouteFeedback.Add(new BoolFeedback(this.Name + "-" + InputNames[1], () => _Chassis4x1.AutoModeOnFeedback.BoolValue)); - } - - for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) - { - var index = i; - var inputName = InputNames[index]; - _Chassis.Inputs[index].Name.StringValue = inputName; - - InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.Hdmi, index, this) - { - FeedbackMatchObject = _Chassis.HdmiInputs[index] - }); - VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[index].VideoDetectedFeedback.BoolValue)); - InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[index].Name.StringValue)); - InputHdcpEnableFeedback.Add(new BoolFeedback(inputName, () => _Chassis.HdmiInputs[index].HdmiInputPort.HdcpSupportOnFeedback.BoolValue)); - } - - for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) - { - var index = i; - var outputName = OutputNames[index]; - _Chassis.Outputs[i].Name.StringValue = outputName; - - OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.Hdmi, index, this) - { - FeedbackMatchObject = _Chassis.HdmiOutputs[index] - }); - VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => (int)_Chassis.Outputs[index].VideoOutFeedback.Number)); - OutputNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].Name.StringValue)); - OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue)); - } - - _Chassis.DMInputChange += new DMInputEventHandler(Chassis_DMInputChange); - _Chassis.DMOutputChange += new DMOutputEventHandler(Chassis_DMOutputChange); - - AddPostActivationAction(AddFeedbackCollections); - } - - #endregion - - #region Methods - - /// - /// Raise an event when the status of a switch object changes. - /// - /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType - private void OnSwitchChange(RoutingNumericEventArgs e) - { - var newEvent = NumericSwitchChange; - if (newEvent != null) newEvent(this, e); - } - - public void EnableHdcp(uint port) - { - if (port > _Chassis.NumberOfInputs) return; - if (port <= 0) return; - - _Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOn(); - InputHdcpEnableFeedback[InputNames[port]].FireUpdate(); - } - - public void DisableHdcp(uint port) - { - if (port > _Chassis.NumberOfInputs) return; - if (port <= 0) return; - - _Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOff(); - InputHdcpEnableFeedback[InputNames[port]].FireUpdate(); - } - - public void EnableAutoRoute() - { - if (_Chassis.NumberOfInputs != 1) return; - - if (_Chassis4x1 == null) return; - - _Chassis4x1.AutoModeOn(); - } - - public void DisableAutoRoute() - { - if (_Chassis.NumberOfInputs != 1) return; - - if (_Chassis4x1 == null) return; - - _Chassis4x1.AutoModeOff(); - } - - #region PostActivate - - public void AddFeedbackCollections() - { - AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback); - AddCollectionsToList(VideoOutputRouteFeedbacks); - AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedbacks, DeviceNameFeedback); - } - - #endregion - - #region FeedbackCollection Methods - - //Add arrays of collections - public void AddCollectionsToList(params FeedbackCollection[] newFbs) - { - foreach (FeedbackCollection fbCollection in newFbs) - { - foreach (var item in newFbs) - { - AddCollectionToList(item); - } - } - } - public void AddCollectionsToList(params FeedbackCollection[] newFbs) - { - foreach (FeedbackCollection fbCollection in newFbs) - { - foreach (var item in newFbs) - { - AddCollectionToList(item); - } - } - } - - public void AddCollectionsToList(params FeedbackCollection[] newFbs) - { - foreach (FeedbackCollection fbCollection in newFbs) - { - foreach (var item in newFbs) - { - AddCollectionToList(item); - } - } - } - - //Add Collections - public void AddCollectionToList(FeedbackCollection newFbs) - { - foreach (var f in newFbs) - { - if (f == null) continue; - - AddFeedbackToList(f); - } - } - - public void AddCollectionToList(FeedbackCollection newFbs) - { - foreach (var f in newFbs) - { - if (f == null) continue; - - AddFeedbackToList(f); - } - } - - public void AddCollectionToList(FeedbackCollection newFbs) - { - foreach (var f in newFbs) - { - if (f == null) continue; - - AddFeedbackToList(f); - } - } - - //Add Individual Feedbacks - public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback newFb) - { - if (newFb == null) return; - - if (!Feedbacks.Contains(newFb)) - { - Feedbacks.Add(newFb); - } - } - - #endregion - - #region IRouting Members - - public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) - { - // Try to make switch only when necessary. The unit appears to toggle when already selected. - var current = _Chassis.HdmiOutputs[(uint)outputSelector].VideoOut; - if (current != _Chassis.HdmiInputs[(uint)inputSelector]) - _Chassis.HdmiOutputs[(uint)outputSelector].VideoOut = _Chassis.HdmiInputs[(uint)inputSelector]; - } - - #endregion - - #region IRoutingNumeric Members - - public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType) - { - ExecuteSwitch(inputSelector, outputSelector, signalType); - } - - #endregion - - #endregion - - #region Bridge Linking - - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new HdMdNxM4kEControllerJoinMap(joinStart); - - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } - - IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); - DeviceNameFeedback[this.Name].LinkInputSig(trilist.StringInput[joinMap.Name.JoinNumber]); - - if (_Chassis4x1 != null) - { - trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOn()); - trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOff()); - AutoRouteFeedback[this.Name + "-" + InputNames[1]].LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); - } - - for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) - { - var joinIndex = i - 1; - //Digital - VideoInputSyncFeedbacks[InputNames[i]].LinkInputSig(trilist.BooleanInput[joinMap.InputSync.JoinNumber + joinIndex]); - InputHdcpEnableFeedback[InputNames[i]].LinkInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + joinIndex]); - InputHdcpEnableFeedback[InputNames[i]].LinkComplementInputSig(trilist.BooleanInput[joinMap.DisableInputHdcp.JoinNumber + joinIndex]); - trilist.SetSigTrueAction(joinMap.EnableInputHdcp.JoinNumber + joinIndex, () => EnableHdcp(i)); - trilist.SetSigTrueAction(joinMap.DisableInputHdcp.JoinNumber + joinIndex, () => DisableHdcp(i)); - - //Serial - InputNameFeedbacks[InputNames[i]].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + joinIndex]); - } - - for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) - { - var joinIndex = i - 1; - //Analog - VideoOutputRouteFeedbacks[OutputNames[i]].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + joinIndex]); - trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + joinIndex, (a) => ExecuteSwitch(a, i, eRoutingSignalType.AudioVideo)); - - //Serial - OutputNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + joinIndex]); - OutputRouteNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + joinIndex]); - } - - _Chassis.OnlineStatusChange += new Crestron.SimplSharpPro.OnlineStatusChangeEventHandler(Chassis_OnlineStatusChange); - - trilist.OnlineStatusChange += new Crestron.SimplSharpPro.OnlineStatusChangeEventHandler((d, args) => - { - if (args.DeviceOnLine) - { - foreach (var feedback in Feedbacks) - { - feedback.FireUpdate(); - } - } - }); - } - - - #endregion - - #region Events - - void Chassis_OnlineStatusChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.OnlineOfflineEventArgs args) - { - if (!args.DeviceOnLine) return; - for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) - { - _Chassis.Inputs[i].Name.StringValue = InputNames[i]; - } - for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) - { - _Chassis.Outputs[i].Name.StringValue = OutputNames[i]; - } - - foreach (var feedback in Feedbacks) - { - feedback.FireUpdate(); - } - } - - void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args) - { - if (args.EventId != DMOutputEventIds.VideoOutEventId) return; - - for (var i = 0; i < VideoOutputRouteFeedbacks.Count; i++) - { - var index = i; - var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1].VideoOutFeedback); - var localOutputPort = - OutputPorts.FirstOrDefault(p => (DMOutput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1]); - - - VideoOutputRouteFeedbacks[i].FireUpdate(); - OnSwitchChange(new RoutingNumericEventArgs((ushort)i, VideoOutputRouteFeedbacks[i].UShortValue, localOutputPort, localInputPort, eRoutingSignalType.AudioVideo)); - } - } - - void Chassis_DMInputChange(Switch device, DMInputEventArgs args) - { - if (args.EventId != DMInputEventIds.VideoDetectedEventId) return; - foreach (var item in VideoInputSyncFeedbacks) - { - item.FireUpdate(); - } - } - - #endregion - - #region Factory - - public class HdMdNxM4kEControllerFactory : EssentialsDeviceFactory - { - public HdMdNxM4kEControllerFactory() - { - TypeNames = new List() { "hdmd4x14ke-bridgeable", "hdmd4x24ke", "hdmd6x24ke" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.Console(1, "Factory Attempting to create new HD-MD-NxM-4K-E Device"); - - var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); - - var type = dc.Type.ToLower(); - var control = props.Control; - var ipid = control.IpIdInt; - var address = control.TcpSshProperties.Address; - - switch (type) - { - case ("hdmd4x14ke-bridgeable"): - return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd4x14kE(ipid, address, Global.ControlSystem), props); - case ("hdmd4x24ke"): - return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd4x24kE(ipid, address, Global.ControlSystem), props); - case ("hdmd6x24ke"): - return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd6x24kE(ipid, address, Global.ControlSystem), props); - default: - return null; - } - } - } - - #endregion - - - - } + [Description("Wrapper class for all HdMdNxM4E switchers")] + public class HdMdNxM4kEBridgeableController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback + { + private HdMdNxM _Chassis; + private HdMd4x14kE _Chassis4x1; + + //IroutingNumericEvent + public event EventHandler NumericSwitchChange; + + public Dictionary InputNames { get; set; } + public Dictionary OutputNames { get; set; } + + public RoutingPortCollection InputPorts { get; private set; } + public RoutingPortCollection OutputPorts { get; private set; } + + public FeedbackCollection VideoInputSyncFeedbacks { get; private set; } + public FeedbackCollection VideoOutputRouteFeedbacks { get; private set; } + public FeedbackCollection InputNameFeedbacks { get; private set; } + public FeedbackCollection OutputNameFeedbacks { get; private set; } + public FeedbackCollection OutputRouteNameFeedbacks { get; private set; } + public FeedbackCollection InputHdcpEnableFeedback { get; private set; } + public FeedbackCollection DeviceNameFeedback { get; private set; } + public FeedbackCollection AutoRouteFeedback { get; private set; } + + #region Constructor + + public HdMdNxM4kEBridgeableController(string key, string name, HdMdNxM chassis, + HdMdNxM4kEBridgeablePropertiesConfig props) + : base(key, name, chassis) + { + _Chassis = chassis; + + if (props == null) + { + Debug.Console(1, this, "HdMdNx4keBridgeableController properties are null, failed to build the device"); + return; + } + + + if (props.Inputs != null) + { + foreach (var kvp in props.Inputs) + { + Debug.Console(0, this, "props.Inputs: {0}-{1}", kvp.Key, kvp.Value); + } + InputNames = props.Inputs; + } + if (props.Outputs != null) + { + foreach (var kvp in props.Outputs) + { + Debug.Console(0, this, "props.Outputs: {0}-{1}", kvp.Key, kvp.Value); + } + OutputNames = props.Outputs; + } + //else + //{ + // OutputNames.Add(1, "Output"); + //} + + VideoInputSyncFeedbacks = new FeedbackCollection(); + VideoOutputRouteFeedbacks = new FeedbackCollection(); + InputNameFeedbacks = new FeedbackCollection(); + OutputNameFeedbacks = new FeedbackCollection(); + OutputRouteNameFeedbacks = new FeedbackCollection(); + InputHdcpEnableFeedback = new FeedbackCollection(); + DeviceNameFeedback = new FeedbackCollection(); + AutoRouteFeedback = new FeedbackCollection(); + + InputPorts = new RoutingPortCollection(); + OutputPorts = new RoutingPortCollection(); + + var deviceName = string.IsNullOrEmpty(this.Name) ? name : this.Name; + DeviceNameFeedback.Add(new StringFeedback(deviceName, () => deviceName)); + + if (_Chassis.NumberOfInputs == 1) + { + _Chassis4x1 = _Chassis as HdMd4x14kE; + AutoRouteFeedback.Add(new BoolFeedback(deviceName + "-" + InputNames[1], () => _Chassis4x1.AutoModeOnFeedback.BoolValue)); + } + + for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) + { + var index = i; + var inputName = InputNames[index]; + _Chassis.Inputs[index].Name.StringValue = inputName; + + InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, index, this) + { + FeedbackMatchObject = _Chassis.HdmiInputs[index] + }); + VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[index].VideoDetectedFeedback.BoolValue)); + InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[index].Name.StringValue)); + InputHdcpEnableFeedback.Add(new BoolFeedback(inputName, () => _Chassis.HdmiInputs[index].HdmiInputPort.HdcpSupportOnFeedback.BoolValue)); + } + + for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) + { + var index = i; + var outputName = OutputNames[index]; + _Chassis.Outputs[i].Name.StringValue = outputName; + + OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, index, this) + { + FeedbackMatchObject = _Chassis.HdmiOutputs[index] + }); + VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => (int)_Chassis.Outputs[index].VideoOutFeedback.Number)); + OutputNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].Name.StringValue)); + OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue)); + } + + _Chassis.DMInputChange += new DMInputEventHandler(Chassis_DMInputChange); + _Chassis.DMOutputChange += new DMOutputEventHandler(Chassis_DMOutputChange); + + AddPostActivationAction(AddFeedbackCollections); + } + + #endregion + + #region Methods + + /// + /// Raise an event when the status of a switch object changes. + /// + /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType + private void OnSwitchChange(RoutingNumericEventArgs e) + { + var newEvent = NumericSwitchChange; + if (newEvent != null) newEvent(this, e); + } + + public void EnableHdcp(uint port) + { + if (port > _Chassis.NumberOfInputs) return; + if (port <= 0) return; + + _Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOn(); + InputHdcpEnableFeedback[InputNames[port]].FireUpdate(); + } + + public void DisableHdcp(uint port) + { + if (port > _Chassis.NumberOfInputs) return; + if (port <= 0) return; + + _Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOff(); + InputHdcpEnableFeedback[InputNames[port]].FireUpdate(); + } + + public void EnableAutoRoute() + { + if (_Chassis.NumberOfInputs != 1) return; + + if (_Chassis4x1 == null) return; + + _Chassis4x1.AutoModeOn(); + } + + public void DisableAutoRoute() + { + if (_Chassis.NumberOfInputs != 1) return; + + if (_Chassis4x1 == null) return; + + _Chassis4x1.AutoModeOff(); + } + + #region PostActivate + + public void AddFeedbackCollections() + { + AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback); + AddCollectionsToList(VideoOutputRouteFeedbacks); + AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedbacks, DeviceNameFeedback); + } + + #endregion + + #region FeedbackCollection Methods + + //Add arrays of collections + public void AddCollectionsToList(params FeedbackCollection[] newFbs) + { + foreach (FeedbackCollection fbCollection in newFbs) + { + foreach (var item in newFbs) + { + AddCollectionToList(item); + } + } + } + public void AddCollectionsToList(params FeedbackCollection[] newFbs) + { + foreach (FeedbackCollection fbCollection in newFbs) + { + foreach (var item in newFbs) + { + AddCollectionToList(item); + } + } + } + + public void AddCollectionsToList(params FeedbackCollection[] newFbs) + { + foreach (FeedbackCollection fbCollection in newFbs) + { + foreach (var item in newFbs) + { + AddCollectionToList(item); + } + } + } + + //Add Collections + public void AddCollectionToList(FeedbackCollection newFbs) + { + foreach (var f in newFbs) + { + if (f == null) continue; + + AddFeedbackToList(f); + } + } + + public void AddCollectionToList(FeedbackCollection newFbs) + { + foreach (var f in newFbs) + { + if (f == null) continue; + + AddFeedbackToList(f); + } + } + + public void AddCollectionToList(FeedbackCollection newFbs) + { + foreach (var f in newFbs) + { + if (f == null) continue; + + AddFeedbackToList(f); + } + } + + //Add Individual Feedbacks + public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback newFb) + { + if (newFb == null) return; + + if (!Feedbacks.Contains(newFb)) + { + Feedbacks.Add(newFb); + } + } + + #endregion + + #region IRouting Members + + public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) + { + // Try to make switch only when necessary. The unit appears to toggle when already selected. + var current = _Chassis.HdmiOutputs[(uint)outputSelector].VideoOut; + if (current != _Chassis.HdmiInputs[(uint)inputSelector]) + _Chassis.HdmiOutputs[(uint)outputSelector].VideoOut = _Chassis.HdmiInputs[(uint)inputSelector]; + } + + #endregion + + #region IRoutingNumeric Members + + public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType) + { + ExecuteSwitch(inputSelector, outputSelector, signalType); + } + + #endregion + + #endregion + + #region Bridge Linking + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new HdMdNxM4kEControllerJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + DeviceNameFeedback[this.Name].LinkInputSig(trilist.StringInput[joinMap.Name.JoinNumber]); + + if (_Chassis4x1 != null) + { + trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOn()); + trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOff()); + AutoRouteFeedback[this.Name + "-" + InputNames[1]].LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); + } + + for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) + { + var joinIndex = i - 1; + //Digital + VideoInputSyncFeedbacks[InputNames[i]].LinkInputSig(trilist.BooleanInput[joinMap.InputSync.JoinNumber + joinIndex]); + InputHdcpEnableFeedback[InputNames[i]].LinkInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + joinIndex]); + InputHdcpEnableFeedback[InputNames[i]].LinkComplementInputSig(trilist.BooleanInput[joinMap.DisableInputHdcp.JoinNumber + joinIndex]); + trilist.SetSigTrueAction(joinMap.EnableInputHdcp.JoinNumber + joinIndex, () => EnableHdcp(i)); + trilist.SetSigTrueAction(joinMap.DisableInputHdcp.JoinNumber + joinIndex, () => DisableHdcp(i)); + + //Serial + InputNameFeedbacks[InputNames[i]].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + joinIndex]); + } + + for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) + { + var joinIndex = i - 1; + //Analog + VideoOutputRouteFeedbacks[OutputNames[i]].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + joinIndex]); + trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + joinIndex, (a) => ExecuteSwitch(a, i, eRoutingSignalType.AudioVideo)); + + //Serial + OutputNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + joinIndex]); + OutputRouteNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + joinIndex]); + } + + _Chassis.OnlineStatusChange += new Crestron.SimplSharpPro.OnlineStatusChangeEventHandler(Chassis_OnlineStatusChange); + + trilist.OnlineStatusChange += new Crestron.SimplSharpPro.OnlineStatusChangeEventHandler((d, args) => + { + if (args.DeviceOnLine) + { + foreach (var feedback in Feedbacks) + { + feedback.FireUpdate(); + } + } + }); + } + + + #endregion + + #region Events + + void Chassis_OnlineStatusChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.OnlineOfflineEventArgs args) + { + if (!args.DeviceOnLine) return; + for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) + { + _Chassis.Inputs[i].Name.StringValue = InputNames[i]; + } + for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) + { + _Chassis.Outputs[i].Name.StringValue = OutputNames[i]; + } + + foreach (var feedback in Feedbacks) + { + feedback.FireUpdate(); + } + } + + void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args) + { + if (args.EventId != DMOutputEventIds.VideoOutEventId) return; + + for (var i = 0; i < VideoOutputRouteFeedbacks.Count; i++) + { + var index = i; + var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1].VideoOutFeedback); + var localOutputPort = + OutputPorts.FirstOrDefault(p => (DMOutput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1]); + + + VideoOutputRouteFeedbacks[i].FireUpdate(); + OnSwitchChange(new RoutingNumericEventArgs((ushort)i, VideoOutputRouteFeedbacks[i].UShortValue, localOutputPort, localInputPort, eRoutingSignalType.AudioVideo)); + } + } + + void Chassis_DMInputChange(Switch device, DMInputEventArgs args) + { + if (args.EventId != DMInputEventIds.VideoDetectedEventId) return; + foreach (var item in VideoInputSyncFeedbacks) + { + item.FireUpdate(); + } + } + + #endregion + + #region Factory + + public class HdMdNxM4kEControllerFactory : EssentialsDeviceFactory + { + public HdMdNxM4kEControllerFactory() + { + TypeNames = new List() { "hdmd4x14ke-bridgeable", "hdmd4x24ke", "hdmd6x24ke" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new HD-MD-NxM-4K-E Device"); + + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + + var type = dc.Type.ToLower(); + var control = props.Control; + var ipid = control.IpIdInt; + var address = control.TcpSshProperties.Address; + + switch (type) + { + case ("hdmd4x14ke-bridgeable"): + return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd4x14kE(ipid, address, Global.ControlSystem), props); + case ("hdmd4x24ke"): + return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd4x24kE(ipid, address, Global.ControlSystem), props); + case ("hdmd6x24ke"): + return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd6x24kE(ipid, address, Global.ControlSystem), props); + default: + return null; + } + } + } + + #endregion + + + + } } \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs index 57c52627..d19c9752 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using Crestron.SimplSharp; using Crestron.SimplSharpPro.DM; using Newtonsoft.Json; @@ -43,14 +44,19 @@ namespace PepperDash.Essentials.DM.Chassis OutputPorts = new RoutingPortCollection(); OutputPorts.Add(new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, null, this)); - + // physical settings if (props != null && props.Inputs != null) { + var inputRegex = new Regex(@"(?\d)", RegexOptions.IgnoreCase); foreach (var kvp in props.Inputs) { - // strip "hdmiIn" - var inputNum = Convert.ToUInt32(kvp.Key.Substring(6)); + // get numnbers from key and convert to int + //var inputNum = Convert.ToUInt32(kvp.Key.Substring(6)); + var inputMatch = inputRegex.Match(kvp.Key); + if (inputMatch == null) continue; + + var inputNum = Convert.ToUInt32(inputMatch.Groups["InputNum"].Value); var port = chassis.HdmiInputs[inputNum].HdmiInputPort; // set hdcp disables From 30f63eee03b9f691ace3f699718f6a90877e3d46 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 30 Jul 2021 10:30:32 -0600 Subject: [PATCH 51/59] fix: Remove reference to DMOutput name sig the HD-MD series of switchers appears to not populate the Name sig of the DMOutput, leading to a NullSig exception when attempting to set output names. This is probably because those names can't be set on the device itself, but some experimentation with hardware may be required to determine that completely. --- .../Chassis/HdMdNxM4kEBridgeableController.cs | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs index 3eece080..270e3461 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs @@ -71,10 +71,6 @@ namespace PepperDash.Essentials.DM.Chassis } OutputNames = props.Outputs; } - //else - //{ - // OutputNames.Add(1, "Output"); - //} VideoInputSyncFeedbacks = new FeedbackCollection(); VideoOutputRouteFeedbacks = new FeedbackCollection(); @@ -117,7 +113,7 @@ namespace PepperDash.Essentials.DM.Chassis { var index = i; var outputName = OutputNames[index]; - _Chassis.Outputs[i].Name.StringValue = outputName; + //_Chassis.Outputs[i].Name.StringValue = outputName; OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, index, this) @@ -125,12 +121,12 @@ namespace PepperDash.Essentials.DM.Chassis FeedbackMatchObject = _Chassis.HdmiOutputs[index] }); VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => (int)_Chassis.Outputs[index].VideoOutFeedback.Number)); - OutputNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].Name.StringValue)); + OutputNameFeedbacks.Add(new StringFeedback(outputName, () => OutputNames[index])); OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue)); } - _Chassis.DMInputChange += new DMInputEventHandler(Chassis_DMInputChange); - _Chassis.DMOutputChange += new DMOutputEventHandler(Chassis_DMOutputChange); + _Chassis.DMInputChange += Chassis_DMInputChange; + _Chassis.DMOutputChange += Chassis_DMOutputChange; AddPostActivationAction(AddFeedbackCollections); } @@ -354,18 +350,18 @@ namespace PepperDash.Essentials.DM.Chassis OutputRouteNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + joinIndex]); } - _Chassis.OnlineStatusChange += new Crestron.SimplSharpPro.OnlineStatusChangeEventHandler(Chassis_OnlineStatusChange); + _Chassis.OnlineStatusChange += Chassis_OnlineStatusChange; - trilist.OnlineStatusChange += new Crestron.SimplSharpPro.OnlineStatusChangeEventHandler((d, args) => + trilist.OnlineStatusChange += (d, args) => { - if (args.DeviceOnLine) - { - foreach (var feedback in Feedbacks) - { - feedback.FireUpdate(); - } - } - }); + if (args.DeviceOnLine) + { + foreach (var feedback in Feedbacks) + { + feedback.FireUpdate(); + } + } + }; } From 70d63a9f99c5eeb4164284a730b13fa03a61cad0 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 30 Jul 2021 10:44:26 -0600 Subject: [PATCH 52/59] chore: Mark non-bridgeable class obsolete Also add a debug message to give the new type to use. --- .../Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs index d19c9752..b47139e2 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs @@ -14,6 +14,7 @@ using PepperDash.Essentials.DM.Config; namespace PepperDash.Essentials.DM.Chassis { + [Obsolete("Please use HdMdNxM4kEBridgeable Controller")] public class HdMdNxM4kEController : CrestronGenericBaseDevice, IRoutingInputsOutputs, IRouting { public HdMdNxM Chassis { get; private set; } @@ -32,6 +33,7 @@ namespace PepperDash.Essentials.DM.Chassis HdMdNxM4kEPropertiesConfig props) : base(key, name, chassis) { + Debug.Console(0, this, "Type hdmd4x14ke is obsolete. Please use hdmd4x14ke-bridgeable"); Chassis = chassis; // logical ports From cad45c04cbfae8db2053291b3090fc9b7dd1784f Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 20 Sep 2021 16:12:39 -0600 Subject: [PATCH 53/59] fix: Add method to register for the correct event for resolution feedback The resolution feedback change events don't appear to bubble up to the main DMInput change event. It appears to require subscribing to an event on the VideoAttributes class that the input contains. --- .../Chassis/DmChassisController.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs index de9a088a..51990f07 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs @@ -8,6 +8,7 @@ using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DM; using Crestron.SimplSharpPro.DM.Cards; using Crestron.SimplSharpPro.DM.Endpoints; +using Crestron.SimplSharpProInternal; using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Essentials.Core; @@ -482,6 +483,29 @@ namespace PepperDash.Essentials.DM } + private void RegisterForInputResolutionFeedback(IVideoAttributesBasic input, uint number, RoutingInputPortWithVideoStatuses inputPort) + { + if (input == null) + { + return; + } + + input.VideoAttributes.AttributeChange += (sender, args) => + { + var inputAttributes = sender as IVideoAttributesBasic; + + if (inputAttributes == null) + { + return; + } + + Debug.Console(1, this, "Input {0} resolution updated", number); + + Debug.Console(1, this, "Updating resolution feedback for input {0}", number); + inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate(); + }; + } + /// /// /// @@ -883,6 +907,8 @@ namespace PepperDash.Essentials.DM { FeedbackMatchObject = Chassis.Inputs[cardNum] }; + + RegisterForInputResolutionFeedback(videoAttributesBasic, cardNum, inputPort as RoutingInputPortWithVideoStatuses); } else { From 2e76b6ba0ae81399458c407c3c45cc118785e0f7 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 21 Sep 2021 09:40:51 -0600 Subject: [PATCH 54/59] fix(DM): Fix issue with bad cast for IVideoAttributesBasic Also updates to use the DM routing input port rather than the tx AnyVideoInput for the DM input resolutions --- .../Chassis/DmChassisController.cs | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs index 51990f07..c74aea2b 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs @@ -490,15 +490,10 @@ namespace PepperDash.Essentials.DM return; } + Debug.Console(1, this, "Registering for resolution feedback for input {0} using Routing Port {1}", number, inputPort.Key); + input.VideoAttributes.AttributeChange += (sender, args) => { - var inputAttributes = sender as IVideoAttributesBasic; - - if (inputAttributes == null) - { - return; - } - Debug.Console(1, this, "Input {0} resolution updated", number); Debug.Console(1, this, "Updating resolution feedback for input {0}", number); @@ -898,9 +893,15 @@ namespace PepperDash.Essentials.DM if (videoAttributesBasic != null) { + Debug.Console(1, this, "card {0} supports IVideoAttributesBasic", cardNum); var statusFuncs = new VideoStatusFuncsWrapper { - VideoResolutionFeedbackFunc = () => videoAttributesBasic.VideoAttributes.GetVideoResolutionString() + VideoResolutionFeedbackFunc = () => + { + var resolution = videoAttributesBasic.VideoAttributes.GetVideoResolutionString(); + Debug.Console(1, this, "Updating resolution for input {0}. New resolution: {1}", cardNum, resolution); + return resolution; + } }; inputPort = new RoutingInputPortWithVideoStatuses(portKey, sigType, portType, Chassis.Inputs[cardNum], this, statusFuncs) @@ -1496,10 +1497,13 @@ namespace PepperDash.Essentials.DM var videoStatus = inputPort as RoutingInputPortWithVideoStatuses; - if (videoStatus != null) + if (videoStatus == null) { - videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]); + return; } + + Debug.Console(1, this, "Linking {0} to join {1} for resolution feedback.", videoStatus.Key, joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin); + videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]); } private void LinkStreamInputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) @@ -1686,14 +1690,16 @@ namespace PepperDash.Essentials.DM var videoStatus = inputPort as RoutingInputPortWithVideoStatuses; - if (videoStatus != null) + if (videoStatus == null) { - videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]); + return; } + Debug.Console(1, this, "Linking {0} to join {1} for resolution feedback.", videoStatus.Key, joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin); + videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]); } private void LinkAdvancedTxToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, - uint ioSlot, uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter) + uint ioSlot, uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter) { var transmitter = basicTransmitter as DmTxControllerBase; if (transmitter == null) return; @@ -1707,7 +1713,9 @@ namespace PepperDash.Essentials.DM if (txRoutingInputs == null) return; - var inputPorts = txRoutingInputs.InputPorts.Where((p) => p.Port is EndpointHdmiInput || p.Port is EndpointDisplayPortInput).ToList(); + var inputPorts = + txRoutingInputs.InputPorts.Where( + (p) => p.Port is EndpointHdmiInput || p.Port is EndpointDisplayPortInput).ToList(); if (inputPorts.Count == 0) { @@ -1741,12 +1749,18 @@ namespace PepperDash.Essentials.DM trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = (ushort) transmitter.HdcpSupportCapability; - var videoStatus = txRoutingInputs.InputPorts.Cast().FirstOrDefault((ip) => ip.Key == DmPortName.AnyVideoIn); - if (videoStatus != null) + var videoStatus = + InputPorts[string.Format("inputCard{0}--dmIn", ioSlot)] as RoutingInputPortWithVideoStatuses; + + if (videoStatus == null) { - videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]); + return; } + Debug.Console(1, this, "Linking {0} to join {1} for resolution feedback.", videoStatus.Key, + joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin); + videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig( + trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]); } private void LinkTxOnlineFeedbackToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, From 49e82f107b26e132e25efcc875bdf90b86da12d6 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 21 Sep 2021 12:06:22 -0600 Subject: [PATCH 55/59] fix(Essentials_DM): Updates to try and fix some exceptions --- .../Chassis/HdMdNxM4kEBridgeableController.cs | 82 ++++++++++++++----- 1 file changed, 62 insertions(+), 20 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs index 270e3461..1594bbdb 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs @@ -59,7 +59,7 @@ namespace PepperDash.Essentials.DM.Chassis { foreach (var kvp in props.Inputs) { - Debug.Console(0, this, "props.Inputs: {0}-{1}", kvp.Key, kvp.Value); + Debug.Console(1, this, "props.Inputs: {0}-{1}", kvp.Key, kvp.Value); } InputNames = props.Inputs; } @@ -67,7 +67,7 @@ namespace PepperDash.Essentials.DM.Chassis { foreach (var kvp in props.Outputs) { - Debug.Console(0, this, "props.Outputs: {0}-{1}", kvp.Key, kvp.Value); + Debug.Console(1, this, "props.Outputs: {0}-{1}", kvp.Key, kvp.Value); } OutputNames = props.Outputs; } @@ -100,7 +100,7 @@ namespace PepperDash.Essentials.DM.Chassis _Chassis.Inputs[index].Name.StringValue = inputName; InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.Hdmi, index, this) + eRoutingPortConnectionType.Hdmi, _Chassis.HdmiInputs[index], this) { FeedbackMatchObject = _Chassis.HdmiInputs[index] }); @@ -116,7 +116,7 @@ namespace PepperDash.Essentials.DM.Chassis //_Chassis.Outputs[i].Name.StringValue = outputName; OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.Hdmi, index, this) + eRoutingPortConnectionType.Hdmi, _Chassis.HdmiOutputs[index], this) { FeedbackMatchObject = _Chassis.HdmiOutputs[index] }); @@ -275,10 +275,19 @@ namespace PepperDash.Essentials.DM.Chassis public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) { + var input = inputSelector as HdMdNxM4kzEHdmiInput; + var output = outputSelector as HdMdNxMHdmiOutput; + + if (output == null) + { + Debug.Console(0, this, "Unable to make switch. output selector is not HdMdNxMHdmiOutput"); + return; + } + // Try to make switch only when necessary. The unit appears to toggle when already selected. - var current = _Chassis.HdmiOutputs[(uint)outputSelector].VideoOut; - if (current != _Chassis.HdmiInputs[(uint)inputSelector]) - _Chassis.HdmiOutputs[(uint)outputSelector].VideoOut = _Chassis.HdmiInputs[(uint)inputSelector]; + var current = output.VideoOut; + if (current != input) + output.VideoOut = input; } #endregion @@ -287,7 +296,9 @@ namespace PepperDash.Essentials.DM.Chassis public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType) { - ExecuteSwitch(inputSelector, outputSelector, signalType); + var input = inputSelector == 0 ? null : _Chassis.HdmiInputs[inputSelector]; + var output = _Chassis.HdmiOutputs[outputSelector]; + ExecuteSwitch(input, output, signalType); } #endregion @@ -327,12 +338,13 @@ namespace PepperDash.Essentials.DM.Chassis for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) { var joinIndex = i - 1; + var input = i; //Digital VideoInputSyncFeedbacks[InputNames[i]].LinkInputSig(trilist.BooleanInput[joinMap.InputSync.JoinNumber + joinIndex]); InputHdcpEnableFeedback[InputNames[i]].LinkInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + joinIndex]); InputHdcpEnableFeedback[InputNames[i]].LinkComplementInputSig(trilist.BooleanInput[joinMap.DisableInputHdcp.JoinNumber + joinIndex]); - trilist.SetSigTrueAction(joinMap.EnableInputHdcp.JoinNumber + joinIndex, () => EnableHdcp(i)); - trilist.SetSigTrueAction(joinMap.DisableInputHdcp.JoinNumber + joinIndex, () => DisableHdcp(i)); + trilist.SetSigTrueAction(joinMap.EnableInputHdcp.JoinNumber + joinIndex, () => EnableHdcp(input)); + trilist.SetSigTrueAction(joinMap.DisableInputHdcp.JoinNumber + joinIndex, () => DisableHdcp(input)); //Serial InputNameFeedbacks[InputNames[i]].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + joinIndex]); @@ -341,9 +353,10 @@ namespace PepperDash.Essentials.DM.Chassis for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) { var joinIndex = i - 1; + var output = i; //Analog VideoOutputRouteFeedbacks[OutputNames[i]].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + joinIndex]); - trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + joinIndex, (a) => ExecuteSwitch(a, i, eRoutingSignalType.AudioVideo)); + trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + joinIndex, (a) => ExecuteNumericSwitch(a, (ushort) output, eRoutingSignalType.AudioVideo)); //Serial OutputNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + joinIndex]); @@ -354,12 +367,19 @@ namespace PepperDash.Essentials.DM.Chassis trilist.OnlineStatusChange += (d, args) => { - if (args.DeviceOnLine) + if (!args.DeviceOnLine) { - foreach (var feedback in Feedbacks) - { - feedback.FireUpdate(); - } + return; + } + foreach (var feedback in Feedbacks) + { + feedback.FireUpdate(); + } + + foreach (var name in InputNames) + { + trilist.SetString(joinMap.InputName.JoinNumber + (name.Key - 1), + InputNameFeedbacks[(int) name.Key].StringValue); } }; } @@ -376,10 +396,11 @@ namespace PepperDash.Essentials.DM.Chassis { _Chassis.Inputs[i].Name.StringValue = InputNames[i]; } - for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) + + /*for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) { _Chassis.Outputs[i].Name.StringValue = OutputNames[i]; - } + }*/ foreach (var feedback in Feedbacks) { @@ -391,7 +412,28 @@ namespace PepperDash.Essentials.DM.Chassis { if (args.EventId != DMOutputEventIds.VideoOutEventId) return; - for (var i = 0; i < VideoOutputRouteFeedbacks.Count; i++) + var output = args.Number; + + var inputNumber = _Chassis.HdmiOutputs[output].VideoOutFeedback == null + ? 0 + : _Chassis.HdmiOutputs[output].VideoOutFeedback.Number; + + var outputName = OutputNames[output]; + + var feedback = VideoOutputRouteFeedbacks[outputName]; + + if (feedback == null) + { + return; + } + var inPort = + InputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.HdmiOutputs[output].VideoOutFeedback); + var outPort = OutputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.HdmiOutputs[output]); + + feedback.FireUpdate(); + OnSwitchChange(new RoutingNumericEventArgs(output, inputNumber, outPort, inPort, eRoutingSignalType.AudioVideo)); + + /*for (var i = 0; i < VideoOutputRouteFeedbacks.Count; i++) { var index = i; var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1].VideoOutFeedback); @@ -401,7 +443,7 @@ namespace PepperDash.Essentials.DM.Chassis VideoOutputRouteFeedbacks[i].FireUpdate(); OnSwitchChange(new RoutingNumericEventArgs((ushort)i, VideoOutputRouteFeedbacks[i].UShortValue, localOutputPort, localInputPort, eRoutingSignalType.AudioVideo)); - } + }*/ } void Chassis_DMInputChange(Switch device, DMInputEventArgs args) From eec4484f7887f9e12e3c22da995ef63ee0fa577d Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 21 Sep 2021 16:11:13 -0500 Subject: [PATCH 56/59] fix: updates to resolve issues with routing and feedbacks in the HdMdNxM4kEBridgeableController class. --- .../Chassis/HdMdNxM4kEBridgeableController.cs | 151 +++++++++--------- 1 file changed, 78 insertions(+), 73 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs index 1594bbdb..3d41af3a 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs @@ -37,8 +37,8 @@ namespace PepperDash.Essentials.DM.Chassis public FeedbackCollection OutputNameFeedbacks { get; private set; } public FeedbackCollection OutputRouteNameFeedbacks { get; private set; } public FeedbackCollection InputHdcpEnableFeedback { get; private set; } - public FeedbackCollection DeviceNameFeedback { get; private set; } - public FeedbackCollection AutoRouteFeedback { get; private set; } + public StringFeedback DeviceNameFeedback { get; private set; } + public BoolFeedback AutoRouteFeedback { get; private set; } #region Constructor @@ -47,6 +47,7 @@ namespace PepperDash.Essentials.DM.Chassis : base(key, name, chassis) { _Chassis = chassis; + Name = name; if (props == null) { @@ -72,32 +73,30 @@ namespace PepperDash.Essentials.DM.Chassis OutputNames = props.Outputs; } + DeviceNameFeedback = new StringFeedback(()=>Name); + VideoInputSyncFeedbacks = new FeedbackCollection(); VideoOutputRouteFeedbacks = new FeedbackCollection(); InputNameFeedbacks = new FeedbackCollection(); OutputNameFeedbacks = new FeedbackCollection(); OutputRouteNameFeedbacks = new FeedbackCollection(); InputHdcpEnableFeedback = new FeedbackCollection(); - DeviceNameFeedback = new FeedbackCollection(); - AutoRouteFeedback = new FeedbackCollection(); - + InputPorts = new RoutingPortCollection(); OutputPorts = new RoutingPortCollection(); - var deviceName = string.IsNullOrEmpty(this.Name) ? name : this.Name; - DeviceNameFeedback.Add(new StringFeedback(deviceName, () => deviceName)); - if (_Chassis.NumberOfInputs == 1) { _Chassis4x1 = _Chassis as HdMd4x14kE; - AutoRouteFeedback.Add(new BoolFeedback(deviceName + "-" + InputNames[1], () => _Chassis4x1.AutoModeOnFeedback.BoolValue)); + AutoRouteFeedback = new BoolFeedback(() => _Chassis4x1.AutoModeOnFeedback.BoolValue); } for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) { var index = i; var inputName = InputNames[index]; - _Chassis.Inputs[index].Name.StringValue = inputName; + //_Chassis.Inputs[index].Name.StringValue = inputName; + _Chassis.HdmiInputs[index].Name.StringValue = inputName; InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, _Chassis.HdmiInputs[index], this) @@ -105,7 +104,8 @@ namespace PepperDash.Essentials.DM.Chassis FeedbackMatchObject = _Chassis.HdmiInputs[index] }); VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[index].VideoDetectedFeedback.BoolValue)); - InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[index].Name.StringValue)); + //InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[index].NameFeedback.StringValue)); + InputNameFeedbacks.Add(new StringFeedback(inputName, () => InputNames[index])); InputHdcpEnableFeedback.Add(new BoolFeedback(inputName, () => _Chassis.HdmiInputs[index].HdmiInputPort.HdcpSupportOnFeedback.BoolValue)); } @@ -113,14 +113,15 @@ namespace PepperDash.Essentials.DM.Chassis { var index = i; var outputName = OutputNames[index]; - //_Chassis.Outputs[i].Name.StringValue = outputName; + //_Chassis.Outputs[index].Name.StringValue = outputName; + //_Chassis.HdmiOutputs[index].Name.StringValue = outputName; OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, _Chassis.HdmiOutputs[index], this) { FeedbackMatchObject = _Chassis.HdmiOutputs[index] }); - VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => (int)_Chassis.Outputs[index].VideoOutFeedback.Number)); + VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback == null ? 0 : (int)_Chassis.Outputs[index].VideoOutFeedback.Number)); OutputNameFeedbacks.Add(new StringFeedback(outputName, () => OutputNames[index])); OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue)); } @@ -185,9 +186,10 @@ namespace PepperDash.Essentials.DM.Chassis public void AddFeedbackCollections() { + AddFeedbackToList(DeviceNameFeedback); AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback); AddCollectionsToList(VideoOutputRouteFeedbacks); - AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedbacks, DeviceNameFeedback); + AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedbacks); } #endregion @@ -274,9 +276,10 @@ namespace PepperDash.Essentials.DM.Chassis #region IRouting Members public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) - { - var input = inputSelector as HdMdNxM4kzEHdmiInput; + { + var input = inputSelector as HdMdNxMHdmiInput; //changed from HdMdNxM4kzEHdmiInput; var output = outputSelector as HdMdNxMHdmiOutput; + Debug.Console(2, this, "ExecuteSwitch: input={0} output={1}", input, output); if (output == null) { @@ -286,8 +289,8 @@ namespace PepperDash.Essentials.DM.Chassis // Try to make switch only when necessary. The unit appears to toggle when already selected. var current = output.VideoOut; - if (current != input) - output.VideoOut = input; + if (current != input) + output.VideoOut = input; } #endregion @@ -296,8 +299,11 @@ namespace PepperDash.Essentials.DM.Chassis public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType) { - var input = inputSelector == 0 ? null : _Chassis.HdmiInputs[inputSelector]; + var input = inputSelector == 0 ? null : _Chassis.HdmiInputs[inputSelector]; var output = _Chassis.HdmiOutputs[outputSelector]; + + Debug.Console(2, this, "ExecuteNumericSwitch: input={0} output={1}", input, output); + ExecuteSwitch(input, output, signalType); } @@ -326,13 +332,13 @@ namespace PepperDash.Essentials.DM.Chassis } IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); - DeviceNameFeedback[this.Name].LinkInputSig(trilist.StringInput[joinMap.Name.JoinNumber]); + DeviceNameFeedback.LinkInputSig(trilist.StringInput[joinMap.Name.JoinNumber]); if (_Chassis4x1 != null) { trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOn()); trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOff()); - AutoRouteFeedback[this.Name + "-" + InputNames[1]].LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); + AutoRouteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); } for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) @@ -340,14 +346,14 @@ namespace PepperDash.Essentials.DM.Chassis var joinIndex = i - 1; var input = i; //Digital - VideoInputSyncFeedbacks[InputNames[i]].LinkInputSig(trilist.BooleanInput[joinMap.InputSync.JoinNumber + joinIndex]); - InputHdcpEnableFeedback[InputNames[i]].LinkInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + joinIndex]); - InputHdcpEnableFeedback[InputNames[i]].LinkComplementInputSig(trilist.BooleanInput[joinMap.DisableInputHdcp.JoinNumber + joinIndex]); + VideoInputSyncFeedbacks[InputNames[input]].LinkInputSig(trilist.BooleanInput[joinMap.InputSync.JoinNumber + joinIndex]); + InputHdcpEnableFeedback[InputNames[input]].LinkInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + joinIndex]); + InputHdcpEnableFeedback[InputNames[input]].LinkComplementInputSig(trilist.BooleanInput[joinMap.DisableInputHdcp.JoinNumber + joinIndex]); trilist.SetSigTrueAction(joinMap.EnableInputHdcp.JoinNumber + joinIndex, () => EnableHdcp(input)); trilist.SetSigTrueAction(joinMap.DisableInputHdcp.JoinNumber + joinIndex, () => DisableHdcp(input)); - //Serial - InputNameFeedbacks[InputNames[i]].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + joinIndex]); + //Serial + InputNameFeedbacks[InputNames[input]].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + joinIndex]); } for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) @@ -355,32 +361,22 @@ namespace PepperDash.Essentials.DM.Chassis var joinIndex = i - 1; var output = i; //Analog - VideoOutputRouteFeedbacks[OutputNames[i]].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + joinIndex]); + VideoOutputRouteFeedbacks[OutputNames[output]].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + joinIndex]); trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + joinIndex, (a) => ExecuteNumericSwitch(a, (ushort) output, eRoutingSignalType.AudioVideo)); //Serial - OutputNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + joinIndex]); - OutputRouteNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + joinIndex]); + OutputNameFeedbacks[OutputNames[output]].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + joinIndex]); + OutputRouteNameFeedbacks[OutputNames[output]].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + joinIndex]); } _Chassis.OnlineStatusChange += Chassis_OnlineStatusChange; trilist.OnlineStatusChange += (d, args) => { - if (!args.DeviceOnLine) - { - return; - } - foreach (var feedback in Feedbacks) - { - feedback.FireUpdate(); - } + if (!args.DeviceOnLine) return; - foreach (var name in InputNames) - { - trilist.SetString(joinMap.InputName.JoinNumber + (name.Key - 1), - InputNameFeedbacks[(int) name.Key].StringValue); - } + // feedback updates was moved to the Chassis_OnlineStatusChange + // due to the amount of time it takes for the device to come online }; } @@ -391,21 +387,17 @@ namespace PepperDash.Essentials.DM.Chassis void Chassis_OnlineStatusChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.OnlineOfflineEventArgs args) { - if (!args.DeviceOnLine) return; - for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) - { - _Chassis.Inputs[i].Name.StringValue = InputNames[i]; - } + IsOnline.FireUpdate(); - /*for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) - { - _Chassis.Outputs[i].Name.StringValue = OutputNames[i]; - }*/ + if (!args.DeviceOnLine) return; + + foreach (var feedback in Feedbacks) + { + feedback.FireUpdate(); + } - foreach (var feedback in Feedbacks) - { - feedback.FireUpdate(); - } + if (_Chassis4x1 != null) + AutoRouteFeedback.FireUpdate(); } void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args) @@ -432,27 +424,40 @@ namespace PepperDash.Essentials.DM.Chassis feedback.FireUpdate(); OnSwitchChange(new RoutingNumericEventArgs(output, inputNumber, outPort, inPort, eRoutingSignalType.AudioVideo)); - - /*for (var i = 0; i < VideoOutputRouteFeedbacks.Count; i++) - { - var index = i; - var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1].VideoOutFeedback); - var localOutputPort = - OutputPorts.FirstOrDefault(p => (DMOutput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1]); - - - VideoOutputRouteFeedbacks[i].FireUpdate(); - OnSwitchChange(new RoutingNumericEventArgs((ushort)i, VideoOutputRouteFeedbacks[i].UShortValue, localOutputPort, localInputPort, eRoutingSignalType.AudioVideo)); - }*/ } void Chassis_DMInputChange(Switch device, DMInputEventArgs args) - { - if (args.EventId != DMInputEventIds.VideoDetectedEventId) return; - foreach (var item in VideoInputSyncFeedbacks) - { - item.FireUpdate(); - } + { + switch (args.EventId) + { + case DMInputEventIds.VideoDetectedEventId: + { + Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", args.EventId); + foreach (var item in VideoInputSyncFeedbacks) + { + item.FireUpdate(); + } + break; + } + case DMInputEventIds.InputNameFeedbackEventId: + case DMInputEventIds.InputNameEventId: + case DMInputEventIds.NameFeedbackEventId: + { + Debug.Console(1, this, "Event ID {0}: Updating name feedbacks.", args.EventId); + Debug.Console(1, this, "Input {0} Name {1}", args.Number, + _Chassis.HdmiInputs[args.Number].NameFeedback.StringValue); + foreach (var item in InputNameFeedbacks) + { + item.FireUpdate(); + } + break; + } + default: + { + Debug.Console(1, this, "Unhandled DM Input Event ID {0}", args.EventId); + break; + } + } } #endregion From 8d1f1876437079d04900a884c7ce893d752ed926 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 21 Sep 2021 17:59:12 -0600 Subject: [PATCH 57/59] feat(essentials): #830 Adds new Cisco features Adds IHasDoNotDisturbMode, IHasStandbyMode and IHasHalfWakeMode interfaces. Implements all interfaces on CiscoSparkCodec class. Adds CiscoCodecJoinMap to allow for bridging new Cisco specific functions. --- .../Codec/IHasDoNotDisturb.cs | 45 +++++++ .../Essentials Devices Common.csproj | 3 + .../CiscoCodec/CiscoCodecJoinMap.cs | 120 ++++++++++++++++++ .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 96 +++++++++++++- .../VideoCodec/CiscoCodec/xStatus.cs | 26 +++- .../VideoCodec/Interfaces/IHasStandbyMode.cs | 32 +++++ .../VideoCodec/VideoCodecBase.cs | 2 +- 7 files changed, 319 insertions(+), 5 deletions(-) create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasDoNotDisturb.cs create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecJoinMap.cs create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStandbyMode.cs diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasDoNotDisturb.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasDoNotDisturb.cs new file mode 100644 index 00000000..7bb9b924 --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasDoNotDisturb.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Describes a device that has Do Not Disturb mode capability + /// + public interface IHasDoNotDisturbMode + { + /// + /// Indictes whether Do Not Disturb mode is on (Activated) + /// + BoolFeedback DoNotDisturbModeIsOnFeedback { get; } + + /// + /// Activates Do Not Disturb mode + /// + void ActivateDoNotDisturbMode(); + + /// + /// Deactivates Do Not Disturb mode + /// + void DeactivateDoNotDisturbMode(); + + /// + /// Toggles Do Not Disturb mode + /// + void ToggleDoNotDisturbMode(); + } + + public interface IHasDoNotDisturbModeWithTimeout : IHasDoNotDisturbMode + { + /// + /// Activates Do Not Disturb mode with a timeout + /// + /// + void ActivateDoNotDisturbMode(int timeout); + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index fc5f68d4..1fcffff2 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 @@ -108,6 +108,7 @@ + @@ -117,6 +118,7 @@ + @@ -125,6 +127,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecJoinMap.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecJoinMap.cs new file mode 100644 index 00000000..8caeaf3e --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecJoinMap.cs @@ -0,0 +1,120 @@ +using System; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges.JoinMaps; + + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco +{ + public class CiscoCodecJoinMap : VideoCodecControllerJoinMap + { + #region Digital + + [JoinName("ActivateDoNotDisturbMode")] + public JoinDataComplete ActivateDoNotDisturbMode = new JoinDataComplete( + new JoinData + { + JoinNumber = 221, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Activates Do Not Disturb Mode. FB High if active.", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DeactivateDoNotDisturbMode")] + public JoinDataComplete DeactivateDoNotDisturbMode = new JoinDataComplete( + new JoinData + { + JoinNumber = 222, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Deactivates Do Not Disturb Mode. FB High if deactivated.", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ToggleDoNotDisturbMode")] + public JoinDataComplete ToggleDoNotDisturbMode = new JoinDataComplete( + new JoinData + { + JoinNumber = 223, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Toggles Do Not Disturb Mode.", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ActivateStandby")] + public JoinDataComplete ActivateStandby = new JoinDataComplete( + new JoinData + { + JoinNumber = 226, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Activates Standby Mode. FB High if active.", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DeactivateStandby")] + public JoinDataComplete DeactivateStandby = new JoinDataComplete( + new JoinData + { + JoinNumber = 227, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Deactivates Standby Mode. FB High if deactivated.", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ActivateHalfWakeMode")] + public JoinDataComplete ActivateHalfWakeMode = new JoinDataComplete( + new JoinData + { + JoinNumber = 228, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Activates Half Wake Mode. FB High if active.", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + #endregion + + + #region Analog + + + #endregion + + + #region Serials + + + #endregion + + public CiscoCodecJoinMap(uint joinStart) + : base(joinStart, typeof(CiscoCodecJoinMap)) + { + } + + public CiscoCodecJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { + } + } +} \ No newline at end of file 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 f894141c..904482b0 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 @@ -28,7 +28,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public class CiscoSparkCodec : VideoCodecBase, IHasCallHistory, IHasCallFavorites, IHasDirectory, IHasScheduleAwareness, IOccupancyStatusProvider, IHasCodecLayouts, IHasCodecSelfView, - ICommunicationMonitor, IRouting, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets, IHasExternalSourceSwitching, IHasBranding, IHasCameraOff, IHasCameraMute + ICommunicationMonitor, IRouting, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets, + IHasExternalSourceSwitching, IHasBranding, IHasCameraOff, IHasCameraMute, IHasDoNotDisturbMode, + IHasHalfWakeMode { private bool _externalSourceChangeRequested; @@ -316,6 +318,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco CameraIsMutedFeedback = CameraIsOffFeedback; SupportsCameraOff = true; + DoNotDisturbModeIsOnFeedback = new BoolFeedback(() => CodecStatus.Status.Conference.DoNotDisturb.BoolValue); + HalfWakeModeIsOnFeedback = new BoolFeedback(() => CodecStatus.Status.Standby.State.Value == "Halfwake"); + PresentationViewMaximizedFeedback = new BoolFeedback(() => CurrentPresentationView == "Maximized"); Communication = comm; @@ -413,7 +418,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco CodecStatus.Status.Audio.Volume.ValueChangedAction = VolumeLevelFeedback.FireUpdate; CodecStatus.Status.Audio.VolumeMute.ValueChangedAction = MuteFeedback.FireUpdate; CodecStatus.Status.Audio.Microphones.Mute.ValueChangedAction = PrivacyModeIsOnFeedback.FireUpdate; - CodecStatus.Status.Standby.State.ValueChangedAction = StandbyIsOnFeedback.FireUpdate; + CodecStatus.Status.Standby.State.ValueChangedAction = new Action(() => + { + StandbyIsOnFeedback.FireUpdate(); + HalfWakeModeIsOnFeedback.FireUpdate(); + }); CodecStatus.Status.RoomAnalytics.PeoplePresence.ValueChangedAction = RoomIsOccupiedFeedback.FireUpdate; CodecStatus.Status.RoomAnalytics.PeopleCount.Current.ValueChangedAction = PeopleCountFeedback.FireUpdate; CodecStatus.Status.Cameras.SpeakerTrack.Status.ValueChangedAction = CameraAutoModeIsOnFeedback.FireUpdate; @@ -423,6 +432,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco CodecStatus.Status.Video.Layout.LayoutFamily.Local.ValueChangedAction = ComputeLocalLayout; CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = SharingContentIsOnFeedback.FireUpdate; CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = FarEndIsSharingContentFeedback.FireUpdate; + CodecStatus.Status.Conference.DoNotDisturb.ValueChangedAction = DoNotDisturbModeIsOnFeedback.FireUpdate; + try { CodecStatus.Status.Video.Input.MainVideoMute.ValueChangedAction = CameraIsOffFeedback.FireUpdate; @@ -1495,7 +1506,49 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { + var joinMap = new CiscoCodecJoinMap(joinStart); + + var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); + + if (customJoins != null) + { + joinMap.SetCustomJoinData(customJoins); + } + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + LinkVideoCodecToApi(this, trilist, joinStart, joinMapKey, bridge); + + LinkCiscoCodecToApi(trilist, joinMap); + } + + public void LinkCiscoCodecToApi(BasicTriList trilist, CiscoCodecJoinMap joinMap) + { + var dndCodec = this as IHasDoNotDisturbMode; + if (dndCodec != null) + { + dndCodec.DoNotDisturbModeIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.ActivateDoNotDisturbMode.JoinNumber]); + dndCodec.DoNotDisturbModeIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.DeactivateDoNotDisturbMode.JoinNumber]); + + trilist.SetSigFalseAction(joinMap.ActivateDoNotDisturbMode.JoinNumber, () => dndCodec.ActivateDoNotDisturbMode()); + trilist.SetSigFalseAction(joinMap.DeactivateDoNotDisturbMode.JoinNumber, () => dndCodec.DeactivateDoNotDisturbMode()); + trilist.SetSigFalseAction(joinMap.ToggleDoNotDisturbMode.JoinNumber, () => dndCodec.ToggleDoNotDisturbMode()); + } + + var halfwakeCodec = this as IHasHalfWakeMode; + if (halfwakeCodec != null) + { + halfwakeCodec.StandbyIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.ActivateStandby.JoinNumber]); + halfwakeCodec.StandbyIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.DeactivateStandby.JoinNumber]); + halfwakeCodec.HalfWakeModeIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.ActivateHalfWakeMode.JoinNumber]); + + trilist.SetSigFalseAction(joinMap.ActivateStandby.JoinNumber, () => halfwakeCodec.StandbyActivate()); + trilist.SetSigFalseAction(joinMap.DeactivateStandby.JoinNumber, () => halfwakeCodec.StandbyDeactivate()); + trilist.SetSigFalseAction(joinMap.ActivateHalfWakeMode.JoinNumber, () => halfwakeCodec.HalfwakeActivate()); + } } /// @@ -2069,6 +2122,45 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco else CameraMuteOn(); } + + #region IHasDoNotDisturbMode Members + + public BoolFeedback DoNotDisturbModeIsOnFeedback { get; private set; } + + public void ActivateDoNotDisturbMode() + { + SendText("xCommand Conference DoNotDisturb Activate"); + } + + public void DeactivateDoNotDisturbMode() + { + SendText("xCommand Conference DoNotDisturb Deactivate"); + } + + public void ToggleDoNotDisturbMode() + { + if (DoNotDisturbModeIsOnFeedback.BoolValue) + { + DeactivateDoNotDisturbMode(); + } + else + { + ActivateDoNotDisturbMode(); + } + } + + #endregion + + #region IHasHalfWakeMode Members + + public BoolFeedback HalfWakeModeIsOnFeedback { get; private set; } + + public void HalfwakeActivate() + { + SendText("xCommand Standby Halfwake"); + } + + #endregion } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index c1cd92cf..a32ff5bf 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -440,9 +440,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public CallId CallId { get; set; } } - public class DoNotDisturb + public class DoNotDisturb : ValueProperty { - public string Value { get; set; } + string _Value; + + public bool BoolValue { get; private set; } + + public string Value + { + get + { + return _Value; + } + set + { + _Value = value; + // If the incoming value is "On" it sets the BoolValue true, otherwise sets it false + BoolValue = value == "On" || value == "Active"; + OnValueChanged(); + } + } } public class Mode @@ -600,6 +617,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public Conference2() { Presentation = new Presentation(); + DoNotDisturb = new DoNotDisturb(); } } @@ -1380,12 +1398,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public class State : ValueProperty { + string _value; + public bool BoolValue { get; private set; } public string Value // Valid values are Standby/EnteringStandby/Halfwake/Off { + get { return _value; } set { + _value = value; // If the incoming value is "On" it sets the BoolValue true, otherwise sets it false BoolValue = value == "On" || value == "Standby"; OnValueChanged(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStandbyMode.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStandbyMode.cs new file mode 100644 index 00000000..55dcd081 --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStandbyMode.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec +{ + /// + /// Describes a device that has Standby Mode capability + /// + public interface IHasStandbyMode + { + BoolFeedback StandbyIsOnFeedback { get; } + + void StandbyActivate(); + + void StandbyDeactivate(); + } + + /// + /// Describes a device that has Half Waek Mode capability + /// + public interface IHasHalfWakeMode : IHasStandbyMode + { + BoolFeedback HalfWakeModeIsOnFeedback { get; } + + void HalfwakeActivate(); + } +} \ 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 d34c9e3b..26ed54bb 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 @@ -25,7 +25,7 @@ using Feedback = PepperDash.Essentials.Core.Feedback; namespace PepperDash.Essentials.Devices.Common.VideoCodec { public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutputs, - IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced + IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced, IHasStandbyMode { private const int XSigEncoding = 28591; protected const int MaxParticipants = 50; From 16db2663a6f82c60f119248c62eb6ff36c966119 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 22 Sep 2021 11:56:06 -0600 Subject: [PATCH 58/59] feat(essentials): #835 comments out some debug messages to clean up console at startup --- .../PepperDashEssentialsBase/Devices/EssentialsDevice.cs | 6 +++--- .../PepperDashEssentialsBase/Factory/DeviceFactory.cs | 4 ++-- .../PepperDashEssentialsBase/Plugins/PluginLoader.cs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs index 46fa819b..a72bd282 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs @@ -57,7 +57,7 @@ namespace PepperDash.Essentials.Core public DescriptionAttribute(string description) { - Debug.Console(2, "Setting Description: {0}", description); + //Debug.Console(2, "Setting Description: {0}", description); _Description = description; } @@ -74,7 +74,7 @@ namespace PepperDash.Essentials.Core public ConfigSnippetAttribute(string configSnippet) { - Debug.Console(2, "Setting Config Snippet {0}", configSnippet); + //Debug.Console(2, "Setting Config Snippet {0}", configSnippet); _ConfigSnippet = configSnippet; } @@ -103,7 +103,7 @@ namespace PepperDash.Essentials.Core { foreach (var typeName in TypeNames) { - Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); + //Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; string description = descriptionAttribute[0].Description; var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs index a17e0d91..ebdc87b1 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs @@ -69,13 +69,13 @@ namespace PepperDash.Essentials.Core /// public static void AddFactoryForType(string typeName, Func method) { - Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName); + //Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName); DeviceFactory.FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = method}); } public static void AddFactoryForType(string typeName, string description, CType cType, Func method) { - Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName); + //Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName); if(FactoryMethods.ContainsKey(typeName)) { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Plugins/PluginLoader.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Plugins/PluginLoader.cs index 7437d75a..136303e3 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Plugins/PluginLoader.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Plugins/PluginLoader.cs @@ -123,7 +123,7 @@ namespace PepperDash.Essentials /// static LoadedAssembly LoadAssembly(string filePath) { - Debug.Console(2, "Attempting to load {0}", filePath); + //Debug.Console(2, "Attempting to load {0}", filePath); var assembly = Assembly.LoadFrom(filePath); if (assembly != null) { From a165ba911f87356c9cec67d217cfc05c8b87b26c Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 22 Sep 2021 15:31:13 -0600 Subject: [PATCH 59/59] feat(essentials): Minor updates after testing against codec hardware --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 6 ++++-- .../VideoCodec/CiscoCodec/xStatus.cs | 1 + 2 files changed, 5 insertions(+), 2 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 904482b0..d625637c 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 @@ -586,6 +586,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco prefix + "/Status/Audio" + Delimiter + prefix + "/Status/Call" + Delimiter + prefix + "/Status/Conference/Presentation" + Delimiter + + prefix + "/Status/Conference/DoNotDisturb" + Delimiter + prefix + "/Status/Cameras/SpeakerTrack" + Delimiter + prefix + "/Status/RoomAnalytics" + Delimiter + prefix + "/Status/RoomPreset" + Delimiter + @@ -594,10 +595,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco prefix + "/Status/Video/Layout" + Delimiter + prefix + "/Status/Video/Input/MainVideoMute" + Delimiter + prefix + "/Bookings" + Delimiter + - prefix + "/Event/CallDisconnect" + Delimiter + prefix + "/Event/Bookings" + Delimiter + prefix + "/Event/CameraPresetListUpdated" + Delimiter + - prefix + "/Event/UserInterface/Presentation/ExternalSource/Selected/SourceIdentifier" + Delimiter; + prefix + "/Event/UserInterface/Presentation/ExternalSource/Selected/SourceIdentifier" + Delimiter + + prefix + "/Event/CallDisconnect" + Delimiter; // Keep CallDisconnect last to detect when feedback registration completes correctly + } #endregion diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index a32ff5bf..29b9f260 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -2113,6 +2113,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco Conference = new Conference2(); SystemUnit = new SystemUnit(); Video = new Video(); + Conference = new Conference2(); } }